OSDN Git Service

upgrade to 3.6.1
authorSHIRAKATA Kentaro <argrath@ub32.org>
Wed, 9 May 2018 20:25:07 +0000 (05:25 +0900)
committerSHIRAKATA Kentaro <argrath@ub32.org>
Thu, 10 May 2018 12:21:33 +0000 (21:21 +0900)
patch jnethack-3.6.0 to nethack-3.6.1 and copy back.

553 files changed:
DEVEL/Developer.txt
DEVEL/code_features.txt
DEVEL/code_style.txt
DEVEL/git_recipes.txt
DEVEL/gitinfo.pl [new file with mode: 0644]
DEVEL/hooksdir/.NHgithook.pm.swp [deleted file]
DEVEL/hooksdir/NHadd
DEVEL/hooksdir/NHgithook.pm
DEVEL/hooksdir/NHsubst
DEVEL/hooksdir/NHtext
DEVEL/hooksdir/applypatch-msg
DEVEL/hooksdir/commit-msg
DEVEL/hooksdir/nhsub
DEVEL/hooksdir/post-applypatch
DEVEL/hooksdir/post-checkout
DEVEL/hooksdir/post-commit
DEVEL/hooksdir/post-merge
DEVEL/hooksdir/post-rewrite
DEVEL/hooksdir/pre-applypatch
DEVEL/hooksdir/pre-auto-gc
DEVEL/hooksdir/pre-commit
DEVEL/hooksdir/pre-push
DEVEL/hooksdir/pre-rebase
DEVEL/hooksdir/prepare-commit-msg
DEVEL/nhgitset.pl
Files
Porting
README
dat/bigroom.des
dat/bogusmon.txt
dat/cmdhelp
dat/data.base
dat/dungeon.def
dat/engrave.txt
dat/epitaph.txt
dat/gehennom.des
dat/help
dat/hh
dat/keyhelp [new file with mode: 0644]
dat/knox.des
dat/medusa.des
dat/mines.des
dat/opthelp
dat/oracle.des
dat/quest.txt
dat/rumors.fal
dat/rumors.tru
dat/symbols
dat/tribute
dat/wizhelp
doc/Guidebook.mn
doc/Guidebook.tex
doc/Guidebook.txt
doc/config.nh [new file with mode: 0644]
doc/dgn_comp.6
doc/dlb.6
doc/fixes30.0
doc/fixes34.1
doc/fixes34.2
doc/fixes34.3
doc/fixes35.0
doc/fixes36.0
doc/fixes36.1 [new file with mode: 0644]
doc/lev_comp.6
doc/makedefs.6
doc/nethack.6
doc/nethack.txt
doc/recover.6
doc/window.doc
include/artifact.h
include/artilist.h
include/attrib.h
include/botl.h
include/config.h
include/config1.h
include/context.h
include/coord.h
include/decl.h
include/dungeon.h
include/engrave.h
include/extern.h
include/flag.h
include/func_tab.h
include/global.h
include/hack.h
include/integer.h [new file with mode: 0644]
include/lev.h
include/lint.h
include/mac-carbon.h
include/mac-qt.h
include/mac-term.h
include/macconf.h
include/macwin.h
include/mail.h
include/mextra.h
include/mfndpos.h
include/micro.h
include/mkroom.h
include/mondata.h
include/monst.h
include/monsym.h
include/ntconf.h
include/obj.h
include/objclass.h
include/os2conf.h
include/patchlevel.h
include/pcconf.h
include/permonst.h
include/prop.h
include/qt_xpms.h
include/qtext.h
include/qttableview.h
include/rm.h
include/skills.h
include/sp_lev.h
include/sys.h
include/system.h
include/tcap.h
include/tile2x11.h
include/tileset.h [new file with mode: 0644]
include/timeout.h
include/tosconf.h
include/tradstdc.h
include/trap.h
include/unixconf.h
include/vmsconf.h
include/winX.h
include/winprocs.h
include/wintty.h
include/wintype.h
include/you.h
include/youprop.h
japanese/jpatchlevel.h
src/allmain.c
src/alloc.c
src/apply.c
src/artifact.c
src/attrib.c
src/ball.c
src/bones.c
src/botl.c
src/cmd.c
src/dbridge.c
src/decl.c
src/detect.c
src/dig.c
src/display.c
src/do.c
src/do_name.c
src/do_wear.c
src/dog.c
src/dogmove.c
src/dokick.c
src/dothrow.c
src/drawing.c
src/dungeon.c
src/eat.c
src/end.c
src/engrave.c
src/exper.c
src/explode.c
src/files.c
src/fountain.c
src/hack.c
src/hacklib.c
src/invent.c
src/light.c
src/lock.c
src/mail.c
src/makemon.c
src/mapglyph.c
src/mcastu.c
src/mhitm.c
src/mhitu.c
src/minion.c
src/mklev.c
src/mkmap.c
src/mkmaze.c
src/mkobj.c
src/mkroom.c
src/mon.c
src/mondata.c
src/monmove.c
src/monst.c
src/mplayer.c
src/mthrowu.c
src/muse.c
src/music.c
src/o_init.c
src/objects.c
src/objnam.c
src/options.c
src/pager.c
src/pickup.c
src/pline.c
src/polyself.c
src/potion.c
src/pray.c
src/priest.c
src/quest.c
src/questpgr.c
src/read.c
src/rect.c
src/region.c
src/restore.c
src/rip.c
src/rnd.c
src/role.c
src/rumors.c
src/save.c
src/shk.c
src/shknam.c
src/sit.c
src/sounds.c
src/sp_lev.c
src/spell.c
src/steal.c
src/steed.c
src/sys.c
src/teleport.c
src/timeout.c
src/topten.c
src/track.c
src/trap.c
src/u_init.c
src/uhitm.c
src/vault.c
src/version.c
src/vision.c
src/weapon.c
src/were.c
src/wield.c
src/windows.c
src/wizard.c
src/worm.c
src/worn.c
src/write.c
src/zap.c
sys/amiga/amirip.c
sys/amiga/winami.c
sys/amiga/winreq.c
sys/atari/tos.c
sys/mac/macmain.c
sys/mac/mactopl.c
sys/mac/macunix.c
sys/mac/mgetline.c
sys/msdos/Makefile.GCC
sys/msdos/pckeys.c
sys/msdos/pctiles.h
sys/msdos/pcvideo.h
sys/msdos/setup.bat
sys/msdos/tile2bin.c
sys/msdos/vesa.h [new file with mode: 0644]
sys/msdos/video.c
sys/msdos/vidtxt.c
sys/msdos/vidvesa.c [new file with mode: 0644]
sys/msdos/vidvga.c
sys/share/NetHack.cnf
sys/share/cppregex.cpp
sys/share/dgn_lex.c
sys/share/dgn_yacc.c
sys/share/ioctl.c
sys/share/lev_lex.c
sys/share/lev_yacc.c
sys/share/pcmain.c
sys/share/pcsys.c
sys/share/pctty.c
sys/share/pcunix.c
sys/share/unixtty.c
sys/unix/Install.unx
sys/unix/Makefile.dat
sys/unix/Makefile.doc
sys/unix/Makefile.src
sys/unix/Makefile.top
sys/unix/Makefile.utl
sys/unix/NewInstall.unx
sys/unix/README.linux
sys/unix/depend.awk
sys/unix/gitinfo.sh [new file with mode: 0644]
sys/unix/hints/linux
sys/unix/hints/linux-chroot
sys/unix/hints/linux-qt4 [new file with mode: 0644]
sys/unix/hints/linux-x11
sys/unix/hints/macosx.sh
sys/unix/hints/macosx10.10
sys/unix/hints/macosx10.5
sys/unix/hints/macosx10.7
sys/unix/hints/macosx10.8 [new file with mode: 0644]
sys/unix/nethack.sh
sys/unix/setup.sh
sys/unix/sysconf
sys/unix/unixmain.c
sys/unix/unixres.c
sys/unix/unixunix.c
sys/vms/Install.vms
sys/vms/Makefile.dat
sys/vms/Makefile.doc
sys/vms/Makefile.src
sys/vms/Makefile.top
sys/vms/Makefile.utl
sys/vms/install.com
sys/vms/nethack.com
sys/vms/spec_lev.com
sys/vms/sysconf
sys/vms/vmsbuild.com
sys/vms/vmsfiles.c
sys/vms/vmsmail.c
sys/vms/vmsmain.c
sys/vms/vmsmisc.c
sys/vms/vmstty.c
sys/vms/vmsunix.c
sys/wince/defaults.nh
sys/wince/mhcmd.c
sys/wince/mhcmd.h
sys/wince/mhmain.c
sys/wince/mhmenu.c
sys/wince/mswproc.c
sys/wince/newres.h
sys/wince/winhack.rc
sys/wince/winhcksp.rc
sys/winnt/Install.nt
sys/winnt/Makefile.gcc
sys/winnt/Makefile.msc
sys/winnt/console.rc
sys/winnt/defaults.nh
sys/winnt/nethack.def
sys/winnt/nh340key.c
sys/winnt/nhdefkey.c
sys/winnt/nhraykey.c
sys/winnt/nhsetup.bat
sys/winnt/nttty.c
sys/winnt/stubs.c
sys/winnt/sysconf
sys/winnt/win32api.h
sys/winnt/winnt.c
util/dgn_comp.l
util/dlb_main.c
util/lev_comp.l
util/lev_comp.y
util/lev_main.c
util/makedefs.c
util/mdgrep.pl
util/panic.c
util/recover.c
win/Qt/Install.Qt
win/Qt/qt_clust.cpp
win/Qt/qt_win.cpp
win/Qt/qttableview.cpp
win/Qt/tileedit.cpp
win/Qt4/qt4bind.cpp [new file with mode: 0644]
win/Qt4/qt4bind.h [new file with mode: 0644]
win/Qt4/qt4click.cpp [new file with mode: 0644]
win/Qt4/qt4click.h [new file with mode: 0644]
win/Qt4/qt4clust.cpp [new file with mode: 0644]
win/Qt4/qt4clust.h [new file with mode: 0644]
win/Qt4/qt4delay.cpp [new file with mode: 0644]
win/Qt4/qt4delay.h [new file with mode: 0644]
win/Qt4/qt4glyph.cpp [new file with mode: 0644]
win/Qt4/qt4glyph.h [new file with mode: 0644]
win/Qt4/qt4icon.cpp [new file with mode: 0644]
win/Qt4/qt4icon.h [new file with mode: 0644]
win/Qt4/qt4inv.cpp [new file with mode: 0644]
win/Qt4/qt4inv.h [new file with mode: 0644]
win/Qt4/qt4kde0.h [new file with mode: 0644]
win/Qt4/qt4key.cpp [new file with mode: 0644]
win/Qt4/qt4key.h [new file with mode: 0644]
win/Qt4/qt4line.cpp [new file with mode: 0644]
win/Qt4/qt4line.h [new file with mode: 0644]
win/Qt4/qt4main.cpp [new file with mode: 0644]
win/Qt4/qt4main.h [new file with mode: 0644]
win/Qt4/qt4map.cpp [new file with mode: 0644]
win/Qt4/qt4map.h [new file with mode: 0644]
win/Qt4/qt4menu.cpp [new file with mode: 0644]
win/Qt4/qt4menu.h [new file with mode: 0644]
win/Qt4/qt4msg.cpp [new file with mode: 0644]
win/Qt4/qt4msg.h [new file with mode: 0644]
win/Qt4/qt4plsel.cpp [new file with mode: 0644]
win/Qt4/qt4plsel.h [new file with mode: 0644]
win/Qt4/qt4rip.cpp [new file with mode: 0644]
win/Qt4/qt4rip.h [new file with mode: 0644]
win/Qt4/qt4set.cpp [new file with mode: 0644]
win/Qt4/qt4set.h [new file with mode: 0644]
win/Qt4/qt4stat.cpp [new file with mode: 0644]
win/Qt4/qt4stat.h [new file with mode: 0644]
win/Qt4/qt4str.cpp [new file with mode: 0644]
win/Qt4/qt4str.h [new file with mode: 0644]
win/Qt4/qt4streq.cpp [new file with mode: 0644]
win/Qt4/qt4streq.h [new file with mode: 0644]
win/Qt4/qt4svsel.cpp [new file with mode: 0644]
win/Qt4/qt4svsel.h [new file with mode: 0644]
win/Qt4/qt4win.cpp [new file with mode: 0644]
win/Qt4/qt4win.h [new file with mode: 0644]
win/Qt4/qt4xcmd.cpp [new file with mode: 0644]
win/Qt4/qt4xcmd.h [new file with mode: 0644]
win/Qt4/qt4yndlg.cpp [new file with mode: 0644]
win/Qt4/qt4yndlg.h [new file with mode: 0644]
win/X11/Install.X11
win/X11/NetHack.ad
win/X11/Window.c
win/X11/dialogs.c
win/X11/nethack.rc
win/X11/tile2x11.c
win/X11/winX.c
win/X11/winmap.c
win/X11/winmenu.c
win/X11/winmesg.c
win/X11/winmisc.c
win/X11/winstat.c
win/X11/wintext.c
win/X11/winval.c
win/chain/wc_chainin.c
win/chain/wc_chainout.c
win/chain/wc_trace.c
win/gem/wingem.c
win/gnome/gnbind.c
win/macosx/NetHackGuidebook.applescript
win/macosx/NetHackRecover.applescript
win/macosx/NetHackTerm.applescript
win/macosx/recover.pl
win/share/bmptiles.c [new file with mode: 0644]
win/share/giftiles.c [new file with mode: 0644]
win/share/objects.txt
win/share/other.txt
win/share/renumtiles.pl
win/share/thintile.c
win/share/tile.doc
win/share/tile.h
win/share/tile2bmp.c
win/share/tilemap.c
win/share/tileset.c [new file with mode: 0644]
win/share/tiletext.c
win/tty/getline.c
win/tty/termcap.c
win/tty/topl.c
win/tty/wintty.c
win/win32/dgnstuff.mak
win/win32/levstuff.mak
win/win32/mhdlg.c
win/win32/mhdlg.h
win/win32/mhfont.c
win/win32/mhmain.c
win/win32/mhmap.c
win/win32/mhmenu.c
win/win32/mhmsg.h
win/win32/mhmsgwnd.c
win/win32/mhsplash.c
win/win32/mhstatus.c
win/win32/mhtext.c
win/win32/mswproc.c
win/win32/nethack.rc [new file with mode: 0644]
win/win32/nhresource.h [new file with mode: 0644]
win/win32/record.uu [new file with mode: 0644]
win/win32/resource.h
win/win32/tiles.mak
win/win32/vs2010/NetHack.sln [deleted file]
win/win32/vs2010/NetHackW.vcxproj [deleted file]
win/win32/vs2010/dgncomp.vcxproj [deleted file]
win/win32/vs2010/dgnstuff.vcxproj [deleted file]
win/win32/vs2010/dlb_main.vcxproj [deleted file]
win/win32/vs2010/levcomp.vcxproj [deleted file]
win/win32/vs2010/levstuff.vcxproj [deleted file]
win/win32/vs2010/makedefs.vcxproj [deleted file]
win/win32/vs2010/recover.vcxproj [deleted file]
win/win32/vs2010/tile2bmp.vcxproj [deleted file]
win/win32/vs2010/tilemap.vcxproj [deleted file]
win/win32/vs2010/uudecode.vcxproj [deleted file]
win/win32/vs2013/NetHack.sln [deleted file]
win/win32/vs2013/NetHack.vcxproj [deleted file]
win/win32/vs2013/NetHackW.vcxproj [deleted file]
win/win32/vs2013/dgncomp.vcxproj [deleted file]
win/win32/vs2013/dgnstuff.vcxproj [deleted file]
win/win32/vs2013/dlb_main.vcxproj [deleted file]
win/win32/vs2013/levcomp.vcxproj [deleted file]
win/win32/vs2013/levstuff.vcxproj [deleted file]
win/win32/vs2013/makedefs.vcxproj [deleted file]
win/win32/vs2013/nhdefkey.vcxproj [deleted file]
win/win32/vs2013/recover.vcxproj [deleted file]
win/win32/vs2013/tile2bmp.vcxproj [deleted file]
win/win32/vs2013/tilemap.vcxproj [deleted file]
win/win32/vs2013/uudecode.vcxproj [deleted file]
win/win32/vs2015/NetHack.vcxproj [new file with mode: 0644]
win/win32/vs2015/NetHackW.vcxproj [new file with mode: 0644]
win/win32/vs2015/afterdgncomp.proj [new file with mode: 0644]
win/win32/vs2015/afterdlb.proj [new file with mode: 0644]
win/win32/vs2015/afterlevcomp.proj [new file with mode: 0644]
win/win32/vs2015/aftermakedefs.proj [new file with mode: 0644]
win/win32/vs2015/afternethack.proj [new file with mode: 0644]
win/win32/vs2015/afterrecover.proj [new file with mode: 0644]
win/win32/vs2015/aftertile2bmp.proj [new file with mode: 0644]
win/win32/vs2015/aftertilemap.proj [new file with mode: 0644]
win/win32/vs2015/afteruudecode.proj [new file with mode: 0644]
win/win32/vs2015/build.bat [new file with mode: 0644]
win/win32/vs2015/common.props [new file with mode: 0644]
win/win32/vs2015/config.props [new file with mode: 0644]
win/win32/vs2015/console.props [new file with mode: 0644]
win/win32/vs2015/default.props [new file with mode: 0644]
win/win32/vs2015/default_dll.props [new file with mode: 0644]
win/win32/vs2015/dgncomp.vcxproj [new file with mode: 0644]
win/win32/vs2015/dirs.props [new file with mode: 0644]
win/win32/vs2015/dlb.vcxproj [new file with mode: 0644]
win/win32/vs2015/dll.props [new file with mode: 0644]
win/win32/vs2015/files.props [new file with mode: 0644]
win/win32/vs2015/levcomp.vcxproj [new file with mode: 0644]
win/win32/vs2015/makedefs.vcxproj [new file with mode: 0644]
win/win32/vs2015/nh340key.def [new file with mode: 0644]
win/win32/vs2015/nh340key.vcxproj [new file with mode: 0644]
win/win32/vs2015/nhdefkey.def [new file with mode: 0644]
win/win32/vs2015/nhdefkey.vcxproj [new file with mode: 0644]
win/win32/vs2015/nhraykey.def [new file with mode: 0644]
win/win32/vs2015/nhraykey.vcxproj [new file with mode: 0644]
win/win32/vs2015/notes.txt [new file with mode: 0644]
win/win32/vs2015/recover.vcxproj [new file with mode: 0644]
win/win32/vs2015/tile2bmp.vcxproj [new file with mode: 0644]
win/win32/vs2015/tilemap.vcxproj [new file with mode: 0644]
win/win32/vs2015/tiles.vcxproj [moved from win/win32/vs2013/tiles.vcxproj with 100% similarity]
win/win32/vs2015/uudecode.vcxproj [new file with mode: 0644]
win/win32/vs2017/NetHack.vcxproj [new file with mode: 0644]
win/win32/vs2017/NetHackW.vcxproj [new file with mode: 0644]
win/win32/vs2017/afterdgncomp.proj [new file with mode: 0644]
win/win32/vs2017/afterdlb.proj [new file with mode: 0644]
win/win32/vs2017/afterlevcomp.proj [new file with mode: 0644]
win/win32/vs2017/aftermakedefs.proj [new file with mode: 0644]
win/win32/vs2017/afternethack.proj [new file with mode: 0644]
win/win32/vs2017/afterrecover.proj [new file with mode: 0644]
win/win32/vs2017/aftertile2bmp.proj [new file with mode: 0644]
win/win32/vs2017/aftertilemap.proj [new file with mode: 0644]
win/win32/vs2017/afteruudecode.proj [new file with mode: 0644]
win/win32/vs2017/build.bat [new file with mode: 0644]
win/win32/vs2017/common.props [new file with mode: 0644]
win/win32/vs2017/config.props [new file with mode: 0644]
win/win32/vs2017/console.props [new file with mode: 0644]
win/win32/vs2017/default.props [new file with mode: 0644]
win/win32/vs2017/default_dll.props [new file with mode: 0644]
win/win32/vs2017/dgncomp.vcxproj [new file with mode: 0644]
win/win32/vs2017/dirs.props [new file with mode: 0644]
win/win32/vs2017/dlb.vcxproj [new file with mode: 0644]
win/win32/vs2017/dll.props [new file with mode: 0644]
win/win32/vs2017/files.props [new file with mode: 0644]
win/win32/vs2017/levcomp.vcxproj [new file with mode: 0644]
win/win32/vs2017/makedefs.vcxproj [new file with mode: 0644]
win/win32/vs2017/nh340key.def [new file with mode: 0644]
win/win32/vs2017/nh340key.vcxproj [new file with mode: 0644]
win/win32/vs2017/nhdefkey.def [new file with mode: 0644]
win/win32/vs2017/nhdefkey.vcxproj [new file with mode: 0644]
win/win32/vs2017/nhraykey.def [new file with mode: 0644]
win/win32/vs2017/nhraykey.vcxproj [new file with mode: 0644]
win/win32/vs2017/recover.vcxproj [new file with mode: 0644]
win/win32/vs2017/tile2bmp.vcxproj [new file with mode: 0644]
win/win32/vs2017/tilemap.vcxproj [new file with mode: 0644]
win/win32/vs2017/tiles.vcxproj [moved from win/win32/vs2010/tiles.vcxproj with 96% similarity]
win/win32/vs2017/uudecode.vcxproj [new file with mode: 0644]
win/win32/winMS.h
win/win32/winhack.rc

index b30fa06..adc3260 100644 (file)
@@ -1,10 +1,12 @@
- ___              _                   
- |   \ _____ _____| |___ _ __  ___ _ _ 
+  ___              _
+ |   \ _____ _____| |___ _ __  ___ _ _
  | |) / -_) V / -_) / _ \ '_ \/ -_) '_|
- |___/\___|\_/\___|_\___/ .__/\___|_|  
-                        |_|            
+ |___/\___|\_/\___|_\___/ .__/\___|_|
+                        |_|
 
-$NHDT-Date: 1447180052 2015/11/10 18:27:32 $
+# NetHack 3.6  Developer.txt       $NHDT-Date: 1524689668 2018/04/25 20:54:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.13 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 Welcome to the NetHack Infrastructure Developer's Guide.
 
@@ -25,6 +27,7 @@ CONTENTS
 5. variable expansion
 6. reserved names
 7. nhadd/nhcommit
+8. hooks
 ------------------------------------------------------------------------------
 1. email
 Email to devteam@nethack.org will usually get a response, but it may take a
@@ -32,10 +35,14 @@ while.  Please do not send save files, binary screen grabs, or other large
 things.
 ------------------------------------------------------------------------------
 2. git repositories
-The public NetHack git repository is available (read-only) on SourceForge at:
-  git://git.code.sf.net/p/nethack/NHsource
-
-XXX need to discuss what branches are available
+A public repository of the latest NetHack code that we've made 
+available can be obtained via git from either of two locations:
+    https://github.com/NetHack/NetHack
+      or
+    https://sourceforge.net/p/nethack/NetHack/
+
+Branches:
+NetHack-3.6.0  The 3.6.0 release code and subsequent fixes and additions.
 ------------------------------------------------------------------------------
 3. bug reporting
 Please use the form at http://www.nethack.org/common/contact.html (or send
@@ -43,12 +50,15 @@ us an email if that's more appropriate).
 ------------------------------------------------------------------------------
 4. git configuration
 
-NOTE: These instructions assume you are on the default branch ("master");
-      this _is_ where you want to be for setting things up.  This may or may
-      not be the branch you want to use for your changes; see the appropriate
+NOTE: These instructions assume you are on the default branch; this _is_
+      where you want to be for setting things up.  This may or may not be
+      the branch you want to use for your changes; see the appropriate
       project private documentation for more information (if you are working
       alone we suggest using branch names starting with "LOCAL-").
 
+NOTE: The following instructions require perl.  If you do not have perl on
+      your system, please install it before proceeding.
+
 A. If you have never set up git on this machine before:
    (This assumes you will only be using git for NetHack.  If you are going to
    use it for other projects as well, think before you type.)
@@ -89,7 +99,8 @@ C. Configure the repository:
                -v verbose
                -n dry run
    You can re-run nhgitset.pl as often as needed; occasionally we will
-   update it and ask you to run it again.
+   update it (or something it installs) and you will need to run it again
+   so the changes take effect.
 D. aliases
    Two aliases are installed by nhgitset.pl:
        nhadd
@@ -206,3 +217,19 @@ D. Using your own hooks
    "perldoc DEVEL/hooksdir/nhsub".
    
 ------------------------------------------------------------------------------
+8. hooks
+
+   nhgitset.pl also installs hooks into .git/hooks.  These hooks provide
+   a framework which allows local hook code to co-exist with hook code we
+   supply - see DEVEL/hooksdir/NHgithook.pm for details.
+
+   We currently use the following hooks:
+    post-checkout
+    post-commit
+    post-merge
+   These are used to generate dat/gitinfo.txt which provides the data that
+   ends up available through the game command #version and the command line
+   option --version.
+
+------------------------------------------------------------------------------
+
index f8bb504..1c60e02 100644 (file)
@@ -1,5 +1,6 @@
-$NHDT-Date: 1432473678 2015/05/24 13:21:18 $  $NHDT-Branch: master $:$NHDT-Revision: 1.2 $
-code_features.txt
+# NetHack 3.6  code_features.txt $NHDT-Date: 1524689669 2018/04/25 20:54:29 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.3 $
+# Copyright (c) 2015 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
 
 Developer-useful info about code features, assumptions, purpose,
 rationale, etc.
index e76a4ad..4f16a89 100644 (file)
@@ -1,3 +1,7 @@
+# NetHack 3.6  code_style.txt       $NHDT-Date: 1524689669 2018/04/25 20:54:29 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $
+# Copyright (c) 2015 by Derek S. Ray
+# NetHack may be freely redistributed.  See license for details.
+
 NetHack DevTeam Coding Style
 ============================
 
index bf69ace..04f36d6 100644 (file)
@@ -1,7 +1,10 @@
+# NetHack 3.6  git_recipes.txt       $NHDT-Date: 1524689669 2018/04/25 20:54:29 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.9 $
+# Copyright (c) 2015 by Derek S. Ray
+# NetHack may be freely redistributed.  See license for details.
+
 Git has a messy learning curve. This file is an attempt to serve as a quick
 reference for basic tasks while you get up to speed.
 
-$NHDT-Date: 1429884051 2015/04/24 14:00:51 $
 ------------------------
 
 [*] git checkout [-f] (branch)
diff --git a/DEVEL/gitinfo.pl b/DEVEL/gitinfo.pl
new file mode 100644 (file)
index 0000000..91f71e6
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+# NetHack 3.6  getinfo.pl       $NHDT-Date: 1524689669 2018/04/25 20:54:29 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $
+# Copyright (c) 2018 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
+
+#STARTUP-START
+BEGIN {
+    # OS hackery has to be duplicated in each of the hooks :/
+    # first the directory separator
+    my $DS = quotemeta('/');
+    my $PDS = '/';
+    # msys: POSIXish over a Windows filesystem (so / not \ but \r\n not \n).
+    # temporarily removed because inconsistent behavior
+    # if ($^O eq "msys")
+    # {
+    #   $/ = "\r\n";
+    #   $\ = "\r\n";
+    # }
+    if($^O eq "MSWin32"){
+        $DS = quotemeta('\\');
+       $PDS = '\\';
+    }
+    $gitdir = `git rev-parse --git-dir`;
+    chomp $gitdir;
+    push(@INC, $gitdir.$PDS."hooks");
+
+       # special case for this script only: allow
+       # it to run from DEVEL or $TOP
+    if (-f "hooksdir/NHgithook.pm" || -f "DEVEL/hooksdir/NHgithook.pm"){
+       push(@INC, "DEVEL/hooksdir");
+    }
+    chdir("..") if (-f "hooksdir/NHgithook.pm");
+}
+use NHgithook;
+
+&NHgithook::nhversioning;
diff --git a/DEVEL/hooksdir/.NHgithook.pm.swp b/DEVEL/hooksdir/.NHgithook.pm.swp
deleted file mode 100644 (file)
index 19e7ec8..0000000
Binary files a/DEVEL/hooksdir/.NHgithook.pm.swp and /dev/null differ
index 55138e7..3e4b24b 100644 (file)
@@ -1,6 +1,9 @@
 #!/usr/bin/perl
+# NetHack 3.6  NHadd       $NHDT-Date: 1524689631 2018/04/25 20:53:51 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
+
 # wrapper for nhadd and nhcommit aliases
-# $NHDT-Date: 1427408239 2015/03/26 22:17:19 $
 
 %ok = map { $_ => 1 } ('add', 'commit');
 
index 6024c1c..0c64ab1 100644 (file)
@@ -1,7 +1,9 @@
 #
-# NHgithook.pm
+# NetHack 3.6  NHgithook.pm       $NHDT-Date: 1524689631 2018/04/25 20:53:51 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.6 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
+
 # NetHack Git Hook Module
-# $NHDT-Date$
 
 package NHgithook;
 use Cwd;
@@ -60,6 +62,51 @@ sub POST {
        &do_hook("POST");
 }
 
+###
+### store githash and gitbranch in dat/gitinfo.txt
+###
+
+sub nhversioning {
+    use strict;
+    use warnings;
+
+    my $git_sha = `git rev-parse HEAD`;
+    $git_sha =~ s/\s+//g;
+    my $git_branch = `git rev-parse --abbrev-ref HEAD`;
+    $git_branch =~ s/\s+//g;
+    die "git rev-parse failed" unless(length $git_sha and length $git_branch);
+    my $exists = 0;
+
+    if (open my $fh, '<', 'dat/gitinfo.txt') {
+        $exists = 1;
+        my $hashok = 0;
+        my $branchok = 0;
+        while (my $line = <$fh>) {
+            if ((index $line, $git_sha) >= 0) {
+                $hashok++;
+            }
+            if ((index $line, $git_branch) >= 0) {
+                $branchok++;
+            }
+        }
+        close $fh;
+        if ($hashok && $branchok) {
+            print "dat/gitinfo.txt unchanged, githash=".$git_sha."\n";
+            return;
+        }
+    } else {
+       print "WARNING: Can't find dat directory\n" unless(-d "dat");
+    }
+    if (open my $fh, '>', 'dat/gitinfo.txt') {
+        my $how = ($exists ? "updated" : "created");
+        print $fh 'githash='.$git_sha."\n";
+        print $fh 'gitbranch='.$git_branch."\n";
+        print "dat/gitinfo.txt ".$how.", githash=".$git_sha."\n";
+    } else {
+       print "WARNING: Unable to open dat/gitinfo.txt: $!\n";
+    }
+}
+
 # PRIVATE
 sub do_hook {
        my($p) = @_;
index 1e19f6e..45e8297 100644 (file)
@@ -1,7 +1,8 @@
 #!/usr/bin/perl
-#
-# NHsubst
-# $NHDT-Date$
+# NetHack 3.6  NHsubst       $NHDT-Date: 1524689631 2018/04/25 20:53:51 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.4 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
+
 # git merge driver for substitutions (like RCS/CVS)
 # driver line:   .... %O %A %B %L
 use strict;
index 0cc065d..44a70db 100644 (file)
@@ -1,7 +1,8 @@
 #!/usr/bin/perl
-#
-# NHtext
-# $NHDT-Date$
+# NetHack 3.6  NHtext       $NHDT-Date: 1524689631 2018/04/25 20:53:51 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.8 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
+
 # clean/smudge filter for handling substitutions
 use strict;
 
index b5bf990..4432174 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  applypatch-msg       $NHDT-Date: 1524689646 2018/04/25 20:54:06 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
index b5bf990..1f2ad49 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  commit-msg       $NHDT-Date: 1524689646 2018/04/25 20:54:06 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
index a1686bd..c0745af 100644 (file)
@@ -1,6 +1,7 @@
 #!/usr/bin/perl
-# nhsub
-# $NHDT-Date: 1427408239 2015/03/26 22:17:19 $
+# $NHDT-Date: 1524689646 2018/04/25 20:54:06 $ Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.7 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 # Note: was originally called nhdate; the rename is not reflected in the code.
 
@@ -245,6 +246,7 @@ my $count = s/\$$PREFIX-(([A-Za-z][A-Za-z0-9_]*)(: ([^\x24]+))?)\$/&handlevar($2
 # XXX had o modifier, why?
        return unless($count>0);
        return if($opt{n});
+       my $mode = 0777 & (stat($file))[2];
 
        my $ofile = $file . ".nht";
        open(TOUT, ">", $ofile) or die "Can't open $ofile";
@@ -263,6 +265,8 @@ my $count = s/\$$PREFIX-(([A-Za-z][A-Za-z0-9_]*)(: ([^\x24]+))?)\$/&handlevar($2
        }
 
        close TOUT or die "Can't close $ofile";
+               # Do the right thing for *nix and hope for the best elsewhere:
+       chmod($mode, $ofile)==1 or warn "Can't set filemode on $ofile";
        rename $ofile, $file or die "Can't rename $ofile to $file";
 }
 
index b5bf990..ec6af70 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# $NHDT-Date: 1524689631 2018/04/25 20:53:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
index b5bf990..c7fde4f 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  post-checkout       $NHDT-Date: 1524689632 2018/04/25 20:53:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
@@ -26,5 +28,6 @@ use NHgithook;
 #STARTUP-END
 
 &NHgithook::PRE;
+&NHgithook::nhversioning;
 &NHgithook::POST;
 exit 0;
index b5bf990..309eec4 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  post-commit       $NHDT-Date: 1524689632 2018/04/25 20:53:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
@@ -26,5 +28,6 @@ use NHgithook;
 #STARTUP-END
 
 &NHgithook::PRE;
+&NHgithook::nhversioning;
 &NHgithook::POST;
 exit 0;
index b5bf990..6ca8dc5 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  post-merge       $NHDT-Date: 1524689632 2018/04/25 20:53:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
@@ -22,9 +24,11 @@ BEGIN {
     chomp $gitdir;
     push(@INC, $gitdir.$PDS."hooks");
 }
+
 use NHgithook;
 #STARTUP-END
 
 &NHgithook::PRE;
+&NHgithook::nhversioning;
 &NHgithook::POST;
 exit 0;
index e1b2524..317edde 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  post-rewrite       $NHDT-Date: 1524689632 2018/04/25 20:53:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
index b5bf990..f71d1fd 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  pre-applypatch       $NHDT-Date: 1524689632 2018/04/25 20:53:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
index b5bf990..e1c39be 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  pre-auto-gc       $NHDT-Date: 1524689632 2018/04/25 20:53:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
index b5bf990..83dacdd 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  pre-commit       $NHDT-Date: 1524689632 2018/04/25 20:53:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
index e1b2524..d65dcbe 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  pre-push       $NHDT-Date: 1524689632 2018/04/25 20:53:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
index b5bf990..e25f41c 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# NetHack 3.6  pre-rebase       $NHDT-Date: 1524689633 2018/04/25 20:53:53 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
index b5bf990..b681385 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# $NHDT-Date: 1524689633 2018/04/25 20:53:53 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 #STARTUP-START
 BEGIN {
index 0806848..86ddfe3 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
-# $NHDT-Date$
+# $NHDT-Date: 1524689669 2018/04/25 20:54:29 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 # value of nethack.setupversion we will end up with when this is done
 # version 1 is reserved for repos checked out before versioning was added
diff --git a/Files b/Files
index f8c169b..0e6674e 100644 (file)
--- a/Files
+++ b/Files
@@ -12,23 +12,24 @@ dat:
 (files for all versions)
 Arch.des        Barb.des        Caveman.des     Healer.des      Knight.des
 Monk.des        Priest.des      Ranger.des      Rogue.des       Samurai.des
-Tourist.des     Valkyrie.des    Wizard.des      bigroom.des     castle.des
-cmdhelp         data.base       dungeon.def     endgame.des     gehennom.des
-help            hh              history         knox.des        license
-medusa.des      mines.des       opthelp         oracle.des      oracles.txt
-quest.txt       rumors.fal      rumors.tru      sokoban.des     symbols
-tower.des       wizhelp         yendor.des      tribute         bogusmon.txt
-engrave.txt     epitaph.txt
+Tourist.des     Valkyrie.des    Wizard.des      bigroom.des     bogusmon.txt
+castle.des      cmdhelp         data.base       dungeon.def     endgame.des
+engrave.txt     epitaph.txt     gehennom.des    help            hh
+history         keyhelp         knox.des        license         medusa.des
+mines.des       opthelp         oracle.des      oracles.txt     quest.txt
+rumors.fal      rumors.tru      sokoban.des     symbols         tower.des
+tribute         wizhelp         yendor.des
 
 doc:
 (files for all versions)
-Guidebook.mn    Guidebook.tex   Guidebook.txt   dgn_comp.6      dgn_comp.txt
-dlb.6           dlb.txt         fixes22.0       fixes30.0       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       lev_comp.6
-lev_comp.txt    makedefs.6      makedefs.txt    nethack.6       nethack.txt
-recover.6       recover.txt     tmac.n          window.doc
+config.nh       Guidebook.mn    Guidebook.tex   Guidebook.txt   dgn_comp.6
+dgn_comp.txt    dlb.6           dlb.txt         fixes22.0       fixes30.0
+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       lev_comp.6      lev_comp.txt    makedefs.6      makedefs.txt
+nethack.6       nethack.txt     recover.6       recover.txt     tmac.n
+window.doc
 
 include:
 (files for all versions)
@@ -36,16 +37,16 @@ align.h         amiconf.h       artifact.h      artilist.h      attrib.h
 beconf.h        botl.h          color.h         config.h        config1.h
 context.h       coord.h         decl.h          def_os2.h       dgn_file.h
 display.h       dlb.h           dungeon.h       engrave.h       extern.h
-flag.h          func_tab.h      global.h        hack.h          lev.h
-lint.h          mail.h          mextra.h        mfndpos.h       micro.h
-mkroom.h        monattk.h       mondata.h       monflag.h       monst.h
-monsym.h        ntconf.h        obj.h           objclass.h      os2conf.h
-patchlevel.h    pcconf.h        permonst.h      prop.h          qtext.h
-quest.h         rect.h          region.h        rm.h            skills.h
-sp_lev.h        spell.h         sys.h           system.h        tcap.h
-timeout.h       tosconf.h       tradstdc.h      trampoli.h      trap.h
-unixconf.h      vision.h        vmsconf.h       wceconf.h       winami.h
-winprocs.h      wintype.h       you.h           youprop.h
+flag.h          func_tab.h      global.h        hack.h          integer.h
+lev.h           lint.h          mail.h          mextra.h        mfndpos.h
+micro.h         mkroom.h        monattk.h       mondata.h       monflag.h
+monst.h         monsym.h        ntconf.h        obj.h           objclass.h
+os2conf.h       patchlevel.h    pcconf.h        permonst.h      prop.h
+qtext.h         quest.h         rect.h          region.h        rm.h
+skills.h        sp_lev.h        spell.h         sys.h           system.h
+tcap.h          timeout.h       tosconf.h       tradstdc.h      trampoli.h
+trap.h          unixconf.h      vision.h        vmsconf.h       wceconf.h
+winami.h        winprocs.h      wintype.h       you.h           youprop.h
 (file for tty versions)
 wintty.h
 (files for X versions)
@@ -86,7 +87,7 @@ wield.c         windows.c       wizard.c        worm.c          worn.c
 write.c         zap.c
 
 sys/amiga:
-(files for Amiga versions - untested for 3.6.0)
+(files for Amiga versions - untested for 3.6.1)
 Build.ami       Install.ami     Makefile.agc    Makefile.ami    NetHack.cnf
 amidos.c        amidos.p        amifont.uu      amifont8.uu     amigst.c
 amii.hlp        amimenu.c       amirip.c        amisnd.c        amistack.c
@@ -97,12 +98,12 @@ winfuncs.c      winkey.c        winmenu.c       winproto.h      winreq.c
 winstr.c        xpm2iff.c
 
 sys/atari:
-(files for Atari version - untested for 3.6.0)
+(files for Atari version - untested for 3.6.1)
 Install.tos     atarifnt.uue    nethack.mnu     setup.g         tos.c
 unx2atar.sed
 
 sys/be:
-(files for BeOS version - untested for 3.6.0)
+(files for BeOS version - untested for 3.6.1)
 README          bemain.c
 
 sys/mac:
@@ -115,27 +116,27 @@ macwin.c        mgetline.c      mmodal.c        mrecover.c      mrecover.hqx
 mttymain.c
 
 sys/msdos:
-(files for MSDOS version - untested for 3.6.0)
+(files for MSDOS version - untested for 3.6.1)
 Install.dos     Makefile.BC     Makefile.GCC    Makefile.MSC    moveinit.pat
 msdos.c         msdoshlp.txt    ovlinit.c       pckeys.c        pctiles.c
 pctiles.h       pcvideo.h       portio.h        schema1.BC      schema2.BC
 schema3.MSC     SCHEMA35.MSC    setup.bat       sound.c         tile2bin.c
-video.c         vidtxt.c        vidvga.c
+vesa.h          video.c         vidtxt.c        vidvesa.c       vidvga.c
 (files for running MSDOS binary under Windows)
 nhico.uu        nhpif.uu
 
 sys/os2:
-(files for OS/2 version - untested for 3.6.0)
+(files for OS/2 version - untested for 3.6.1)
 Install.os2     Makefile.os2    nhpmico.uu      os2.c
 
 sys/share:
-(files for MSDOS and OS/2 versions - untested for 3.6.0)
+(files for MSDOS and OS/2 versions - untested for 3.6.1)
 Makefile.lib    termcap.uu
-(file for MSDOS, OS/2, NT, Amiga, and Atari versions - untested for 3.6.0)
+(file for MSDOS, OS/2, NT, Amiga, and Atari versions - untested for 3.6.1)
 pcmain.c
-(files for MSDOS, OS/2, NT, and Atari versions - untested for 3.6.0)
+(files for MSDOS, OS/2, NT, and Atari versions - untested for 3.6.1)
 pcsys.c         pcunix.c
-(file for MSDOS, OS/2, and Atari versions - untested for 3.6.0)
+(file for MSDOS, OS/2, and Atari versions - untested for 3.6.1)
 NetHack.cnf     pctty.c
 (files for UNIX and Be versions)
 ioctl.c         unixtty.c
@@ -168,9 +169,9 @@ wdnflute.uu     wdnharp.uu
 sys/unix:
 (files for UNIX versions)
 Install.unx     Makefile.dat    Makefile.doc    Makefile.src    Makefile.top
-Makefile.utl    README.linux    depend.awk      mkmkfile.sh     nethack.sh
-NewInstall.unx  setup.sh        sysconf         unixmain.c      unixres.c
-unixunix.c
+Makefile.utl    README.linux    depend.awk      gitinfo.sh      mkmkfile.sh
+nethack.sh      NewInstall.unx  setup.sh        sysconf         unixmain.c
+unixres.c       unixunix.c
 (files for replacement cpp, only needed by some ancient UNIX systems)
 cpp1.shr        cpp2.shr        cpp3.shr
 (file for sound driver for 386 UNIX)
@@ -178,8 +179,9 @@ snd86unx.shr
 
 sys/unix/hints:
 (files for configuring UNIX NetHack versions)
-linux           linux-chroot    linux-x11       macosx          macosx10.5
-macosx10.7      macosx.sh       macosx10.10     unix
+linux           linux-chroot    linux-qt4       linux-x11       macosx
+macosx10.5      macosx10.7      macosx10.8      macosx10.10     macosx.sh
+unix
 
 sys/vms:
 (files for VMS version)
@@ -189,7 +191,7 @@ spec_lev.com    sysconf         vmsbuild.com    vmsfiles.c      vmsmail.c
 vmsmain.c       vmsmisc.c       vmstty.c        vmsunix.c
 
 sys/wince:
-(files for Windows CE and PocketPC - untested for 3.6.0)
+(files for Windows CE and PocketPC - untested for 3.6.1)
 Install.ce      bootstrp.mak    celib.c         cesetup.bat     cesound.c
 defaults.nh     keypad.uu       menubar.uu      mhaskyn.c       mhaskyn.h
 mhcmd.c         mhcmd.h         mhcolor.c       mhcolor.h       mhdlg.c
@@ -202,11 +204,11 @@ resource.h      winMS.h         winhack.c       winhack.rc      winhcksp.rc
 winmain.c
 
 sys/wince/ceinc:
-(header files for Windows CE and PocketPC - untested for 3.6.0)
+(header files for Windows CE and PocketPC - untested for 3.6.1)
 assert.h        errno.h         fcntl.h
 
 sys/wince/ceinc/sys:
-(sys/stat.h for Windows CE and PocketPC - untested for 3.6.0)
+(sys/stat.h for Windows CE and PocketPC - untested for 3.6.1)
 stat.h
 
 sys/winnt:
@@ -224,11 +226,24 @@ mdgrep.pl       panic.c         recover.c
 dgn_comp.l      dgn_comp.y      lev_comp.l      lev_comp.y
 
 win/Qt:
-(files for the Qt widget library - X11, Windows, Mac OS X, or Qtopia)
+(files for the Qt widget library - X11, Windows, Mac OS X, or Qtopia)
 Info.plist      Install.Qt      knethack.lnk    knh-mini.xpm    knh.xpm
 nhicns.uu       nhsplash.xpm    qt_clust.cpp    qt_win.cpp      qttableview.cpp
 tileedit.cpp    tileedit.h      qpe-nethack.control
 
+win/Qt4:
+(files for the Qt 4 widget library - X11, Windows, Mac OS X)
+qt4bind.cpp     qt4bind.h       qt4click.cpp    qt4click.h      qt4clust.cpp
+qt4clust.h      qt4delay.cpp    qt4delay.h      qt4glyph.cpp    qt4glyph.h
+qt4icon.cpp     qt4icon.h       qt4inv.cpp      qt4inv.h        qt4kde0.h
+qt4key.cpp      qt4key.h        qt4line.cpp     qt4line.h       qt4main.cpp
+qt4main.h       qt4map.cpp      qt4map.h        qt4menu.cpp     qt4menu.h
+qt4msg.cpp      qt4msg.h        qt4plsel.cpp    qt4plsel.h      qt4rip.cpp
+qt4rip.h        qt4set.cpp      qt4set.h        qt4stat.cpp     qt4stat.h
+qt4str.cpp      qt4streq.cpp    qt4streq.h      qt4str.h        qt4svsel.cpp
+qt4svsel.h      qt4win.cpp      qt4win.h        qt4xcmd.cpp     qt4xcmd.h
+qt4yndlg.cpp    qt4yndlg.h
+
 win/X11:
 (files for X versions)
 Install.X11     NetHack.ad      Window.c        dialogs.c       ibm.bdf
@@ -242,13 +257,13 @@ win/chain:
 wc_chainin.c    wc_chainout.c   wc_trace.c
 
 win/gem:
-(files for GEM versions - untested for 3.6.0)
+(files for GEM versions - untested for 3.6.1)
 Install.gem     bitmfile.c      gem_rsc.uu      gem_rso.uu      gr_rect.c
 gr_rect.h       load_img.c      tile2img.c      title.uu        wingem.c
 wingem1.c       xpm2img.c
 
 win/gnome:
-(files for GNOME versions - untested for 3.6.0)
+(files for GNOME versions - untested for 3.6.1)
 README          gn_xpms.h       gnaskstr.c      gnaskstr.h      gnbind.c
 gnbind.h        gnglyph.c       gnglyph.h       gnmain.c        gnmain.h
 gnmap.c         gnmap.h         gnmenu.c        gnmenu.h        gnmesg.c
@@ -264,38 +279,50 @@ NetHackTerm.applescript         recover.pl
 
 win/share:
 (files for versions using optional tiles)
-gifread.c       monsters.txt    objects.txt     other.txt       ppmwrite.c
-renumtiles.pl   thintile.c      tile.doc        tile.h          tile2bmp.c
-tilemap.c       tiletext.c
+gifread.c       giftiles.c      monsters.txt    objects.txt     other.txt
+ppmwrite.c      renumtiles.pl   thintile.c      tile.doc        tile.h
+tile2bmp.c      tilemap.c       tiletext.c
 
 win/tty:
 (files for tty versions)
 getline.c       termcap.c       topl.c          wintty.c
 
 win/win32:
-(files for Windows Windows 200x, Windows XP and Windows 7 version)
+(files for Windows versions - tested up to Windows 10)
 mhaskyn.c       mhaskyn.h       mhdlg.c         mhdlg.h         mhfont.c
 mhfont.h        mhinput.c       mhinput.h       mhmain.c        mhmain.h
 mhmap.c         mhmap.h         mhmenu.c        mhmenu.h        mhmsg.h
 mhmsgwnd.c      mhmsgwnd.h      mhrip.c         mhrip.h         mhsplash.c
 mhsplash.h      mhstatus.c      mhstatus.h      mhtext.c        mhtext.h
-mnsel.uu        mnselcnt.uu     mnunsel.uu      mswproc.c
-petmark.uu      pilemark.uu     resource.h      rip.uu          splash.uu
+mnsel.uu        mnselcnt.uu     mnunsel.uu      mswproc.c       petmark.uu
+pilemark.uu     record.uu       resource.h      rip.uu          splash.uu
 tiles.mak       winMS.h         winhack.c       winhack.rc
 
-win/win32/vs2010:
-(files for Visual Studio 2010 Express Edition builds)
-dgncomp.vcxproj     dgnstuff.vcxproj    dlb_main.vcxproj    levcomp.vcxproj
-levstuff.vcxproj    makedefs.vcxproj    NetHack.sln         NetHackW.vcxproj
-recover.vcxproj     tile2bmp.vcxproj    tilemap.vcxproj     tiles.vcxproj
+win/win32/vs2015:
+(files for Visual Studio 2015 Express Edition builds)
+afterdgncomp.proj  afterdlb.proj      afterlevcomp.proj   aftermakedefs.proj
+afternethack.proj  afterrecover.proj  aftertile2bmp.proj  aftertilemap.proj
+afteruudecode.proj build.bat          common.props        config.props
+console.props      default.props      default_dll.props   dgncomp.vcxproj
+dirs.props         dlb.vcxproj        dll.props           files.props
+levcomp.vcxproj    makedefs.vcxproj   NetHack.sln         NetHack.vcxproj
+NetHackW.vcxproj   nh340key.def       nh340key.vcxproj    nhdefkey.def
+nhdefkey.vcxproj   nhraykey.def       nhraykey.vcxproj    notes.txt
+recover.vcxproj    tile2bmp.vcxproj   tilemap.vcxproj     tiles.vcxproj
 uudecode.vcxproj
 
-win/win32/vs2013:
-(files for Visual Studio 2013 Express Edition builds)
-dgncomp.vcxproj     dgnstuff.vcxproj    dlb_main.vcxproj    levcomp.vcxproj
-levstuff.vcxproj    makedefs.vcxproj    NetHack.sln         NetHack.vcxproj
-NetHackW.vcxproj    nhdefkey.vcxproj    recover.vcxproj     tile2bmp.vcxproj
-tilemap.vcxproj     tiles.vcxproj       uudecode.vcxproj
+win/win32/vs2017:
+(files for Visual Studio 2017 Community Edition builds)
+afterdgncomp.proj  afterdlb.proj      afterlevcomp.proj   aftermakedefs.proj
+afternethack.proj  afterrecover.proj  aftertile2bmp.proj  aftertilemap.proj
+afteruudecode.proj build.bat          common.props        config.props
+console.props      default.props      default_dll.props   dgncomp.vcxproj
+dirs.props         dlb.vcxproj        dll.props           files.props
+levcomp.vcxproj    makedefs.vcxproj   NetHack.sln         NetHack.vcxproj
+NetHackW.vcxproj   nh340key.def       nh340key.vcxproj    nhdefkey.def
+nhdefkey.vcxproj   nhraykey.def       nhraykey.vcxproj    recover.vcxproj
+tile2bmp.vcxproj   tilemap.vcxproj    tiles.vcxproj       uudecode.vcxproj
+
 
 This is a list of files produced by auxiliary programs.  They can all be
 regenerated from the files in the distribution.
@@ -375,7 +402,7 @@ uudecode.exe
 
 DEVEL:
 (files for people developing changes to NetHack)
-code_features.txt   code_style.txt  Developer.txt   git_recipes.txt 
+code_features.txt   code_style.txt  Developer.txt   git_recipes.txt
 nhgitset.pl
 
 DEVEL/DOTGIT:
diff --git a/Porting b/Porting
index d8cd026..baccb37 100644 (file)
--- a/Porting
+++ b/Porting
@@ -171,3 +171,7 @@ creation.
        An object of the NetHack development project is to get the game
 working on as many different types of hardware and under as many different
 operating systems as is practical.  Any assistance will be appreciated.
+
+# NetHack 3.6  Porting       $NHDT-Date: 1524689603 2018/04/25 20:53:23 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.5 $
+# Copyright (c) 2005 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
diff --git a/README b/README
index 8013ec6..70545da 100644 (file)
--- a/README
+++ b/README
@@ -1,24 +1,39 @@
-                NetHack 3.6.0 -- General information
+                NetHack 3.6.1 -- General information
 
-NetHack 3.6 is an enhancement to the dungeon exploration game NetHack.
-It is a distant descendent of Rogue and Hack, and a direct descendent of
-NetHack 3.4. In order to avoid confusion with interim development code 
-that was posted online in 2014 by others, there is no NetHack 3.5 release.
+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.0 contains some code reorganization, new features, and bugfixes.
-
-The file doc/fixes36.0 in the source distribution has a full list of each. 
+NetHack 3.6.1 contains over 470 bug fixes to NetHack 3.6.0. The 
+file doc/fixes36.1 in the source distribution has a full list of them. 
 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 "new features" section.
 
-Here are some additional general notes that are not considered spoilers:
- * Some code paths and long-established game features have been made 
-   part of the base build and no longer conditional on compile settings.
- * Several treasured NetHack community patches, or a variation of 
-   them, have been rolled in to the base NetHack source tree, incuding: 
-   menucolors, pickup thrown, statue glyphs, dungeon overview, sortloot.
+Below you will find some other general notes that were not considered
+spoilers:
+* additional Terry Pratchett tribute passages
+* enhanced map position picking
+* new status line conditions Stone Strngl Deaf Lev Fly Ride
+* updated status hilites and several interface enhancements
+* new paranoid_confirm settings
+* a new extended command #kick
+* the vanquished monsters list can be sorted during end of game disclosure
+* fountains are bright blue
+* travel accepts 'm' (request menu) prefix
+* pressing a or A when cursor positioning shows menu of "interesting" features
+* pressing z or Z when cursor positioning can cycle through valid locations
+* add option herecmd_menu to make a mouse click on your character pop up a menu
+* #adjust's behavior altered when collecting compatible stacks
+* Some community patches that were included:
+    - Malcolm Ryan's improved tin opener
+    - Ray Chason's MSDOS port support for some VESA modes
+    - Ray Chason's Qt4 windowport
+    - Darshan Shaligram's pet ranged attack
+    - Jason Dorje Short's key rebinding
+    - Maxime Bacoux's new DUMPLOG
+* updated database entries for several things
 
                         - - - - - - - - - - -
 
@@ -66,6 +81,9 @@ Please read items (1), (2) and (3) BEFORE doing anything with your new code.
        Mac OS X 10.9
        OpenVMS (aka VMS) V8.4 on Alpha and on Integrity/Itanium/IA64
 
+    Instructions have been provided by way of community contribution on:
+        msdos protected mode using djgpp
+
     Previous versions of NetHack were tested and known to run on the 
     following systems, but it is unknown if they can still build and 
     execute NetHack 3.6:
@@ -122,11 +140,16 @@ Please read items (1), (2) and (3) BEFORE doing anything with your new code.
 
 If you have problems building the game, or you find bugs in it, we recommend 
 filing a bug report from our "Contact Us" web page at:
-    http://www.nethack.org/ 
+    https://www.nethack.org/common/contact.html or
+    http://www.nethack.org/common/contact.html
+Please include the version information from #version or the command line
+option --version in the apropriate field.
 
 A public repository of the latest NetHack code that we've made
 available can be obtained via git here:
-    <FIXME>
+    https://github.com/NetHack/NetHack
+      or
+    https://sourceforge.net/p/nethack/NetHack/
 
 When sending correspondence, please observe the following:
 o Please be sure to include your machine type, OS, and patchlevel.
@@ -158,3 +181,7 @@ be able to provide support or receive bug reports for it.
 In our own patches, we will assume that your code is synchronized with ours.
 
                   -- Good luck, and happy Hacking --
+
+# $NHDT-Date: 1524689604 2018/04/25 20:53:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.42 $
+# Copyright (c) 2012 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
index f6d1657..dcec985 100644 (file)
@@ -139,15 +139,22 @@ MAP
 ---------------------------------------------------------------------------
 ENDMAP
 # Dungeon Description
-REGION:(01,01,23,06),lit,"ordinary"
-REGION:(01,07,23,10),unlit,"ordinary"
-REGION:(01,11,23,16),lit,"ordinary"
-REGION:(24,01,50,06),unlit,"ordinary"
-REGION:(24,07,50,10),lit,"ordinary"
-REGION:(24,11,50,16),unlit,"ordinary"
-REGION:(51,01,73,06),lit,"ordinary"
-REGION:(51,07,73,10),unlit,"ordinary"
-REGION:(51,11,73,16),lit,"ordinary"
+REGION:(01,01,73,16),lit,"ordinary"
+SWITCH [ 3 ] {
+  CASE 0:
+    REGION:(01,07,22,09),unlit,"ordinary"
+    REGION:(24,01,50,05),unlit,"ordinary"
+    REGION:(24,11,50,16),unlit,"ordinary"
+    REGION:(52,07,73,09),unlit,"ordinary"
+    BREAK
+  CASE 1:
+    REGION:(24,01,50,16),unlit,"ordinary"
+    BREAK
+  CASE 2:
+    REGION:(01,01,22,16),unlit,"ordinary"
+    REGION:(52,01,73,16),unlit,"ordinary"
+    BREAK
+}
 # Stairs
 STAIR:random,up
 STAIR:random,down
@@ -708,7 +715,7 @@ LOOP [28] {
   MONSTER:random,random
 }
 
-MAZEWALK:(4, 2), south
+MAZEWALK:(4, 2), south, false
 
 # Stairs up, not in the fog maze
 STAIR:(00,00,70,18),(02,03,68,15),up
index 6530b8a..47158ef 100644 (file)
@@ -1,3 +1,7 @@
+# NetHack 3.6  bogusmon.txt       $NHDT-Date: 1524689579 2018/04/25 20:52:59 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.7 $
+# Copyright (c) 2016 by Pasi Kallinen
+# NetHack may be freely redistributed.  See license for details.
+#
 # Hallucinatory monsters
 #
 #
@@ -73,6 +77,9 @@ _
 \83E\81[\83o\81[\83n\83\8b\83N
 \83g\81[\83t\83@\81[\83L\81[
 +\83_\83b\83h\83\8a\81[
+shrinking violet
+shallow one
+spherical cow
 
 # Quendor (Zork, &c.)
 \83O\83\8b\81[
@@ -119,6 +126,7 @@ _
 
 # Discworld
 \81\83\89×\95¨\81\84
+\8bz\8c\8c\83X\83C\83J
 
 # Lord of the Rings
 \83G\83\93\83g
@@ -230,6 +238,7 @@ _
 \91¾\82Á\82½\83l\83Y\83~\83C\83\8b\83J
 \83N\83\8f\83b\83J
 \83^\83`\83\88\83^\83J
+\83\8c\83~\83\93\83O
 
 # european cryptids
 \83\94\83H\83\8b\83y\83\8b\83e\83B\83\93\83K\81[
@@ -297,6 +306,7 @@ COBOL
 \83O\83\8c\83C\81E\83O\81[
 \8e¥\8bC\92P\8bÉ\8eq
 \91æ\88ê\8eí\89i\8bv\8b@\8aÖ
+\8b\90\91å\95¨\91Ì
 
 # Ultima
 +\83\8d\81[\83h\81E\83u\83\8a\83e\83B\83b\83V\83\85
index b9aee26..807593c 100644 (file)
-^       ã©\82Ì\8eí\97Þ\82ð\92²\82×\82é
-^[      \83R\83}\83\93\83h\82ð\83L\83\83\83\93\83Z\83\8b\82·\82é
-^A      \91O\82Ì\83R\83}\83\93\83h\82ð\8cJ\82è\95Ô\82·
-^C      \83Q\81[\83\80\82ð\82â\82ß\82é
-^D      \89½\82©\82ð\8fR\82é (\95\81\92Ê\82Í\94à)
-^E      \95\94\89®\82ð\92T\82· (\83f\83o\83b\83O\83\82\81[\83h\82Ì\82Ý)
-^F      \82»\82Ì\8aK\82Ì\92n\90}\82ð\89æ\82­ (\83f\83o\83b\83O\83\82\81[\83h\82Ì\82Ý)
-^G      \89ö\95¨\82ð\82Â\82­\82é (\83f\83o\83b\83O\83\82\81[\83h\82Ì\82Ý)
-^I      \93¹\8bï\82ð\8e¯\95Ê\82·\82é (\83f\83o\83b\83O\83\82\81[\83h\82Ì\82Ý)
-^O      \93Á\8eê\82È\8aK\82Ì\8fê\8f\8a\82ð\92m\82é (\83f\83o\83b\83O\83\82\81[\83h\82Ì\82Ý)
-^P      \91O\82Ì\83\81\83b\83Z\81[\83W\82ð\8c©\82é
-^R      \89æ\96Ê\82ð\8f\91\82«\82È\82¨\82·
-^T      \82»\82Ì\8aK\82Å\8fu\8aÔ\88Ú\93®\82·\82é
-^V      \88á\82¤\8aK\82Ö\8fu\8aÔ\88Ú\93®\82·\82é (\83f\83o\83b\83O\83\82\81[\83h\82Ì\82Ý)
-^W      \96]\82Ý\82ð\82©\82È\82¦\82é (\83f\83o\83b\83O\83\82\81[\83h\82Ì\82Ý)
-^X      \82 \82È\82½\82Ì\91®\90«\82ð\8c©\82é (\8d×\82©\82¢\8fî\95ñ\82Í\94­\8c©\81E\83f\83o\83b\83O\83\82\81[\83h\82Ì\82Ý)
-^Z      \83Q\81[\83\80\82ð\92\86\92f\82·\82é (\92è\8b`\82µ\82Ä\82¢\82é\82È\82ç)
-a       \93¹\8bï\82ð\8eg\97p\82·\82é
-A       \8aZ\82ð\91S\82Ä\92E\82®
-b       \93ì\90¼\82É\95à\82­
-B       \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\93ì\90¼\82É\95à\82­
-^B      \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\93ì\90¼\82É\95à\82­
-c       \94à\82ð\95Â\82ß\82é
-C       \89ö\95¨\81C\8cÂ\81X\82Ì\95¨\81C\95¨\82Ì\8eí\97Þ\82É\96¼\91O\82ð\82Â\82¯\82é
-d       \95¨\82ð\92u\82­
-D       \8eí\97Þ\82ð\91I\82ñ\82Å\95¨\82ð\92u\82­
-e       \89½\82©\90H\82×\82é
-E       \8f°\82Ì\82Ù\82±\82è\82É\95\8e\9a\82ð\8f\91\82­
-g       \8e\9f\82É\95û\8cü\82ð\8ew\92è\82·\82é\82Æ\89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\95à\82­
-G       \8e\9f\82É\95û\8cü\82ð\8ew\92è\82·\82é\82Æ\89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\95à\82­
-h       \90¼\82É\95à\82­ (number_pad\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82Æ\82«\82Í\81C\83w\83\8b\83v)
-H       \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\90¼\82É\95à\82­
-^H      \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\90¼\82É\95à\82­
-i       \82 \82È\82½\82Ì\8e\9d\82¿\95¨\88ê\97\97\82ð\8c©\82é
-I       \8eí\97Þ\82ð\91I\91ð\82µ\82Ä\8e\9d\82¿\95¨\88ê\97\97\82ð\8c©\82é
-j       \93ì\82É\95à\82­ (number_pad\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82Æ\82«\82Í\81C\91¼\82Ì\8fê\8f\8a\82É\94ò\82Ô)
-J       \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\93ì\82É\95à\82­
-^J      \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\93ì\82É\95à\82­
-k       \96k\82É\95à\82­ (number_pad\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82Æ\82«\82Í\81C\89½\82©\82ð\8fR\82é)
-K       \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\96k\82É\95à\82­
-^K      \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\96k\82É\95à\82­
-l       \93\8c\82É\95à\82­ (number_pad\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82Æ\82«\82Í\81C\94 \82Ì\92\86\90g\82ð\97ª\92D\82·\82é)
-L       \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\93\8c\82É\95à\82­
-^L      \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\93\8c\82É\95à\82­
-m       \8e\9f\82É\95û\8cü\82ð\8ew\92è\82·\82é\82Æ\81C\82à\82Ì\82ð\8fE\82í\82¸\82É\88Ú\93®\82·\82é
-M       \8e\9f\82É\95û\8cü\82ð\8ew\92è\82·\82é\82Æ\81C\82à\82Ì\82ð\8fE\82í\82¸\82É\89\93\82­\82É\88Ú\93®\82·\82é
-n       \93ì\93\8c\82É\95à\82­
-N       \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\93ì\93\8c\82É\95à\82­(number_pad\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82Æ\82«\82Í\81C\96¼\91O\82ð\82Â\82¯\82é)
-^N      \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\93ì\93\8c\82É\95à\82­
-o       \94à\82ð\8aJ\82¯\82é
-O       \83I\83v\83V\83\87\83\93\82ð\83Z\83b\83g\82·\82é (O?\82Í\83I\83v\83V\83\87\83\93\82ð\90à\96¾\82·\82é)
-p       \93X\82Ì\8a¨\92è\82ð\95¥\82¤
-P       \83A\83N\83Z\83A\83\8a\82ð\90g\82É\82Â\82¯\82é(\8ew\97Ö\81C\96\82\8f\9c\82¯\81C\82È\82Ç)
-q       \89½\82©\82ð\88ù\82Þ(\90\85\96ò, \90\85\82È\82Ç)
-Q       \83Q\81[\83\80\82ð\82â\82ß\82é
-r       \8aª\95¨(\82Ü\82½\82Í\81C\92è\8b`\82µ\82Ä\82¢\82é\82È\82ç\96\82\96@\82Ì\96{)\82ð\93Ç\82Þ
-R       \83A\83N\83Z\83T\83\8a\82ð\82Í\82¸\82·(\8ew\97Ö\81C\96\82\8f\9c\82¯\81C\82È\82Ç)
-s       ã©\82â\94é\96§\82Ì\94à\82ð\92T\82·
-S       \83Q\81[\83\80\82ð\95Û\91\82·\82é
-t       \89½\82©\82ð\93\8a\82°\82é
-T       \8aZ\82ð\92E\82®
-u       \96k\93\8c\82É\95à\82­ (number_pad\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82Æ\82«\82Í\81Cã©\82ð\82Í\82¸\82·)
-U       \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\96k\93\8c\82É\95à\82­
-^U      \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\96k\93\8c\82É\95à\82­
-v       \83o\81[\83W\83\87\83\93\82ð\8c©\82é
-V       \83o\81[\83W\83\87\83\93\82¨\82æ\82Ñ\97ð\8ej\82ð\8c©\82é (\92·\95¶)
-w       \95\90\8aí\82ð\91\95\94õ\82·\82é
-W       \8aZ\82ð\92\85\82é
-x       \92m\82Á\82Ä\82¢\82é\96\82\96@\82Ì\88ê\97\97 (\92è\8b`\82³\82ê\82Ä\82¢\82é\82È\82ç)
-X       \93ñ\93\81\97¬\82ð\90Ø\82è\91Ö\82¦\82é
-y       \96k\90¼\82É\95à\82­
-Y       \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\96k\90¼\82É\95à\82­
-^Y      \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\96k\90¼\82É\95à\82­
-z       \8fñ\82ð\82Ó\82é
-Z       \96\82\96@\82ð\8f¥\82¦\82é (\92è\8b`\82³\82ê\82Ä\82¢\82é\82È\82ç)
-<       \8aK\92i\82ð\8f¸\82é
->       \8aK\92i\82ð\8d~\82è\82é
-/       \8bL\8d\86\82ª\89½\82É\91Î\89\9e\82µ\82Ä\82¢\82é\82©\92²\82×\82é
-?       \83w\83\8b\83v
-&       \82±\82Ì\83R\83}\83\93\83h\82ª\89½\82©\92²\82×\82é
-!       \83V\83F\83\8b\82É\94²\82¯\82é (\92è\8b`\82³\82ê\82Ä\82¢\82é\82È\82ç)
-\       \8d¡\82Ü\82Å\82É\94­\8c©\82³\82ê\82½\95¨\82Ì\88ê\97\97
-`       \88ê\82Â\82Ì\95¨\82Ì\8eí\97Þ\82É\91Î\82µ\82Ä\94­\8c©\82µ\82½\95¨\82Ì\88ê\97\97
-_       \83}\83b\83v\82Å\8e¦\82³\82ê\82½\93_\82É\8dÅ\8f¬\8co\98H\83A\83\8b\83S\83\8a\83Y\83\80\82Å\88Ú\93®\82·\82é
-.       \82»\82Ì\8fê\82Å\8bx\82Þ
-        \89½\82à\82µ\82È\82¢\82Å\82»\82Ì\8fê\82Å\8bx\82Þ (rest_on_space\82ª\92è\8b`\82³\82ê\82Ä\82¢\82é\82È\82ç) 
-:       \82»\82±\82É\89½\82ª\82 \82é\82©\8c©\82é
-;       \89æ\96Ê\8fã\82Ì\8bL\8d\86\82ª\89½\82Å\82 \82é\82©\82ð\92²\82×\82é
-,       \91«\8c³\82Ì\95¨\82ð\8fE\82¤
-@       pickup\83I\83v\83V\83\87\83\93\82ð\90Ø\82è\91Ö\82¦\82é
-)       \91\95\94õ\82µ\82Ä\82¢\82é\95\90\8aí\82ð\8c©\82é
-[       \91\95\94õ\82µ\82Ä\82¢\82é\8aZ\82ð\8c©\82é
-=       \90g\82É\82Â\82¯\82Ä\82¢\82é\8ew\97Ö\82ð\8c©\82é
-"       \90g\82É\82Â\82¯\82Ä\82¢\82é\96\82\8f\9c\82¯\82ð\8c©\82é
-(       \8eg\82Á\82Ä\82¢\82é\93¹\8bï\82ð\8c©\82é
-$       \82¨\8bà\82ð\90\94\82¦\82é
-+       \92m\82Á\82Ä\82¢\82é\96\82\96@\82Ì\88ê\97\97 (\92è\8b`\82³\82ê\82Ä\82¢\82é\82È\82ç)
-#       \8ag\92£\83R\83}\83\93\83h
-M-?     \8ag\92£\83R\83}\83\93\83h\82Ì\83w\83\8b\83v (\91Î\89\9e\82µ\82Ä\82¢\82é\83v\83\89\83b\83g\83t\83H\81[\83\80\82È\82ç)
-M-2     \93ñ\93\81\97¬\90í\93¬\82Ì\90Ø\82è\91Ö\82¦ (number_pad\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82È\82¢\82È\82ç)
-M-a     \8e\9d\82¿\95¨\88ê\97\97\82Ì\92²\90® (fixinv\83I\83v\83V\83\87\83\93\82ª\95K\97v)
-M-A     \8c»\8dÝ\82Ì\8aK\82É\96¼\91O\82ð\82Â\82¯\82é
-M-c     \92N\82©\82É\98b\82µ\82©\82¯\82é
-M-C     \8c»\8dÝ\88Û\8e\9d\82µ\82Ä\82¢\82é\8e©\94­\93I\92§\90í\82Ì\88ê\97\97
-M-d     \95¨\82ð\89½\82©\82É\90Z\82·
-M-e     \95\90\8aí\82Ì\8bZ\97Ê\82ð\8d\82\82ß\82é\82Ü\82½\82Í\8c©\82é
-M-f     \8c®\82ð\82±\82\82 \82¯\82é
-M-i     \95¨\82Ì\93Á\95Ê\82È\97Í\82ð\8eg\82¤
-M-j     \91¼\82Ì\88Ê\92u\82Ì\94ò\82Ñ\82¤\82Â\82é
-M-l     \8f°\82Ì\8fã\82Ì\94 \82Ì\92\86\90g\82ð\97ª\92D\82·\82é
-M-m     \89ö\95¨\82Ì\93Á\95Ê\94\\97Í\82ð\8eg\82¤ (\92è\8b`\82³\82ê\82Ä\82¢\82é\82È\82ç)
-M-n     \89ö\95¨\81C\8cÂ\81X\82Ì\95¨\81C\95¨\82Ì\8eí\97Þ\82É\96¼\91O\82ð\82Â\82¯\82é
-M-o     \90_\82É\8b\9f\95¨\82ð\95ù\82°\82é
-M-O     \92T\8dõ\82µ\82½\96À\8b{\82Ì\8aT\97v\82ð\95\\8e¦
-M-p     \90_\82É\8bF\82é
-M-r     \83\89\83\93\83v\82ð\82±\82·\82é
-M-R     \88Æ\82Ì\95t\82¢\82½\90\82«\95¨\82É\8fæ\82é\82Ü\82½\82Í\8d~\82è\82é
-M-s     \8dÀ\82é
-M-t     \83A\83\93\83f\83b\83g\82ð\93y\82É\82©\82¦\82·
-M-T     \93ü\82ê\95¨\82ð\8bó\82É\82·\82é
-M-u     ã©\82ð\82Í\82¸\82· (\92Ê\8fí\82Í\82µ\82©\82¯\82ç\82ê\82½\95¨)
-M-v     \83R\83\93\83p\83C\83\8b\8e\9e\82Ì\83I\83v\83V\83\87\83\93\82ð\95\\8e¦\82·\82é
-M-w     \8aç\82ð\90@\82¤
+&# cmdhelp
+&      \89\9f\82µ\82½\83L\81[\82ª\89½\82Ì\83R\83}\83\93\83h\82©\82ð\92m\82ç\82¹\82é
+^      \97×\82É\82 \82éã©\82Ì\8eí\97Þ\82ð\92²\82×\82é
+^[     \83R\83}\83\93\83h\82ð\83L\83\83\83\93\83Z\83\8b\82·\82é(ESC\83L\81[\82Æ\93¯\82¶)
+&? debug
+^E     \8bß\82­\82Ìã©\81C\89B\82µ\94à\81C\8c©\82¦\82È\82¢\89ö\95¨\82ð\92T\82·
+^F     \82»\82Ì\8aK\82Ì\92n\90}\82ð\8f\91\82­; ã©\82Æ\89B\82µ\92Ê\98H\82Í\95\\8e¦\82·\82é\82ª\89B\82µ\94à\82Í\95\\8e¦\82µ\82È\82¢
+^G     \96¼\91O\82â\83N\83\89\83X\82ð\8ew\92è\82µ\82Ä\89ö\95¨\82ð\82Â\82­\82é
+^I     \91S\82Ä\82Ì\8e\9d\82¿\95¨\82ð\8e¯\95Ê\82µ\82Ä\95\\8e¦\82·\82é
+^O     \93Á\8eê\82È\8aK\82Ì\8fê\8f\8a\82ð\92m\82é
+^V     \88á\82¤\8aK\82Ö\8fu\8aÔ\88Ú\93®\82·\82é
+^W     \89½\82©\82ð\8aè\82¤
+&: #!debug
+^E     unavailable debugging command
+^F     unavailable debugging command
+^G     unavailable debugging command
+^I     unavailable debugging command
+^O     Shortcut for '#overview': list interesting levels you have visited
+^V     unavailable debugging command
+^W     unavailable debugging command
+&. #?debug
+&? number_pad=0,-1
+b      \93ì\90¼\82É\95à\82­
+B      \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\93ì\90¼\82É\95à\82­
+h      \90¼\82É\95à\82­
+H      \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\90¼\82É\95à\82­
+j      \93ì\82É\95à\82­
+J      \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\93ì\82É\95à\82­
+k      \96k\82É\95à\82­
+K      \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\96k\82É\95à\82­
+l      \93\8c\82É\95à\82­
+L      \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\93\8c\82É\95à\82­
+n      \93ì\93\8c\82É\95à\82­
+N      \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\93ì\93\8c\82É\95à\82­
+u      \96k\93\8c\82É\95à\82­
+U      \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\96k\93\8c\82É\95à\82­
+&# y,Y handled below
+&: #number_pad=1,2,3,4
+h      Help: synonym for '?'
+j      Jump: shortcut for '#jump'
+k      Kick: synonym for '^D'
+l      Loot: shortcut for '#loot'
+n      Start a count; continue with digit(s)
+N      Name: shortcut for '#name'
+u      Untrap: shortcut for '#untrap'
+&. #0,-1 vs 1,2,3,4
+a      \93¹\8bï\82ð\8eg\97p\82·\82é\82©\8fñ\82ð\90Ü\82é
+A      \8aZ\82ð\91S\82Ä\92E\82®\82©\91S\82Ä\82Ì\83A\83N\83Z\83T\83\8a\82ð\8aO\82·\82©\91\95\94õ\82µ\82Ä\82¢\82È\82¢\95\90\8aí\82ð\8aO\82·
+^A     \91O\82Ì\83R\83}\83\93\83h\82ð\8cJ\82è\95Ô\82·
+^B     \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\93ì\90¼\82É\95à\82­
+c      \94à\82ð\95Â\82ß\82é
+C      \89ö\95¨\81C\8cÂ\81X\82Ì\95¨\81C\95¨\82Ì\8eí\97Þ\82É\96¼\91O\82ð\82Â\82¯\82é
+^C     \92\86\92f: \83Q\81[\83\80\82ð\94²\82¯\82é
+d      \95¨\82ð\92u\82­
+D      \8eí\97Þ\82ð\91I\82ñ\82Å\95¨\82ð\92u\82­
+^D     \89½\82©\82ð\8fR\82é (\95\81\92Ê\82Í\94à)
+e      \89½\82©\90H\82×\82é
+E      \8f°\82Ì\82Ù\82±\82è\82É\95\8e\9a\82ð\8f\91\82­
+f      Fire ammunition from quiver
+F      Followed by direction, fight a monster (even if you don't sense it)
+g      \8e\9f\82É\95û\8cü\82ð\8ew\92è\82·\82é\82Æ\89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\95à\82­
+G      \8e\9f\82É\95û\8cü\82ð\8ew\92è\82·\82é\82Æ\89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\95à\82­
+^H     \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\90¼\82É\95à\82­
+i      \82 \82È\82½\82Ì\8e\9d\82¿\95¨\88ê\97\97\82ð\8c©\82é
+I      \8eí\97Þ\82ð\91I\91ð\82µ\82Ä\8e\9d\82¿\95¨\88ê\97\97\82ð\8c©\82é
+^J     \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\93ì\82É\95à\82­
+^K     \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\96k\82É\95à\82­
+^L     \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\93\8c\82É\95à\82­
+m      \8e\9f\82É\95û\8cü\82ð\8ew\92è\82·\82é\82Æ\81C\82à\82Ì\82ð\8fE\82í\82¸\82É\88Ú\93®\82·\82é
+M      \8e\9f\82É\95û\8cü\82ð\8ew\92è\82·\82é\82Æ\81C\82à\82Ì\82ð\8fE\82í\82¸\82É\89\93\82­\82É\88Ú\93®\82·\82é
+^N     \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\93ì\93\8c\82É\95à\82­
+o      \94à\82ð\8aJ\82¯\82é
+O      \83I\83v\83V\83\87\83\93\82ð\83Z\83b\83g\82·\82é (O?\82Í\83I\83v\83V\83\87\83\93\82ð\90à\96¾\82·\82é)
+p      \93X\82Ì\8a¨\92è\82ð\95¥\82¤
+P      \83A\83N\83Z\83A\83\8a\82ð\90g\82É\82Â\82¯\82é(\8ew\97Ö\81C\96\82\8f\9c\82¯\81C\82È\82Ç; \96h\8bï\82É\82à\97L\8cø)
+^P     \91O\82Ì\83\81\83b\83Z\81[\83W\82ð\8c©\82é
+q      \89½\82©\82ð\88ù\82Þ(\90\85\96ò, \90\85\82È\82Ç)
+Q      Select ammunition for quiver (use '#quit' to quit)
+r      \8aª\95¨(\82Ü\82½\82Í\81C\92è\8b`\82µ\82Ä\82¢\82é\82È\82ç\96\82\96@\82Ì\96{)\82ð\93Ç\82Þ
+R      \83A\83N\83Z\83T\83\8a\82ð\82Í\82¸\82·(\8ew\97Ö\81C\96\82\8f\9c\82¯\81C\82È\82Ç; \96h\8bï\82É\82à\97L\8cø)
+^R     \89æ\96Ê\82ð\8f\91\82«\82È\82¨\82·
+s      \82·\82®\97×\82É\82 \82éã©\82â\94é\96§\82Ì\94à\82ð\92T\82·
+S      \83Q\81[\83\80\82ð\95Û\91\82·\82é (\82»\82µ\82Ä\8fI\97¹\82·\82é;\81u\95Û\91\82µ\82Ä\91±\8ds\81v\82Í\82È\82¢)
+t      \89½\82©\82ð\93\8a\82°\82é (\95¨\82ð\91I\82ñ\82Å\82©\82ç\81A\96Ú\95W\82Å\82Í\82È\82­\95û\8cü\82ð\8ew\92è\82·\82é)
+T      \8aZ\82ð\92E\82® (\83A\83N\83Z\83T\83\8a\82É\82à\97L\8cø)
+^T     \82»\82Ì\8aK\82Å\8fu\8aÔ\88Ú\93®\82·\82é
+^U     \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\96k\93\8c\82É\95à\82­
+v      \83o\81[\83W\83\87\83\93\82ð\8c©\82é ('#version'\82Å\92Ç\89Á\8fî\95ñ\82ð\95\\8e¦)
+V      \83Q\81[\83\80\8aJ\94­\82Ì\97ð\8ej\82ð\8c©\82é
+w      \95\90\8aí\82ð\91\95\94õ\82·\82é (\95¡\90\94\95\90\8aí\82Ì\8fê\8d\87: 'w' \97\\94õ\95\90\8aí 'x' 'w' \8eå\95\90\8aí 'X')
+W      \8aZ\82ð\92\85\82é (\83A\83N\83Z\83T\83\8a\82É\82à\97L\8cø)
+x      \92m\82Á\82Ä\82¢\82é\96\82\96@\82Ì\88ê\97\97 (\92è\8b`\82³\82ê\82Ä\82¢\82é\82È\82ç)
+X      \93ñ\93\81\97¬\82ð\90Ø\82è\91Ö\82¦\82é
+^X     \82 \82È\82½\82Ì\91®\90«\82ð\8c©\82é (\8d×\82©\82¢\8fî\95ñ\82Í\94­\8c©\81E\83f\83o\83b\83O\83\82\81[\83h\82Ì\82Ý)
+&? number_pad=0,1,2,3,4
+&? number_pad=0
+y      \96k\90¼\82É\95à\82­
+Y      \89½\82©\82É\82Ô\82Â\82©\82é\82Ü\82Å\96k\90¼\82É\95à\82­
+&.
+^Y     \89½\82©\82ª\8c©\82¦\82é\82Ü\82Å\96k\90¼\82É\95à\82­
+z      \8fñ\82ð\82Ó\82é
+Z      \96\82\96@\82ð\8f¥\82¦\82é (\92è\8b`\82³\82ê\82Ä\82¢\82é\82È\82ç)
+&? suspend
+^Z     \83Q\81[\83\80\82ð\92\86\92f\82·\82é; 'fg' (foreground) \82Å\8dÄ\8aJ\82·\82é
+&:
+^Z     unavailable command: suspend
+&.
+&: number_pad=-1
+y      Zap a wand
+Y      Zap (cast) a spell
+&? suspend
+^Y     Suspend game; 'fg' (foreground) to resume
+&:
+^Y     unavailable command: suspend
+&.
+z      Go northwest 1 space
+Z      Go northwest until you are on top of something
+^Z     Go northwest until you are near something
+&. #0,1..4 vs -1
+<      \8aK\92i\82ð\8f¸\82é
+>      \8aK\92i\82ð\8d~\82è\82é
+/      \8bL\8d\86\82ª\89½\82É\91Î\89\9e\82µ\82Ä\82¢\82é\82©\92²\82×\82é
+?      \83w\83\8b\83v
+&? shell
+!      \83V\83F\83\8b\82É\94²\82¯\82é; \96ß\82é\82É\82Í\83V\83F\83\8b\82ð'exit'\82·\82é
+&:
+!      unavailable command: shell
+&.
+\      \8d¡\82Ü\82Å\82É\94­\8c©\82³\82ê\82½\95¨\82Ì\88ê\97\97
+`      \88ê\82Â\82Ì\95¨\82Ì\8eí\97Þ\82É\91Î\82µ\82Ä\94­\8c©\82µ\82½\95¨\82Ì\88ê\97\97
+_      \83}\83b\83v\82Å\8e¦\82³\82ê\82½\93_\82É\8dÅ\8f¬\8co\98H\83A\83\8b\83S\83\8a\83Y\83\80\82Å\88Ú\93®\82·\82é
+.      \82»\82Ì\8fê\82Å\8bx\82Þ
+&? rest_on_space
+       \89½\82à\82µ\82È\82¢\82Å\82»\82Ì\8fê\82Å\8bx\82Þ
+&.
+:      \82»\82±\82É\89½\82ª\82 \82é\82©\8c©\82é
+;      \89æ\96Ê\8fã\82Ì\8bL\8d\86\82ª\89½\82Å\82 \82é\82©\82ð\92²\82×\82é
+,      \91«\8c³\82Ì\95¨\82ð\8fE\82¤
+@      pickup\83I\83v\83V\83\87\83\93\82ð\90Ø\82è\91Ö\82¦\82é
+)      \91\95\94õ\82µ\82Ä\82¢\82é/\8f\80\94õ\82µ\82Ä\82¢\82é\95\90\8aí\82ð\8c©\82é
+[      \91\95\94õ\82µ\82Ä\82¢\82é\8aZ\82ð\8c©\82é
+=      \90g\82É\82Â\82¯\82Ä\82¢\82é\8ew\97Ö\82ð\8c©\82é
+"      \90g\82É\82Â\82¯\82Ä\82¢\82é\96\82\8f\9c\82¯\82ð\8c©\82é
+(      \8eg\82Á\82Ä\82¢\82é\93¹\8bï\82ð\8c©\82é
+*      Show all equipment in use (combination of the ),[,=,",( commands)
+$      \82¨\8bà\82ð\90\94\82¦\82é
++      \92m\82Á\82Ä\82¢\82é\96\82\96@\82Ì\88ê\97\97 (\92è\8b`\82³\82ê\82Ä\82¢\82é\82È\82ç)
+#      \8ag\92£\83R\83}\83\93\83h ('#?'\82Å\91I\91ð\8e\88\82Ì\88ê\97\97)
+&# number_pad:
+&#  -1 = numpad off, swap y with z (including Y with Z, ^Y with ^Z, M-y &c)
+&#   0 = numpad off (default)
+&#   1 = numpad on, normal keypad layout, '5'->'g'
+&#   2 = numpad on, normal keypad layout, '5'->'G'
+&#   3 = numpad on, phone keypad layout, '5'->'g'
+&#   4 = numpad on, phone keypad layout, '5'->'G'
+&? number_pad = 1,2,3,4
+0      Show inventory
+4      Move west
+6      Move east
+-      'F' prefix; force fight
+&: #-1,0
+0      Continue a count
+4      Start or continue a count
+6      Start or continue a count
+&. #1,2,3,4 vs -1,0
+&? number_pad=1,2
+7      Move northwest
+8      Move north
+9      Move northeast
+1      Move southwest
+2      Move south
+3      Move southeast
+&: number_pad=3,4
+1      Move northwest
+2      Move north
+3      Move northeast
+7      Move southwest
+8      Move south
+9      Move southeast
+&: #-1,0
+1      Start or continue a count
+2      Start or continue a count
+3      Start or continue a count
+7      Start or continue a count
+8      Start or continue a count
+9      Start or continue a count
+&. #1,2 vs 3,4 vs -1,0
+&? number_pad=1,3
+5      'g' movement prefix
+M-5    'G' movement prefix
+&: number_pad=2,4
+5      'G' movement prefix
+M-5    'g' movement prefix
+M-0    Inventory specific item types
+&: #-1,0
+5      Start or continue a count
+M-2    \93ñ\93\81\97¬\90í\93¬\82Ì\90Ø\82è\91Ö\82¦
+&. #1,3 vs 2,4 vs -1,0
+M-?    \8ag\92£\83R\83}\83\93\83h\82Ì\83w\83\8b\83v (\91Î\89\9e\82µ\82Ä\82¢\82é\83v\83\89\83b\83g\83t\83H\81[\83\80\82È\82ç)
+M-a    \8e\9d\82¿\95¨\88ê\97\97\82Ì\92²\90® (fixinv\83I\83v\83V\83\87\83\93\82ª\95K\97v)
+M-A    \8c»\8dÝ\82Ì\8aK\82É\96¼\91O\82ð\82Â\82¯\82é
+M-c    \97×\82É\82¢\82é\90\95¨\82Æ\98b\82·
+M-C    \8c»\8dÝ\88Û\8e\9d\82µ\82Ä\82¢\82é\8e©\94­\93I\92§\90í\82Ì\88ê\97\97
+M-d    \95¨\82ð\89½\82©\82É\90Z\82·
+M-e    \95\90\8aí\82Ì\8bZ\97Ê\82ð\8c©\82Ä\81C\89Â\94\\82È\82ç\8d\82\82ß\82é
+M-f    \8c®\82ð\82±\82\82 \82¯\82é
+M-i    \95¨\82Ì\93Á\95Ê\82È\97Í\82ð\8eg\82¤
+M-j    \8bß\82­\82Ì\88Ê\92u\82É\94ò\82Ñ\82¤\82Â\82é
+M-l    \8f°\82Ì\8fã\82Ì\94 \82Ì\92\86\90g\82ð\97ª\92D\82·\82é
+M-m    \95Ï\89»\82µ\82Ä\82¢\82é\82Æ\82«\82É\81C\89ö\95¨\82Ì\93Á\95Ê\94\\97Í\82ð\8eg\82¤
+M-n    \89ö\95¨\81C\8cÂ\81X\82Ì\95¨\81C\95¨\82Ì\8eí\97Þ\82É\96¼\91O\82ð\82Â\82¯\82é
+M-N    \89ö\95¨\81C\8cÂ\81X\82Ì\95¨\81C\95¨\82Ì\8eí\97Þ\82É\96¼\91O\82ð\82Â\82¯\82é
+M-o    \90_\82É\8b\9f\95¨\82ð\95ù\82°\82é
+M-O    \92T\8dõ\82µ\82½\96À\8b{\82Ì\8aT\97v\82ð\95\\8e¦
+M-p    \90_\82É\8bF\82é
+M-q    \94²\82¯\82é (\95Û\91\82¹\82¸\82É\8fI\97¹\82·\82é)
+M-r    \83\89\83\93\83v\82â\8e\8e\8bà\90Î\82ð\82±\82·\82é
+M-R    \88Æ\82Ì\95t\82¢\82½\90\82«\95¨\82É\8fæ\82é\82Ü\82½\82Í\8d~\82è\82é
+M-s    \8dÀ\82é
+M-t    \83A\83\93\83f\83b\83g\82ð\93y\82É\82©\82¦\82·
+M-T    \93ü\82ê\95¨\82ð\8bó\82É\82·\82é
+M-u    ã©\82ð\82Í\82¸\82· (\92Ê\8fí\82Í\82µ\82©\82¯\82ç\82ê\82½\95¨)
+M-v    \83R\83\93\83p\83C\83\8b\8e\9e\82Ì\83I\83v\83V\83\87\83\93\82ð\95\\8e¦\82·\82é
+M-w    \8aç\82ð\90@\82¤
index db475be..6dd0014 100644 (file)
@@ -1,4 +1,5 @@
-# NetHack 3.6  data.base       $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# NetHack 3.6  data.base
+# $NHDT-Date: 1524683801 2018/04/25 19:16:41 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.84 $
 #      Copyright (c) 1994, 1995, 1996 by the NetHack Development Team
 #      Copyright (c) 1994 by Boudewijn Wayers
 #      NetHack may be freely redistributed.  See license for details.
@@ -54,6 +55,7 @@ suit or piece of armor
                [ When Help Collides, by J. D. Berry ]
 aclys
 aklys
+thonged club
        A short studded or spiked club attached to a cord allowing
        it to be drawn back to the wielder after having been thrown.
        It should not be confused with the atlatl, which is a device
@@ -80,7 +82,7 @@ sacrific*
        top will have grooves for blood, and the whole will be covered
        with _dry brown stains of a troubling kind_ from former
        Sacrifices.
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 
        To every man upon this earth
        Death cometh soon or late;
@@ -215,15 +217,14 @@ apelike creature
        the apes have the forelimbs much better developed than
        the hind limbs.  Tail entirely absent.  Growth is slow
        and sexual maturity reached at quite an advanced age.
-       [ A Field Guide to the Larger Mammals of Africa by Dorst ]
+         [ A Field Guide to the Larger Mammals of Africa by Dorst ]
 
        Aldo the gorilla had a plan.  It was a good plan.  It was
        right.  He knew it.  He smacked his lips in anticipation as
        he thought of it.  Yes.  Apes should be strong.  Apes should
        be masters.  Apes should be proud.  Apes should make the
        Earth shake when they walked.  Apes should _rule_ the Earth.
-               [ Battle for the Planet of the Apes,
-                       by David Gerrold ]
+         [ Battle for the Planet of the Apes, by David Gerrold ]
 apple
        NEWTONIAN, adj.  Pertaining to a philosophy of the universe
        invented by Newton, who discovered that an apple will fall
@@ -278,8 +279,7 @@ arioch
        I found the arrow still unbroke;
        And the song, from beginning to end,
        I found again in the heart of a friend.
-               [ The Arrow and the Song,
-                 by Henry Wadsworth Longfellow ]
+         [ The Arrow and the Song, by Henry Wadsworth Longfellow ]
 ashikaga takauji
        Ashikaga Takauji was a daimyo of the Minamoto clan who
        joined forces with the Go-Daigo to defeat the Hojo armies.
@@ -289,7 +289,7 @@ ashikaga takauji
        Go-Daigo eventually escaped and established another
        government in the town of Yoshino.  This period of dual
        governments was known as the Nambokucho.
-       [ Samurai - The Story of a Warrior Tradition, by Cook ]
+         [ Samurai - The Story of a Warrior Tradition, by Cook ]
 asmodeus
        It is said that Asmodeus is the overlord over all of hell.
        His appearance, unlike many other demons and devils, is
@@ -428,8 +428,8 @@ barbed devil
        Barbed devils lack any real special abilities, though they
        are quite difficult to kill.
 # takes "bat or bird" when specifying 'B'
-~combat
-~wombat
+~*combat
+~*wombat
 *bat
 bat or bird
        A bat, flitting in the darkness outside, took the wrong turn
@@ -557,6 +557,17 @@ candelabrum*
        (Enter all the Friars to sing the dirge)
                [ Doctor Faustus and Other Plays, by Christopher Marlowe ]
 boomerang
+#: this one is commented out because two from the same source feels a
+#: bit excessive; if uncommented, it should be first since the punchline
+#: is about coming back while the other one is disdainful about that, so
+#: if this one came second, its joke would be weakened
+#      "It's a boomerang," said Vimes.  "You find something like this
+#      all over the world.  You have to wave it carefully and suddenly
+#      your opponent gets it in the back.  I've heard that there's a lad
+#      in Fourecks who can throw a boomerang with such precision that it
+#      can get the morning paper and come back with it."
+#              [ Raising Steam, by Terry Pratchett ]
+#
        Rincewind pulled himself up and thought about reaching for his
        stick.  And then he thought again.  The man had a couple of spears
        stuck in the ground, and people here were good at spears, because
@@ -579,7 +590,7 @@ boomerang
        the formula for making this splendid footwear is a closely
        guarded secret, possibly derived from nonhumans (see Dwarfs,
        Elves, and Gnomes).
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 *booze
 potion of sleeping
        On waking, he found himself on the green knoll whence he had
@@ -874,13 +885,19 @@ chih*sung*tzu
        do so.  He became the heavenly controller of the rain, and
        lived with other celestial beings in their paradise on Mount
        Kunlun.
-       [ The Illustrated Who's Who In Mythology, by Michael Senior ]
+         [ The Illustrated Who's Who In Mythology, by Michael Senior ]
 chromatic dragon
 tiamat
        Tiamat is said to be the mother of evil dragonkind.  She is
        extremely vain.
 citrine*
        A pale yellow variety of crystalline quartz resembling topaz.
+cleaver
+       Hither came Conan, the Cimmerian, black-haired, sullen-eyed,
+       sword in hand, a thief, a reaver, a slayer, with gigantic
+       melancholies and gigantic mirth, to tread the jeweled
+       thrones of the Earth under his sandalled feet.
+               [ The Phoenix on the Sword, by Robert E. Howard ]
 ~elven cloak
 ~oilskin cloak
 *cloak*
@@ -895,7 +912,7 @@ citrine*
        with trees_ or _swords_, or needing to be _pulled close
        around her/his shivering body_.  This seems to suggest they
        are less than practical for anyone on an arduous Tour.
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 cloud*
        I wandered lonely as a cloud
        That floats on high o'er vales and hills,
@@ -943,8 +960,8 @@ c*ckatrice
        But even a dead basilisk is dangerous, for it is said that
        merely touching its lifeless body can cause a person to
        sicken and die.
-       [ Mythical Beasts by Deirdre Headon (The Leprechaun Library)
-         and other sources ]
+         [ Mythical Beasts by Deirdre Headon (The Leprechaun Library)
+             and other sources ]
 *coin
 ~creeping coins
 *coins
@@ -1055,21 +1072,20 @@ crom
        his weapon, and mutters under his breath:
        "By Crom, there will be blood spilt today."
 
-       [ Conan the Avenger by Robert E. Howard, Bjorn Nyberg, and
-         L. Sprague de Camp ]
+           [ Conan the Avenger by Robert E. Howard, Bjorn Nyberg,
+               and L. Sprague de Camp ]
 crossbow*
        "God save thee, ancient Mariner!
        From the fiends, that plague thee thus! -
        Why look'st thou so?" - With my cross-bow
        I shot the Albatross.
-               [ The Rime of the Ancient Mariner, by Samuel Taylor
-                 Coleridge ]
+         [ The Rime of the Ancient Mariner, by Samuel Taylor Coleridge ]
 crystal ball
        You look into one of these and see _vapours swirling like
        clouds_.  These shortly clear away to show a sort of video
        without sound of something that is going to happen to you
        soon.  It is seldom good news.
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 curse*
        Curses are longstanding ill-wishings which, in Fantasyland,
        often manifest as semisentient.  They have to be broken or
@@ -1082,7 +1098,7 @@ curse*
        want to do this.  Swords usually resist all attempts to
        raise their Curses.  Your best source is to hide the Sword
        or give it to someone you dislike.
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 cwn*n
        A pack of snow-white, red-eared spectral hounds which
        sometimes took part in the kidnappings and raids the
@@ -1183,7 +1199,7 @@ major demon
        through a keyhole yet not be pierced with a Sword.  This makes
        them difficult to deal with, even on the rare occasions when
        they are friendly.
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 diamond
        The hardest known mineral (with a hardness of 10 on Mohs' scale).
        It is an allotropic form of pure carbon that has crystallized in
@@ -1231,7 +1247,8 @@ dingo
        A wolflike wild dog, Canis dingo, of Australia, having a
        reddish- or yellowish-brown coat, believed to have been
        introduced by the aborigines.
-       [Webster's Encyclopedic Unabridged Dictionary of the English Language]
+               [ Webster's Encyclopedic Unabridged Dictionary
+                   of the English Language ]
 disenchanter
        Ask not, what your magic can do to it.  Ask what it can do
        to your magic.
@@ -1320,7 +1337,7 @@ doppelganger
        not only with clouds of sulphurous fumes pouring from its fire
        breathing nostrils, but also with the thrashings of its tail,
        the most deadly part of its serpent-like body.
-       [ Mythical Beasts by Deirdre Headon (The Leprechaun Library) ]
+         [ Mythical Beasts by Deirdre Headon (The Leprechaun Library) ]
 
        "One whom the dragons will speak with," he said, "that is a
        dragonlord, or at least that is the center of the matter.  It's
@@ -1636,9 +1653,16 @@ fire trap
        _anywhere_?'
                [ The Last Hero, by Terry Pratchett ]
 f* brand
-       One of a pair of legendary swords that possess the powers
-       of elemental flame and ice, and will grant these to whoever
-       is fortunate enough to wield them.
+       Some say the world will end in fire,
+       Some say in ice.
+       From what I've tasted of desire
+       I hold with those who favor fire.
+       But if it had to perish twice,
+       I think I know enough of hate
+       To say that for destruction ice
+       Is also great
+       And would suffice.
+               [ Fire and Ice, by Robert Frost ]
 flesh golem
        With an anxiety that almost amounted to agony, I collected
        the instruments of life around me, that I might infuse a spark
@@ -1770,8 +1794,8 @@ fox
        imagination.  In this year, with Man's thoughts turned toward
        the many ills he has brought among himself, Man has forgotten
        his most ancient adversary, the gargoyles.
-       [ Excerpt from the opening narration to the movie
-               _Gargoyles_, written by Stephen and Elinor Karpf ]
+               [ Excerpt from the opening narration to the movie
+                   _Gargoyles_, written by Stephen and Elinor Karpf ]
 *garlic
        1 November - All day long we have travelled, and at a good
        speed.  The horses seem to know that they are being kindly
@@ -1943,7 +1967,7 @@ goddess
        by narrowing down your available choices of what to do next:
        if a deity is pushing you, things will go miserably badly until
        there is only one choice left to you.
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 gold
 gold piece
        A metal of characteristic yellow colour, the most precious
@@ -2056,7 +2080,7 @@ hachi
        Its strings break only in very rare instances, usually
        because the Harper is sulking or crossed in love.  This is
        just as well as no one seems to make or sell spare strings.
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 
        After breakfast was over, the ogre called out: "Wife, wife,
        bring me my golden harp."  So she brought it and put it on
@@ -2141,7 +2165,7 @@ hell hound*
        savage, more appalling, more hellish be conceived than that
        dark form and savage face which broke upon us out of the wall
        of fog.
-       [ The Hound of the Baskervilles, by Sir Arthur Conan Doyle. ]
+         [ The Hound of the Baskervilles, by Sir Arthur Conan Doyle. ]
 hermes
        Messenger and herald of the Olympians.  Being required to do
        a great deal of travelling and speaking in public, he became
@@ -2325,7 +2349,7 @@ hunger
        and Hell followed with him.  And power was given unto them over
        the fourth part of the earth, to kill with sword, and with
        hunger, and with death, and with the beasts of the earth.
-            [ Revelations of John, 6:1-8 ]
+               [ Revelations of John, 6:1-8 ]
 huan*ti
        The first of five mythical Chinese emperors, Huan Ti is known
        as the yellow emperor.  He rules the _moving_ heavens, as
@@ -2567,13 +2591,13 @@ jaguar
        Large, flesh-eating animal of the cat family, of Central and
        South America.  This feline predator (_Panthera onca_) is
        sometimes incorrectly called a panther.
-        [ Van Dale's Groot Woordenboek der Nederlandse Taal ]
+           [ Van Dale's Groot Woordenboek der Nederlandse Taal ]
 jellyfish
        I do not care to share the seas
        With jellyfishes such as these;
        Particularly Portuguese.
-               [ Lines on Meeting a Portuguese Man-o'-war while
-                       Bathing, by Michael Flanders ]
+         [ Lines on Meeting a Portuguese Man-o'-war while Bathing,
+             by Michael Flanders ]
 juiblex
 jubilex
        Little is known about the Faceless Lord, even the correct
@@ -2688,8 +2712,7 @@ knight
        And was a bugbear in men's eyes;
        But had the fortune in his age
        To live a fool and die a sage.
-               [ Don Quixote of La Mancha, by Miquel de
-                 Cervantes Saavedra ]
+         [ Don Quixote of La Mancha, by Miquel de Cervantes Saavedra ]
 ~kobold ??m*
 *kobold*
        The race of kobolds are reputed to be an artificial creation
@@ -2805,8 +2828,7 @@ lance
        his lance into shivers, carrying him and his horse after it,
        and finally tumbled him a good way off from it on the field in
        evil plight.
-               [ Don Quixote of La Mancha, by Miquel de
-                 Cervantes Saavedra ]
+         [ Don Quixote of La Mancha, by Miquel de Cervantes Saavedra ]
 land mine
        Your heart is intact, your brain is not badly damaged, but the rest
        of your injuries are comparable to stepping on a land mine.  You'd
@@ -2842,7 +2864,7 @@ lava
        of its own, which lends an additional infernal splendor to the
        already hellish scene.  A dark, forboding passage exits to the
        south.
-               [ Adventure, by Will Crowther and Doug Woods. ]
+               [ Adventure, by Will Crowther and Don Woods. ]
 leash
        They had splendid heads, fine shoulders, strong legs, and
        straight tails.  The spots on their bodies were jet-black and
@@ -2911,7 +2933,7 @@ leprechaun
        way to divert his captor's attention and vanishes in the
        twinkling of an eye.
                [ A Field Guide to the Little People
-                              by Nancy Arrowsmith & George Moorse ]
+                   by Nancy Arrowsmith & George Moorse ]
 *lich
        But on its heels ere the sunset faded, there came a second
        apparition, striding with incredible strides and halting when
@@ -3029,10 +3051,12 @@ bad luck
        that?"
        Jack shrugged [...].  "Bad grace, I suppose.  Just because I
        shot off his ear and made him jump into a pit full of spikes."
-                       [ the hollow chocolate bunnies of
-                         the apocalypse, by Robert Rankin ]
-#                      [no relation... both cover and title page list
-#                       this book's title in all lower case]
+               [ the hollow chocolate bunnies of the apocalypse,
+                   by Robert Rankin ]
+#              [no relation... both cover and title page list this
+#               book's title in all lower case; however, its sequel,
+#               "the toyminator", refers to it using conventional
+#               capitalization in a couple of early footnotes]
 lug*
        Lugh, or Lug, was the sun god of the Irish Celts.  One of his
        weapons was a rod-sling which worshippers sometimes saw in
@@ -3157,6 +3181,15 @@ mars
        explain why he became a god of death and finally a god of war.
        He is the son of Jupiter and Juno.
                [ Encyclopedia Mythica, ed. M.F. Lindemans ]
+martial arts
+unarmed combat
+bare*handed combat
+       "What else can we do? None of this is fast enough." "It will have
+       to be." He stood up, a tall, broad wall of a man.  "Why don't you
+       ask around, see if anyone in the neighborhoods knows anything
+       about martial arts.  You need more than a book or two to learn
+       good dependable unarmed combat."
+               [ Parable of the Sower, by Octavia Butler ]
 master assassin
        He strolled down the stairs, followed by a number of assassins.
        When he was directly in front of Ymor he said: "I've come for
@@ -3182,7 +3215,7 @@ master key of thievery
        a powerful magic which allows it to open any lock.  When
        carried, it grants its owner warning, teleport control, and
        reduces all physical damage by half.  Finally, when invoked,
-       it has the ability to disarm any trap.
+       it has the ability to disarm any trapped lock.
 master of thieves
        There was a flutter of wings at the window.  Ymor shifted his
        bulk out of the chair and crossed the room, coming back with
@@ -3282,7 +3315,7 @@ gnomish mines
        unwanted emeralds, etc., still embedded in the rock of the
        walls.  Metal will also be present, but only when made up into
        armor and weapons (_wondrous_).
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 minotaur
        The Minotaur was a monster, half bull, half human, the
        offspring of Minos' wife Pasiphae and a wonderfully beautiful
@@ -3307,9 +3340,8 @@ mit*ra*
        and contracts.  He is attributed with the creation of both
        plants and animals.  His chief adversary is Ahriman, the
        power of darkness.
-               [ The Encyclopaedia of Myths and Legends of All
-                       Nations, by Herbert Spencer Robinson and
-                       Knox Wilson ]
+           [ The Encyclopaedia of Myths and Legends of All Nations,
+               by Herbert Spencer Robinson and Knox Wilson ]
 *mithril*
        _Mithril_!  All folk desired it.  It could be beaten like
        copper, and polished like glass; and the Dwarves could make
@@ -3556,9 +3588,8 @@ ninja-to
        good condition by placing fresh earth around it daily.  In her
        fury, Skuld often spoiled the work of her sisters by tearing
        the web to shreds.
-               [ The Encyclopedia of Myths and Legends of All
-                       Nations by Herbert Spencer Robinson and Knox
-                       Wilson ]
+           [ The Encyclopedia of Myths and Legends of All Nations
+               by Herbert Spencer Robinson and Knox Wilson ]
 nunchaku
        A nunchaku is two sections of wood (or metal in modern
        incarnations) connected by a cord or chain.  There is much
@@ -3812,7 +3843,7 @@ panther
        Nay, rather did impede so much my way,
        That many times I to return had turned.
                [ Dante's Inferno, as translated
-                       by Henry Wadsworth Longfellow ]
+                   by Henry Wadsworth Longfellow ]
 *paper
        Some players, who unconsciously perceive Paper as weak or a
        sign of surrender, will shy away from using it entirely or
@@ -3913,6 +3944,41 @@ user
        Might just kill you.
                [ It's a Jungle Out There, by Randy Newman ]
 #                      [ theme song from "Monk" ]
+polearm
+* polearm
+partisan
+ranseur
+spetum
+glaive
+halberd
+bardiche
+angled poleaxe
+long poleaxe
+voulge
+pole cleaver
+fauchard
+pole sickle
+guisarme
+bill-guisarme
+lucern hammer
+bec de corbin
+       Many of the weapons of the Middle Ages were poled or long-shafted
+       arms.  Unlike the ancient spear or javelin, however, they were not
+       intended to be thrown.  Some were devices with simple single- or
+       double-edged blades and nothing more, while others combined
+       the pick, spear, and hammer or axe all in one weapon.
+               [ Heraldry and Armor of the Middle Ages, by Marvin H. Pakula ]
+polymorph trap
+       One morning, as Gregor Samsa was waking up from anxious dreams,
+       he discovered that in bed he had been changed into a monstrous
+       verminous bug.  He lay on his armour-hard back and saw, as he
+       lifted his head up a little, his brown, arched abdomen divided
+       up into rigid bow-like sections.  From this height the blanket,
+       just about ready to slide off completely, could hardly stay in
+       place.  His numerous legs, pitifully thin in comparison to the
+       rest of his circumference, flickered helplessly before his eyes.
+               [ The Metamorphosis, by Franz Kafka,
+                       translated by Ian Johnston ]
 pony
                Hey! now! Come hoy now! Whither do you wander?
                Up, down, near or far, here, there or yonder?
@@ -3934,7 +4000,7 @@ pony
        You will travel through them both to distant parts of the
        continent and to and from our own world.  The precise manner
        of their working is a Management secret.
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 poseido*n
        Poseido(o)n, lord of the seas and father of rivers and
        fountains, was the son of Chronos and Rhea, brother of Zeus,
@@ -3951,8 +4017,8 @@ poseido*n
        shake the earth, a power which makes him the god of
        earthquakes as well.  Physically, he is shown as a strong and
        powerful ruler, every inch a king.
-               [ The Encyclopedia of Myths and Legends of All
-                 Nations, by Herbert Robinson and Knox Wilson ]
+           [ The Encyclopedia of Myths and Legends of All Nations,
+               by Herbert Robinson and Knox Wilson ]
 ~*sleeping
 ~*booze
 *potion*
@@ -4105,7 +4171,7 @@ quasit
        why not?  By then you will have had a lot of practice in
        that sort of thing and, besides, the Quest Object is usually
        designed to help you do it.
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 quetzalcoatl
        One of the principal Aztec-Toltec gods was the great and wise
        Quetzalcoatl, who was called Kukumatz in Guatemala, and
@@ -4222,7 +4288,7 @@ robe
        are dealing with.
        2.  For Kings.  The OMT here is _falling in stately folds_.
        3.  As the garb of Desert Nomads.  [...]
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+           [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 rock
        Bilbo saw that the moment had come when he must do something.
        He could not get up at the brutes and he had nothing to shoot
@@ -4425,7 +4491,7 @@ scalpel
        This mace was created aeons ago in some unknown cave,
        and has been passed down from generation to generation of
        cave dwellers.  It is a very mighty mace indeed, and in
-       addition will protect anyone who carries it from magic
+       addition will protect anyone who wields it from magic
        missile attacks.  When invoked, it causes conflict in the
        area around it.
 scimitar
@@ -4685,8 +4751,8 @@ javelin
        of Rome in Nero's time, for instance?  Why, it would merely
        say 'Town burned down; no insurance; boy brast a window,
        fireman brake his neck!'  Why, that ain't a picture!
-               [ A Connecticut Yankee in King Arthur's Court, by Mark
-                 Twain ]
+               [ A Connecticut Yankee in King Arthur's Court,
+                   by Mark Twain ]
 *spellbook*
        The Book of Three lay closed on the table.  Taran had never
        been allowed to read the volume for himself; now he was sure
@@ -4846,6 +4912,11 @@ straw golem
        figure was raised above the stalks of corn by means of the
        pole stuck up its back.
                [ The Wonderful Wizard of Oz, by L. Frank Baum ]
+sunsword
+       What you seek is a blade of light,
+       a weapon for vengeance.
+               [ Expedition to Castle Ravenloft,
+                       by Bruce Cordell and James Wyatt ]
 susano*o
        The Shinto chthonic and weather god and brother of the sun
        goddess Amaterasu, he was born from the nose of the
@@ -4862,7 +4933,7 @@ tengu
        feuds and prolonging enmity between families.  Indeed, the
        belligerent tengu were supposed to have been man's first
        instructors in the use of arms.
-       [ Mythical Beasts, by Deirdre Headon (The Leprechaun Library) ]
+         [ Mythical Beasts, by Deirdre Headon (The Leprechaun Library) ]
 thoth
        The Egyptian god of the moon and wisdom, Thoth is the patron
        deity of scribes and of knowledge, including scientific,
@@ -5008,6 +5079,8 @@ tourist
        Tourist, Rincewind had decided, meant "idiot".
                [ The Colour of Magic, by Terry Pratchett ]
 towel
+wet towel
+moist towel
        The Hitchhiker's Guide to the Galaxy has a few things to say
        on the subject of towels.
        A towel, it says, is about the most massively useful thing
@@ -5026,8 +5099,7 @@ towel
        wave your towel in emergencies as a distress signal, and of
        course dry yourself off with it if it still seems to be clean
        enough.
-               [ The Hitchhiker's Guide to the Galaxy,
-                 by Douglas Adams ]
+         [ The Hitchhiker's Guide to the Galaxy, by Douglas Adams ]
 *tower
 *tower of darkness
        Towers (_brooding_, _dark_) stand alone in Waste Areas and
@@ -5036,7 +5108,7 @@ towel
        blocks of masonry that make them very hard to climb. [...]
        You will have to go to a Tower and then break into it at some
        point towards the end of your Tour.
-       [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
+         [ The Tough Guide to Fantasyland, by Diana Wynne Jones ]
 trap*door
        I knew my Erik too well to feel at all comfortable on jumping
        into his house.  I knew what he had made of a certain palace at
@@ -5187,7 +5259,7 @@ unicorn horn
        tamed and captured by a maiden.  Made gentle by the sight of a
        virgin, the unicorn can be lured to lay its head in her lap, and
        in this docile mood, the maiden may secure it with a golden rope.
-       [ Mythical Beasts, by Deirdre Headon (The Leprechaun Library) ]
+         [ Mythical Beasts, by Deirdre Headon (The Leprechaun Library) ]
 
        Martin took a small sip of beer.  "Almost ready," he said.
        "You hold your beer awfully well."
@@ -5196,6 +5268,9 @@ unicorn horn
        warm glow stage, then I use my horn to burn off any excess and
        keep me right there."
                [ Unicorn Variations, by Roger Zelazny ]
+unreconnoitered
+       Area of map which is beyond limited perception range when
+       underwater or engulfed by a monster.
 valkyrie
 * valkyrie
        The Valkyries were the thirteen choosers of the slain, the
@@ -5208,9 +5283,8 @@ valkyrie
        without restraint and fighting over again the battles in
        which they died and in which they had won their deathless
        fame.
-               [ The Encyclopaedia of Myths and Legends of All
-                       Nations, by Herbert Robinson and Knox
-                       Wilson ]
+           [ The Encyclopaedia of Myths and Legends of All Nations,
+               by Herbert Robinson and Knox Wilson ]
 vampire
 ~vampire bat
 vampire lord
@@ -5322,8 +5396,7 @@ water
        And all the boards did shrink;
        Water, water, everywhere
        Nor any drop to drink.
-               [ The Rime of the Ancient Mariner, by Samuel Taylor
-                 Coleridge ]
+         [ The Rime of the Ancient Mariner, by Samuel Taylor Coleridge ]
 water demon
        [ The monkey king ] walked along the bank, around the pond.
        He examined the footprints of the animals that had gone into
@@ -5422,8 +5495,8 @@ wolf
        some of these plants, which yield a poisonous alkaloid that
        was formerly used medicinally.  In both senses also called
        monkshood.
-       [ The American Heritage Dictionary of the English Language,
-         Fourth Edition. ]
+               [ The American Heritage Dictionary of
+                   the English Language, Fourth Edition. ]
 wood golem
        Come, old broomstick, you are needed,
        Take these rags and wrap them round you!
@@ -5442,8 +5515,8 @@ wood golem
        How the water spills,
        How the water basins
        Brimming full he fills!
-       [ The Sorcerer's Apprentice, by Johann Wolfgang von Goethe,
-         translation by Edwin Zeydel ]
+         [ The Sorcerer's Apprentice, by Johann Wolfgang von Goethe,
+             translation by Edwin Zeydel ]
 woodchuck
        The Usenet Oracle requires an answer to this question!
 
index a9505dc..26ceeb3 100644 (file)
@@ -1,4 +1,4 @@
-# NetHack 3.6  dungeon.def     $NHDT-Date: 1432512783 2015/05/25 00:13:03 $  $NHDT-Branch: master $:$NHDT-Revision: 1.13 $
+# NetHack 3.6  dungeon.def     $NHDT-Date: 1462486876 2016/05/05 22:21:16 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.14 $
 #      Copyright (c) 1990-95 by M. Stephenson
 # NetHack may be freely redistributed.  See license for details.
 #
@@ -119,6 +119,10 @@ DESCRIPTION:       mazelike
 ALIGNMENT:     chaotic
 ENTRY:         -1
 LEVEL:         "tower1" "none" @ (1, 0)
+# it isn't necessary to list these last two, but doing so makes them
+# show up in ^O output and in the level teleport menu
+LEVEL:         "tower2" "none" @ (2, 0)
+LEVEL:         "tower3" "none" @ (3, 0)
 
 #
 #      The Endgame levels
index 2eb3614..3188516 100644 (file)
@@ -1,3 +1,6 @@
+# NetHack 3.6  engrave.txt       $NHDT-Date: 1524689579 2018/04/25 20:52:59 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $
+# Copyright (c) 2015 by Pasi Kallinen
+# NetHack may be freely redistributed.  See license for details.
 # Random engravings on the floor
 #
 Elbereth
index d2ee9a6..9b9f9b7 100644 (file)
@@ -1,3 +1,6 @@
+# NetHack 3.6  epitaph.txt       $NHDT-Date: 1524689580 2018/04/25 20:53:00 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.3 $
+# Copyright (c) 2015 by Pasi Kallinen
+# NetHack may be freely redistributed.  See license for details.
 # Epitaphs for random headstones
 #
 #
@@ -106,7 +109,7 @@ Algernon
 All else failed...
 All hail RNG
 All right, we'll call it a draw!
-All's well that end well
+All's well that ends well
 Alone at last!
 Always attack a floating eye from behind!
 Am I having fun yet?
index 50541e0..9b9498d 100644 (file)
@@ -521,27 +521,37 @@ TRAP:"magic", random
 MAZE:"baalz",' '
 FLAGS: noteleport,corrmaze
 GEOMETRY:right,center
+# the two pools are fakes used to mark spots which need special wall fixups
+# the two iron bars are eyes and spots to their left will be made diggable
 MAP
 -------------------------------------------------
-|                    ---               ----      
-|          ----      |   ------------  |         
-| ------      |  --------|..........|---         
-| |....|  -------|...........--------------      
+|                   ----               ----      
+|          ----     |     -----------  |         
+| ------      |  ---------|.........|--P         
+| F....|  -------|...........--------------      
 ---....|--|..................S............|----  
-....--....S..----------------|............S...|  
++...--....S..----------------|............S...|  
 ---....|--|..................|............|----  
-| |....|  -------|...........-----S--------      
-| ------      |  --------|..........|---         
-|          ----     |    ------------  |         
-|                   ---                ----      
+| F....|  -------|...........-----S--------      
+| ------      |  ---------|.........|--P         
+|          ----     |     -----------  |         
+|                   ----               ----      
 -------------------------------------------------
 ENDMAP
 STAIR:levregion(01,00,15,20),levregion(15,1,70,16),up
 BRANCH:levregion(01,00,15,20),levregion(15,1,70,16)
 TELEPORT_REGION:levregion(01,00,15,20),levregion(15,1,70,16)
-NON_DIGGABLE:(00,00,46,12)
+# this actually leaves the farthest right column diggable
+NON_DIGGABLE:(00,00,47,12)
 MAZEWALK:(00,06),west
 STAIR:(44,06),down
+DOOR:locked,(00,06)
+IF [50%] {
+   TERRAIN:(34,08),'-'
+   TERRAIN:(34,04),'S'
+   TERRAIN:(29,05),'|'
+   TERRAIN:(29,07),'S'
+}
 # The fellow in residence
 MONSTER:('&',"Baalzebub"),(35,06)
 # Some random weapons and armor.
index ef2d927..df8f03a 100644 (file)
--- a/dat/help
+++ b/dat/help
@@ -73,7 +73,9 @@ b j n   1 2 3           g<dir>:   
         NetHack \82Å\82Í\88È\89º\82Ì\83R\83}\83\93\83h\82ð\8eg\82¤\82±\82Æ\82ª\82Å\82«\82é\81D
         ?       \83w\83\8b\83v\83\81\83j\83\85\81[\81D
         /       \83V\83\93\83{\83\8b\82ª\89½\82ð\95\\82µ\82Ä\82¢\82é\82©\8b³\82¦\82é\81D
-                \88Ê\92u\82Å\8ew\92è\82·\82é\82©\81C\83A\81[\83M\83\85\83\81\83\93\83g\82Å\8ew\92è\82·\82é\82©\82Å\91I\82Ô\81D
+                \88Ê\92u\82Å\8ew\92è\82·\82é\82©\81C\83V\83\93\83{\83\8b\82ð\88ø\90\94\82Å\8ew\92è\82·\82é\82©\82Å\91I\82Ô\81D
+                autodescribe\83I\83v\83V\83\87\83\93\82ð\83I\83\93\82É\82·\82é\82Æ\83J\81[\83\\83\8b\82ð\93®\82©\82·\96\88\82É
+                \82»\82Ì\8fê\8f\8a\82Ì\83V\83\93\83{\83\8b\82É\8aÖ\82·\82é\8fî\95ñ\82ð\95\\8e¦\82·\82é\81D
         &       \83R\83}\83\93\83h\82Ì\88Ó\96¡\82ð\8b³\82¦\82é\81D
         <       \8aK\92i\82ð\93o\82é\81D  (\82»\82Ì\8fã\82É\82¢\82é\8fê\8d\87\82Ì\82Ý)
         >       \8aK\92i\82ð\8d~\82è\82é\81D(\82»\82Ì\8fã\82É\82¢\82é\8fê\8d\87\82Ì\82Ý)
diff --git a/dat/hh b/dat/hh
index f9baa58..d065ce5 100644 (file)
--- a/dat/hh
+++ b/dat/hh
@@ -26,7 +26,7 @@ S       save    
 !       sh      (\82à\82µ\82Å\82«\82é\82È\82ç)\83V\83F\83\8b\82ð\8eÀ\8ds\82·\82é\81D
 ^Z      suspend \83Q\81[\83\80\82ð\92\86\92f\82·\82é\81D
 O       options \83I\83v\83V\83\87\83\93\82ð\90Ý\92è\82·\82é\81D
-/       whatis  \89æ\96Ê\82Ì\8bL\8d\86\82ª\89½\82©\82ð\92m\82é\81D
+/       what-is \89æ\96Ê\82Ì\8bL\8d\86\82ª\89½\82©\82ð\92m\82é\81D
 \       known   \8d¡\82Ü\82Å\82É\94­\8c©\82µ\82½\93¹\8bï\82Ì\88ê\97\97\82ð\95\\8e¦\82·\82é\81D
 v       version \83o\81[\83W\83\87\83\93\82ð\95\\8e¦\82·\82é\81D
 V       history \83Q\81[\83\80\82Ì\97ð\8ej\82ð\95\\8e¦\82·\82é\81D
@@ -36,6 +36,7 @@ V       history 
 ^P      prevmsg \91O\82Ì\83\81\83b\83Z\81[\83W\82ð\8c©\82é\81D(^P\82Í\8cJ\82è\95Ô\82µ\8eg\82¦\82é)
 `               \83I\83\8a\83W\83i\83\8b\83\82\81[\83h\82Æ\93ú\96{\8cê\83\82\81[\83h\82Ì\90Ø\82è\91Ö\82¦
 #               \8ag\92£\83R\83}\83\93\83h(#?\82Å\83w\83\8b\83v)
+&       what-does \83L\81[\82ð\89\9f\82µ\82Ä\8bN\93®\82·\82é\83R\83}\83\93\83h\82ð\90à\96¾\82·\82é\81D
 
 \83Q\81[\83\80:
 ^D      kick    \8fR\82é\81D(\94à\93\99)
@@ -59,7 +60,7 @@ o       open    
 p       pay     \8a¨\92è\82ð\95¥\82¤\81D(\93X\82Ì\92\86\82Å)
 P       puton   \83A\83N\83Z\83T\83\8a\82ð\90g\82É\82Â\82¯\82é\81D(\8ew\97Ö\81C\96\82\8f\9c\82¯\82È\82Ç)
 q       quaff   \89½\82©\82ð\88ù\82Þ(\90\85\96ò, \90\85\82È\82Ç)
-Q       quiver  \91\95\93U\82·\82é\82à\82Ì\82ð\91I\91ð\82·\82é\81D
+Q       quiver  \91\95\93U\82·\82é\82à\82Ì\82ð\91I\91ð\82·\82é\81D(\8fI\97¹\82Í'#quit')
 r       read    \8aª\95¨\82â\96\82\96@\82Ì\96{\82ð\93Ç\82Þ\81D
 R       remove  \83A\83N\83Z\83T\83\8a\82ð\82Í\82¸\82·\81D(\8ew\97Ö\81C\96\82\8f\9c\82¯\82È\82Ç)
 s       search  \94é\96§\82Ì\94à\81C\89B\82ê\82½ã©\81C\89ö\95¨\82ð\92T\82·\81D
@@ -68,7 +69,7 @@ T       takeoff 
 w       wield   \95\90\8aí\82ð\91\95\94õ\82·\82é\81D(w-  \89½\82à\91\95\94õ\82µ\82È\82¢)
 W       wear    \8aZ\82ð\92\85\82é\81D
 x       xchange \8d\89E\82Ì\95\90\8aí\82ð\8cð\8a·\82·\82é\81D
-X       twoweapon \93ñ\93\81\97¬\82ð\90Ø\82è\91Ö\82¦\82é\81D
+X       twoweapon \93ñ\93\81\97¬\82ð\90Ø\82è\91Ö\82¦\82é\81D(\92T\8dõ\83\82\81[\83h\82Í'#explore')
 z       zap     \8fñ\82ð\90U\82è\82©\82´\82·\81D(number_pad \82ª -1 \82È\82ç z \82Å\82Í\82È\82­ y)
 Z       Zap     \8eô\95\82ð\8f¥\82¦\82é\81D(number_pad \82ª -1 \82È\82ç Z \82Å\82Í\82È\82­ Y)
 <       up      \8aK\92i\82ð\8f¸\82é\81D
@@ -92,21 +93,27 @@ _       travel  
 M-?             \8ag\92£\83R\83}\83\93\83h\83w\83\8b\83v\82Ì\95\\8e¦ (\83v\83\89\83b\83g\83t\83H\81[\83\80\82ª\8b\96\82¹\82Î)
 M-2     twoweapon \93ñ\93\81\97¬\82Ì\90Ø\82è\91Ö\82¦ (number_pad \82ª\96³\8cø\82È\82ç)
 M-a     adjust  \8e\9d\82¿\95¨\88ê\97\97\82Ì\92²\90®
+M-A     annotate \8c»\8dÝ\82Ì\8aK\82É1\8ds\83\81\83\82\82ð\92Ç\89Á\82·\82é(M-O\8eQ\8fÆ)
 M-c     chat    \92N\82©\82Æ\98b\82·
+M-C     conduct \8e©\94­\93I\92§\90í\82ð\95\\8e¦\82·\82é
 M-d     dip     \89½\82©\82É\95¨\82ð\90Z\82·\81D
-M-e     enhance \95\90\8aí\82Ì\8bZ\97Ê\82ð\8d\82\82ß\82é\82Ü\82½\82Í\8c©\82é    
+M-e     enhance \95\90\8aí\82Ì\8bZ\97Ê\82ð\8d\82\82ß\82é\82Ü\82½\82Í\8c©\82é
 M-f     force   \8c®\82ð\82±\82\82 \82¯\82é\81D
 M-i     invoke  \95¨\82Ì\93Á\95Ê\82È\97Í\82ð\8eg\82¤\81D
 M-j     jump    \91¼\82Ì\88Ê\92u\82É\94ò\82Ñ\82¤\82Â\82é\81D
 M-l     loot    \8f°\82Ì\8fã\82Ì\94 \82Ì\92\86\90g\82ð\97ª\92D\82·\82é\81D
 M-m     monster \89ö\95¨\82Ì\93Á\95Ê\94\\97Í\82ð\8eg\82¤\81D
 M-n     name    \93Á\92è\82Ì\89ö\95¨\81C\8cÂ\81X\82Ì\83A\83C\83e\83\80\81C\83A\83C\83e\83\80\82Ì\8eí\97Þ\82É\96¼\91O\82ð\82Â\82¯\82é\81D
+M-N     name    M-n\82Ì\95Ê\96¼
 M-o     offer   \90_\82É\8b\9f\95¨\82ð\95ù\82°\82é\81D
+M-O     overview \96K\82ê\82½\8aK\82É\8aÖ\82·\82é\8fî\95ñ\82Æ\83\81\83\82\82ð\95\\8e¦\82·\82é
 M-p     pray    \90_\82É\8bF\82é\81D
 M-q     quit    \83Q\81[\83\80\82ð\82â\82ß\82é
 M-r     rub     \83\89\83\93\83v\82ð\82±\82·\82é\81D
+M-R     ride    \8bR\8fæ\82·\82é\82Ü\82½\82Í\8bR\8fæ\82ð\82â\82ß\82é
 M-s     sit     \8dÀ\82é\81D
 M-t     turn    \83A\83\93\83f\83b\83g\82ð\93y\82É\95Ô\82·\81D
+M-T     tip     \93ü\82ê\95¨\82ð\82Ð\82Á\82­\82è\95Ô\82·
 M-u     untrap  ã©\82ð\82Í\82¸\82·\81D
 M-v     version \83R\83\93\83p\83C\83\8b\8e\9e\82Ì\83I\83v\83V\83\87\83\93\82ð\95\\8e¦\82·\82é\81D
 M-w     wipe    \8aç\82ð\90@\82¤\81D
diff --git a/dat/keyhelp b/dat/keyhelp
new file mode 100644 (file)
index 0000000..d4df8d4
--- /dev/null
@@ -0,0 +1,58 @@
+       Depending upon hardware or operating system or NetHack's interface,
+       some keystrokes may be off-limits.
+
+       For example, ^S and ^Q are often used for XON/XOFF flow-control,
+       meaning that ^S suspends output and subsequent ^Q resumes suspended
+       output.  When that it the case, neither of those characters will
+       reach NetHack when it is waiting for a command keystroke.  So they
+       aren't used as commands, but 'whatdoes' might not be able to tell
+       you that if they don't get passed through to NetHack.
+
+       ^M or <return> or <enter> is likely to be transformed into ^J or
+       <linefeed> or 'newline' before being passed to NetHack for handling.
+       So it isn't used as a command, and 'whatdoes' might seem as if it
+       is reporting the wrong character but will be operating correctly if
+       it describes ^J when you type ^M.
+
+       A NUL character, which is typed as ^<space> on some keyboards,
+       ^@ on others, and maybe not typeable at all on yet others, is not
+       used as a command, and will be converted into ESC before reaching
+       'whatdoes'.  Unlike ^M, this transformation is performed within
+       NetHack.  But like ^M, if you type NUL and get feedback about ESC,
+       the situation is expected.
+
+       ESC itself is a synonym for ^[, and is another source of oddity.
+       Various function keys, including cursor arrow keys, may transmit
+       an "escape sequence" of ESC + [ + other stuff, confusing NetHack
+       as to what command was intended since the ESC will be processed
+       and then whatever follows will seem to NetHack like--and be used
+       as--something typed by the user.  (If you press a function key and
+       a menu of the armor your hero is wearing appears, what happened
+       was that an escape sequence was sent to NetHack, its ESC aborted
+       any pending key operation, its '[' was then treated as a command
+       to show worn armor, and the "other stuff" probably got silently
+       discarded as invalid choices while you dismissed the menu.)
+
+       If you have NetHack's 'altmeta' option enabled, meaning that the
+       <alt> or <option> key, when used as shift while typing some other
+       character, transmits ESC and then the other character so NetHack
+       should treat that other character as a meta-character, then ESC
+       takes on added potential for confusion.  Implicit in the handling
+       of a two character sequence ESC + something is the fact that when
+       NetHack sees ESC, it needs to wait for another character before
+       it can decide what to do.  So if you type ESC manually, you'll
+       need to type it a second time or NetHack will sit there waiting.
+       (It will then be treated as if you typed ESC rather than M-ESC.)
+
+       On some systems, typing ^\ will send a QUIT signal to the current
+       process, probably killing it and possibly causing it to save a
+       core dump.  It is not used for any NetHack command, so don't type
+       that character.
+
+       One last note:  characters shown as ^x mean that you should hold
+       down the <control> or <ctrl> key as a shift and then type 'x'.
+       Control characters are all implicitly uppercase, but you don't
+       need to press the shift key while typing them.  The opposite is
+       true for meta-characters:  they can be either case, so you need
+       to use shift as well as <meta> or <alt> to generate an uppercase
+       letter meta-character.
index bf602c1..65e6c56 100644 (file)
@@ -6,17 +6,19 @@
 MAZE:"knox",' '
 FLAGS: noteleport
 GEOMETRY:center,center
+# Fort's entry is via a secret door rather than a drawbridge;
+# the moat must be manually circumvented.
 MAP
 ----------------------------------------------------------------------------
 | |........|...............................................................|
 | |........|.................................................------------..|
-| -------+--.................................................|..........|..|
-|       |........}}}}}}}....................}}}}}}}..........|..........|..|
-|       |........}-----}....................}-----}..........--+--+--...|..|
-|     ---........}|...|}}}}}}}}}}}}}}}}}}}}}}|...|}.................|...|..|
-|     |..........}---S------------------------S---}.................|...|..|
-|     |..........}}}|...............|..........|}}}.................+...|..|
-| -------..........}|...............S..........|}...................|...|..|
+| --S----S--.................................................|..........|..|
+|   #   |........}}}}}}}....................}}}}}}}..........|..........|..|
+|   #   |........}-----}....................}-----}..........--+--+--...|..|
+|   # ---........}|...|}}}}}}}}}}}}}}}}}}}}}}|...|}.................|...|..|
+|   # |..........}---S------------------------S---}.................|...|..|
+|   # |..........}}}|...............|..........|}}}.................+...|..|
+| --S----..........}|...............S..........|}...................|...|..|
 | |.....|..........}|...............|......\...S}...................|...|..|
 | |.....+........}}}|...............|..........|}}}.................+...|..|
 | |.....|........}---S------------------------S---}.................|...|..|
@@ -33,15 +35,31 @@ NON_DIGGABLE:(00,00,75,19)
 # Portal arrival point
 BRANCH:(08,16,08,16),(0,0,0,0)
 # accessible via ^V in wizard mode; arrive near the portal
-TELEPORT_REGION:(06,16,09,17),(0,0,0,0),up
-TELEPORT_REGION:(06,16,09,17),(0,0,0,0),down
+TELEPORT_REGION:(06,15,09,16),(0,0,0,0),up
+TELEPORT_REGION:(06,15,09,16),(0,0,0,0),down
 #   Throne room, with Croesus on the throne
 REGION:(37,08,46,11),lit,"throne"
-MONSTER:('@',"Croesus"),(43,10),hostile
+#   50% chance each to move throne and/or fort's entry secret door up one row
+IF [50%] {
+   MONSTER:('@',"Croesus"),(43,10),hostile
+} ELSE {
+   MONSTER:('@',"Croesus"),(43,09),hostile
+   TERRAIN:(43,09), '\'
+   TERRAIN:(43,10), '.'
+}
+IF [50%] {
+   TERRAIN:(47,09), 'S'
+   TERRAIN:(47,10), '|'
+}
 #   The Vault
 #   Using unfilled morgue for
 #   identification in mkmaze.c
 REGION:(21,08,35,11),lit,"morgue",unfilled
+#   Vault entrance also varies
+IF [50%] {
+   TERRAIN:(36,09), '|'
+   TERRAIN:(36,10), 'S'
+}
 #   Corner towers
 REGION:(19,06,21,06),lit,"ordinary"
 REGION:(46,06,48,06),lit,"ordinary"
@@ -64,6 +82,8 @@ DOOR:locked,(08,11)
 DOOR:open,(68,11)
 DOOR:closed,(63,14)
 DOOR:closed,(66,14)
+DOOR:closed,(04,03)
+DOOR:closed,(04,09)
 # Soldiers guarding the fort
 MONSTER:('@',"soldier"),(12,14)
 MONSTER:('@',"soldier"),(12,13)
@@ -82,6 +102,8 @@ MONSTER:('@',"soldier"),(54,13)
 MONSTER:('@',"soldier"),(57,10)
 MONSTER:('@',"soldier"),(57,09)
 MONSTER:('@',"lieutenant"),(15,08)
+# Possible source of a boulder
+MONSTER:('H',"stone giant"),(03,01)
 # Four dragons guarding each side
 MONSTER:'D',(18,09)
 MONSTER:'D',(49,10)
index 3e1a705..b449a29 100644 (file)
@@ -218,7 +218,7 @@ MONSTER:random,random
 
 
 LEVEL:"medusa-3"
-FLAGS: noteleport,mazelevel
+FLAGS: noteleport,mazelevel,shortsighted
 INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 #
index a441389..de0ecac 100644 (file)
@@ -1140,7 +1140,7 @@ DOOR:closed,(37,8)
 DOOR:closed,(47,8)
 DOOR:closed,(73,5)
 DOOR:closed,(2,15)
-MAZEWALK:(36,8),west
+MAZEWALK:(36,8),west,false
 STAIR:(42,8),up
 WALLIFY
 
index 8ce02c9..fb18ea6 100644 (file)
@@ -2,25 +2,39 @@
 ('O'\83R\83}\83\93\83h\82ð\8eg\97p\82µ\82Ä\8c»\8dÝ\82Ì\83I\83v\83V\83\87\83\93\82Ì\90Ý\92è\82ð\83`\83F\83b\83N\82µ\81C\82Ç\82Ì\83I\83v\83V\83\87\83\93\82ª
 \82 \82È\82½\82Ì\83o\81[\83W\83\87\83\93\82É\82 \82é\82©\92m\82é\82±\82Æ\82ª\82Å\82«\82é)
 
+acoustics      can your character hear anything                        [TRUE]
+autodescribe   describe the terrain under cursor                       [FALSE]
 autodig        \8c@\82é\93¹\8bï\82ð\91\95\94õ\82µ\82Ä\88Ú\93®\82µ\82½\8fê\8d\87\82Í\8c@\82é                    [FALSE]
 autoopen       \94à\82É\8cü\82©\82Á\82Ä\88Ú\93®\82·\82é\82Æ\8aJ\82¯\82æ\82¤\82Æ\82·\82é                    [TRUE]
 autopickup     \88Ú\93®\82µ\82½\82Æ\82«\8e©\93®\82Å\95¨\82ð\8fE\82¤                              [TRUE]
 autoquiver     \89½\82©\82ð\8eË\82é\82Æ\82«\82É\96î\93\9b(\82È\82Ç)\82ª\8bó\82Ì\8fê\8d\87\81C\93K\93\96\82È\95\90\8aí\82ð
                \91\95\93U\82·\82é\81D                                              [FALSE]
+BIOS           allow the use of IBM ROM BIOS calls                     [FALSE]
+blind          your character is permanently blind                     [FALSE]
+bones          allow loading bones files                               [TRUE]
+clicklook      look at map by clicking right mouse button              [FALSE]
 cmdassist      \95û\8cü\82â\82»\82Ì\91¼\82Ì\83R\83}\83\93\83h\82Å\83G\83\89\81[\8e\9e\82É\83w\83\8b\83v\82ð\95\\8e¦\82·\82é      [TRUE]
 confirm        \83y\83b\83g\82â\97F\8dD\93I\82È\89ö\95¨\82ð\8dU\8c\82\82·\82é\91O\82É\8am\94F\82·\82é              [TRUE]
-DECgraphics    \83_\83\93\83W\83\87\83\93\82ÉDEC/VT\82Ì\8cr\90ü\82ð\8eg\97p\82·\82é                      [FALSE]
+dark_room      show floor not in sight in different color              [TRUE]
 eight_bit_tty  8-bit\83L\83\83\83\89\83N\83^\82ð\92[\96\96\82É\82»\82Ì\82Ü\82Ü\91\97\90M\82·\82é                 [FALSE]
 extmenu        \8ag\92£\83R\83}\83\93\83h (#) \82ð\91I\91ð\82·\82é\82Æ\82«\82É\83\81\83j\83\85\81[\82ð\8eg\97p\82·\82é     [FALSE]
 fixinv         \82Å\82«\82é\82¾\82¯\81C\93¯\82\95¨\82Í\93¯\82\95\8e\9a\82É\93\96\82Ä\82é                    [TRUE]
+force_invmenu  commands asking for inventory item show a menu          [FALSE]
+goldX          when filtering objects by bless/curse state,            [FALSE]
+               whether to classify gold as X (unknown) or U (uncursed)
 help           '/'\83R\83}\83\93\83h\8e\9e\82É\82³\82ç\82È\82é\8fî\95ñ\82ð\8c©\82é\82©\8am\94F\82·\82é             [TRUE]
-IBMgraphics    \83_\83\93\83W\83\87\83\93\82ÉIBM\8ag\92£\95\8e\9a\82ð\8eg\97p\82·\82é                       [FALSE]
+herecmd_menu   show menu of some possible commands when clicking
+               on yourself or next to you with mouse                   [FALSE]
 ignintr        \83u\83\8c\81[\83N\82ð\8aÜ\82Þ\83C\83\93\83^\83\89\83v\83g\83V\83O\83i\83\8b\82ð\96³\8e\8b\82·\82é            [FALSE]
 implicit_uncursed \89Â\94\\82È\82ç\8e\9d\82¿\95¨\95\\8e¦\82Ì\8e\9e\82É\81u\8eô\82í\82ê\82Ä\82¢\82È\82¢\81v\95\\8e¦\82ð\8f\9c\82­ [TRUE]
 legacy         \83Q\81[\83\80\8dÅ\8f\89\82É\83C\83\93\83g\83\8d\83_\83N\83V\83\87\83\93\82ð\95\\8e¦\82·\82é                [TRUE]
 lit_corridor   \88Ã\82¢\89ñ\98L\82Å\82à\83v\83\8c\81[\83\84\82Ì\8eü\88Í\82ð\96¾\82é\82­\95\\8e¦\82·\82é              [FALSE]
 lootabc        \94 \82ð\8aJ\82¯\82½\82Æ\82«\82Éo/i/b\82Å\82Í\82È\82­a/b/c\82ð\8eg\82¤                [FALSE]
 mail           \83\81\81[\83\8b\83f\81[\83\82\83\93\82Ì\91\8dÝ\82ð\8b\96\82·                              [TRUE]
+mention_walls  give feedback when walking against a wall               [FALSE]
+menu_objsyms   show object symbols in menus if it is selectable        [FALSE]
+menu_overlay   overlay menus on the screen and align to right          [TRUE]
+nudist         start your character without armor                      [FALSE]
 null           \92[\96\96\82É\83k\83\8b\82ð\91\97\82é\81D                                      [TRUE]
                \88Ú\93®\82·\82é\95¨\91Ì\82ª\95\94\89®\82ð\83e\83\8c\83|\81[\83g\82µ\82Ä\82¢\82é\82æ\82¤\82É\8c©\82¦\82é\82È\82ç
                \82Î\81C\82±\82Ì\83I\83v\83V\83\87\83\93\82ð\83I\83t\82É\82¹\82æ\81D(\8b­\90§\93I\82É\83f\83B\83\8c\83C\83R\81[\83h
@@ -32,16 +46,15 @@ pushweapon     
 rawio          raw I/O\82Ì\8ed\97l\82ð\8b\96\89Â\82·\82é                                 [FALSE]
 rest_on_space  \83X\83y\81[\83X\83o\81[\82Å\8bx\8ce\82·\82é                                  [FALSE]
 safe_pet       (\82í\82©\82Á\82Ä\82¢\82é\82È\82ç)\83y\83b\83g\82ð\8dU\8c\82\82·\82é\82Ì\82ð\94ð\82¯\82é            [TRUE]
+sanity_check   perform data sanity checks                              [FALSE]
 showexp        \8co\8c±\92l\82ð\95\\8e¦\82·\82é                                        [FALSE]
 showrace       \8e©\95ª\8e©\90g\82ð\90E\8bÆ\82Å\82È\82­\8eí\91°\82Å\95\\8e¦\82·\82é                      [FALSE]
 silent         \92[\96\96\82Ì\83x\83\8b\82ð\96Â\82ç\82³\82È\82¢                                  [TRUE]
 sortpack       \8e\97\82½\82æ\82¤\82È\8eí\97Þ\82Ì\95¨\82ð\82Ü\82Æ\82ß\82é                            [TRUE]
-sound          \83L\83\83\83\89\83N\83^\82ª\95·\82¢\82½\82à\82Ì\82É\82Â\82¢\82Ä\82Ì\83\81\83b\83Z\81[\83W\82ð\95\\8e¦\82·\82é    [TRUE]
-               (\92\8d\88Ó: \82±\82ê\82Í\82 \82È\82½\82Ì\83R\83\93\83s\83\85\81[\83^\81[\82Ì\83I\81[\83f\83B\83I\8b@\94\\82É
-               \89½\82©\82ð\82·\82é\82à\82Ì\82Å\82Í\82È\82¢\81D\82Ü\82½\92è\8aú\93I\82É\83\8a\83Z\83b\83g\82³\82ê\82é\81D)
 sparkle        \96\82\96@\8dU\8c\82\82É\83\8c\83W\83X\83g\82µ\82½\82Æ\82«(\89Î\82Ö\82Ì\91Ï\90«\82ð\8e\9d\82Â\89ö\95¨\82É       [TRUE]
                \89Î\82Ì\8dU\8c\82\82ð\8ds\82Á\82½\82Æ\82«\82È\82Ç)\82É\83G\83t\83F\83N\83g\82ð\95\\8e¦\82·\82é
 standout       --More--\82ð\91¾\8e\9a\82Å\95\\8e¦\82·\82é                                [FALSE]
+status_updates update the status lines                                 [TRUE]
 time           \83Q\81[\83\80\82Ì\8co\89ß\8e\9e\8aÔ\82ð\95\\8e¦\82·\82é                              [FALSE]
 tombstone      \8e\80\82ñ\82¾\82Æ\82«\95æ\90Î\82ð\95\\8e¦\82·\82é                                [TRUE]
 toptenwin      \83g\83b\83v10\82ð\95W\8f\80\8fo\97Í\82Å\82Í\82È\82­\83E\83B\83\93\83h\83E\82É\95\\8e¦\82·\82é          [FALSE]
@@ -50,7 +63,8 @@ travel         
 use_darkgray   \8d\95\82¢\83V\83\93\83{\83\8b\82Ì\8e\9e\82É\90Â\82Å\82Í\82È\82­\8d\95\82Ì\91¾\8e\9a\82ð\8eg\82¤              [TRUE]
 use_inverse    \8a´\92m\82µ\82½\89ö\95¨\82ð\83n\83C\83\89\83C\83g\82µ\82Ä\95\\8e¦\82·\82é                    [FALSE]
 verbose        \83Q\81[\83\80\82Ì\83R\83\81\83\93\83g\82ð\8fÚ\82µ\82­\95\\8e¦\82·\82é                        [TRUE]
-
+whatis_menu    show menu when getting a map location                   [FALSE]
+whatis_moveskip skip same glyphs when getting a map location           [FALSE]
 
 
 \83R\83\93\83p\83C\83\8b\8e\9e\82Ì\90Ý\92è\82É\82æ\82Á\82Ä\82Í\82³\82ç\82É\90^\8bU\83I\83v\83V\83\87\83\93\82ª\91\8dÝ\82·\82é\81D
@@ -74,6 +88,7 @@ showscore      
 \83R\83\93\83p\83C\83\8b\8e\9e\82É TEXTCOLOR \82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82È\82ç\82Î:
 color          \89æ\96Ê\82Ì\95¨\82Ì\90F\81X\82È\90F\82ð\8eg\97p\82·\82é                  [TRUE for micros]
 hilite_pet     \83y\83b\83g\82ð\8b­\92²\95\\8e¦\82·\82é                                    [FALSE]
+hilite_pile    display item piles in a highlighted manner              [FALSE]
 
 \83R\83\93\83p\83C\83\8b\8e\9e\82É TIMED_DELAY \82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82È\82ç\82Î(tty \83C\83\93\83^\81[\83t\83F\81[\83X\82Ì\82Ý):
 timed_delay    UNIX\82âVMS\82Å\82Í\83f\83B\83X\83v\83\8c\83C\82Ö\95\\8e¦\82ð\83|\81[\83Y\82·\82é\91ã\82è\82É       [TRUE]
@@ -83,14 +98,17 @@ timed_delay    UNIX
 
 Amiga\82©\81A\83R\83\93\83p\83C\83\8b\8e\9e\82ÉALTMETA\82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82È\82ç\82Î:
 altmeta        Amiga\82Å\81AAlt+\83L\81[\82ðMeta+\83L\81[\82Æ\82µ\82Ä\88µ\82¤\81D                [TRUE]
-altmeta        unix\82ÆVMS\82Å\81Cjnethack\82ª\83v\83\8c\83C\83\84\81[\82Ì\83L\81[\83{\81[\83h\82©\82ç\83R\83}\83\93\83h\82ð\93¾\82é
-               \8e\9e\81C2\95\8e\9a\95À\82Ñ"ESC c"\82ðM-c(Meta+c,\8dÅ\8fã\88Ê\83r\83b\83g\90Ý\92è)\82Æ\82µ\82Ä\88µ\82¤\81D
-                                                                       [FALSE]
+altmeta        unix\82ÆVMS\82Å\81Cjnethack\82ª\83v\83\8c\83C\83\84\81[\82Ì\83L\81[\83{\81[\83h\82©\82ç       [FALSE]
+               \83R\83}\83\93\83h\82ð\93¾\82é\8e\9e\81C2\95\8e\9a\95À\82Ñ"ESC c"\82ðM-c(Meta+c,
+               \8dÅ\8fã\88Ê\83r\83b\83g\90Ý\92è)\82Æ\82µ\82Ä\88µ\82¤\81D
 
 \83R\83\93\83p\83C\83\8b\8e\9e\82É USE_TILES \82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82È\82ç\82Π(MSDOS \83v\83\8d\83e\83N\83g\83\82\81[\83h\82Ì\82Ý):
-preload_tiles  \83Q\81[\83\80\8aJ\8en\8e\9e\82É\83^\83C\83\8b\82ð\97\\82ß RAM \82É\93Ç\82Ý\8d\9e\82Þ\82©\82ð\90§\8cä\82·\82é\81D
+preload_tiles  \83Q\81[\83\80\8aJ\8en\8e\9e\82É\83^\83C\83\8b\82ð\97\\82ß RAM \82É\93Ç\82Ý\8d\9e\82Þ\82©\82ð\90§\8cä\82·\82é\81D [TRUE]
                \82±\82ê\82É\82æ\82è\83^\83C\83\8b\83O\83\89\83t\83B\83b\83N\82Ì\90«\94\\82ª\8cü\8fã\82·\82é\82ª\81C
-               \82æ\82è\91½\82­\82Ì\83\81\83\82\83\8a\82ð\8eg\82¤\81D                                [TRUE]
+               \82æ\82è\91½\82­\82Ì\83\81\83\82\83\8a\82ð\8eg\82¤\81D
+
+Boolean option if TTY_TILES_ESCCODES was set at compile time (tty only):
+vt_tiledata    insert extra data escae code markers into output        [FALSE]
 
 \94C\88Ó\82Ì\90^\8bU\83I\83v\83V\83\87\83\93\82Í'!'\82â'no'\82ð\82Â\82¯\82é\82±\82Æ\82É\82æ\82è\94Û\92è\82Å\82«\82é\81D
 
@@ -99,11 +117,18 @@ preload_tiles  
 
 \83Q\81[\83\80\92\86\82É\90Ý\92è\82Å\82«\82é\83p\83\89\83\81\81[\83^\82Â\82«\83I\83v\83V\83\87\83\93\82Í:
 
-boulder        \8b\90\8aâ\82Ì\95\8e\9a\82ð\91¼\82Ì\82à\82Ì\82É\95Ï\82¦\82é [`]
-disclose       \83Q\81[\83\80\8fI\97¹\8e\9e\82É\8c©\82é\8fî\95ñ\82Ì\8eí\97Þ [ni na nv ng nc no]
+boulder        \8b\90\8aâ\82Ì\95\8e\9a\82ð\95Ï\82¦\82é                                      [`]
+disclose       \83Q\81[\83\80\8fI\97¹\8e\9e\82É\8c©\82é\8fî\95ñ\82Ì\8eí\97Þ                [ni na nv ng nc no]
+              (space separated list of two-character values;
+              prefix: '+' always disclose, '-' never disclose,
+              'n' prompt with default "no", 'y' prompt with default "yes",
+              'a' prompt to select sorting order (for suffix 'v' only);
+              suffix: 'i' inventory, 'a' attributes, 'v' vanquished
+              monsters, 'g' genocided and extinct monsters, 'c' conduct,
+              'o' dungeon overview)
 fruit          \8dD\95¨\82Ì\89Ê\95¨\82Ì\96¼\91O [slime mold]
                (\8aî\96{\93I\82ÉNetHack\82ª\8bC\82Ü\82®\82ê\82Å\8eg\82Á\82Ä\82«\82½)
-menustyle      \95¡\90\94\83I\83u\83W\83F\83N\83g\82ð\91I\91ð\82·\82é\82Æ\82«\82Ì\83\86\81[\83U\81[\83C\83\93\83^\83t\83F\81[\83X
+menustyle      \95¡\90\94\83I\83u\83W\83F\83N\83g\82ð\91I\91ð\82·\82é\82Æ\82«\82Ì\83\86\81[\83U\81[\83C\83\93\83^\83t\83F\81[\83X   [Full]
                Traditional -- \91Î\8fÛ\82Æ\82·\82é\83N\83\89\83X\82ð\93ü\97Í\82µ\81C\82»\82ê\82©\82ç\82»\82Ì\83N\83\89\83X\82Ì\83A
                               \83C\83e\83\80\82ð\88ê\82Â\82¸\82Â\91I\82Ô
                Combination -- \91Î\8fÛ\82Æ\82·\82é\83N\83\89\83X\82ð\93ü\97Í\82µ\81C\82»\82ê\82©\82ç\83A\83C\83e\83\80\82ð\91I\82Ô
@@ -112,21 +137,25 @@ menustyle      
                               \83\80\82ð\91I\82Ô\82Ì\82É\83\81\83j\83\85\81[\82ð\8eg\82¤
                Partial     -- \83N\83\89\83X\91I\91ð\82ð\8eg\97p\82¹\82¸\81C\91S\82Ä\82Ì\83A\83C\83e\83\80\82Ì\83\81\83j\83\85\81[\82ð
                               \8eg\82¤
-               \8dÅ\8f\89\82Ì\88ê\95\8e\9a('T', 'C', 'P', 'F')\82Å\8c\88\92è\81D'N' \82Í 'T' \82Æ\93¯\97l\82Ì\88Ó
-               \96¡\81D[Full]
-number_pad     \88Ú\93®\82É\89p\8e\9a\82ð\8eg\82¤\82©\90\94\8e\9a\82ð\8eg\82¤\82©:
+               \8dÅ\8f\89\82Ì\88ê\95\8e\9a('T', 'C', 'F', 'P')\82Å\8c\88\92è\81D
+              (With Traditional, many actions allow pseudo-class 'm' to
+              request a menu for choosing items: one-shot Combination.)
+number_pad     \88Ú\93®\82É\89p\8e\9a\82ð\8eg\82¤\82©\90\94\8e\9a\82ð\8eg\82¤\82©: [0]
                0 -- \93`\93\9d\93I\82È hjkl + yubn \88Ú\93® (\83f\83t\83H\83\8b\83g);
                1 -- \83e\83\93\83L\81[\97p\82É\90\94\8e\9a\82Å\88Ú\93®;
                2 -- 1\82Æ\93¯\97l\82¾\82ª'5'\82Í'G'\82Å\82Í\82È\82­'g'\90Ú\93ª\8e«\82Æ\82µ\82Ä\93®\8dì;
                3 -- \8cg\91Ñ\93d\98b\82Ì\90\94\8e\9a\83L\81[ (1,2,3\82Í\8fã, 7,8,9\82Í\89º);
-               4 -- \8cg\91Ñ\93d\98b\90\94\8e\9a\83L\81[(3)\82ÆMSDOS\8cÝ\8a·(2)\82Ì\91g\82Ý\8d\87\82í\82¹;
-              -1 -- \89p\8e\9a\88Ú\93®\82¾\82ª'z'\82Æ'y'\82ð\8cð\8a·\82·\82é\81D[0]
-packorder      \94w\95\89\82¢\91Ü\93à\82Ì\95¨\82Ì\8f\87\94Ô\82ð\8c\88\82ß\82é\83V\83\93\83{\83\8b [")[%?+!=/(*`0_]
+               4 -- \8cg\91Ñ\93d\98b\90\94\8e\9a\83L\81[(3)\82Æ'5'\82É\8aÖ\82·\82é\90Ý\92è(2)\82Ì\91g\82Ý\8d\87\82í\82¹;
+              -1 -- \89p\8e\9a\88Ú\93®\82¾\82ª'z'\82Æ'y'\82ð\8cð\8a·\82·\82é\81D
+              Setting number_pad (to a positive value) affects how all
+              digit keys are handled, not just those on numeric keypad.
+packorder      'sortpack'\83I\83v\83V\83\87\83\93\82ª\83I\83\93\82Ì\8e\9e\82É\81A\8e\9d\82¿\95¨\88ê\97\97\82Ì [")[%?+!=/(*`0_]
+               \8f\87\94Ô\82ð\8c\88\82ß\82é\83V\83\93\83{\83\8b
                (\82¢\82­\82Â\82©\82Ì\95¨\91Ì\82µ\82©\93Á\92è\82µ\82È\82¢\8fê\8d\87\81C\8ec\82è\82Ì\82Í\83f\83t\83H\83\8b\83g\82Ì
                \8f\87\94Ô\82É\95À\82Ô)
 paranoid_confirmation  \91z\92è\82Æ\88á\82¤\96â\82¢\8d\87\82í\82¹\82ð\82·\82é\8fó\8bµ\82Ì\8bó\94\92\8bæ\90Ø\82è\82Ì\83\8a\83X\83g
               [paranoid_confirmation:pray]
-              Confirm -- yes\82ª\95K\97v\82È\82Æ\82«\81C\94Û\92è\82É\82Íno\82ª\95K\97v
+              Confirm -- "yes"\82ª\95K\97v\82È\82Æ\82«\81C\94Û\92è\82É\82Í"no"\82ª\95K\97v
               quit    -- \94²\82¯\82½\82è\92T\8dõ\83\82\81[\83h\82É\93ü\82é\8am\94F\82Íyes\82©y\82©
               die     -- (\92T\8dõ\82â\83f\83o\83b\83O\83\82\81[\83h\82Å)\8e\80\82Ê\82Æ\82«\82Ì\8am\94F\82Íyes\82©y\82©
               bones   -- \83f\83o\83b\83O\83\82\81[\83h\82Å\8d\9c\82ð\8ec\82·\8am\94F\82Íyes\82©y\82©
@@ -134,20 +163,20 @@ paranoid_confirmation  
               pray    -- \8bF\82é\82Æ\82«\82Éy\82Å\8am\94F\82·\82é; \83f\83t\83H\83\8b\83g\82Åon
               Remove  -- \8aO\82·\82±\82Æ\82ª\82Å\82«\82é\83A\83C\83e\83\80\82ª\88ê\82Â\82Ì\8e\9e\82à'R'\82â'T'\82Å\8am\94F
                          \82·\82é\82©
-pickup_burden  \89½\82©\82ð\8e\9d\82¿\82 \82°\82æ\82¤\82Æ\82µ\82Ä\82Ó\82ç\82ß\82­\8fó\91Ô\82É\82È\82Á\82½\82Æ\82«\82É\81C\91±\82¯\82é\82©
+pickup_burden  \89½\82©\82ð\8e\9d\82¿\82 \82°\82æ\82¤\82Æ\82µ\82Ä\82Ó\82ç\82ß\82­\8fó\91Ô\82É\82È\82Á\82½\82Æ\82«\82É\81C\91±\82¯\82é\82©[S]
                \82Ç\82¤\82©\82Ì\8am\94F\82ð\82·\82é\81D(\92Ê\8fí:U\81C\82æ\82ë\82ß\82«:B\81C\88³\94\97:S\81C\8cÀ\8aE:N\81C
-               \89×\8fd:N\81C\92´\89ß:T)  [S]
-pickup_types   \8e©\93®\82Å\8fE\82¢\82 \82°\82é\95¨\82Ì\83V\83\93\83{\83\8b [all]
-pile_limit     \83A\83C\83e\83\80\82ª\97\8e\82¿\82Ä\82¢\82é\8f°\82Ì\8fã\82ð\95à\82­\8e\9e\81C\83A\83C\83e\83\80\82Ì\88ê\97\97\82Å\82Í\82È\82­
+               \89×\8fd:N\81C\92´\89ß:T)
+pickup_types   \8e©\93®\82Å\8fE\82¢\82 \82°\82é\95¨\82Ì\83V\83\93\83{\83\8b\81D\8bó\82Í\91S\82Ä\82ð\88Ó\96¡\82·\82é\81D           []
+pile_limit     \83A\83C\83e\83\80\82ª\97\8e\82¿\82Ä\82¢\82é\8f°\82Ì\8fã\82ð\95à\82­\8e\9e\81C\83A\83C\83e\83\80\82Ì\88ê\97\97\82Å\82Í\82È\82­  [5]
               \81u\82±\82±\82É\82Í\82½\82­\82³\82ñ\82Ì\82à\82Ì\82ª\82 \82é\81v\82Æ\95\\8e¦\82·\82éè\87\92l\81D
-               (0\82Í\81u\8fí\82É\83A\83C\83e\83\80\82Ì\88ê\97\97\82ð\95\\8e¦\81v\81D)  [5]
-runmode        (\97l\81X\82È\88Ú\93®\83R\83}\83\93\83h\82â\83g\83\89\83x\83\8b\83R\83}\83\93\83h\82É\82æ\82Á\82Ä)\95¡\90\94\83}\83X\88Ú\93®\82·\82é
-               \8fê\8d\87\82É\92n\90}\83E\83B\83\93\83h\83E\82ð\8dX\90V\82·\82é\95p\93x\82ð\8ew\92è\82·\82é:
+               (0\82Í\81u\8fí\82É\83A\83C\83e\83\80\82Ì\88ê\97\97\82ð\95\\8e¦\81v\81D)
+runmode        (\97l\81X\82È\88Ú\93®\83R\83}\83\93\83h\82â\83g\83\89\83x\83\8b\83R\83}\83\93\83h\82É\82æ\82Á\82Ä)\95¡\90\94\83}\83X    [run]
+               \88Ú\93®\82·\82é\8fê\8d\87\82É\92n\90}\83E\83B\83\93\83h\83E\82ð\8dX\90V\82·\82é\95p\93x\82ð\8ew\92è\82·\82é:
                teleport -- \88Ú\93®\82ª\8fI\97¹\82·\82é\82Ü\82Å\8dX\90V\82µ\82È\82¢;
                run      -- \8e\9e\81X\92n\90}\82ð\8dX\90V\82·\82é (\8aÔ\8au\82Í 7 \83}\83X);
                walk     -- \88ê\95à\96\88\82É\92n\90}\82ð\8dX\90V\82·\82é;
                crawl    -- walk \82Æ\93¯\97l\82¾\82ª\81A\88ê\95à\96\88\82É\83E\83F\83C\83g\82ð\93ü\82ê\82é;
-               (\82±\82ê\82Í\89æ\96Ê\95\\8e¦\82É\82Ì\82Ý\8dì\97p\82µ\81C\8eÀ\8dÛ\82Ì\88Ú\93®\82É\82Í\89e\8b¿\82µ\82È\82¢\81D) [run]
+               (\82±\82ê\82Í\89æ\96Ê\95\\8e¦\82É\82Ì\82Ý\8dì\97p\82µ\81C\8eÀ\8dÛ\82Ì\88Ú\93®\82É\82Í\89e\8b¿\82µ\82È\82¢\81D)
 scores         \83Q\81[\83\80\8fI\97¹\8e\9e\82É\8c©\82é\83X\83R\83A\82Ì\8eí\97Þ [!own/3 top/2 around]
                \83g\83b\83v\83X\83R\83A\81C\83g\83b\83v\83X\83R\83A\82Ì\8eü\95Ó\81C\82 \82È\82½\8e©\90g\82Ì\83X\83R\83A\82Ì
                \91g\82Ý\8d\87\82¹\82ð\91I\82Ô\81
@@ -155,105 +184,94 @@ suppress_alert 
                \82Æ\82¢\82Á\82½\81A\83Q\81[\83\80\83v\83\8c\83C\82â\83\86\81[\83U\81[\83C\83\93\83^\81[\83t\83F\81[\83X\82Ì\83o\81[\83W\83\87\83\93
                \8aÔ\82Ì\88á\82¢\82É\8aÖ\82·\82é\8cx\8d\90\83\81\83b\83Z\81[\83W\82ð\96³\8cø\89»\82·\82é\81D
                (\97á: suppress_alert:3.3.1 \82Æ\82·\82é\82Æ\81A\82±\82Ì\83o\81[\83W\83\87\83\93\88È\91O\82É\89Á\82¦\82ç
-               \82ê\82½\8cx\8d\90\83\81\83b\83Z\81[\83W\82ª\92â\8e~\82³\82ê\82é\81D) [(none)]
-kcode          \92[\96\96\82Ì\8a¿\8e\9a\83R\81[\83h [EUC]
+               \82ê\82½\8cx\8d\90\83\81\83b\83Z\81[\83W\82ª\92â\8e~\82³\82ê\82é\81D)
+whatis_coord  controls whether to include map coordinates when          [n]
+              autodescribe is active for the '/' and ';' commands.
+              Value is the first letter of one of
+              compass      -- (relative to you; 'east' or '3s' or '2n,4w')
+              full compass -- ('east' or '3south' or '2north,4west')
+              map          -- <x,y>        (map column x=0 is not used)
+              screen       -- [row,column] (row is offset to match tty usage)
+              none         -- no coordinates shown.
+whatis_filter controls how to filter eligible map coordinates when      [n]
+              getting a map location for eg. the travel command.
+              Value is the one of
+              n - no filtering
+              v - locations in view only
+              a - locations in same area (room, corridor, etc)
+kcode          \92[\96\96\82Ì\8a¿\8e\9a\83R\81[\83h                                         [EUC]
 
 \83X\83^\81[\83g\8e\9e\82É\82Ì\82Ý\90Ý\92è\82Å\82«\82é\83p\83\89\83\81\81[\83^\82Â\82«\83I\83v\83V\83\87\83\93\82Í:
 
-align      \83Q\81[\83\80\83X\83^\81[\83g\8e\9e\82Ì\91®\90«(align:lawful, align:neutral, align:chaotic
-           \82Ì\82¢\82¸\82ê\82©)\81D\8dÅ\8f\89\82Ì\88ê\95\8e\9a\82ð\8ew\92è\82·\82é\82¾\82¯\82Å\82æ\82¢\81D[RANDOM]
-catname    \96`\8c¯\82ð\8b\9f\82É\82·\82é\8dÅ\8f\89\82Ì\94L\82Ì\96¼\91O [NONE]
-dogname    \96`\8c¯\82ð\8b\9f\82É\82·\82é\8dÅ\8f\89\82Ì\8c¢\82Ì\96¼\91O [NONE]
-dungeon
-           \83_\83\93\83W\83\87\83\93\82ð\95`\89æ\82·\82é\82½\82ß\82É\83f\83t\83H\83\8b\83g\82Ì\91ã\82í\82è\82É\97p\82¢\82é\83V\83\93\83{\83\8b\82Ì\83\8a\83X
-           \83g\81D
-           \83V\83\93\83{\83\8b\82Í\91ò\8eR\82Ì\8f\88\97\9d\82ð\82±\82È\82¹\82é\82æ\82¤\82É\82È\82Á\82Ä\82¢\82é\81C
-           \83R\83\93\83g\83\8d\81[\83\8b\83L\83\83\83\89\83N\83^ ^x\82â\83\81\83^\83L\83\83\83\89\83N\83^ \Mx\82Í\82à\82¿\82ë\82ñ
-           \n\82â \081\82Ì\82æ\82¤\82È C\8c¾\8cê\83\89\83C\83N\82È\83G\83X\83P\81[\83v\82ð\8eg\82¦\82é\81D
-           \95\81\92Ê, \\82Í\8e\9f\82Ì\95\8e\9a\82ð\8b­\90§\93I\82É\95\8e\9a\92Ê\82è\82É\82·\82é\81D\83f\83t\83H\83\8b\83g\82Ì\83V\83\93
-           \83{\83\8b\82Ì\91½\82­\82ª\8fd\95¡\82³\82ê\8eg\97p\82³\82ê\82Ä\82¢\82é\82Ì\82Å\81C\82±\82±\82Å\82Í\82¢\82­\82Â\82©\82Ì\92\8d
-           \88Ó\82Æ\82Æ\82à\82É\83V\83\93\83{\83\8b\82Ì\91ã\82è\82É\96¼\91O\82ð\97^\82¦\82é:
-
-           stone                                   (\8cÅ\82¢\8aâ\81C\95\81\92Ê\82Í ' ' )
-           vwall hwall tlcorn trcorn blcorn brcorn            (\95\94\89®\82Ì\95Ç)
-           crwall tuwall tdwall tlwall trwall   (\82Ü\82ª\82è\82­\82Ë\82Á\82½\96À\98H\82Ì\95Ç)
-           nodoor vodoor hodoor             (\82È\82µ\81C\90\82\92¼\81C\90\85\95½\82Ì\8aJ\82¢\82½\94à)
-           vcdoor hcdoor                          (\90\82\92¼\81C\90\85\95½\82Ì\95Â\82\82½\94à)
-           irocnbars tree room darkcorr litcorr
-           upstair dnstair upladder dnladder
-           altar grave throne sink fountain pool ice lava
-           vodbridge hodbridge                (\90\82\92¼\81C\90\85\95½\82Ì\8aJ\82¢\82½\92µ\82Ë\8b´)
-           vcdbridge hcdbridge                (\90\82\92¼\81C\90\85\95½\82Ì\8d~\82è\82½\92µ\82Ë\8b´)
-           air cloud water
-           default:  \ |--------||.-|++.##<><>_\\#{}.}..##\ #}
-effects
-           dungeon \93¯\97l\82¾\82ª\81C\93Á\8eê\8cø\89Ê\82Ì\95`\89æ\82É\8eg\82í\82ê\82é\82à\82Ì\81D
-           vbeam hbeam lslant rslant                  (\95\81\92Ê\82Í\8fñ\82Ì\83r\81[\83\80)
-           digbeam flashbeam              (\8c\8a\8c@\82è\82Æ\83J\83\81\83\89\82Ì\93Á\8eê\82È\83r\81[\83\80)
-           boomleft boomright                               (\83u\81[\83\81\83\89\83\93)
-           ss1 ss2 ss3 ss4                                  (\96h\8cä\82Ì\89Û\92ö)
-           sw_topl, sw_topm, sw_topr,           (\88ù\82Ý\8d\9e\82Ü\82ê\82½\82Æ\82«\82Ì\8fã\92i)
-           sw_midl, sw_midr,                    (\88ù\82Ý\8d\9e\82Ü\82ê\82½\82Æ\82«\82Ì\92\86\92i)
-           sw_botl, sw_botm, sw_botr            (\88ù\82Ý\8d\9e\82Ü\82ê\82½\82Æ\82«\82Ì\89º\92i)
-           extl extm extr                                   (\94\9a\94­\82Ì\8fã\92i)
-           exml exmm exmr                                   (\94\9a\94­\82Ì\92\86\92i)
-           exbl exbm exbr                                   (\94\9a\94­\82Ì\89º\92i)
-           default:  |-\\/*!)(0#@*/-\\||\\-//-\\|\ |\\-/
-gender     \83Q\81[\83\80\8aJ\8en\8e\9e\82Ì\90«\95Ê(gender:male \82Ü\82½\82Í gender:female)\81D\8dÅ\8f\89\82Ì
-           1 \95\8e\9a\82ð\8ew\92è\82·\82é\82¾\82¯\82Å\82æ\82¢\81Dmale \82â female \83I\83v\83V\83\87\83\93\82à\8eg\97p\82Å\82«
+align      \83Q\81[\83\80\83X\83^\81[\83g\8e\9e\82Ì\91®\90«(lawful, neutral, chaotic, random    [random]
+           \82Ì\82¢\82¸\82ê\82©)\81D
+           \91½\82­\82Ì\90E\8bÆ\82Í\91®\90«\82Ì\91I\91ð\82É\90§\8cÀ\82ð\97^\82¦\82é\81B
+           \8dÅ\8f\89\82Ì\88ê\95\8e\9a\82ð\8ew\92è\82·\82é\82¾\82¯\82Å\82æ\82¢\81D
+catname    \96`\8c¯\82ð\8b\9f\82É\82·\82é\8dÅ\8f\89\82Ì\94L\82Ì\96¼\91O [none]
+dogname    \96`\8c¯\82ð\8b\9f\82É\82·\82é\8dÅ\8f\89\82Ì\8c¢\82Ì\96¼\91O [none]
+           Several roles who start with a dog have one whose name is
+           pre-set (for example, "Hachi" for Samurai), but that name
+           will be overridden if you specify dogname.
+gender     \83Q\81[\83\80\8aJ\8en\8e\9e\82Ì\90«\95Ê(male, female, random)\81D\8dÅ\8f\89\82Ì           [random]
+           1 \95\8e\9a\82ð\8ew\92è\82·\82é\82¾\82¯\82Å\82æ\82¢\81D\8cÃ\82¢ male, female \83I\83v\83V\83\87\83\93\82à\8eg\97p\82Å\82«
            \82é\82ª\81Cgender \83I\83v\83V\83\87\83\93\82ª\97D\90æ\82·\82é\81D
-horsename  \96`\8c¯\82ð\8b\9f\82É\82·\82é\8dÅ\8f\89\82Ì\94n\82Ì\96¼\91[NONE]
+horsename  \96`\8c¯\82ð\8b\9f\82É\82·\82é\8dÅ\8f\89\82Ì\94n\82Ì\96¼\91                              [none]
 menu_*     \83\81\83j\83\85\81[\83R\83}\83\93\83h\82Å\8eg\97p\82·\82é\88ê\95\8e\9a\82Ì\83L\83\83\83\89\83N\83^\81D\88È\89º\82É\82 \82é\82Ì\82Í
-           \91S\82Ä\82Ì\83R\83}\83\93\83h\82Ì\83\81\83j\83\85\81[\82Å\82 \82é\81D\82»\82ê\82¼\82ê\82É\91±\82­( )\93à\95\8e\9a\82Ì\88Ó\96¡
-           \82Í\8e\9f\82Ì\92Ê\82è: 'x' = x11, 't' = tty, 'g' = Gem, 'a' = Amiga.
-           menu_deselect_all  \91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\94ñ\91I\91ð [-](gxta)
-           menu_deselect_page \8c»\8dÝ\95\\8e¦\82³\82ê\82Ä\82¢\82é\83y\81[\83W\82Ì\83A\83C\83e\83\80\82ð\94ñ\91I\91ð [\](gta)
-           menu_first_page    \83\81\83j\83\85\81[\82Ì\8dÅ\8f\89\82Ì\83y\81[\83W\82Ö [^](gta)
-           menu_invert_all    \91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\94½\93] [@](gxta)
-           menu_invert_page   \8c»\8dÝ\95\\8e¦\82³\82ê\82Ä\82¢\82é\83y\81[\83W\82Ì\83A\83C\83e\83\80\82ð\94½\93] [~](gta)
-           menu_last_page     \83\81\83j\83\85\81[\82Ì\8dÅ\8cã\82Ì\83y\81[\83W\82Ö [|](gta)
-           menu_next_page     \8e\9f\82Ì\83\81\83j\83\85\81[\82Ì\83y\81[\83W\82Ö [>](gta)
-           menu_previous_page \91O\82Ì\83\81\83j\83\85\81[\82Ì\83y\81[\83W\82Ö [<](gta)
-           menu_search        \83\81\83j\83\85\81[\82Ì\8c\9f\8dõ [:](gxta)
-           menu_select_all    \91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\91I\91ð [.](gxta)
-           menu_select_page   \8c»\8dÝ\95\\8e¦\82³\82ê\82Ä\82¢\82é\91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\91I\91ð [,](gta)
-monsters
-           dungeon\93¯\97l\81C\89ö\95¨\82Ì\82½\82ß\82Ì\83V\83\93\83{\83\8b\81D
-           \83f\83t\83H\83\8b\83g:  abcdefghijklmnopqrstuvwxyz
-                        ABCDEFGHIJKLMNOPQRSTUVWXYZ@\ \\&;:~]
+           \91S\82Ä\82Ì\83R\83}\83\93\83h\82Ì\83\81\83j\83\85\81[\82Æ\83f\83t\83H\83\8b\83g\82Ì\83L\81[\81D\82»\82ê\82¼\82ê\82É\91±\82­
+           ( )\93à\95\8e\9a\82Ì\88Ó\96¡\82Í\8e\9f\82Ì\92Ê\82è:
+           'x' = x11, 't' = tty, 'g' = Gem, 'a' = Amiga.
+           menu_deselect_all  \91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\94ñ\91I\91ð             [-](xtga)
+           menu_deselect_page \8c»\8dÝ\82Ì\83y\81[\83W\82Ì\83A\83C\83e\83\80\82ð\94ñ\91I\91ð     [\](tga)
+           menu_first_page    \83\81\83j\83\85\81[\82Ì\8dÅ\8f\89\82Ì\83y\81[\83W\82Ö           [^](tga)
+           menu_invert_all    \91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\94½\93]               [@](xtga)
+           menu_invert_page   \8c»\8dÝ\82Ì\83y\81[\83W\82Ì\83A\83C\83e\83\80\82ð\94½\93]       [~](tga)
+           menu_last_page     \83\81\83j\83\85\81[\82Ì\8dÅ\8cã\82Ì\83y\81[\83W\82Ö           [|](tga)
+           menu_next_page     \8e\9f\82Ì\83\81\83j\83\85\81[\82Ì\83y\81[\83W\82Ö             [>](tga)
+           menu_previous_page \91O\82Ì\83\81\83j\83\85\81[\82Ì\83y\81[\83W\82Ö             [<](tga)
+           menu_search        \83\81\83j\83\85\81[\82Ì\8c\9f\8dõ                     [:](xtga)
+           menu_select_all    \91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\91I\91ð               [.](xtga)
+           menu_select_page   \8c»\8dÝ\82Ì\83y\81[\83W\82Ì\91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\91I\91ð [,](tga)
 msghistory \90æ\93ª\8ds\82É\95\\8e¦\82³\82ê\82½\83\81\83b\83Z\81[\83W\97\9a\97ð\82Ì\95Û\91\90\94 [20]
-name       \82 \82È\82½\82Ì\96¼\91O [\83V\83X\83e\83\80\82©\82 \82È\82½\82É\96¼\91O\82ð\90q\82Ë\82Ä\93¾\82ç\82ê\82½\82à\82Ì]
-objects    dungeon\93¯\97l\81C\83I\83u\83W\83F\83N\83g\82Ì\83V\83\93\83{\83\8b
-           \83f\83t\83H\83\8b\83g:  ])[="(%!?+/$*`0_.
-pettype    \82 \82È\82½\82Ì\83L\83\83\83\89\83N\83^\82ª\82Ç\82¿\82ç\82à\8eg\82¦\82é\82È\82ç\81C\82 \82È\82½\82Ì\8dD\82«\82È
-           \83y\83b\83g\82Ì\8eí\97Þ(\94L\82©\8c¢\82©)\81D'none' \82Æ\82·\82é\82Æ\83y\83b\83g\82È\82µ\82É\82È\82é\81D[RANDOM]
+name       \82 \82È\82½\82Ì\96¼\91O       [defaults to username on multi-
+           user systems, asks "who are you?" on single-user systems or if
+           the username is classified as generic like "games"]
+           MS Windows is treated as single-user even though it supports
+           usernames.  If character name is specified on the command
+           line (typically via 'nethack -u myname' depending upon type
+           of system and method of access to it), that name overrides
+           'name' from your options.
+pettype    \82 \82È\82½\82Ì\8dD\82«\82È\83y\83b\83g\82Ì\8eí\97Þ (cat, dog, horse, random,    [random]
+           or none), if your role allows more than one type (or if you
+           want to avoid a starting pet).  Most roles allow dog or cat
+           but not horse.  For roles which force a particular type,
+           pettype is ignored unless it specifies 'none'.
 playmode   \92Ê\8fí(normal)\83v\83\8c\83C\82©\83X\83R\83A\82Ì\8ec\82ç\82È\82¢\92T\8dõ(explore)\83\82\81[\83h\82©\83f\83o\83b\83O
            (debug)\83\82\81[\83h\82© [normal]
-race       \83Q\81[\83\80\8aJ\8en\8e\9e\82Ì\8eí\91° (\97á race:Human, race:Elf) [RANDOM]
-role       \83Q\81[\83\80\8aJ\8en\8e\9e\82Ì\90E\8bÆ (\97á race:Barbarian, role: Valk)
+race       \83Q\81[\83\80\8aJ\8en\8e\9e\82Ì\8eí\91° (\97á race:Human, race:Elf)             [random]
+           \82Ù\82Æ\82ñ\82Ç\82Ì\90E\8bÆ\82Í\8eí\91°\82Ì\91I\91ð\82É\90§\8cÀ\82ð\97^\82¦\82é\81D
+role       \83Q\81[\83\80\8aJ\8en\8e\9e\82Ì\90E\8bÆ (\97á race:Barbarian, role: Valk)       [random]
            \8dÅ\8f\89\82Ì\88ê\95\8e\9a\82ð\8ew\92è\82·\82é\82¾\82¯\82Å\82æ\82¢\82ª\81C\92P\82É\8dÅ\8f\89\82É\83}\83b\83`\82µ\82½
            \90E\8bÆ\82ð\91I\82Ô\82¾\82¯\82Å\82 \82é\81D\8a®\91S\82É\8e¯\95Ê\89Â\94\\82È\95\8e\9a\82ð\8bL\8fq\82·\82é\82±\82Æ
            \82ð\82¨\91E\82ß\82·\82é\81D\96¼\91O\82Ì\8cã\82É\90E\8bÆ\82ð\8ew\92è\82·\82é\82±\82Æ\82à\89Â\94\\82Å\82 \82é\82ª\81C
            (\97á Vic-V)role\83I\83v\83V\83\87\83\93\82ª\97D\90æ\82·\82é\81D
-traps
-           dungeon\93¯\97l\81Cã©\82Ì\82½\82ß\82Ì\83V\83\93\83{\83\8b\81D
-           arrow_trap dart_trap falling_rock_trap squeaky_board
-           bear_trap land_mine rolling_boulder_trap sleeping_gas_trap
-           rust_trap fire_trap pit spiked_pit hole trap_door
-           teleportation_trap level_teleporter magic_portal web statue_trap
-           magic_trap anti_magic_trap polymorph_trap
-           \83f\83t\83H\83\8b\83g:  ^^^^^^^^^^^^^^^^^"^^^^
-windowtype \8eg\97p\82·\82é\83E\83C\83\93\83h\83D\83V\83X\83e\83\80 [\83V\83X\83e\83\80\88Ë\91¶]
+windowtype \8eg\97p\82·\82é\83E\83C\83\93\83h\83D\83V\83X\83e\83\80 [\83V\83X\83e\83\80\82Æ\83R\83\93\83p\83C\83\8b\90Ý\92è\88Ë\91¶]
+           if more than one choice is available.
+           Most instances of the program support only one window-type;
+           when that is the case, you don't need to specify anything.
+           The list of supported window-types in your program can be
+           seen while the program is running by using the #version
+           command or from outside the program by examining the text file
+           named 'options' which is generated when building it.
 
 \83R\83\93\83p\83C\83\8b\8e\9e\82É TTY_GRAPHICS \82ª\90Ý\92è\82³\82ê\82Ä\82¢\82é\82È\82ç\82Î:
-msg_window \8eg\97p\82·\82é\83\81\83b\83Z\81[\83W\83E\83B\83\93\83h\83E\82Ì\8eí\97Þ:
+msg_window \8eg\97p\82·\82é\83\81\83b\83Z\81[\83W\83E\83B\83\93\83h\83E\82Ì\8eí\97Þ:                      [single]
            single      -- \88ê\93x\82É 1 \83\81\83b\83Z\81[\83W\82¸\82Â
            full        -- \95Û\91\82³\82ê\82Ä\82¢\82é\91S\82Ä\82Ì\83\81\83b\83Z\81[\83W\82ð\8d~\82é\83E\83B\83\93\83h\83E\82Å\95\\8e¦
            reverse     -- full \82Æ\93¯\97l\82¾\82ª\81A\90V\82µ\82¢\83\81\83b\83Z\81[\83W\82©\82ç\8f\87\82É\95\\8e¦
            combination -- 1 \83\81\83b\83Z\81[\83W\82ð 2 \89ñ\81A\82»\82Ì\8cã\82Í full
-           default:  single
+           default:  
+
 
 \83I\83v\83V\83\87\83\93\82Ì\97á:
 !autopickup,!tombstone,name:Gandalf,scores:own/3 top/2 around
-female,nonews,dogname:Rover,dungeon: |--------||.-|++.##<><>_\\#{}.}..## #}
-rest_on_space,!verbose,menustyle:traditional
+female,nonews,dogname:Rover,rest_on_space,!verbose,menustyle:traditional
index bf861fa..64603a9 100644 (file)
@@ -1,4 +1,5 @@
-# NetHack 3.6  oracle.des      $NHDT-Date: 1432512784 2015/05/25 00:13:04 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $
+# NetHack 3.6  oracle.des      $NHDT-Date: 1524689580 2018/04/25 20:53:00 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $
+# Copyright (c) 2015 by Pasi Kallinen
 # NetHack may be freely redistributed.  See license for details.
 #
 # Oracle level
index 0650d65..f2adc2a 100644 (file)
@@ -1,4 +1,4 @@
-# NetHack 3.6  quest.txt       $NHDT-Date: 1448540693 2015/11/26 12:24:53 $  $NHDT-Branch: master $:$NHDT-Revision: 1.32 $
+# NetHack 3.6  quest.txt       $NHDT-Date: 1505170340 2017/09/11 22:52:20 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.34 $
 #      Copyright (c) 1991 by M. Stephenson
 # NetHack may be freely redistributed.  See license for details.
 #
 #      QT_FIRSTLOCATE  35
 #      QT_NEXTLOCATE   36
 #
-#      QT_FIRSTACQUIRE 40
-#      QT_NEXTACQUIRE  41
+#      QT_FIRSTGOAL    40      /* %n (nemesis) and %o (artifact) will always
+#                                 be present on first visit in normal play */
+#      QT_NEXTGOAL     41      /* subsequent visits to goal level */
+#      QT_ALTGOAL      42      /* alternate to NEXTGOAL if quest artifact
+#                                 is absent from the level (optional) */
 #
 #      QT_FIRSTNEMESIS 50
 #      QT_NEXTNEMESIS  51
 %Cp Arc 00041
 %o\82Ì\91\8dÝ\82ª\8bó\8bC\82ð\92Ê\82µ\82Ä\82Â\82½\82í\82Á\82Ä\82«\82½\81D
 %E
+# delivered instead of 00041 if %o is not on the level anymore;
+# hero might already be carrying it, so don't say anything like
+# "%o's presence can't be felt"
+%Cp Arc 00042
+%ns\82Ì\82Ë\82®\82ç\82É\8bA\82Á\82Ä\82«\82½\81D
+%E
 %Cc Arc 00050
 \81u\82¯\81I%p\82æ\81C\82¨\91O\82Í%o\82ð\92D\89ñ\82Å\82«\82é\82Æ\8ev\82Á\82Ä\82¢\82é\82¾\82ë\82¤\81C\82¾\82ª
   \82¨\91O\82Ì\8et\82Å\82 \82é%l\82Í\8e¸\94s\82µ\82Ä\82¢\82é\82Ì\82¾\81D
 %E [You are a failure as a healer.]
 %Cc Hea 00019
 \81u\82 \82 \81I%p\82æ\81C\82¨\91O\82Í\82Ü\82¾\82±\82Ì\97l\82È\93ï\82µ\82¢\8ed\8e\96\82ð\82±\82È\82·\82É
-  \82Í\82 \82Ü\82è\82É\82à\96¢\8fn\82¾\81D\88À\90S\82µ\82Ä\82±\82Ì\92T\8dõ\82É\91\97\82è\8fo\82·\91O\82É\82Í\81C\90A\95¨\8aw\81C\8fb\88ã\8aw\81C
-  \98B\8bà\8fp\82Ì\92m\8e¯\82ð\97\98\97p\82Å\82«\82È\82¯\82ê\82Î\82È\82ç\82Ê\81D
+  \82Í\82 \82Ü\82è\82É\82à\96¢\8fn\82¾\81D\88À\90S\82µ\82Ä\82±\82Ì\92T\8dõ\82É\91\97\82è\8fo\82·\91O\82É\82Í\81C\90A\95¨\8aw\81C\98B\8bà\8fp\81C
+  \8fb\88ã\8aw\82Ì\92m\8e¯\82ð\97\98\97p\82Å\82«\82È\82¯\82ê\82Î\82È\82ç\82Ê\81D
 
 \81u%Ra\82Ì\8eÖ\8fñ\82ð\90g\82É\82Â\82¯\82½\82ç\96ß\82Á\82Ä\97\88\82é\82Ì\82¾\81D\81v
 %E [You are too inexperienced.  Return when you are %Ra.]
 %n\82Ì\92n\82Ö\82à\82¤\88ê\93x\96ß\82é\82Æ\82«\82Í\81C%o\82¾\82¯\82ð\8dl\82¦\82Ä
 \82¢\82é\82æ\82¤\82È\8bC\82ª\82µ\82½\81D
 %E
+%Cp Sam 00042
+\8dÄ\82Ñ%n\82Ì\92n\82É\8bA\82Á\82Ä\82«\82½\81D
+%E
 %Cp Sam 00050
 \81u\82¨\82Ü\82¦\82©\81C%p\82æ\81D\90Ø\95 \82·\82é\82Æ\82¢\82¤\8eè\92i\82ª\8ec\82Á\82Ä\82¢\82é\82¼\82æ\81D
   \82¨\91O\82ª\96]\82Þ\82È\82ç\81C\89î\8dö\90l\82É\82È\82ë\82¤\82¼\81D\81v
 \82 \82È\82½\82Í\82à\82¤\8f­\82µ\82µ\82½\82ç%o\82Æ\8b¤\82É\82È\82ê\82é\81C
 \82Æ\82¢\82¤\82±\82Æ\82Å\8e©\90M\82ð\8eæ\82è\96ß\82µ\82½\81D
 %E
+%Cp Tou 00042
+%ns\82Ì\82Ë\82®\82ç\82É\8bA\82Á\82Ä\82«\82½\81D
+%E
 %Cc Tou 00050
 \81u\82Ù\82Ù\82¤\81C%p\81C%l\82Í\82¨\91O\82²\82Æ\82«\82ª\8e\84\82©\82ç
 %o\82ð\8eæ\82è\95Ô\82¹\82é\82Æ\8ev\82Á\82Ä\82¢\82é\82Ì\82©\81I\81v
 %Cp Wiz 00041
 %o\82Ì\83I\81[\83\89\82Ì\82¹\82¢\82Å\81C\82 \82È\82½\82Ì\92m\8ao\82Ì\82Ö\82è\82ª\82Ð\82è\82Ð\82è\82µ\82½\81D
 %E
+%Cp Wiz 00042
+%ns\82Ì\82Ë\82®\82ç\82É\8bA\82Á\82Ä\82«\82½\81D
+%E
 %Cc Wiz 00050
 \81u\82¨\82¨\81C%p\81C\8cN\82©\81D\82Â\82Ü\82è\81C%l\82Í\82í\82½\82µ\82©\82ç%o\82ð
   \93\90\82Ý\8fo\82·\82½\82ß\82É\8cN\82ð\91\97\82è\8d\9e\82ñ\82¾\82Á\82Ä\82í\82¯\82¾\82Ë\81H\82±\82ñ\82È\82¤\82·\82ç\94n\8e­\82ð\82í\82½\82µ\82É
index 4426e12..af6eab8 100644 (file)
@@ -156,6 +156,7 @@ Segmentation fault (core dumped).
 \81w\96³\81x\82ª\93\9a\82¦\82Ì\82Æ\82«\82à\82 \82é\81D\r
 \8ec\94O\82Å\82µ\82½\81D\8d¡\89ñ\90è\82¢\82Í\93ü\82Á\82Ä\82Ü\82¹\82ñ\81I\8e\9f\89ñ\82Ì\83N\83b\83L\81[\82É\8aú\91Ò\82µ\82Ü\82µ\82å\82¤\81D\r
 \90H\97¿\82ð\8dì\82é\8aª\95¨\82Í\82»\82ê\82ª\95K\97v\82É\82È\82é\82Ü\82Å\8eg\82í\82È\82¢\82æ\82¤\82É\82µ\82Ä\82¨\82¯\81D\r
+\96_\82Æ\90Î\82Í\82 \82È\82½\82Ì\8d\9c\82ð\90Ü\82é\82©\82à\82µ\82ê\82È\82¢\82ª\81C\96S\97ì\82Í\8c\88\82µ\82Ä\82 \82È\82½\82ð\8f\9d\82Â\82¯\82È\82¢\81D\r
 \83X\83g\81[\83\80\83u\83\8a\83\93\83K\81[\82ª\8d°\82ð\92D\82¤\82Ì\82Å\82Í\82È\82¢\81D\90l\82ª\8d°\82ð\92D\82¤\82Ì\82¾\81D\r
 \93Ë\91R\81C\96À\8b{\82ª\95ö\82ê\82½\81D\81D\81D\r
 \83\81\83C\83\8b\83f\81[\83\82\83\93\82ð\8eè\82È\82¸\82¯\82é\82±\82Æ\82Í\83V\83X\83e\83\80\83Z\83L\83\85\83\8a\83e\83B\88á\94½\82Å\82 \82é\81D\r
@@ -165,6 +166,7 @@ Segmentation fault (core dumped).
 \96\82\96@\82Ì\8c¾\97t\81u\83C\83\8d\83C\83b\83J\83C\83Y\83c\81v\r
 \8f_\98a\82È\90l\82Í\82 \82È\82½\82Ì\8d\9c\83t\83@\83C\83\8b\82ð\8eó\82¯\8cp\82®\82Å\82 \82ë\82¤\81D\r
 \92Y\8dB\82Í\88Ã\82­\90[\82¢\81D\8e\84\82Í\81C\90Q\82é\91O\82É\8ds\82¯\82é\83\8c\83x\83\8b\82É\82µ\82Ä\82¢\82é\81D\r
+E\82Ì\8e\9a\82Í\8eg\82¦\82Î\8eg\82¤\82Ù\82Ç\97Ç\82­\82È\82é\81D\r
 \83_\83C\83i\83}\83C\83g\82ð\96À\8b{\82Å\8eg\82¤\82Ì\82Í\8aë\8c¯\82¾\81D\r
 \82t\82m\82h\82w\83o\81[\83W\83\87\83\93\82É\82Í\83\8f\81[\83\80\82Í\82¢\82È\82¢\81D\r
 \82±\82Ì\8aK\82É\82Íã©\82ª\82 \82é\82¼\81I\r
index d320a6c..364317b 100644 (file)
@@ -19,7 +19,7 @@
 \8c\8e\82Ì\96\9e\82¿\8c\87\82¯\82É\82Í\8bC\82ð\82Â\82¯\82ë\81I\r
 \8fd\97v\82È\83\81\83b\83Z\81[\83W\82ð\8d\8f\82Þ\91O\82É\82Í\82¢\82Â\82à\8f°\82ð\91|\8f\9c\82µ\82ë\81D\r
 \83C\83F\83\93\83_\81[\82Ì\96\82\8f\9c\82¯\82ð\8dì\82è\8fo\82·\82±\82Æ\82Í\8d¢\93ï\82¾\81D\82½\82Æ\82¦\8aè\82¢\82Ì\8fñ\82ð\82à\82Á\82Ä\82µ\82Ä\82à\81D\r
-\83G\83\8b\83t\82Ì\83N\83\8d\81[\83N\82Í\96\82\96@\82É\91Î\82µ\82Ä\90g\82ð\8eç\82Á\82Ä\82­\82ê\82é\81D\r
+\83G\83\8b\83t\82Ì\83N\83\8d\81[\83N\82Í\96\82\96@\82É\91Î\82µ\82Ä\97L\8cø\82¾\81D\r
 \83A\83\93\83o\81[\83n\83\8b\83N\82Í\8d¬\97\90\82³\82¹\82é\8e\8b\90ü\82ð\8e\9d\82Á\82Ä\82¢\82é\81D\r
 \83N\83\8d\83\80\82ª\89ä\82ª\8fØ\90l\82Å\82 \82é\82©\82¬\82è\81C\8e\84\82Í\93ñ\93x\82Æ\8bQ\82¦\82é\82±\82Æ\82Í\82È\82¢\81I\r
 \89ö\95¨\82É\82Â\82¢\82Ä\90q\82Ë\82é\82±\82Æ\82Í\81C\94ñ\8fí\82É\97L\89v\82È\82±\82Æ\82¾\82ë\82¤\81D\r
index 02e49a3..903a736 100644 (file)
@@ -1,3 +1,7 @@
+# NetHack 3.6  symbols       $NHDT-Date: 1524689580 2018/04/25 20:53:00 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $
+# Copyright (c) 2006 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
+#
 # Symbol sets for use in NetHack's text-based display.
 #
 # IBMgraphics works by specifying special characters which reside
@@ -194,20 +198,6 @@ start: RogueEpyx
        Restrictions: rogue
        Handling: IBM
        Color: Yes
-       S_weapon: \x18                  # up arrow
-       S_armor: \x0a                   # Vert rect with o
-       S_ring: \x09                    # circle with arrow
-       S_amulet: \x0c                  # "female" symbol
-       S_food: \x05                    # club (as in cards)                    
-       S_potion: \xad                  # upside down '!'
-       S_scroll: \x0e                  # musical note
-       S_wand: \xe7                    # greek tau
-       S_coin: \x0f                    # yes it's the same as gems
-       S_gem: \x0f                     # fancy '*'
-       S_rock: \x60
-       S_ball: \x30
-       S_chain: \x5f
-       S_venom: \x2e
        S_vwall: \xba                   # all walls now use
        S_hwall: \xcd                   # double line graphics
        S_tlcorn: \xc9 
@@ -249,18 +239,24 @@ start: RogueEpyx
        S_magic_trap: \x04 
        S_anti_magic_trap: \x04 
        S_polymorph_trap: \x04 
-       S_weapon: \x18
-       S_armor: \x5b
-       S_ring: \x3d
-       S_amulet: \xc
-       S_tool: \x28
-       S_food: \x5
-       S_potion: \xad
-       S_scroll: \xe
-       S_book: \x2b
-       S_wand: \xe7
-       S_coin: \xf
-       S_gem: \xf
+       S_weapon: \x18                  # up arrow
+# ^J   S_armor: \x0a                   # Vert rect with o
+       S_armor: \x5b                   # default: '['
+# ^I   S_ring: \x09                    # circle with arrow
+       S_ring: \x3d                    # default: '='
+       S_amulet: \x0c                  # "female" symbol
+       S_tool: \x28                    # default: '('
+       S_food: \x05                    # club (as in cards)
+       S_potion: \xad                  # upside down '!'
+       S_scroll: \x0e                  # musical note
+       S_book: \x2b                    # default: '+'
+       S_wand: \xe7                    # greek tau
+       S_coin: \x0f                    # yes it's the same as gems
+       S_gem: \x0f                     # fancy '*'
+       S_rock: \x60
+       S_ball: \x30
+       S_chain: \x5f
+       S_venom: \x2e
        S_rock: \x60
        S_ball: \x30
        S_chain: \x5f
@@ -394,5 +390,197 @@ start: NHAccess
        S_explode9: \047
 finish
 
+# All symbols are spaces
+start: Blank
+       Description: Completely blank symbols
+        S_air: \032
+        S_altar: \032
+        S_amulet: \032
+        S_angel: \032
+        S_ant: \032
+        S_anti_magic_trap: \032
+        S_armor: \032
+        S_armour: \032
+        S_arrow_trap: \032
+        S_ball: \032
+        S_bars: \032
+        S_bat: \032
+        S_bear_trap: \032
+        S_blcorn: \032
+        S_blob: \032
+        S_book: \032
+        S_boomleft: \032
+        S_boomright: \032
+        S_boulder: \032
+        S_brcorn: \032
+        S_centaur: \032
+        S_chain: \032
+        S_cloud: \032
+        S_cockatrice: \032
+        S_coin: \032
+        S_corr: \032
+        S_crwall: \032
+        S_darkroom: \032
+        S_dart_trap: \032
+        S_demon: \032
+        S_digbeam: \032
+        S_dnladder: \032
+        S_dnstair: \032
+        S_dog: \032
+        S_dragon: \032
+        S_eel: \032
+        S_elemental: \032
+        S_explode1: \032
+        S_explode2: \032
+        S_explode3: \032
+        S_explode4: \032
+        S_explode5: \032
+        S_explode6: \032
+        S_explode7: \032
+        S_explode8: \032
+        S_explode9: \032
+        S_eye: \032
+        S_falling_rock_trap: \032
+        S_feline: \032
+        S_fire_trap: \032
+        S_flashbeam: \032
+        S_food: \032
+        S_fountain: \032
+        S_fungus: \032
+        S_gem: \032
+        S_ghost: \032
+        S_giant: \032
+        S_gnome: \032
+        S_golem: \032
+        S_grave: \032
+        S_gremlin: \032
+        S_hbeam: \032
+        S_hcdbridge: \032
+        S_hcdoor: \032
+        S_hodbridge: \032
+        S_hodoor: \032
+        S_hole: \032
+        S_human: \032
+        S_humanoid: \032
+        S_hwall: \032
+        S_ice: \032
+        S_imp: \032
+        S_invisible: \032
+        S_jabberwock: \032
+        S_jelly: \032
+        S_kobold: \032
+        S_kop: \032
+        S_land_mine: \032
+        S_lava: \032
+        S_leprechaun: \032
+        S_level_teleporter: \032
+        S_lich: \032
+        S_light: \032
+        S_litcorr: \032
+        S_lizard: \032
+        S_lslant: \032
+        S_magic_portal: \032
+        S_magic_trap: \032
+        S_mimic: \032
+        S_mimic_def: \032
+        S_mummy: \032
+        S_naga: \032
+        S_ndoor: \032
+        S_nymph: \032
+        S_ogre: \032
+        S_orc: \032
+        S_piercer: \032
+        S_pit: \032
+        S_poisoncloud: \032
+        S_polymorph_trap: \032
+        S_pool: \032
+        S_potion: \032
+        S_pudding: \032
+        S_quadruped: \032
+        S_quantmech: \032
+        S_ring: \032
+        S_rock: \032
+        S_rodent: \032
+        S_rolling_boulder_trap: \032
+        S_room: \032
+        S_rslant: \032
+        S_rust_trap: \032
+        S_rustmonst: \032
+        S_scroll: \032
+        S_sink: \032
+        S_sleeping_gas_trap: \032
+        S_snake: \032
+        S_spider: \032
+        S_spiked_pit: \032
+        S_squeaky_board: \032
+        S_ss1: \032
+        S_ss2: \032
+        S_ss3: \032
+        S_ss4: \032
+        S_statue_trap: \032
+        S_stone: \032
+        S_strange_obj: \032
+        S_sw_bc: \032
+        S_sw_bl: \032
+        S_sw_br: \032
+        S_sw_ml: \032
+        S_sw_mr: \032
+        S_sw_tc: \032
+        S_sw_tl: \032
+        S_sw_tr: \032
+        S_tdwall: \032
+        S_teleportation_trap: \032
+        S_throne: \032
+        S_tlcorn: \032
+        S_tlwall: \032
+        S_tool: \032
+        S_trap_door: \032
+        S_trapper: \032
+        S_trcorn: \032
+        S_tree: \032
+        S_troll: \032
+        S_trwall: \032
+        S_tuwall: \032
+        S_umber: \032
+        S_unicorn: \032
+        S_upladder: \032
+        S_upstair: \032
+        S_vampire: \032
+        S_vbeam: \032
+        S_vcdbridge: \032
+        S_vcdoor: \032
+        S_venom: \032
+        S_vibrating_square: \032
+        S_vodbridge: \032
+        S_vodoor: \032
+        S_vortex: \032
+        S_vwall: \032
+        S_wand: \032
+        S_water: \032
+        S_weapon: \032
+        S_web: \032
+        S_worm: \032
+        S_worm_tail: \032
+        S_wraith: \032
+        S_xan: \032
+        S_xorn: \032
+        S_yeti: \032
+        S_zombie: \032
+        S_zruty: \032
+finish
+
+start: plain
+       Description: Same as Default symbols, except '+' for corner walls
+       S_tlcorn: '+'
+       S_trcorn: '+'
+       S_blcorn: '+'
+       S_brcorn: '+'
+       S_crwall: '+'
+       S_tuwall: '+'
+       S_tdwall: '+'
+       S_tlwall: '+'
+       S_trwall: '+'
+finish #plain -- other symbols implicitly retain their default values
+
 start: default
 finish
index 4664c63..46777f2 100644 (file)
@@ -1,4 +1,7 @@
-# NetHack 3.6.0 tribute to:
+# NetHack 3.6  tribute       $NHDT-Date: 1524689580 2018/04/25 20:53:00 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.82 $
+# Copyright (c) 2017 by Robert Patrick Rankin
+# NetHack may be freely redistributed.  See license for details.
+# A tribute introduced in NetHack 3.6.0 to:
 #
 #         Sir Terence David John "Terry" Pratchett
 #              April 28, 1948 - March 12, 2015
 #
 #
 #
-%title The Colour of Magic  (2)
+%title The Colour of Magic  (14)
+# p. 67 (Signet edition; 'Morpork':  initially Ankh and Morpork were twin
+#        cities with distinct characteristics on opposite sides of the Ankh
+#        river--they were eventually consolidated into Ankh-Morpork without
+#        regard to which area was where)
 %passage 1
-It has been remarked before that those who are sensitive to radiation in
-the far octarine - the eighth colour, the pigment of the Imagination - can
+It has been remarked before that those who are sensitive to radiations in
+the far octarine--the eighth colour, the pigment of the Imagination--can
 see things that others cannot.
 
 Thus it was that Rincewind, hurrying through the crowded, flare-lit,
-evening bazarrs of Morpork with the Luggage trundling behind him, jostled a
-tall figure, turned to deliver a few suitable curses, and beheld Death.
+evening bazaars of Morpork with the Luggage trundling behind him, jostled
+a tall dark figure, turned to deliver a few suitable curses, and beheld
+Death.
 
-It had to be Death.  No-one else went around with empty eye sockets and, of
-course, the scythe over one shoulder was another clue.
+It had to be Death.  No-one else went around with empty eye sockets and,
+of course, the scythe over one shoulder was another clue.  [...]
 
   [The Colour of Magic, by Terry Pratchett]
 %e passage 1
+# p. 116
 %passage 2
 As he was drawn towards the Eye the terror-struck Rincewind raised the box
-protectively, and at the same time heard the picture imp say, 'They're
-about ripe now, can't hold them any longer.  Every-one smile, please.'
+protectively, and at the same time heard the picture imp say, "They're
+about ripe now, can't hold them any longer.  Everyone smile, please."
 
-There was a -
-- flash of light so white and so bright - 
-- it didn't seem like light at all.
+There was a--
+--flash of light so white and so bright--
+--it didn't seem like light at all.
 
 Bel-Shamharoth screamed, a sound that started in the far ultrasonic and
 finished somewhere in Rincewind's bowels.  The tentacles went momentarily
-as stiff as rods, hurling their various cargos around the room, before
+as stiff as rods, hurling their various cargoes around the room, before
 bunching up protectively in front of the abused Eye.  The whole mass
 dropped into the pit and a moment later the big slab was snatched up by
 several dozen tentacles and slammed into place, leaving a number of
@@ -43,298 +52,2876 @@ thrashing limbs trapped around the edge.
 
   [The Colour of Magic, by Terry Pratchett]
 %e passage 2
+# p. 8 (passage starts mid-paragraph)
+%passage 3
+[...]  In the meantime, they could only speculate about the revealed
+cosmos.
+
+There was, for example, the theory that A'Tuin had come from nowhere and
+would continue at a uniform crawl, or steady gait, into nowhere, for all
+time.  This theory was popular among academics.
+
+An alternative, favoured by those of a religious persuasion, was that
+A'Tuin was crawling from the Birthplace to the Time of Mating, as were
+all the stars in the sky which were, obviously, also carried by giant
+turtles.  When they arrived they would briefly and passionately mate, for
+the first and only time, and from that fiery union new turtles would be
+born to carry a new pattern of worlds.  This was known as the Big Bang
+hypothesis.
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# p. 13 (end of a long footnote; the initial obsession with 'eight' ended
+#        fairly quickly within the Discworld series)
+%passage 4
+[...]
+
+There are, of course, eight days in a disc week and eight colours in its
+light spectrum.  Eight is a number of some considerable occult
+significance on the disc and must never, ever, be spoken by a wizard.
+
+Precisely why all the above should be so is not clear, but goes some way
+to explain why, on the disc, the Gods are not so much worshipped as blamed.
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# p. 38 (first speaker is Rincewind, second is a pre-Vetinari Patrician)
+%passage 5
+"I assure you the thought never even crossed my mind, lord."
+
+"Indeed?  Then if I were you I'd sue my face for slander."
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# p. 41 (title of 5th book is "Sourcery" but it's spelled "sorcery" here;
+#        'organising': British spelling)
+%passage 6
+All the heroes of the Circle Sea passed through the gates of Ankh-Morpork
+sooner or later.  Most of them were from the barbaric tribes nearer the
+frozen Hub, which had a sort of export trade in heroes.  Almost all of
+them had crude magic swords, whose unsuppressed harmonics on the astral
+plane played hell with any delicate experiments in applied sorcery for
+miles around, but Rincewind didn't object to them on that score.  He knew
+himself to be a magical dropout, so it didn't bother him that the mere
+appearance of a hero at the city gates was enough to cause retorts to
+explode and demons to materialize all through the Magical Quarter.  No,
+what he didn't like about heroes was that they were usually suicidally
+gloomy when sober and homicidally insane when drunk.  There were too many
+of them, too.  Some of the most notable questing grounds were a veritable
+hubbub in the season.  There was talk of organising a rota.
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# pp. 82-83 (passage starts mid-paragraph;
+#            pronouns for deities are not capitalized;
+#            Bravd and the Weasel, obviously a parody of Fritz Leiber's
+#            Fafhrd and the Gray Mouser, appear at the beginning of the 1st
+#            of 4 stories and then are left behind, never to be seen again;
+#            "wenegrade wiffard" is Rincewind and "fome fort of clerk" is
+#            Twoflower the tourist; the seemingly abrupt end of the passage
+#            is the end of the 2nd of the 4 stories that make up the book;
+#            'centre': British spelling; 'billion': British usage gives it a
+#            value of 'million millions', equivalent to American 'trillion';
+#            the second paragraph of this passage is the data.base quote
+#            for "blind io" and the second half of the passage is the
+#            data.base quote for "*lady" and "offler")
+%passage 7
+[...]  The disc gods themselves, despite the splendor of the world below
+them, are seldom satisfied.  It is embarrassing to know that one is a god
+of a world that only exists because every improbability curve must have
+its far end; especially when one can peer into other dimensions at worlds
+whose Creators had more mechanical aptitude than imagination.  No wonder,
+then, that the disc gods spend more time bickering than in omnicognizance.
+
+On this particular day Blind Io, by dint of constant vigilance the chief
+of the gods, sat with his chin on his hand and looked at the gaming board
+on the red marble table in front of him.  Blind Io had got his name
+because, where his eye sockets should have been, there were nothing but
+two areas of blank skin.  His eyes, of which he had an impressively large
+number, led a semi-independent life of their own.  Several were currently
+hovering above the table.
+
+The gaming board was a carefully-carved map of the disc world, overprinted
+with squares.  A number of beautifully modelled playing pieces were now
+occupying some of the squares.  A human onlooker would, for example, have
+recognized in two of them the likenesses of Bravd and the Weasel.  Others
+represented yet more heroes and champions, of which the disc had a more
+than adequate supply.
+
+Still in the game were Io, Offler the Crocodile God, Zephyrus the god of
+slight breezes, Fate, and the Lady.  There was an air of concentration
+around the board now that the lesser players had been removed from the
+Game.  Chance had been an early casualty, running her hero into a full
+house of armed gnolls (the result of a lucky throw by Offler) and shortly
+afterwards Night had cashed his chips, pleading an appointment with
+Destiny.  Several minor deities had drifted up and were kibitzing over
+the shoulders of the players.
+
+Side bets were made that the Lady would be the next to leave the board.
+Her last champion of any standing was now a pinch of potash in the ruins
+of still-smoking Ankh-Morpork, and there were hardly any pieces that she
+could promote to first rank.
+
+Blind Io took up the dice-box, which was a skull whose various orifices
+had been stoppered with rubies, and with several of his eyes on the Lady
+he rolled three fives.
+
+She smiled.  This was the nature of the Lady's eyes:  they were bright
+green, lacking iris or pupil, and they glowed from within.
+
+The room was silent as she scrabbled in her box of pieces and, from the
+very bottom, produced a couple that she set down on the board with two
+decisive clicks.  The rest of the players, as one God, craned forward to
+peer at them.
+
+"A wenegrade wiffard and fome fort of clerk," said Offler the Crocodile
+God, hindered as usual by his tusks.  "Well, weally!"  With one claw he
+pushed a pile of bone-white tokens into the centre of the table.
+
+The Lady nodded slightly.  She picked up the dice-cup and held it as steady
+as a rock, yet all the gods could hear the three cubes rattling about
+inside.  And then she sent them bouncing across the table.
+
+A six.  A three.  A five.
+
+Something was happening to the five, however.  Battered by the chance
+collision of several billion molecules, the die flipped onto a point, spun
+gently and came down a seven.
+
+Blind Io picked up the cube and counted the sides.
+
+"Come /on/," he said wearily.  "Play fair."
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# p. 84 (Ankh-Morpork was burned soon after Twoflower introduced the concept
+#        of fire insurance; a longer version of this passage is the data.base
+#        quote for "tourist")
+%passage 8
+Picturesque.  That was a new word to Rincewind the wizard (B. Mgc.,
+Unseen University [failed]).  It was one of a number he had picked up
+since leaving the charred ruins of Ankh-Morpork.  Quaint was another one.
+Picturesque meant--he decided after careful observation of the scenery
+that inspired Twoflower to use the word--that the landscape was horribly
+precipitous.  Quaint, when used to describe the occasional village through
+which they passed, meant fever-ridden and tumbledown.
+
+Twoflower was a tourist, the first ever seen on the discworld.  Tourist,
+Rincewind decided, meant "idiot."
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# p. 85 ('memorising': British spelling)
+%passage 9
+Currently Twoflower was showing a great interest in the theory and practice
+of magic.
+
+"It all seems, well, rather useless to me," he said.  "I always thought
+that, you know, a wizard just said the words and that was that.  Not all
+this tedious memorising."
+
+Rincewind agreed moodily.  He tried to explain that magic had indeed once
+been wild and lawless, but had been tamed back in the mists of time by the
+Olden Ones, who had bound it to obey among other things the Law of
+Conservation of Reality; this demanded that the effort needed to achieve
+a goal should be the same regardless of the means used.  In practical
+terms, this meant that, say, creating the illusion of a glass of wine was
+relatively easy, since it involved merely the subtle shifting of light
+patterns.  On the other hand, lifting a genuine wineglass a few feet in
+the air by sheer mental energy required several hours of systematic
+preparation if the wizard wished to prevent the simple principle of
+leverage flicking his brain out through his ears.
+
+He went on to add that some of the ancient magic could still be found in
+its raw state, recognizable--to the initiated--by the eightfold shape it
+made in the crystalline structure of space-time.  There was the metal
+octiron, for example, and the gas octogen.  Both radiated dangerous
+amounts of raw enchantment.
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# p. 166 ('Lio!rt' with embedded exclamation point is correct; book's text
+#         is missing the opening quote before ["]You arrogant barbarian--")
+%passage 10
+"I challenge you," said Hrun, glaring at the brothers, "both at once."
+
+Lio!rt and Liartes exchanged looks.
+
+"You'll fight us both together?" said Liartes, a tall, wiry man with long
+black hair.
+
+"Yah."
+
+"That's pretty uneven odds, isn't it?"
+
+"Yah.  I outnumber you one to two."
+
+Lio!rt scowled.  "You arrogant barbarian--"
+
+"That just about does it!" growled Hrun.  "I'll--"
+
+The Loremaster put out a blue-veined hand to restrain him.
+
+"It is forbidden to fight on the Killing Ground," he said, and paused
+while he considered the sense of this.  "You know what I mean, anyway," he
+hazarded, giving up, and added, "As the challenged parties my lords Lio!rt
+and Liartes have choice of weapons."
+
+"Dragons," they said together.  Liessa snorted.
+
+"Dragons can be used offensively, therefore they are weapons," said Lio!rt
+firmly.  "If you disagree we can fight over it."
+
+"Yah," said his brother, nodding at Hrun.
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# p. 196
+%passage 11
+Some pirates achieved immortality by great deeds of cruelty or derring-do.
+Some achieved immortality by amassing great wealth.  But the captain had
+long ago decided that he would, on the whole, prefer to achieve immortality
+by not dying.
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# p. 201 (entire paragraph is enclosed within parentheses)
+%passage 12
+Plants on the disc, while including the categories known commonly as
+/annuals/, which were sown this year to come up later this year,
+/biennials/, sown this year to grow next year, and /perennials/, sown this
+year to grow until further notice, also included a few rare /re-annuals/
+which, because of an unusual four-dimensional twist in their genes, could
+be planted this year to come up /last year/.  The /vul/ nut vine was
+particularly exceptional in that it could flourish as many as eight years
+prior to its seed actually being sown.  /Vul/ nut wine was reputed to give
+certain drinkers an insight into the future which was, from the nut's
+point of view, the past.  Strange but true.
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# p. 217 (Rincewind and Twoflower are slated to become ritual sacrifices)
+%passage 13
+"I hope you're not proposing to enslave us," said Twoflower.
+
+Marchesa looked genuinely shocked.  "Certainly not!  Whatever could
+have given you that idea?  Your lives in Krull will be rich, full and
+comfortable--"
+
+"Oh, good," said Rincewind.
+
+"--just not very long."
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
+# pp. 228-229 (passage starts mid-paragraph)
+%passage 14
+[...]  She was the Goddess Who Must Not Be Named; those who sought her
+never found her, yet she was known to come to the aid of those in greatest
+need.  And, then again, sometimes she didn't.  She was like that.  She
+didn't like the clicking of rosaries, but was attracted to the sound of
+dice.  No man knew what She looked like, although there were many times
+when a man who was gambling his life on the turn of the cards would pick
+up the hand he had been dealt and stare Her full in the face.  Of course,
+sometimes he didn't.  Among all the gods she was at one and the same time
+the most courted and the most cursed.
+
+  [The Colour of Magic, by Terry Pratchett]
+%e passage
 %e title
 #
 #
 #
-%title The Light Fantastic (2)
+%title The Light Fantastic (12)
+# p. 92 (Signet edition)
 %passage 1
-'Cohen is my name, boy' Belthan's hands stopped moving.
-'Cohen?' she said, 'Cohen the Barbarian?'
+'Cohen ish my name, boy.'  Bethan's hands stopped moving.
+
+'Cohen?' she said.  'Cohen the Barbarian?'
+
 'The very shame.'
-'Hang on, hang on,' said Rincewind, 'Cohen's a great big chap, neck like a
+
+'Hang on, hang on,' said Rincewind.  'Cohen's a great big chap, neck like a
 bull, got chest muscles like a sack of footballs.  I mean, he's the Disc's
 greatest warrior, a legend in his own lifetime.  I remember my grandad
-telling me he saw him ... my grandad telling me he ... my grandad ...'
-He faltered under the gimlit gaze.
-'Oh,' he said, 'Oh. Of course, Sorry.'
-'Yesh,' said Cohen, and sighed, 'Thatsh right boy, I'm a lifetime in my own
-legend.'
+telling me he saw him... my grandad telling me he... my grandad...'
+
+He faltered under the gimlet gaze.
+
+'Oh,' he said.  'Oh.  Of course.  Sorry.'
+
+'Yesh,' said Cohen, and sighed.  'That's right boy.  I'm a lifetime in my
+own legend.'
 
   [The Light Fantastic, by Terry Pratchett]
 %e passage 1
+# p. 113 (Twoflower is teaching the Riders how to play bridge;
+#         in /The Light Fantastic/, Death's dialog uses quotation marks
+#         and full uppercase rather than the small capital letters used in
+#         the other books)
 %passage 2
-Death sat at one side of a black baize table in the entre of the room,
+Death sat at one side of a black baize table in the centre of the room,
 arguing with Famine, War and Pestilence.  Twoflower was the only one to
 look up and notice Rincewind.
+
 'Hey, how did you get here?' he said.
-'Well, some say that the creator took a handful - oh, I see, well, it's
-hard to explain but I -'
+
+'Well, some say that the creator took a handful--oh, I see, well, it's
+hard to explain but I--'
+
 'Have you got the Luggage?'
+
 The wooden box pushed past Rincewind and settled down in front of its
 owner, who opened its lid and rummaged around inside until he came up with
 a small, leatherbound book which he handed to War, who was hammering the
 table with a mailed fist.
-'It's "Nosehinger on the Laws of Contract",' he said. 'It's quite good,
-there's a lot in it about double finessing and how to -'
-Death snatched the book with a bony hand and flipped through the pages, 
+
+'It's "Nosehinger on the Laws of Contract",' he said.  'It's quite good,
+there's a lot in it about double finessing and how to--'
+
+Death snatched the book with a bony hand and flipped through the pages,
 quite oblivious to the presence of the two men.
-'RIGHT,' he said, 'PESTILENCE, OPEN ANOTHER PACK OF CARDS. I'M GOING TO GET
-TO THE BOTTOM OF THIS IF IT KILLS ME. FIGURATIVELY SPEAKING OF COURSE.'
+
+'RIGHT,' he said, 'PESTILENCE, OPEN ANOTHER PACK OF CARDS.  I'M GOING TO
+GET TO THE BOTTOM OF THIS IF IT KILLS ME.  FIGURATIVELY SPEAKING OF COURSE.'
 
   [The Light Fantastic, by Terry Pratchett]
 %e passage 2
+# p. 7 (passage starts mid-sentence; the too-long-to-answer question is
+#       "Why have Rincewind and Twoflower fallen off the Disc's rim?",
+#       alluding to the conclusion of /The Colour of Magic/;
+#       in /Sourcery/ and /Interesting Times/ and probably others, the
+#       famous philosopher's name is spelled "Ly Tin Wheedle")
+%passage 3
+[...] such questions take time and could be more trouble than they are
+worth.  For example, it is said that someone at a party once asked the
+famous philosopher Ly Tin Weedle "Why are you here?" and the reply took
+three years.
+
+  [The Light Fantastic, by Terry Pratchett]
+%e passage
+# p. 8 ('libraries': plural is accurate)
+%passage 4
+The only furnishing in the room was a lectern of dark wood, carved into the
+shape of a bird--well, to be frank, into the shape of a winged thing it is
+probably best not to examine too closely--and on the lectern, fastened to
+it by a heavy chain covered in padlocks, was a book.
+
+A large, but not particularly impressive, book.  Other books in the
+University's libraries had covers inlaid with rare jewels and fascinating
+wood, or bound with dragon skin.  This one was just a rather tatty leather.
+It looked the sort of book described in library catalogues as "slightly
+foxed," although it would be more honest to admit that it looked as though
+it had been badgered, wolved and possibly beared as well.
+
+  [The Light Fantastic, by Terry Pratchett]
+%e passage
+# pp. 41-42
+%passage 5
+The barbarian chieftain said:  "What then are the greatest things that a
+man may find in life?"  This is the sort of thing you're supposed to say to
+maintain steppecred in barbarian circles.
+
+The man on his right thoughtfully drank his cocktail of mare's milk and
+snowcat blood, and spoke thus:  "The crisp horizon of the steppe, the wind
+in your hair, a fresh horse under you."
+
+The man on his left said:  "The cry of the white eagle in the heights, the
+fall of snow in the forest, a true arrow in your bow."
+
+The chieftain nodded and said:  "Surely it is the sight of your enemy
+slain, the humiliation of his tribe and the lamentation of his women."
+
+There was a general murmur of whiskery approval at this outrageous display.
+
+Then the chieftain turned respectfully to his guest, a small figure
+carefully warming his chilblains by the fire, and said:  "But our guest,
+whose name is legend, must tell us truly:  what is it that a man may call
+the greatest things in life?"
+
+The guest paused in the middle of another unsuccessful attempt to light up.
+
+"What shay?" he said, toothlessly.
+
+"I said:  what is it that a man may call the greatest things in life?"
+
+The warriors leaned closer.  This should be worth hearing.
+
+The guest thought long and hard and then said, with deliberation:  "Hot
+water, good dentishtry and shoft lavatory paper."
+
+  [The Light Fantastic, by Terry Pratchett]
+%e passage
+# p. 48 (Hanzel and Gretel, obviously...)
+%passage 6
+"Have a bit more table," said Rincewind.
+
+"No thanks, I don't like marzipan," said Twoflower.  "Anyway, I'm sure it's
+not right to eat other people's furniture."
+
+"Don't worry," said Swires.  "The old witch hasn't been seen for years.
+They say she was done up good and proper by a couple of young tearaways."
+
+"Kids of today," said Rincewind.
+
+"I blame the parents," said Twoflower.
+
+  [The Light Fantastic, by Terry Pratchett]
+%e passage
+# p. 103
+%passage 7
+It is a well known fact that warriors and wizards do not get along, because
+one side considers the other side to be a collection of bloodthirsty idiots
+who can't walk and think at the same time, while the other side is naturally
+suspicious of a body of men who mumble a lot and wear long dresses.  Oh, say
+the wizards, if we're going to be like that, then, what about all those
+studded collars and oiled muscles down at the Young Men's Pagan Association?
+To which the heroes reply, that's a pretty good allegation coming from a
+bunch of wimpsoes who won't go near a woman on account, can you believe it,
+of their mystical power being sort of drained out.  Right, say the wizards,
+that just about does it, you and your leather posing pouches.  Oh yeah, say
+the heroes, why don't you...
+
+And so on.  This sort of thing has been going on for centuries, and caused
+a number of major battles which have left large tracts of land uninhabitable
+because of magical harmonics.
+
+  [The Light Fantastic, by Terry Pratchett]
+%e passage
+# p. 128
+%passage 8
+"He'sh mad?"
+
+"Sort of mad.  But mad with lots of money."
+
+"Ah, then he can't be mad.  I've been around; if a man hash lotsh of money
+he'sh just ecshentric."
+
+  [The Light Fantastic, by Terry Pratchett]
+%e passage
+# p. 182 (Cohen is now wearing dentures with teeth made from diamonds)
+%passage 9
+Cohen tapped him on the shoulder.  The man looked around irritably.
+
+"What do you want, grandad?" he snarled.
+
+Cohen paused until he had the man's full attention, and then he smiled.  It
+was a slow, lazy smile, unveiling about 300 carats of mouth jewelry that
+seemed to light up the room.
+
+"I will count to three," he said, in a friendly tone of voice.  "One, Two."
+His bony knee came up in the man's groin with a satisfyingly meaty noise,
+and he half-turned to bring the full force of an elbow into the kidneys as
+the leader collapsed around his private universe of pain.
+
+"Three," to told the ball of agony on the floor.  Cohen had heard of
+fighting fair, and had long ago decided he wanted no part of it.
+
+  [The Light Fantastic, by Terry Pratchett]
+%e passage
+# pp. 193-194 (this passage is the data.base quote for shopkeeper)
+%passage 10
+There have been three general theories put forward to explain the
+phenomenon of the wandering shops, or as they are generically known,
+/tabernae vagantes/.
+
+The first postulates that many thousands of years ago there evolved
+somewhere in the multiverse a race whose single talent was to buy cheap
+and sell dear.  Soon they controlled a vast galactic empire or, as they put
+it, Emporium, and the more advanced members of the species found a way to
+equip their very shops with unique propulsion units that could break the
+dark walls of space itself and open up vast new markets.  And long after
+the worlds of the Emporium perished in the heat death of their particular
+universe, after one last defiant fire sale, the wandering starshops still
+ply their trade, eating their way through the pages of space-time like a
+worm through a three-volume novel.
+
+The second is that they are the creation of a sympathetic Fate, charged
+with the role of supplying exactly the right thing at the right time.
+
+The third is that they are simply a very clever way of getting around the
+various Sunday Closing acts.
+
+All these theories, diverse as they are, have two things in common.  They
+explain the observed facts, and they are completely and utterly wrong.
+
+  [The Light Fantastic, by Terry Pratchett]
+%e passage
+# p. 205
+%passage 11
+"Where to they all come from?" said Twoflower, as they fled yet another mob.
+
+"Inside every sane person there's a madman struggling to get out," said the
+shopkeeper,  "That's what I've always thought.  No one goes mad quicker than
+a totally sane person."
+
+  [The Light Fantastic, by Terry Pratchett]
+%e passage
+# pp. 229-230 ('grey': British spelling is accurate)
+%passage 12
+Trymon was looking at him.  /Something/ was looking at him.  And still the
+others hadn't noticed.  Could he even explain it?  Trymon looked the same
+as he had always done, except for the eyes, and a slight sheen to his skin.
+
+Rincewind stared, and knew that there were far worse things than Evil.  All
+the demons in Hell would torture your very soul, but that was precisely
+because they value souls very highly; evil would always try to steal the
+universe, but at least it considered the universe worth stealing.  But the
+grey world behind those empty eyes would trample and destroy without even
+according its victims the dignity of hatred.  It wouldn't even notice them.
+
+  [The Light Fantastic, by Terry Pratchett]
+%e passage
 %e title
 #
 #
 #
-%title Equal Rites (3)
+%title Equal Rites (10)
+# p. 118 (Signet edition; passage starts mid-sentence and ends mid-paragraph)
 %passage 1
-...it is well known that a vital ingredient of success is not knowing that 
-what you're attempting can't be done.
+[...] it is well known that a vital ingredient of success is not knowing
+that what you're attempting can't be done.  [...]
 
   [Equal Rites, by Terry Pratchett]
 %e passage
+# p. 218 (speaker is Granny Weatherwax)
 %passage 2
-Million-to-one chances...crop up nine times out of ten.
+"Million-to-one chances," she said, "crop up nine times out of ten."
 
   [Equal Rites, by Terry Pratchett]
 %e passage
+# pp. 96-97 ('Tannoy': public address speaker)
 %passage 3
-Animal minds are simple, and therefore sharp. Animals never spend time
-dividing experience into little bits and speculating about all the bits 
-they've missed. The whole panoply of the universe has been neatly 
-expressed to them as things to (a) mate with, (b) eat, (c) run away from, 
-and (d) rocks. This frees the mind from unnecessary thoughts and gives 
-it a cutting edge where it matters. Your normal animal, in fact, never
-tries to walk and chew gum at the same time. 
-
-The average human, on the other hand, thinks about all sorts of things 
+Animal minds are simple, and therefore sharp.  Animals never spend time
+dividing experience into little bits and speculating about all the bits
+they've missed.  The whole panoply of the universe has been neatly
+expressed to them as things to (a) mate with, (b) eat, (c) run away from,
+and (d) rocks.  This frees the mind from unnecessary thoughts and gives
+it a cutting edge where it matters.  Your normal animal, in fact, never
+tries to walk and chew gum at the same time.
+
+The average human, on the other hand, thinks about all sorts of things
 around the clock, on all sorts of levels, with interruptions from dozens
-of biological calendars and timepieces. There's thoughts about to be said,
-and private thoughts, and real thoughts, and thoughts about thoughts, and 
-a whole gamut of subconscious thoughts. To a telepath the human head is 
-a din. It is a railway terminus with all the Tannoys talking at once. 
-It is a complete FM waveband- and some of those stations aren't reputable,
+of biological calendars and timepieces.  There's thoughts about to be said,
+and private thoughts, and real thoughts, and thoughts about thoughts, and
+a whole gamut of subconscious thoughts.  To a telepath the human head is
+a din.  It is a railway terminus with all the Tannoys talking at once.
+It is a complete FM waveband--and some of those stations aren't reputable,
 they're outlawed pirates on forbidden seas who play late-night records with
 limbic lyrics.
 
   [Equal Rites, by Terry Pratchett]
 %e passage
-%e title
-#
-#
-#
-%title Mort (1)
-%passage 1
-Ankh-Morpork had dallied with many forms of government and hand ended up
- with that form of democracy known as One Man, One Vote. The Patrician was
-the Man; he had the Vote. 
+# pp. 18-19
+%passage 4
+Smith took a spade from beside the back door and hesitated.
 
-  [Mort, by Terry Pratchett]
-%e passage
-%e title
-#
-#
-#
-%title Sourcery (2)
-%passage 1
-And what would humans be without love?
-RARE, said Death.
+"Granny."
 
-  [Sourcery, by Terry Pratchett]
-%e passage
-%passage 2
-They suffered from the terrible delusion that something could be done. 
-They seemed prepared to make the world the way they wanted it or die in the
-attempt,  and the trouble with dying in the attempt was that you died in
-the attempt. 
+"What?"
 
-  [Sourcery, by Terry Pratchett]
-%e passage
-%e title
-#
-#
-#
-%title Wyrd Sisters (2)
-%passage 1
+"Do you know how wizards like to be buried?"
 
-Destiny is important, see, but people go wrong when they think it controls
-them. It's the other way around. 
+"Yes!"
 
-  [Wyrd Sisters, by Terry Pratchett]
+"Well, how?"
+
+Granny paused at the bottom of the stairs.
+
+"Reluctantly."
+
+  [Equal Rites, by Terry Pratchett]
 %e passage
-%passage 2
-#submitted by Boudewijn
-Verence tried to avoid walking through walls. A man had his dignity.
-He became aware that he was being watched.
-He turned his head.
-There was a cat sitting in the doorway, subjecting him to a slow blink.
-It was a mottled grey and extremely fat...
-No. It was extremely /big/. It was covered with so much scar tissue 
-that it looked like a fist with fur on it. Its ears were a couple of
-perforated stubs, its eyes two yellow slits of easy-going malevolence,
-its tail a twitching series of question marks as it stared at him.
-Greebo had heard that Lady Felmet had a small white female cat and had
-strolled up to pay his respects. Verence had never seen an animal with
-so much built-in villainy. He didn't resist as it waddled across the
-floor and dried to rub itself against his legs, purring like a 
-waterfall.
-
-'Well, well,' said the king, vaguely. He reached down and made an 
-effort to scratch it behind the two ragged bits on top of its head. 
-It was a relief to find someone else besides another ghost who could 
-see him, and Greebo, he couldn't help feeling, was a distinctly unusual
-cat. Most of the castle cats were either pampered pets or flat-eared 
-kitchen and stable habitues who generally resembled the very rodents
-they lived on. This cat, on the other hand, was its own animal. All 
-cats give that impression, of course, but instead of the mindless 
-animal self-absorption that passes for secret wisdom in the creatures, 
-Greebo radiated genuime intelligence. He also radiated a smell that 
-would have knocked over a wall and caused sinus trouble in a dead fox. 
+# p. 70
+%passage 5
+Granny sighed.  "You have learned something," she said, and thought it
+was safe to insert a touch of sternness into her voice.  "They say that a
+little knowledge is a dangerous thing, but it is not one half so bad as a
+lot of ignorance."
 
-  [Wyrd Sisters, by Terry Pratchett]
+  [Equal Rites, by Terry Pratchett]
 %e passage
-%e title
-#
-#
-#
-%title Pyramids (2)
-%passage 1
-The trouble with life was that you didn't get a chance to practice before
-doing it for real. 
+# pp. 113-114 (Esk is a young girl)
+%passage 6
+The barges stopped at some of the towns.  By tradition only the men went
+ashore, and only Amschat, wearing his ceremonial Lying hat, spoke to
+non-Zoons.  Esk usually went with him.  He tried hinting that she should
+obey the unwritten rules of Zoon life and stay afloat, but a hint was to
+Esk what a mosquito bite was to the average rhino because she was already
+learning that if you ignore the rules people will, half the time, quietly
+rewrite them so that they don't apply to you.
 
-  [Pyramids, by Terry Pratchett]
+  [Equal Rites, by Terry Pratchett]
 %e passage
-%passage 2
-Mere animals couldn't possibly manage to act like this. You need to be a
-human being to be really stupid. 
+# pp. 119-120 (next passage is a direct continuation of this one)
+%passage 7
+The town was smaller than Ohulan, and very different because it lay on the
+junction of three trade routes quite apart from the river itself.  It was
+built around one enormous square which was a cross between a permanent
+exotic traffic jam and a tent village.  Camels kicked mules, mules kicked
+horses, horses kicked camels and they all kicked humans; there was a riot
+of colours, a din of noise, a nasal orchestration of smells and the steady,
+heady sound of hundreds of people working hard at making money.
+
+One reason for the bustle was that over large parts of the continent other
+people preferred to make money without working at all, and since the Disc
+had yet to develop a music recording industry they were forced to fall back
+on older, more traditional forms of banditry.
+
+Strangely enough these often involved considerable effort.  Rolling heavy
+rocks to the top of cliffs for a decent ambush, cutting down trees to
+block the road, and digging a pit lined with spikes while still keeping a
+wicked edge on a dagger probably involved a much greater expenditure of
+thought and muscle than more socially-acceptable professions but,
+nevertheless, there were still people misguided enough to endure all this,
+plus long nights in uncomfortable surroundings, merely to get their hands
+on perfectly ordinary large boxes of jewels.
 
-  [Pyramids, by Terry Pratchett]
+  [Equal Rites, by Terry Pratchett]
 %e passage
-%e title
-#
-#
-#
-%title Guards! Guards! (2)
-%passage 1
-Never build a dungeon you wouldn't be happy to spend the night in yourself.
-The world would be a happier place if more people remembered that. 
+# pp. 120-121 (this passage is a direct continuation of preceding one;
+#              "I said, what is happening here?" actually omits "is"
+#              but must be a typo--fixed here to avoid bug reports;
+#              'broomstick' is Esk's disguised wizard's staff)
+%passage 8
+So a town like Zemphis was the place where caravans split, mingled and
+came together again, as dozens of merchants and travellers banded together
+for protection against the socially disadvantaged on the trails ahead.
+Esk, wandering unregarded amidst the bustle, learned all this by the simple
+method of finding someone who looked important and tugging on the hem of
+his coat.
 
-  [Guards! Guards!, by Terry Pratchett]
+This particular man was counting bales of tobacco and would have succeeded
+but for the interruption.
+
+"What?"
+
+"I said, what is happening here?"
+
+The man meant to say:  "Push off and bother someone else."  He meant to
+give her a light cuff about the head.  So he was astonished to find himself
+bending down and talking seriously to a small, grubby-faced child holding
+a large broomstick (which also, it seemed to him later, was in some
+indefinable way /paying attention/).
+
+He explained about the caravans.  The child nodded.
+
+"People all get together to travel?"
+
+"Precisely."
+
+"Where to?"
+
+"All sorts of places.  Sto Lat, Pseudopolis... Ankh-Morpork, of course...."
+
+"But the river goes there," said Esk, reasonably.  "Barges.  The Zoons."
+
+"Ah, yes," said the merchant, "but they charge high prices and they can't
+carry everything and, anyway, no one trusts them much."
+
+"But they're very honest!"
+
+"Huh, yes," he said.  "But you know what they say:  never trust an honest
+man."  He smiled knowingly.
+
+"Who says that?"
+
+"They do.  You know.  People," he said, a certain uneasiness entering his
+voice.
+
+"Oh," said Esk.  She thought about it.  "They must be very silly," she said
+primly.  "Thank you, anyway."
+
+  [Equal Rites, by Terry Pratchett]
 %e passage
-%passage 2
-These weren't encouraged in the city, since the heft and throw of a
-longbow's arrow could send it  through an innocent bystander a hundred
-yards away instead of the innocent bystander at whom it was aimed. 
+# pp. 127-128 (this time broomstick is Granny's defective witch's broomstick)
+%passage 9
+The broomstick lay between two trestles.  Granny Weatherwax sat on a rock
+outcrop while a dwarf half her height, wearing an apron that was a mass of
+pockets, walked around the broom and occasionally poked it.
 
-  [Guards! Guards!, by Terry Pratchett]
+Eventually he kicked the bristles and gave a long intake of breath, a sort
+of reverse whistle, which is the secret sign of craftsman across the
+universe and means that something expensive is about to happen.
+
+"Weellll," he said.  "I could get the apprentices in to look at this, I
+could.  It's an education in itself.  And you say it actually managed to
+get airborne?"
+
+"It flew like a bird," said Granny.
+
+The dwarf lit a pipe.  "I should very much like to see that bird," he said
+reflectively.  "I should imagine it's quite something to watch, a bird like
+that."
+
+"Yes, but can you repair it?" said Granny.  "I'm in a hurry."
+
+The dwarf sat down, slowly and deliberately.
+
+"As for /repair/," he said, "well, I don't know about /repair/.  Rebuild,
+maybe.  Of course, it's hard to get the bristles these days even if you can
+find people to do the proper binding, and the spells need--"
+
+"I don't want it rebuilt, I just want it to work properly," said Granny.
+
+"It's an early model, you see," the dwarf plugged on.  "Very tricky, those
+early models.  You can't get the wood--"
+
+He was picked up bodily until his eyes were level with Granny's.  Dwarves,
+being magical in themselves as it were, are quite resistant to magic but
+her expression looked as though she was trying to weld his eyeballs to the
+back of his skull.
+
+"Just repair it," she hissed.  "Please?"
+
+"What, make a bodge job?" said the dwarf, his pipe clattering to the floor.
+
+"Yes."
+
+"Patch it up, you mean?  Betray my training by doing half a job?"
+
+"Yes," said Granny.  Her pupils were two little black holes.
+
+"Oh," said the dwarf.  "Right, then."
+
+  [Equal Rites, by Terry Pratchett]
+%e passage
+# p. 185 (actually uses four periods to mark a sentence ending in a ellipsis)
+%passage 10
+There may be universes where librarianship is considered a peaceful sort of
+occupation, and where the risks are limited to large volumes falling off
+the shelves on to one's head, but the keeper of a /magic/ library is no job
+for the unwary.  Spells have power, and merely writing them down and
+shoving them between covers doesn't do anything to reduce it.  The stuff
+leaks.  Books tend to react with one another, creating randomized magic
+with a mind of its own.  Books of magic are usually chained to their
+shelves, but not to prevent them being stolen....
+
+  [Equal Rites, by Terry Pratchett]
 %e passage
 %e title
 #
 #
 #
-%title Eric (2)
+%title Mort (11)
+# p. 136 (Signet edition; passage is a footnote;
+#         Vetinari doesn't show up as recurring Patrician until /Sourcery/)
 %passage 1
-No enemies had ever taken Ankh-Morpork. Well, /technically/ they had, quite
- often; the city welcomed free-spending barbarian invaders, but somehow the
- puzzled raiders always found, after a few days, that they didn't own their
- own horses any more, and within a couple of months they were just another
-minority group with its own graffiti and food shops. 
+Ankh-Morpork had dallied with many forms of government and had ended up
+with that form of democracy known as One Man, One Vote.  The Patrician was
+the Man; he had the Vote.
 
-  [Eric, by Terry Pratchett]
+  [Mort, by Terry Pratchett]
 %e passage
+# p. 11
 %passage 2
-Rincewind looked down at the broad steps they were climbing. They were
- something of a novelty; each one was built out of large stone letters. The
- one he was just stepping on to, for example, read: I Meant It For The Best.
-The next one was: I Thought You'd Like It.
-Eric was standing on: For The Sake Of The Children.
-'Weird, isn't it?' he said. 'Why do it like this?'
-'I think they're meant to be good intentions,' said Rincewind. This was a
-road to hell, and demons were, after all, traditionalists. 
+Mort was getting interested in the rock.  It had curly shells in it, relics
+of the early days of the world when the Creator had made creatures out of
+stone, no-one knew why.
 
-  [Eric, by Terry Pratchett]
+Mort was interested in lots of things.  Why people's teeth fitted together
+so neatly, for example.  He'd given that one a lot of thought.  Then there
+was the puzzle of why the sun came out during the day, instead of at night
+when the light would come in useful.  He knew the standard explanation,
+which somehow didn't seem satisfying.
+
+In short, Mort is one of those people who are more dangerous than a bag
+full of rattlesnakes.  He was determined to discover the underlying logic
+behind the universe.
+
+Which was going to be hard, because there wasn't one.  The Creator had a
+lot of remarkably good ideas when he put the world together, but making it
+understandable hadn't been one of them.
+
+  [Mort, by Terry Pratchett]
 %e passage
-%e title
+# p. 18
+%passage 3
+"But you're Death," said Mort.  "You go around killing people!"
+
+I?  KILL? said Death, obviously offended.  CERTAINLY NOT.  PEOPLE /GET/
+KILLED, BUT THAT'S THEIR BUSINESS.  I JUST TAKE OVER FROM THEN ON.  AFTER
+ALL, IT'D BE A BLOODY STUPID WORLD IF PEOPLE GOT KILLED WITHOUT DYING,
+WOULDN'T IT?
+
+  [Mort, by Terry Pratchett]
+%e passage
+# p. 25
+%passage 4
+"Is it magic?" said Mort.
+
+WHAT DO YOU THINK? said Death.  AM I REALLY HERE, BOY?
+
+"Yes," said Mort slowly.  "I... I've watched people.  They look at you but
+the don't see you, I think.  You do something to their minds."
+
+Death shook his head.
+
+THEY DO IT ALL THEMSELVES, he said.  THERE'S NO MAGIC.  PEOPLE CAN'T SEE ME,
+THEY SIMPLY WON'T ALLOW THEMSELVES TO DO IT.  UNTIL IT'S TIME, OF COURSE.
+WIZARDS CAN SEE ME, AND CATS.  BUT YOUR AVERAGE HUMAN... NO, NEVER.  He blew
+a smoke ring at the sky, and added, STRANGE BUT TRUE.
+
+  [Mort, by Terry Pratchett]
+%e passage
+# pp. 48-49 (Binky is Death's white horse, who was left 'parked' on a
+#            castle's roof; Mort is Death's novice apprentice)
+%passage 5
+They were on the roof before he spoke again.
+
+YOU TRIED TO WARN HIM, he said, removing Binky's nosebag.
+
+"Yes, sir.  Sorry."
+
+YOU CANNOT INTERFERE WITH FATE.  WHO ARE YOU TO JUDGE WHO SHOULD LIVE AND
+WHO SHOULD DIE?
+
+Death watched Mort's expression carefully.
+
+ONLY THE GODS ARE ALLOWED TO DO THAT, he added.  TO TINKER WITH THE FATE OF
+EVEN ONE INDIVIDUAL COULD DESTROY THE WHOLE WORLD.  DO YOU UNDERSTAND?
+
+Mort nodded miserably.
+
+"Are you going to send me home?" he said.
+
+Death reached down and swung him up behind the saddle.
+
+BECAUSE YOU SHOWED COMPASSION?  NO.  I MIGHT HAVE DONE IF YOU HAD SHOWN
+PLEASURE.  BUT YOU MUST LEARN THE COMPASSION PROPER TO YOUR TRADE.
+
+"What's that?"
+
+A /SHARP/ EDGE.
+
+  [Mort, by Terry Pratchett]
+%e passage
+# pp. 59-61 (in Ankh-Morpork, Mort has accidentally walked through a wall
+#            into an immigrant Klatchian family's dining room; 'the creature
+#            who was not there' refers to Death during an earlier event)
+%passage 6
+"I'm no demon!  I'm a human!" he said, and stopped in shock as his words
+emerged in perfect Klatch.
+
+"You're a thief?" said the father.  "A murderer?  To creep in thus, are you
+a /tax-gatherer/?"  His hand slipped under the table and came up holding a
+meat cleaver honed to paper thinness.  His wife screamed and dropped the
+plate and clutched the youngest children to her.
+
+Mort watched the blade weave through the air, and gave in.
+
+"I bring you greetings from the uttermost circles of hell," he hazarded.
+
+The change was remarkable.  The cleaver was lowered and the family broke
+into broad smiles.
+
+"There is much luck to us if a demon visits," beamed the father.  "What is
+your wish, O foul spawn of Offler's loins?"
+
+"Sorry?" said Mort.
+
+"A demon brings blessing and good fortune on the man that helps it," said
+the man.  "How may we be of assistance, O evil dogsbreath of the nether
+pit?"
+
+"Well, I'm not very hungry," said Mort, "but if you know where I can get a
+fast horse, I could be in Sto Lat before sunset."
+
+The man beamed and bowed.  "I know the very place, noxious extrusion of the
+bowels, if you would be so good as to follow me."
+
+Mort hurried out after him.  The ancient ancestor watched them go with a
+critical expression, its jowls rhythmically chewing.
+
+"That was what they call a demon around here?" it said.  "Offler rot this
+country of dampness, even their demons are third-rate, not a patch on the
+demons we had in the Old Country."
+
+The wife placed a small bowl of rice in the folded middle pair of hands of
+the Offler statue (it would be gone in the morning) and stood back.
+
+"Husband did say that last month at the /Curry Gardens/ he served a creature
+who was not there," she said.  "He was impressed."
+
+Ten minutes later the man returned and, in solemn silence, placed a small
+heap of gold coins on the table.  They represented enough wealth to
+purchase quite a large part of the city.
+
+"He had a bag of them," he said.
+
+The family stared at the money for some time.  The wife sighed.
+
+"Riches bring many problems," she said.  "What are we to do?"
+
+"We return to Klatch," said the husband firmly, "where our children can grow
+up in a proper country, true to the glorious traditions of our ancient race
+and men do not need to work as waiters for wicked masters but can stand tall
+and proud.  And we must leave right now, fragrant blossom of the date palm."
+
+"Why so soon, O hard-working son of the desert?"
+
+"Because," said the man, "I have just sold the Patrician's champion
+racehorse."
+
+  [Mort, by Terry Pratchett]
+%e passage
+# pp. 139-140 (passage ends mid-sentence)
+%passage 7
+"You don't know much about monarchy, do you?" said Keli.
+
+"Um, no?"
+
+"She means better to be a dead queen in your own castle than a live
+commoner somewhere else," said Cutwell, [...]
+
+  [Mort, by Terry Pratchett]
+%e passage
+# p. 158
+%passage 8
+"You mean you won't help?" said Mort.  "Not even if you can?"
+
+"Give the boy a prize," growled Albert.  "And it's no good thinking you can
+appeal to my better nature under this here crusty exterior," he added,
+"'cos my interior's pretty damn crusty too."
+
+  [Mort, by Terry Pratchett]
+%e passage
+# pp. 159-160 (Death has come to an employment agency--a new concept in
+#              Ankh-Morpork--looking for a job)
+%passage 9
+"And what was your previous position?"
+
+I BEG YOUR PARDON?
+
+"What did you do for a living?" said the thin young man behind the desk.
+
+I USHERED SOULS INTO THE NEXT WORLD.  I WAS THE GRAVE OF ALL HOPE.  I WAS
+THE ULTIMATE REALITY.  I WAS THE ASSASSIN AGAINST WHOM NO LOCK WOULD HOLD.
+
+"Yes, point taken, but do you have any particular skills?"
+
+I SUPPOSE A CERTAIN AMOUNT OF EXPERTISE WITH AGRICULTURAL IMPLEMENTS? he
+ventured after a while.
+
+The young man shook his head firmly.
+
+NO?
+
+  [Mort, by Terry Pratchett]
+%e passage
+# p. 205
+%passage 10
+Death raised his skull and sniffed the air.
+
+The sound cut through all the other noises in the hall and forced them
+into silence.
+
+It is the kind of noise that is heard on the twilight edges of dreams,
+the sort that you wake from in the cold sweat of mortal horror.  It was
+the snuffling under the door of dread.  It was like the snuffling of a
+hedgehog, but if so then it was the kind of hedgehog that crashes out of
+the verges and flattens lorries.  It was the kind of noise you wouldn't
+want to hear twice; you wouldn't want to hear it /once/.
+
+  [Mort, by Terry Pratchett]
+%e passage
+# p. 207
+%passage 11
+"Well, that was a lesson to all of us," the bursar continued, brushing dust
+and candle wax off his robe.  He looked up, expecting to see the statue of
+Alberto Malich back on its pedestal.
+
+"Clearly even statues have feelings," he said.  "I myself recall, when I
+was but a first-year student, writing my name on his... well, never mind.
+The point is, I propose here and now we replace the statue."
+
+Dead silence greeted this suggestion.
+
+"With, say, an exact likeness cast in gold.  Suitably embellished with
+jewels, as befits our great founder," he went on brightly.
+
+"And to make sure no students deface it in any way I suggest we then erect
+it in the deepest cellar," he continued.
+
+"And then lock the door," he added.  Several wizards began to cheer up.
+
+"And throw away the key?" said Rincewind.
+
+"And /weld/ the door," the bursar said.  He had just remembered about The
+Mended Drum.  He thought for a while and remembered about the physical
+fitness regime as well.
+
+"And then brick up the doorway," he said.  There was a round of applause.
+
+"And throw away the brick layer!" chortled Rincewind, who felt he was
+getting the hang of this.
+
+The bursar scowled at him.  "No need to get carried away," he said.
+
+  [Mort, by Terry Pratchett]
+%e passage
+%e title
+#
+#
+#
+%title Sourcery (10)
+# p. 9 (Signet edition; passage starts mid-paragraph and ends mid-paragraph)
+%passage 1
+"[...]  And what would humans be without love?"
+
+RARE, said Death.  [...]
+
+  [Sourcery, by Terry Pratchett]
+%e passage
+%passage 2
+They suffered from the terrible delusion that something could be done.
+They seemed prepared to make the world the way they wanted it or die in the
+attempt, and the trouble with dying in the attempt was that you died in
+the attempt.
+
+  [Sourcery, by Terry Pratchett]
+%e passage
+# p. 11 ('worth while': two words is accurate, although strange)
+%passage 3
+"I meant," said Ipslore, bitterly, "what is there in this world that makes
+living worth while?"
+
+CATS, he said eventually, CATS ARE NICE.
+
+"Curse you!"
+
+MANY HAVE, said Death evenly.
+
+  [Sourcery, by Terry Pratchett]
+%e passage
+# pp. 40-41 (text has 'the moment and the words' which is obviously a typo;
+#            it might have intended 'that' for 'and'; we just drop 'and')
+%passage 4
+The thief, as will become apparent, was a special type of thief.  This
+thief was an artist of theft.  Other thieves merely stole everything that
+was not nailed down, but this thief stole the nails as well.  This thief
+had scandalised Ankh by taking a particular interest in stealing, with
+astonishing success, things that were in fact not only nailed down but
+also guarded by keen-eyed guards in inaccessible strongrooms.  There are
+artists that will paint an entire chapel ceiling; this was the kind of
+thief that could steal it.
+
+This particular thief was credited with stealing the jeweled disemboweling
+knife from the temple of Offler the Crocodile God during the middle of
+Evensong, and the silver shoes from the Patrician's finest racehorse
+while it was in the process of winning a race.  When Gritoller Mimpsey,
+vice-president of the Thieves' Guild, was jostled in the marketplace and
+then found on returning home that a freshly-stolen handful of diamonds
+had vanished from their place of concealment, he knew who to blame.(1)
+This was the type of thief that could steal the initiative, the moment the
+words were out of your mouth.
+
+(1) This was because Gritoller had swallowed the jewels for safe keeping.
+
+  [Sourcery, by Terry Pratchett]
+%e passage
+# pp. 63-64 ('Compleet', 'Majik', 'enterr', 'physycal', 'hys', 'bodie',
+#            'Destinie', 'Deathe', 'werre', 'nowe', 'menne', 'Ende',
+#            'Worlde', 'hadd', 'bee', 'goddes', 'ould', 'Apocralypse',
+#            'legende', 'thee': all accurate; 'ould' may be a typo...)
+%passage 5
+It was deathly quiet in the Library.  The books were no longer frantic.
+They'd passed through their fear and out into the calm waters of abject
+terror, and they crouched on their shelves like so many mesmerised rabbits.
+
+A long hairy arm reached up and grabbed /Casplock's Compleet Lexicon of
+Majik and Precepts for the Wise/ before it could back away, soothed its
+terror with a long-fingered hand, and opened it under 'S'.  The Librarian
+smoothed the trembling page gently and ran a horny nail down the entries
+until he came to:
+
+    *Sourceror*, /n. (mythical).  A proto-wizard, a doorway through/
+    /which new majik may enterr the world, a wizard not limited by/
+    /the physycal capabilities of hys own bodie, not by Destinie,/
+    /nor by Deathe.  It is written that there once werre sourcerors/
+    /in the youth of the world but not may there by nowe and blessed/
+    /be, for sourcery is not for menne and the return of sourcery/
+    /would mean the Ende of the Worlde...  If the Creator hadd meant/
+    /menne to bee as goddes, he ould have given them wings./
+    /SEE ALSO:  thee Apocralypse, the legende of thee Ice Giants,/
+    /and thee Teatime of the Goddes./
+
+The Librarian read the cross-references, turned back to the first entry,
+and stared at it through deep dark eyes for a long time.  Then he put the
+book back carefully, crept under his desk, and pulled the blanket over
+his head.
+
+  [Sourcery, by Terry Pratchett]
+%e passage
+# pp. 71-72
+%passage 6
+The current Patrician, head of the extremely rich and powerful Vetinari
+family, was thin, tall and apparently as cold-blooded as a dead penguin.
+Just by looking at him you could tell he was the sort of man you'd expect
+to keep a white cat, and caress it idly while sentencing people to death
+in a piranha tank; and you'd hazard for good measure that he probably
+collected rare, thin porcelain, turning it over and over in his blue-white
+fingers while distant screams echoed from the depths of the dungeons.  You
+wouldn't put it past him to use the word "exquisite" and have thin lips.
+He looked the kind of person who, when they blinked, you mark it off on
+the calendar.
+
+Practically none of this was in fact the case, although he did have a small
+and exceedingly elderly wire-haired terrier called Wuffles that smelled
+badly and wheezed at people.  It was said to be the only thing in the
+entire world he truly cared about.  He did of course sometimes have people
+horribly tortured to death, but this was considered to be perfectly
+acceptable behaviour for a civic ruler and generally approved of by the
+overwhelming majority of citizens.(1)  The people of Ankh are of a
+practical persuasion, and felt that the Patrician's edict forbidding all
+street theatre and mime artists made up for a lot of things.  He didn't
+administer a reign of terror, just the occasional light shower.
+
+(1) The overwhelming majority of citizens being defined in this case as
+everyone not currently hanging upside down over a scorpion pit.
+
+  [Sourcery, by Terry Pratchett]
+%e passage
+# p. 75
+%passage 7
+"What exactly /is/ the Aprocralypse?"
+
+Rincewind hesitated.  "Well," he said, "it's the end of the world.  Sort
+of."
+
+"Sort of?  /Sort of/ the end of the world?  You mean we won't be certain?
+We'll all look around and say 'Pardon me, did you hear something?'?"
+
+"It's just that no two seers have ever agreed about it.  There have been
+all kinds of vague predictions.  Quite mad, some of them.  So it was
+called the Apocralypse."  He looked embarrassed.  "It's a sort of
+apocryphal Apocalypse.  A kin of pun, you see."
+
+  [Sourcery, by Terry Pratchett]
+%e passage
+# p. 110
+%passage 8
+"You're very quiet, Spelter.  Do you not agree?"
+
+No.  The world had sourcery once, and gave it up for wizardry.  Wizardry is
+magic for men, not gods.  It's not for us.  There was something wrong with
+it, and we have forgotten what it was.  I liked wizardry.  It didn't upset
+the world.  It fitted.  It was right.  A wizard was all I wanted to be.
+
+He looked down at his feet.
+
+"Yes," he whispered.
+
+  [Sourcery, by Terry Pratchett]
+%e passage
+# pp. 141-142 (Rincewind and Nijel have just entered a harem)
+%passage 9
+Rincewind had eyes for none of this.  [...] they were swamped by the
+considerably bigger flood of panic at the sight of four guards turning
+towards him with scimitars in their hands and the light of murder in their
+eyes.
+
+Without hesitation, Rincewind took a step backwards.
+
+"Over to you, friend," he said.
+
+"Right!"
+
+Nijel drew his sword and held it out in front of him, his arms trembling at
+the effort.
+
+There were a few seconds of total silence as everyone waited to see what
+would happen next.  And then Nijel uttered the battle cry that Rincewind
+would never quite forget to the end of this life.
+
+"Erm," he said, "excuse me...."
+
+  [Sourcery, by Terry Pratchett]
+%e passage
+# pp. 198-199
+%passage 10
+The astro-philosophers of Krull once succeeded in proving conclusively
+that all places are one place and that the distance between them is an
+illusion, and this news was an embarrassment to all thinking philosophers
+because it did not explain, among other things, signposts.  After years of
+wrangling the whole thing was then turned over to Ly Tin Wheedle, arguably
+the Disc's greatest philosopher,(1) who after some thought proclaimed that
+although it was indeed true that all places were one place, that place was
+/very large/.
+
+And so psychic order was restored.  Distance is, however, an entirely
+subjective phenomenon and creatures of magic can adjust it to suit
+themselves.
+
+They are not necessarily very good at it.
+
+(1) He always argued that he was.
+
+  [Sourcery, by Terry Pratchett]
+%e passage
+%e title
+#
+#
+#
+%title Wyrd Sisters (15)
+# p. 318 (ROC edition; passage starts mid-paragraph;
+#         speaker is Granny Weatherwax)
+%passage 1
+"[...]  Destiny /is/ important, see, but people go wrong when they think it
+controls them.  It's the other way around."
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# pp. 105-106
+%passage 2
+Verence tried to avoid walking through walls.  A man had his dignity.
+
+He became aware that he was being watched.
+
+He turned his head.
+
+There was a cat sitting in the doorway, subjecting him to a slow blink.  It
+was a mottled grey and extremely fat...
+
+No.  It was extremely /big/.  It was covered with so much scar tissue that
+it looked like a fist with fur on it.  Its ears were a couple of perforated
+stubs, its eyes two yellow slits of easy-going malevolence, its tail a
+twitching series of question marks as it stared at him.
+
+Greebo had heard that Lady Felmet had a small white female cat and had
+strolled up to pay his respects.
+
+Verence had never seen an animal with so much built-in villainy.  He didn't
+resist as it waddled across the floor and dried to rub itself against his
+legs, purring like a waterfall.
+
+"Well, well," said the king, vaguely.  He reached down and made an effort
+to scratch it behind the two ragged bits on top of its head.   It was a
+relief to find someone else besides another ghost who could see him, and
+Greebo, he couldn't help feeling, was a distinctly unusual cat.  Most of
+the castle cats were either pampered pets or flat-eared kitchen and stable
+habitues who generally resembled the very rodents they lived on.  This cat,
+on the other hand, was its own animal.  All cats give that impression, of
+course, but instead of the mindless animal self-absorption that passes for
+secret wisdom in the creatures, Greebo radiated genuine intelligence.  He
+also radiated a smell that would have knocked over a wall and caused sinus
+trouble in a dead fox.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# pp. 14-15
+%passage 3
+He wondered if ghosts hunted.  Almost certainly not, he imagined.  Or ate,
+or drank either for that matter, and that was really depressing.  He liked
+a big noisy banquet and had quaffed(1) many a pint of good ale.  And bad
+ale, come to that.  He'd never been able to tell the difference till the
+following morning, usually.
+
+(1) Quaffing is like drinking, but you spill more.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# pp. 60-61 (dwarfish mechanics: see /Equal Rites/)
+%passage 4
+Granny Weatherwax milked and fed the goats, banked the fire, and put a
+cloth over the mirror and pulled her broomstick out from behind the door.
+She went out, locked the door behind her, and hung the key on its nail in
+the privy.
+
+This was quite sufficient.  Only once, in the entire history of witchery
+in the Ramtops, had a thief broken into a witch's cottage.  The witch
+concerned visited the most terrible punishment on him.(1)
+
+Granny sat on the broom and muttered a few words, but without much
+conviction.  After a further couple of tries, she got off, fiddled with
+the binding, and had another go.  There was a suspicion of glitter from
+one end of the stick, which quickly died away.
+
+"Drat," she said, under her breath.
+
+She looked around carefully, in case anyone was watching.  In fact it was
+only a hunting badger who, hearing the thumping of running feet, poked its
+head out from the bushes and saw Granny hurtling down the path with the
+broomstick held stiff-armed beside her.  At last the magic caught, and she
+managed to vault clumsily on to it before it trundled into the night sky
+as gracefully as a duck with one wing missing.
+
+From above the trees came a muffled curse against all dwarfish mechanics.
+
+(1) She did nothing, although sometimes when she saw him in the village
+she'd smile in a faint, puzzled way.  After three weeks of this the
+suspense was too much for him and he took his own life; in fact he took it
+all the way across the continent, where he became a reformed character and
+never went home again.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 76 (passage starts mid-paragraph)
+%passage 5
+And, with alarming suddenness, nothing happened.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 82 ('/Good/ fool': lowercase 'fool' is accurate)
+%passage 6
+"Is this a dagger I see before me?" he mumbled.
+
+"Um.  No, my lord.  It's my hankerchief, you see.  You can sort of tell the
+difference if you look closely.  It doesn't have as many sharp edges."
+
+"/Good/ fool," said the duke, vaguely.
+
+Totally mad, the Fool thought.  Several bricks short of a bundle.  So far
+round the twist you could use him to open wine bottles.
+
+"Kneel beside me," my Fool.
+
+The Fool did so.  The duke laid a soiled bandage on his shoulder.
+
+"Are you loyal, Fool?" he said.  "Are you trustworthy?"
+
+"I swore to follow my lord until death," said the Fool hoarsely.
+
+The duke pressed his mad face close to the Fool, who looked up into a pair
+of bloodshot eyes.
+
+"I didn't want to," he hissed conspiratorially.  "They made me do it.  I
+didn't want--"
+
+The door swung open.  The duchess filled the doorway.  In fact, she was
+nearly the same shape.
+
+"Leonal!" she barked.
+
+The fool was fascinated by what happened to the duke's eyes.  The mad red
+flame vanished, was sucked backwards, and replaced by the hard blue stare
+he had come to recognize.  It didn't mean, he realized, that the duke was
+any less mad.  Even the coldness of his sanity was madness in a way.  The
+duke had a mind that ticked like a clock and, like a clock, it regularly
+went cuckoo.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 85
+%passage 7
+On the crest of the moor, where in the summer partridges lurked among the
+bushes like small, whirring idiots, was a standing stone.  It stood roughly
+where the witches' territories met, although the boundaries were never
+formally marked out.
+
+The stone was about the same height as a tall man, and made of a bluish
+tinted rock.  It was considered intensely magical because, although there
+was only one of it, /no-one had ever been able to count it/; if it saw
+anyone looking at it speculatively, it shuffled behind them.  It was the
+most self-effacing monolith ever discovered.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 92 (passage starts mid-paragraph)
+%passage 8
+Demons were like genies or philosophy professors--if you didn't word things
+/exactly/ right, they delighted in giving you absolutely accurate and
+completely misleading answers.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 121
+%passage 9
+Nanny Ogg was also out early.  She hadn't been able to get any sleep
+anyway, and besides, she was worried about Greebo.  Greebo was one of her
+few blind spots.  While intellectually she would concede that he was
+indeed a fat, cunning, evil-smelling multiple rapist, she nevertheless
+instinctively pictured him as the small fluffy kitten he had been decades
+before.  The fact that he had once chased a female wolf up a tree and
+seriously surprised a she-bear who had been innocently digging for roots
+didn't stop her worrying that something bad might happen to him.  It was
+generally considered by everyone else in the kingdom that the only thing
+that might slow Greebo down was a direct meteorite strike.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 133 (the duke has locked Nanny Ogg in the castle dungeon)
+%passage 10
+"I really advise you all to return home," said Granny Weatherwax.  "There
+has probably been a misunderstanding.  Everyone knows a witch cannot be
+held against her will."
+
+"It's gone too far this time," said a peasant.  "All this burning and
+taxing and now this.  I blame you witches.  It's got to stop.  I know my
+rights."
+
+"What rights are they?" said Granny.
+
+"Dunnage, cowhage-in-ordinary, badinage, leftovers, scrommidge, clary and
+spunt." said the peasant promptly.  "And acornage, every other year, and
+the right to keep two-thirds of a goat on the common.  Until he set fire to
+it.  It was a bloody good goat, too."
+
+"A man could go far, knowing his rights like you do," said Granny.  "But
+right now he should go home."
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 164
+%passage 11
+"Whatever happened to the rule about not meddling in politics?" said Magrat,
+watching her retreating back.
+
+Nanny Ogg massaged some like back into her fingers.
+
+"By Hoki, that woman's got a jaw like an anvil," she said.  "What was that?"
+
+"I said, what about this rule about not meddling?" said Magrat.
+
+"Ah," said Nanny. She took the girl's arm.  "The thing is," she explained,
+"as you advance in the Craft, you'll learn there is another rule.  Esme's
+obeyed it all her life."
+
+"And what's that?"
+
+"When you break rules, break 'em good and hard," said Nanny, and grinned a
+set of gums that were more menacing than teeth.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 238
+%passage 12
+"I mean it.  Look at me.  I wasn't supposed to be writing plays.  Dwarfs
+aren't even supposed to be able to /read/.  I shouldn't worry too much
+about destiny, if I was you.  I was destined to be a miner.  Destiny gets
+it wrong half the time."
+
+"But you said he looks like the Fool person.  I can't see it myself, mark
+you."
+
+"The light's got to be right."
+
+"Could be some destiny at work there."
+
+Hwel shrugged.  Destiny was funny stuff, he knew.  You couldn't trust it.
+Often you couldn't even see it.  Just when you knew you had it cornered, it
+turned out to be something else--coincidence, maybe, or providence.  You
+barred the door against it, and it was standing behind you.  Then just when
+you thought you had it nailed down it walked away with the hammer.
+
+He used destiny a lot.  As a tool for his plays it was even better than a
+ghost.  There was nothing like a bit of destiny to get the old plot rolling.
+But it was a mistake to think you could spot the shape of it.  And as for
+thinking it could be controlled...
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 242 (passage starts mid-paragraph; Lancre has recently come out of a
+#         magic-induced 15-year stasis; 'things ... is': 'things' plural is
+#         accurate, though probably a typo)
+%passage 13
+On top of the general suspicion of witches, it was dawning on the few people
+in Lancre who had any dealings with the outside world that a) either more
+things had been happening than they had heard about before or b) time was
+out of joint.  It wasn't easy to prove(1) but the few traders who came along
+the mountain tracks after the winter seemed to be rather older than they
+should have been.  Unexplained happenings were always more or less expected
+in the Ramtops because of the high magical potential, but several years
+disappearing overnight was a bit of a first.
+
+(1) Because of the way time was recorded among the various states, kingdoms
+and cities.  After all, when over an area of a hundred square miles the same
+year is variously the Year of the Small Bat, the Anticipated Monkey, the
+Hunting Cloud, Fat Cows, Three Bright Stallions and at least nine numbers
+recording the time since(2) assorted kings, prophets, and strange events were
+either crowned, born or happened, and each year was a different number of
+months, and some of them don't have weeks, and one of them refuses to accept
+the day as a measure of time, the only things it is possible to be sure of
+is that good sex doesn't last long enough.(3)
+
+(2) The calendar of the Theocracy of Muntab counts /down/, not up.  No-one
+knows why, but it might not be a good idea to hang around and find out.
+
+(3) Except for the Zapingo tribe of the Great Nef, of course.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 250 (passage starts mid-paragraph)
+%passage 14
+It was a land of describable beauty.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+# p. 265 (passage starts mid-paragraph)
+%passage 15
+The past used to be a lot better than it is now.
+
+  [Wyrd Sisters, by Terry Pratchett]
+%e passage
+%e title
+#
+#
+#
+%title Pyramids (11)
+# p. 218 (ROC edition)
+%passage 1 (passage ends mid-paragraph)
+What a chap needed at a time like this was a sign, some sort of book of
+instructions.  The trouble with life was that you didn't get a chance to
+practice before doing it for real.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+# p. 128 (passage starts mid-paragraph and ends mid-paragraph)
+%passage 2
+Mere animals couldn't possibly manage to act like this.  You need to be a
+human being to be really stupid.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+# pp. 9-10 ('tlingas' is accurate)
+%passage 3
+It was a full-length mirror.  All assassins had a full-length mirror in
+their rooms, because it would be a terrible insult to anyone to kill them
+when you were badly dressed.
+
+Teppic examined himself critically.  The outfit had cost him his last
+penny, and was heavy on the black silk.  It whispered as he moved.  It was
+pretty good.
+
+At least the headache was going.  It had nearly crippled him all day; he'd
+been in dread of having to start the run with purple spots in front of his
+eyes.
+
+He sighed and opened the black box and took out his rings and slipped them
+on.  Another box held a set of knives of Klatchian steel, their blades
+darkened with lamp black.  Various cunning and intricate devices were taken
+from velvet bags and dropped into pockets.  A couple of long-bladed
+throwing /tlingas/ were slipped into their sheaths inside his boots.  A
+thin silk line and folding grapnel were wound around his waist, over the
+chain-mail shirt.  A blowpipe was attached to its leather thong and dropped
+down his back under his cloak; Teppic pocketed a slim tin container with an
+assortment of darts, their tips corked and their stems braille-coded for
+ease of selection in the dark.
+
+He winced, checked the blade of his rapier and slung the baldric over his
+right shoulder, to balance the bag of lead slingshot ammunition.  As an
+afterthought he opened his sock drawer and took a pistol crossbow, a flask
+of oil, a roll of lockpicks and, after some consideration, a punch dagger,
+a bag of assorted caltraps and a set of brass knuckles.
+
+Teppic picked up his hat and checked its lining for the coil of cheesewire.
+He placed it on his head at a jaunty angle, took a last satisfied look at
+himself in the mirror, turned on his heel and, very slowly, fell over.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+# p. 30
+%passage 4
+He'd always remember the first night in the dormitory.  It was long enough
+to accommodate all eighteen boys in Viper House, and draughty enough to
+accommodate the great outdoors.  Its designer may have had comfort in mind,
+but only so that he could avoid it whenever possible:  he had contrived a
+room that could actually be colder than the weather outside.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+# p. 92
+%passage 5
+A few stars had been let out early.  Teppic looked up at them.  Perhaps, he
+thought, there is life somewhere else.  On the stars, maybe.  If it's true
+that there are billions of universes stacked along side one another, the
+thickness of a thought apart, then there must be people elsewhere.
+
+But wherever they are, no matter how mightily they try, no matter how
+magnificent the effort, they surely can't manage to be as godawfully stupid
+as us.  I mean, we work at it.  We were given a spark of it to start with,
+but over hundreds of thousands of years we've really improved on it.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+# p. 96 (Ptaclusp the pyramid builder, sons Ptaclusp IIa and Ptaclusp IIb)
+%passage 6
+Descendants!  The gods had seen fit to give him one son who charged you for
+the amount of breath expended in saying "Good morning", and another one who
+worshipped geometry and stayed up all night designing aqueducts.  You
+scrimped and saved to send them to the best schools, and then they went and
+paid you back by getting educated.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+# p. 136
+%passage 7
+It's a fact as immutable as the Third Law of Sod that there is no such
+thing as a good Grand Vizier.  A predilection to cackle and plot is
+apparently part of the job spec.
+
+High priests tend to get put in the same category.  They have to face the
+implied assumption that no sooner do they get the funny hat than they're
+issuing strange orders, e.g., princesses tied to rocks for itinerant sea
+monsters and throwing little babies in the sea.
+
+This is a gross slander.  Throughout the history of the Disc most high
+priests have been serious, pious and conscientious men who have done their
+best to interpret the wishes of the gods, sometimes disembowelling or
+flaying alive hundreds of people in a day in order to make sure they're
+getting it absolutely right.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+# pp. 206-208 (text has 'that's now it happened'; 'now' changed to 'how' here)
+%passage 8
+Copolymer, the greatest storyteller in the history of the world, sat back
+and beamed at the greatest minds in the world, assembled at the dining
+table.
+
+Teppic had added another iota to his store of new knowledge.  'Symposium'
+meant a knife-and-fork tea.
+
+"Well," said Copolymer, and launched into the story of the Tsortean Wars.
+
+"You see, what happened was, /he'd/ taken /her/ back home, and her
+father--this wasn't the old king, this was the one before, the one with the
+wossname, he married some girl from over Elharib way, she had a squint,
+what was her name now, began with a P.  Or an L.  One of them letters,
+anyway.  Her father owned an island out on the bay there, Papylos I think
+it was.  No, I tell a lie, it was Crinix.  /Anyway/ the king, the other
+king, he raised an army and they....  Elenor, that was her name.  She had
+a squint, you know.  But quite attractive, they say.  When I say married,
+I trust I do not have to spell it out for you.  I mean, it was a bit
+unofficial.  Er.  Anyway, there was this wooden horse and after they'd got
+in...  Did I tell you about this horse?  It was a horse.  I'm pretty sure
+it was a horse.  Or maybe it was a chicken.  Forget my own name next!  It
+was wossname's idea, the one with the limp.  Yes.  The limp in his leg, I
+mean.  Did I mention him?  There'd been this fight.  No, that was the other
+one, I think.  Yes.  Anyway, this wooden pig, damn clever idea, they made
+it out of thing.  Tip of my tongue.  Wood.  But that was later, you know.
+The fight!  Nearly forgot the fight.  Yes.  Damn good fight.  Everyone
+banging on their shields and yelling.  Wossname's armour shone like shining
+armour.  Fight and a half, that fight.  Between thingy, not the one with
+the limp, the other one, wossname, had red hair.  /You/ know.  Tall fellow,
+talked with a lisp.  Hold on, just remembered, he was from some other
+island.  Not him.  The other one, with the limp.  Didn't want to go, he
+said he was mad.  Of course, he /was/ bloody mad, definitely.  I mean, a
+wooden cow!  Like wossname said, the king, no not that king, the other one,
+he saw the goat, he said 'I fear the Ephibeans, especially when they're mad
+enough to leave bloody great wooden livestock on the doorstep, talk about
+nerve, they must think we was born yesterday, set fire to it,' and, of
+course, wossname had nipped in round the back and put everyone to the
+sword, talk about laugh.  Did I say she had a squint?  They said she was
+pretty, but it takes all sorts.  Yes.  Anyway, that's how it happened.
+/Now/, of course, wossname--I think he was called Melycanus, had a limp--he
+wanted to go home, well, you would, they'd been there for /years/, he
+wasn't getting any younger.  That's why he dreamt up the thing about the
+wooden wossname.  Yes.  I tell a lie, Lavaelous was the one with the knee.
+Pretty good fight, that fight, take it from me."
+
+He lapsed into self-satisfied silence.
+
+"Pretty good fight," he mumbled and, smiling faintly, dropped off to sleep.
+
+Teppic was aware that his own mouth was hanging open.  He shut it.  Along
+the table several of the diners were wiping their eyes.
+
+"Magic," said Xeno.  "Sheer magic.  Every word a tassle on the canopy of
+Time."
+
+"It's the way he remembers every tiny detail.  Pin sharp," murmured Ibid.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+# p. 211
+%passage 9
+"I'd love to stay and listen to you listening to me all day," he said.
+"But there's a man over there I'd like to see."
+
+"That's amazing," said Endos, making a short note and turning his attention
+to a conversation further along the table.  A philosopher had averred that
+although truth was beauty, beauty was not necessarily truth, and a fight was
+breaking out.  Endos listened carefully.(1)
+
+(1) The role of listeners has never been fully appreciated.  However, it is
+well known that most people don't listen.  They use the time when someone
+else is speaking to think of what they're going to say next.  True Listeners
+have always been revered among oral cultures, and prized for their rarity
+value; bards and poets are ten a cow, but a good Listener is hard to find,
+or at least hard to find twice.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+# p. 278 (perhaps ought to end this one with the first paragraph...)
+%passage 10
+In the middle of the firestorm the Great Pyramid appeared to lift up a few
+inches, on a beam of incandescence, and turn through ninety degrees.  This
+was almost certainly the special type of optical illusion which can take
+place /even though no-one is actually looking at it/.
+
+And then, with deceptive slowness and considerable dignity, it exploded.
+
+It was almost too crass a word.  What it did was this:  it came apart
+ponderously into building-sized chunks which drifted gently away from one
+another, flying serenely out and over the necropolis.  Several of them
+struck other pyramids, badly damaging them in a lazy, unselfconscious way,
+and then bounded on in silence until they ploughed to a halt behind a small
+mountain of rubble.
+
+Only then did the boom come.  It went on for quite a long time.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+# p. 280 (passage starts mid-paragraph and ends mid-paragraph)
+%passage 11
+Man was never intended to understand things he meddled with.
+
+  [Pyramids, by Terry Pratchett]
+%e passage
+%e title
+#
+#
+#
+%title Guards! Guards! (14)
+# p. 283 (ROC edition)
+%passage 1
+"I see you're very comfortable here," said Vimes weakly.
+
+"Never build a dungeon you wouldn't be happy to spend the night in
+yourself," said the Patrician, laying out the food on the cloth.  "The
+world would be a happier place if more people remembered that."
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 133
+%passage 2
+These weren't encouraged in the city, since the heft and throw of a
+longbow's arrow could send it through an innocent bystander a hundred
+yards away rather than the innocent bystander at whom it was aimed.
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 26 (first and second paragraphs are actually end of one section,
+#        start of next one; first 'Thunder rolled...' had three dot
+#        ellipsis, second has four, elipsis plus final period--
+#        first changed to four here so that they match)
+%passage 3
+Thunder rolled....
+
+It is said that the gods play games with the lives of men.  But what games,
+and why, and the identities of the actual pawns, and what the game is, and
+what the rules are--who knows?
+
+Best not to speculate.
+
+Thunder rolled....
+
+It rolled a six.
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 48 (passage is a footnote)
+%passage 4
+One of the remarkable innovations introduced by the Patrician was to make
+the Thieves' Guilde /responsible/ for theft, with annual budgets, forward
+planning and, above all, rigid job protection.  Thus, in return for an
+agreed average level of crime per annum, the thieves themselves saw to it
+that unauthorized crime was met with the full force of Injustice, which was
+generally a stick with nails in it.
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 87 (passage ends mid-paragraph)
+%passage 5
+"Well, sir," he said, "I know that dragons have been extinct for thousands
+of years, sir--"
+
+"Yes?"  The Patrician's eyes narrowed.
+
+Vimes plunged on.  "But sir, the thing is, do /they/ know?"  [...]
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 114 (passage is a footnote)
+%passage 6
+The Guild of Fire Fighters had been outlawed by the Patrician the previous
+year after many complaints.  The point was that, if you bought a contract
+from the Guild, your house would be protected against fire.  Unfortunately,
+the general Ankh-Morpork ethos quickly came to the fore and fire fighters
+would tend to go to prospective clients' houses in groups, making loud
+comments like "Very inflammable looking place, this" and "Probably go up
+like a firework with just one carelessly dropped match, know what I mean?"
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 131 (Sherlock Holmes)
+%passage 7
+Once you've ruled out the impossible then whatever is left, however
+improbable, must be the truth.  The problem lay in working out what was
+impossible, of course.  That was the trick, all right.
+
+There was also the curious incident of the orangutan in the night-time....
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 150 (Dirty Harry with a small swamp dragon rather than a .45 Magnum...)
+%passage 8
+A streak of green fire blasted out of the back of the shed, passed a foot
+over the heads of the mob, and burned a charred rosette in the woodwork
+over the door.
+
+Then came a voice that was a honeyed purr of shear deadly menace.
+
+"/This is Lord Mountjoy Quickfang Winterforth IV, the hottest dragon in the
+city.  It could burn your head clean off./"
+
+Captain Vimes limped forward from the shadows.
+
+A small and extremely frightened golden dragon was clamped firmly under one
+arm.  His other hand held it by the tail.
+
+The rioters watched it, hypnotised.
+
+"Now I know what you're thinking," Vimes went on, softly.  "You're
+wondering, after all this excitement, has it got enough flame left?  And,
+y'know, I ain't so sure myself..."
+
+He leaned forward, sighting between the dragon's ears, and his voice
+buzzed like a knife blade:
+
+"What you've got to ask yourself is:  Am I feeling lucky?"
+
+They swayed backwards as he advanced.
+
+"Well?" he said.  "/Are/ you feeling lucky?"
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 154 (passage is a footnote; ten pages later, Sergeant Colon uses the
+#         old version of the proverb)
+%passage 9
+The phrase "Set a thief to catch a thief" had by this time (after strong
+representations from the Thieves' Guilde) replaced a much older and
+quintessentially Ankh-Morpork proverb, which was "Set a deep hole with
+spring-loaded sides, tripwires, whirling knife blades driven by water power,
+broken glass and scorpions, to catch a thief."
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 174 (passage starts mid-paragraph)
+%passage 10
+[...]  There was no difference at all between the richest man and the
+poorest beggar, apart from the fact that the former had lots of money,
+food, power, fine clothes, and good health.  But at least he wasn't
+any /better/.  Just richer, fatter, more powerful, better dressed and
+healthier.  It had been like that for hundreds of years.
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 205
+%passage 11
+"Might have been just an innocent bystander, sir," said Carrot.
+
+"What, in Ankh-Morpork?"
+
+"Yes, sir."
+
+"We should have grabbed him, then, just for the rarity value," said Vimes.
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# pp. 262-263 (passage is a footnote; 'practise', 'practised' are accurate)
+%passage 12
+A number of religions in Ankh-Morpork still practised human sacrifice,
+except that they really didn't need to practise any more because they had
+got so good at it.  City law said that only condemned criminals should be
+used, but that was all right because in most of the religions refusing to
+volunteer for sacrifice was an offense punishable by death.
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# p. 292
+%passage 13
+There were times when an ape had to do what a man had to do...
+
+The orangutan threw a complex salute and swung away into the darkness.
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+# pp. 299-300 + 325 (final part comes quite a bit later; Carrot is trying to
+#                    alert oblivious Sergeant Colon that the dragon is coming)
+%passage 14
+"This is what it comes to!" muttered Colon.  "Decent women can't walk down
+the street without being eaten!  Right, you bastards, you're... you're
+/geography/--"
+
+"Sergeant!" Carrot repeated urgently.
+
+"It's history, not geography," said Nobby.  "That's what you're supposed to
+say.  History.  'You're history!' you say."
+
+"Well, whatever," snapped Colon.  "Let's see now--"
+
+[...(quite a while later)...]
+
+"You heard the Man," he rasped.  "One false move and you're... you're--" he
+took a desperate stab at it--"you're Home Economics!"
+
+  [Guards! Guards!, by Terry Pratchett]
+%e passage
+%e title
+#
+#
+# The original publication of /Eric/ featured extensive illustrations by
+# Josh Kirby but the mass-market paperback edition contains none of them
+# and omits his name.  In the Harper Torch edition, the list of other
+# books by the same author has "Eric (with Josh Kirby)" even though the
+# copyright and title pages of that very book do not mention him.
+#
+%title Eric (9)
+# pp. 3-4 (Harper Torch edition)
+%passage 1
+No enemies had ever taken Ankh-Morpork.  Well, /technically/ they had,
+quite often; the city welcomed free-spending barbarian invaders, but
+somehow the puzzled raiders always found, after a few days, that they
+didn't own their own horses anymore, and within a couple of months they
+were just another minority group with its own graffiti and food shops.
+
+  [Eric, by Terry Pratchett]
+%e passage
+# p. 195
+%passage 2
+"I can see blue sky!" said Eric.  "Where do you think we'll come out?" he
+added.  "And when?"
+
+"Anywhere," said Rincewind.  "Anytime."
+
+He looked down at the broad steps they were climbing.  They were something
+of a novelty; each one was built out of large stone letters.  The one he
+was just stepping on to, for example, read: I Meant It For The Best.
+
+The next one was: I Thought You'd Like It.
+
+Eric was standing on: For The Sake Of The Children.
+
+'Weird, isn't it?' he said.  'Why do it like this?'
+
+'I think they're meant to be good intentions,' said Rincewind.  This was a
+road to Hell, and demons were, after all, traditionalists.
+
+  [Eric, by Terry Pratchett]
+%e passage
+# pp. 9-10 (passage has an interesting start but not much of a finish...)
+%passage 3
+"It's a haunting," he ventured.  "Some short of ghost, maybe.  A bell, book
+and candle job."
+
+The Bursar sighed.  "We tried that, Archchancellor."
+
+The Archchancellor leaned toward him.
+
+"Eh?" he said.
+
+"I /said/, we tried that, Archchancellor," said the Bursar loudly,
+directing his voice at the old man's ear.  "After dinner, you remember?
+We used Humptemper's /Names of the Ants/ and rang Old Tom."(1)
+
+"Did we, indeed.  Worked, did it?"
+
+"/No/, Archchancellor."
+
+"Eh?"
+
+(1) Old Tom was the single cracked bronze bell in the University bell
+tower.  The clapper dropped out shortly after it was cast, but the bell
+still tolled out some tremendously sonorous silences every hour.
+
+  [Eric, by Terry Pratchett]
+%e passage
+# pp. 14-15 (the top wizards have performed the Rite of AshkEnte)
+%passage 4
+Death pointedly picked invisible particles off the edge of his scythe.
+
+The Archchancellor cupped a gnarled hand over his ear.
+
+"What'd he say?  Who's the fella with the stick?"
+
+"It's Death, Archchancellor," said the Bursar patiently.
+
+"Eh?"
+
+"It's Death, sir.  /You/ know."
+
+"Tell him we don't want any," said the old wizard, waving his stick.
+
+The Bursar sighed.  "We summoned him, Archchancellor."
+
+"Is it?  What'd we go and do that for?  Bloody silly thing to do."
+
+The Bursar gave Death an embarrassed grin.  He was on the point of asking
+him to excuse the Archchancellor on account of age, but realized that this
+would in the circumstances be a complete waste of breath.
+
+"Are we talking about the wizard Rincewind?  The one with the--" the Bursar
+gave a shudder-- "horrible Luggage on legs?  But he got blown up when there
+was all that business with the sourcerer, didn't he?"(1)
+
+INTO THE DUNGEON DIMENSIONS.  AND NOW HE IS TRYING TO GET BACK HOME.
+
+(1) The Bursar was referring obliquely to the difficult occasion when the
+University very nearly caused the end of the world, and would in fact have
+done so had it not been for a chain of events involving Rincewind, a magic
+carpet and a half-brick in a sock.  (See /Sourcery/.)  The whole affair
+was very embarrassing to wizards, as it always is to people who find out
+afterward that they were on the wrong side all along,(2) and it is
+remarkable how many of the University's senior staff were now adamant that
+at the time they had been off sick, visiting their aunt, or doing research
+with the door locked while humming loudly and had had no idea of what was
+going on outside.  There had been some desultory talk about putting up a
+statue to Rincewind but, by the curious alchemy that tends to apply in
+these sensitive issues, this quickly became a plaque, then a note on the
+Role of Honor, and finally a motion of censure for being improperly dressed.
+
+(2) ie, the one that lost.
+
+  [Eric, by Terry Pratchett]
+%e passage
+# p. 34
+%passage 5
+"Not that he was particularly successful.  It was all a bit trial and
+wossname."
+
+"I thought you said great big scaly--"
+
+"Oh, /yes/.  But that wasn't what he was after.  He was trying to conjure
+up a succubus."  It should be impossible to leer when all you've got is a
+beak, but the parrot managed it.  "That's a female demon what comes in the
+night and makes mad passionate wossn--"
+
+"I've heard of them," said Rincewind.  "Bloody dangerous things."
+
+The parrot put its head on one side.  "It never worked.  All he ever got
+was a neuralger."
+
+"What's that?"
+
+"It's a demon that comes and has a headache at you."
+
+  [Eric, by Terry Pratchett]
+%e passage
+# p. 35 (passage is a footnote)
+%passage 6
+Demons and their Hell are quite different from the Dungeon Dimensions,
+those endless parallel wastelands outside space and time.  The sad, mad
+Things in the Dungeon Dimensions have no understanding of the world but
+simply crave light and shape and try to warm themselves by the fires of
+reality, clustering around it with about the same effect--if they ever
+broke through--as an ocean trying to warm itself around a candle.  Whereas
+demons belong to the same space-time wossname, more or less, as humans,
+and have a deep and abiding interest in humanity's day-to-day affairs.
+Interestingly enough, the gods of the Disc have never bothered much about
+judging the souls of the dead, so people can only go to hell if that's
+where they believe, in their deepest heart, that they deserve to go.
+Which they won't do if they don't know about it.  This explains why it is
+important to shoot missionaries on sight.
+
+  [Eric, by Terry Pratchett]
+%e passage
+# p. 153
+%passage 7
+"Multiple exclamation marks," he went on, shaking his head, "are a sure
+sign of a diseased mind."
+
+  [Eric, by Terry Pratchett]
+%e passage
+# pp. 178-179 (Ponce da Quirm, encountered in hell)
+%passage 8
+"So you didn't find the Fountain of Youth, then," he said, feeling that he
+should make some conversation.
+
+"Oh, but I did," said da Quirm earnestly.  "A clear spring, deep in the
+jungle.  It was very impressive.  I had a good long drink, too.  Or draft,
+which I think is the more appropriate word.
+
+"And--?" said Rincewind.
+
+"It definitely worked.  Yes.  For a while there I could definitely feel
+myself getting younger.
+
+"But--" Rincewind waved a vague hand to take in da Quirm, the treadmill,
+the towering circles of the Pit.
+
+"Ah," said the old man.  "Of course, that's the really annoying bit.  I'd
+read so much about the Fountain, and you'd have thought someone in all
+those books would have mentioned the really vital thing about the water,
+wouldn't you?"
+
+"Which was--?"
+
+"/Boil it first./  Says it all, doesn't it?  Terrible shame, really."
+
+  [Eric, by Terry Pratchett]
+%e passage
+# p. 179
+%passage 9
+The Luggage trotted down the great spiral road that linked the circles of
+the Pit.  Even if conditions had been normal it probably would not have
+attracted much attention.  If anything, it was rather less astonishing
+than most of the denizens.
+
+  [Eric, by Terry Pratchett]
+%e passage
+%e title
+#
+#
+#
+%title Moving Pictures (16)
+# p. 7 (ROC Edition)
+%passage 1
+This is space.  It's sometimes called the final frontier.
+
+(Except that of course you can't have a /final/ frontier, because there'd
+be nothing for it to be a frontier /to/, but as frontiers go, it's pretty
+penultimate...)
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# pp. 22-23 (very short but happens to span a page boundary...)
+%passage 2
+By and large, the only skill the alchemists of Ankh-Morpork had discovered
+so far was the ability to turn gold into less gold.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# pp. 44, 45, 46 (multiple paragraphs skipped in the first two gaps)
+%passage 3
+He looked down.  There was a dog sitting by his feet.
+
+It was small, bow-legged and wiry, and basically grey but with patches of
+brown, white, and black in outlying areas, and it was staring.
+
+It was certainly the most penetrating stare Victor had ever seen.  It
+wasn't menacing, or fawning.  It was just very slow and very thorough, as
+though the dog was memorising details so that it could give a full
+description to the authorities later.
+
+[...]
+
+Victor let his gaze slide downwards.  There was nothing there but the little
+dog, industriously scratching itself.  It looked up slowly, and said "Woof?"
+
+[...]
+
+Victor poked an exploratory finger in his ear.  It must have  been a trick
+of an echo, or something.  It wasn't that the dog had gone "woof!", although
+that was practically unique in itself; most dogs in the universe /never/
+went "woof!", they had complicated barks like "whuuugh!" and "hwhoouf!".
+No, it was that it hadn't in fact /barked/ at all.  It had /said/ "woof".
+
+[...]
+
+One of the last things Victor remembered was a voice beside his knee saying,
+"Could have bin worse, mister.  I could have said 'miaow'."
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# p. 322
+%passage 4
+"'Twas beauty killed the beast," said the Dean, who liked to say things
+like that.
+
+"No it wasn't," said the Chair.  "It was it splatting into the ground like
+that."
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# p. 12
+%passage 5
+There's a saying that all roads lead to Ankh-Morpork, greatest of Discworld
+cities.
+
+At least, there's a /saying/ that there's a saying that all roads lead to
+Ankh-Morpork.
+
+And it's wrong.  All roads lead /away/ from Ankh-Morpork, but sometimes
+people just walk along them the wrong way.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# p. 34 (Victor Tugelbend and Ponder Stibbons are students at Unseen Uni.)
+%passage 6
+"Rain's stopped.  Let's go over the wall," he said.  "We deserve a drink."
+
+Victor waggled a finger.  "Just one drink, then.  Got to keep sober," he
+said.  "It's Finals tomorrow.  Got to keep a clear head!"
+
+"Huh!", said Ponder.
+
+Of course, it's very important to be sober when you take an exam.  Many
+worthwhile careers in the street-cleansing, fruit-picking and subway-guitar-
+playing industries have been founded on a lack of understanding of this
+simple fact.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# p. 37
+%passage 7
+In a sense which his tutors couldn't quite define, much to their annoyance,
+Victor Tugelbend was also the laziest person in the history of the world.
+
+Not simply, ordinarily lazy.  Ordinary laziness was merely the absence of
+effort.  Victor had passed through there a long time ago, had gone straight
+through commonplace idleness and out on the far side.  He put more effort
+into avoiding work than most people put into hard labour.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# p. 60
+%passage 8
+Cut-me-own-Throat Dibbler was one of those rare people with the ability to
+think in straight lines.
+
+Most people think in curves and zig-zags.  For example, they start with a
+thought like:  I wonder how I can become very rich, and then proceed along
+an uncertain course which includes thoughts like:  I wonder what's for
+supper, and:  I wonder who I know that can lend me five dollars?
+
+Whereas Throat was one of those people who could identify the thought at the
+other end of the process, in this case /I am now very rich/, draw a line
+between the two, and then think his way along it, slowly and patiently,
+until he got to the other end.
+
+Not that it worked.  There was always, he found, some small but vital flaw
+in the process.  It generally involved a strange reluctance on the part of
+people to buy what he had to sell.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# pp. 71-72
+%passage 9
+"Tell me, Mr Dibbler." said Silverfish, "what exactly is your profession?"
+
+"I sell merchandise," said Dibbler.
+
+"Mostly sausages," Victor volunteered.
+
+"/And/ merchandise," said Dibbler, sharply.  "I only sell sausages when the
+merchandising trade is a bit slow."
+
+"And the sale of sausages leads you to believe you can make better moving
+pictures?" said Silverfish.  "Anyone can sell sausages!  Isn't that so,
+Victor?"
+
+"Well..." said Victor, reluctantly.  No-one except Dibbler could possibly
+sell Dibbler's sausages.
+
+"There you are then," said Silverfish.
+
+"The thing is," said Victor, "that Mr Dibbler can even sell sausages to
+people who have bought them off him /before/."
+
+"That's right!" said Dibbler.  He beamed at Victor.
+
+"And a man who could sell Mr Dibbler's sausages twice could sell anything,"
+said Victor.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# pp. 111-112 ('dis', 'ort', 'yore', 'finking', 'mayonnaisey', 'specialitay',
+#              'de lar mayson' all accurate)
+%passage 10
+Borgle's commissary had decided to experiment with salads tonight.  The
+nearest salad growing district was thirty slow miles away.
+
+"What dis?" demanded a troll, holding up something limp and brown.
+
+Fruntkin the short-order chef hazarded a guess.
+
+'Celery?" he said.  He peered closer.  "Yeah, celery."
+
+"It /brown/."
+
+"'S'right.  'S'right!  Ripe celery ort to be brown," said Fruntkin, quickly.
+"Shows it's ripe," he added.
+
+"It should be /green/."
+
+"Nah.  Yore finking about the tomatoes," said Fruntkin.
+
+"Yeah, and what's this runny stuff?" said a man in the queue.
+
+Fruntkin drew himself up to his full height.
+
+"That," he said, "is the mayonnaisey.  Made it myself.  Out of a /book/, he
+added proudly.
+
+"Yead, I expect you did," said the man, prodding it.  "Clearly oil, eggs
+and vinegar were not involved, right?"
+
+"Specialitay de lar mayson," said Fruntkin.
+
+"Right, right," said the man.  "Only it's attacking my lettuce."
+
+Fruntkin grasped his ladle angrily.
+
+"Look--" he began.
+
+"No, it's all right," said the prospective diner.  "The slugs have formed a
+defensive ring."
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# p. 137 (CMOT Dibbler has become a director, Rock is a troll actor)
+%passage 11
+"Er, I was just wondering, Mr Dibbler... what is my motivation for this
+scene?"
+
+"Motivation?"
+
+"Yes.  Er.  I got to know, see," said Rock.
+
+"How about:  I'll fire you if you don't do it properly?"
+
+Rock grinned.  "Right you are, Mr Dibbler," he said.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# p. 189
+%passage 12
+Magic wasn't difficult.  That was the big secret that the whole baroque
+edifice or wizardry had been set up to conceal.  Anyone with a bit of
+intelligence and enough perseverance could do magic, which was why the
+wizards cloaked it with rituals and the whole pointy-hat business.
+
+The trick was to do magic and /get away with it/.
+
+Because it was as if the human race was a field of corn and magic helped
+the users grow just that bit taller, so that they stood out.  That
+attracted the attention of gods and--Victor hesitated--other Things outside
+this world.  People who used magic without knowing what they were doing
+usually came to a sticky end.
+
+All over the entire room, sometimes.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# p. 204 (passage ends mid-paragraph; musings are by Gaspode the dog)
+%passage 13
+Sunnink dreadful in there, he thought.  Prob'ly tentacled fings that rips
+your face off.  I mean, when you finds mysterious doors in old hills, it
+stands to reason wot comes out ain't going to be pleased to see you.  Evil
+creatures wot Man shouldn't wot of, and here's one dog wot don't want to
+wot of them either.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# pp. 206-207 (passage starts mid-paragraph; Dibbler now controls Silverfish's
+#              moving pictures studio;  Detritus isn't part of the Watch yet)
+%passage 14
+"[...]  Detritus, throw this bum out!"
+
+"Right you are, Mr Dibbler," rumbled the troll, gripping Silverfish's
+collar.
+
+"You haven't heard the last of this, you--you scheming, devious
+megalomaniac!"
+
+Dibbler removed his cigar.
+
+"That's /Mister/ Megalomanic to you," he said.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# p. 274 (passage starts mid-sentence; senior wizards of the University are
+#         attending a 'click' and have decided to take their hats off...)
+%passage 15
+[...] inside every old person is a young person wondering what happened.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+# p. 295 (passage starts mid-sentence; the movie theater owner's daughter
+#         is playing a pipe organ to accompany the silent movie)
+%passage 16
+[...] whatever piece of music she was playing, it was definitely losing.
+
+  [Moving Pictures, by Terry Pratchett]
+%e passage
+%e title
 #
 #
 #
-%title Moving Pictures (4)
+%title Reaper Man (15)
+# pp. 301-302 (ROC edition)
 %passage 1
-This is space. It's sometimes called the final frontier.
-(Except that of course you can't have a /final/ frontier, because there'd
- be nothing for it to be a frontier /to/, but as frontiers go, it's pretty
-penultimate...) 
+It was later that the story of Windle Poons really came to an end, if
+"story" means all that he did and caused and set in motion.  In the Ramtop
+villages where they dance the real Morris dance, for example, they believe
+that no one is finally dead until the ripples they cause in the world die
+away--until the clock he wound up winds down, until the wine she made has
+finished its ferment, until the crop they planted is harvested.  The span
+of someone's life, they say, is only the core of their actual existence.
 
-  [Moving Pictures, by Terry Pratchett]
+  [Reaper Man, by Terry Pratchett]
 %e passage
+# p. 251 (passage starts mid-paragraph)
 %passage 2
-By and large, the only skill the alchemists of Ankh-Morpork had discovered
-so far was the ability to turn gold into less gold. 
+Five exclamation marks, the sure sign of an insane mind.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# p. 305 (passage starts mid-paragraph)
+%passage 3
+Light thinks it travels faster than anything but it is wrong.  No matter
+how fast light travels it finds the darkness has always got there first,
+and is waiting for it.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# p. 245
+%passage 4
+"That's not fair, you know.  If we knew when we were going to die, people
+would lead better lives."
+
+IF PEOPLE KNEW WHEN THEY WERE GOING TO DIE, I THINK THEY PROBABLY WOULDN'T
+LIVE AT ALL.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# p. 19
+%passage 5
+YOU FEAR TO DIE?
+
+"It's not that I don't want... I mean, I've always... it's just that life
+is a habit that's hard to break..."
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# pp. 30-31
+%passage 6
+Wizards don't believe in gods in the same way that most people don't find it
+necessary to believe in, say, tables.  They know they're there, they know
+they're there for a purpose, they'd probably agree that they have a place in
+a well-organized universe, but they wouldn't see the point of /believing/,
+of going around saying, "O great table, without whom we are as naught".
+Anyway, either the gods are there whether you believe or not, or exist only
+as a function of the belief, so either way you might as well ignore the
+whole business and, as it were, eat off your knees.
+
+Nevertheless, there is a small chapel off the University's Great Hall,
+because while the wizards stand right behind the philosophy as outlined
+above, you don't become a successful wizard by getting up gods' noses even
+if those noses only exist in an ethereal or metaphorical sense.  Because
+while wizards don't believe in gods they know for a fact that /gods/ believe
+in gods.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# p. 50 (Dibbler is so low because he's on steps leading down to a cellar;
+#        'favour' and 'pedlar' are the spelling used)
+%passage 7
+"Sergeant!"
+
+Colon froze.  Then he looked down.  A face was staring up at him from ground
+level.  When he'd got a grip on himself, he made out the sharp features of
+his old friend Cut-Me-Own-Throat Dibbler, the Discworld's walking, talking
+argument in favour of the theory that mankind had descended from a species
+of rodent.  C. M. O. T. Dibbler like to describe himself as a merchant
+adventurer; everyone else liked to describe him as itinerant pedlar whose
+moneymaking schemes were always let down by some small but vital flaw, such
+as trying to sell things he didn't own or which didn't work or, sometimes,
+didn't even exist.  Fairy gold is well known to evaporate by morning, but
+it was a reinforced concrete slab by comparison to some of Dibbler's
+merchandise.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# pp. 58-59
+%passage 8
+Over the fireplace was an ornamental candlestick, fixed to a bracket on the
+wall.  It was such a familiar piece of furniture that Windle hadn't really
+seen it for fifty years.
+
+It was coming unscrewed.  It spun around slowly, squeaking once a turn.
+After half a dozen turns it fell off and clattered to the floor.
+
+Inexplicable phenomena were not in themselves unusual on the Discworld.(1)
+It was just that they normally had more point, or at least were a bit more
+interesting.
+
+(1) Rains of fish, for example, were so common in the little land-locked
+village of Pine Dressers that it had a flourishing smoking, canning and
+kipper filleting industry.  And in the mountain regions of Syrrit many
+sheep, left out in the fields all night, would be found in the morning to
+/be facing the other way/, without the apparent intervention of any human
+agency.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# pp. 68-69 (130 year old wizard Windle Poon has become a zombie after dying)
+%passage 9
+"And now let's put the lid on and go and have some lunch," said Ridcully.
+"Don't worry, Windle.  It's bound to work.  Today is the last day of the
+rest of your life."
+
+Windle lay in the darkness, listening to the hammering.  There was a thump
+and a muffled imprecation against the Dean for not holding the end properly.
+And then the patter of soil on the lid, getting fainter and more distant.
+
+After a while a distant rumbling suggested that the commerce of the city
+was being resumed.  He could even hear muffled voices.
+
+He banged on the coffin lid.
+
+"Can you keep it down?" he demanded.  "There's people down here trying to
+be dead!"
+
+He heard the voices stop.  There was the sound of feet hurrying away.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# pp. 81-82 (things have stopped dying because Death is no longer on the job)
+%passage 10
+Everything that exists, yearns to live.  That's what the cycle of life is
+all about.  That's the engine that drives the great biological pumps of
+evolution.  Everything tries to inch its way up the tree, clawing or
+tentacling or sliming its way up to the next niche until it gets to the
+very top--which, on the whole, never seems to have been worth all the
+effort.
+
+Everything that exists, yearns to live.  Even things that are not alive.
+Things that have a kind of sub-life, a metaphorical life, an /almost/ life.
+And now, in the same way that a sudden hot spell brings forth unnatural and
+exotic blooms...
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# p. 101
+%passage 11
+Dead.  That was the point.  All the religions had very strong views about
+talking to the dead.  And so did Mrs Cake.  They held that it was sinful.
+Mrs Cake held that it was only common courtesy.
+
+This usually led to a fierce ecclesiastical debate which resulted in Mrs
+Cake giving the chief priest what she called "a piece of her mind".  There
+were so many pieces of Mrs Cake's mind left around the city now that it
+was quite surprising that there was enough left to power Mrs Cake but,
+strangely enough, the more pieces of her mind she gave away the more there
+seemed to be left.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# p. 222
+%passage 12
+"No--" Ridcully began, and realised that it was hopeless.  And he was losing
+the initiative.  He carefully formulated the most genteel battle cry in the
+history of bowdlerism,
+
+"Darn them to Heck!" he yelled, and ran after the Dean.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# p. 226
+%passage 13
+Miss Flitworth disappeared into the scullery.  There was the creaking of a
+pump.  She returned with a damp flannel and a glass of water.
+
+THERE'S A NEWT IN IT!
+
+"Shows it's fresh," said Miss Flitworth,(1) fishing the amphibian out and
+releasing it on the flagstones, where it scuttled away into a crack.
+
+(1) People have believed for hundreds of years that newts in a well mean
+that the water's fresh and drinkable, and /in all that time/ never asked
+themselves whether the newts got out to go to the lavatory.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# p. 247
+%passage 14
+"Have you got any last words?"
+
+YES.  I DON'T WANT TO GO.
+
+"Well.  Succinct, anyway."
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+# pp. 249-250
+%passage 15
+"Where's everyone gone, Librarian?"
+
+"Oook oook."
+
+"Just like them.  I'd have done that.  Rush off without thinking.  May the
+gods bless them and help them, if they can find the time from their family
+squabbles."
+
+And then he thought:  well, what now?  I've thought, and what am I going to
+do?
+
+Rush off, or course,  But slowly.
+
+  [Reaper Man, by Terry Pratchett]
+%e passage
+%e title
+#
+#
+#
+%title Witches Abroad (14)
+# p. 92 (ROC edition)
+%passage 1
+Vampires have risen from the dead, the grave and the crypt, but have never
+managed it from the cat.
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# pp. 12-13
+%passage 2
+Desiderata Hollow was making her will.
+
+When Desiderata Hollow was a girl, her grandmother had given her four
+important pieces of advice to guide her young footsteps on the unexpectedly
+twisting pathway of life.
+
+They were:
+
+Never trust a dog with orange eyebrows,
+
+Always get the young man's name and address,
+
+Never get between two mirrors,
+
+And always wear completely clean underwear every day because you never knew
+when you were going to be knocked down and killed by a runaway horse and if
+people found you had unsatisfactory underwear on, you'd die of shame.
+
+And then Desiderata grew up to become a witch.  And one of the minor
+benefits of being a witch is that you know exactly when you're going to die
+and can wear what underwear you like.(1)
+
+That had been eighty years earlier, when the idea of knowing exactly when
+you were going to die had seemed quite attractive because secretly, of
+course, you knew you were going to live forever.
+
+That was then.
+
+And this was now.
+
+Forever didn't seem to last as long these days as once it did.
+
+(1) Which explains a lot about witches.
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# p. 64 (passage ends mid-paragraph)
+%passage 3
+"You know," said Nanny, investigating the recesses of the basket, "whenever
+I deals with dwarfs, the phrase 'Duck's arse' swims across my mind."
+
+"Mean little devils.  You should see the prices they tries to charge me
+when I takes my broom to be repaired," said Granny.
+
+"Yes, but you never pay," said Magrat.
+
+"That's not the point," said Granny Weatherwax.  "They shouldn't be allowed
+to charge that sort of money.  That's thievin', that is."
+
+"I don't see how it can be thieving if you don't pay anyway," said Magrat.
+
+"I never pay for anything," said Granny.  [...]
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# p. 93 (passage is a footnote)
+%passage 4
+Nanny Ogg sent a number of cards home to her family, not a single one of
+which got back before she did.  This is traditional, and happens everywhere
+in the universe.
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# pp. 118-119 (Magrat has been teaching herself martial arts via books)
+%passage 5
+"Lobsang Dibbler says sometimes you have to lose in order to win," said
+Magrat.
+
+"Sounds daft to me," said Nanny.  "That's Yen Buddhism, is it?"
+
+"No.  They're the ones who say you have to have lots of money to win," said
+Magrat.(1)  "In the Path of the Scorpion, the way to win is to lose every
+fight except the last one.  You use the enemy's strength against himself."
+
+"What, you get him to hit himself, sort of thing?" said Nanny.  "Sounds
+daft."
+
+(1) The Yen Buddhists are the richest religious sect in the universe.  They
+hold that the accumulation of money is a great evil and burden to the soul.
+They therefore, regardless of personal hazard, see it as their unpleasant
+duty to acquire as much as possible to reduce the risk to innocent people.
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# p. 131
+%passage 6
+They had breakfast in a forest clearing.  It was grilled pumpkin.  The dwarf
+bread was brought out for inspection.  But it was miraculous, the dwarf
+bread.  No one ever went hungry when they had some dwarf bread to avoid.
+You only had to look at it for a moment, and instantly you could think of
+dozens of things you'd rather eat.  Your boots for example.  Mountains.  Raw
+sheep.  Your own foot.
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# pp. 194-195 ("he just" is accurate; cockerel == adolescent rooster)
+%passage 7
+"This is Legba, a dark and dangerous spirit," said Mrs. Gogol.  She leaned
+closer and spoke out of the corner of her mouth.  "Between you and me, he
+just a big black cockerel.  But you know how it is."
+
+"It pays to advertise," Nanny agreed.  "This is Greebo.  Between you and me,
+he's a fiend from hell."
+
+"Well, he's a cat," said Mrs. Gogol, generously.  "It's only to be expected."
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# p. 218
+%passage 8
+"/And/ still a bit of the wedding cake," said the first coachman.  "Ain't
+you et that up yet?"
+
+"We have it every night," said the undercoachman.
+
+The shed shook with the ensuing laughter.  It is a universal fact that any
+innocent comment made by any recently married young member of any workforce
+is an instant trigger for coarse merriment among his or her older and more
+cynical colleagues.  This happens even if everyone concerned has nine legs
+and lives at the bottom of an ocean of ammonia on a huge cold planet.  It's
+just one of those things.
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# p. 228
+%passage 9
+"You ought to be more adventurous, Granny," said Magrat.
+
+"I ain't against adventure, in moderation," said Granny, "but not when I'm
+eatin'."
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# pp. 263-264 (Nanny is trying to stop an elaborate clock; despite damage
+#              inflicted on it, it goes on to announce midnight [early])
+%passage 10
+Let's see thought Nanny.  This bit is connected to that bit, this one turns,
+that one turns /faster/, this spiky bit wobbles backwards and forwards...
+
+Oh, well.  Just twist the first thing you can grab, as the High Priest said
+to the vestal virgin.(1)
+
+Nanny Ogg spat on her hands, gripped the largest cog-wheel, and twisted.
+
+It carried on turning, pulling her with it.
+
+Blimey.  Oh, well...
+
+Then she did was neither Granny Weatherwax nor Magrat would have dreamed of
+doing in the circumstances.  But Nanny Ogg's voyages on the sea of
+intersexual dalliance had gone rather further than twice around the
+lighthouse, and she saw nothing demeaning in getting a man to help her.
+
+She simpered at Casanunda.
+
+"Things would be a lot more comfortable in our little /pie-de-terre/ if you
+could just push this little wheel around a bit," she said.  "I'm sure /you/
+could manage it," she added.
+
+"Oh, no problem, good lady," said Casanunda.  He reached up with one hand.
+Dwarfs are immensely strong for their size.  The wheel seemed to offer him
+no resistance at all.
+
+Somewhere in the mechanism something resisted for a moment and then went
+/clonk/.  Big wheels turned reluctantly.  Little wheels screamed on their
+axles.  A small important piece flew out and pinged off of Casanunda's
+small bullet head.
+
+And, much faster than nature had ever intended, the hands sped around the
+face.
+
+(1) This is the last line to a Discworld joke lost, alas, to posterity.
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# p. 265 ('pate' has a couple of accent marks which can't be rendered in ascii)
+%passage 11
+There are various forms of voodoo in the multiverse, because it's a
+religion that can be put together from any ingredients that happen to be
+lying around.  And all of them try, in some way, to call a god into the body
+of a human being.
+
+That was stupid, Mrs. Gogol thought.  That was dangerous.
+
+Mrs. Gogol's voodoo worked the other way about.  What was a god?  A focus of
+belief.  If people believed, a god began to grow.  Feebly at first, but if
+the swamp taught anything, it taught patience.  Anything could be the focus
+of a god.  A handful of feathers with a red ribbon around them, a hat and
+coat on a couple of sticks... anything.  Because when all people had was
+practically nothing, then anything could be almost everything.  And then you
+fed it, and lulled it, like a goose heading for pate, and let the power grow
+very slowly, and when the time was ripe you opened the path... backwards.
+A human could ride the god, rather than the other way around.  There would
+be a price to pay later, but there always was.  In Mrs. Gogol's experience,
+everyone ended up dying.
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# p. 270 (Greebo has been temporarily transformed--polymorphed?--into a human)
+%passage 12
+Greebo wasn't a happy cat.  [...]
+
+Then he'd smelled the kitchen.  Cats gravitate to kitchens like rocks
+gravitate to gravity.
+
+  [Witches Abroad, by Terry Pratchett]
+%e passage
+# p. 282 (Casanunda the dwarf is Discworld's Casanova; he appears again in
+#         /Lords and Ladies/)
+%passage 13
+"How come you're in the palace guard, Casanunda?"
+
+"Soldier of fortune takes whatever jobs are going, Mrs. Ogg," said Casanunda
+earnestly.
+
+"But all the rest of 'em are six foot tall and you're--of the shorter
+persuasion."
+
+"I lied about my height, Mrs. Ogg.  I'm a world-famous liar."
+
+"Is that true?"
+
+"No."
+
+"What about you being the world's greatest lover?"
 
-  [Moving Pictures, by Terry Pratchett]
-%e passage
-%passage 3
-There was a dog sitting by his feet.
-It was small, bow-legged and wiry, and basically grey but with patches of
-brown, white, and black in outlying areas...   It looked up slowly, and
-said 'Woof?'   Victor poked an exploratory finger in his ear. It must have
- been a trick of an echo, or something. It wasn't that the dog had gone
- 'woof!', although that was practically unique in itself; most dogs in the
- universe /never/ went 'woof!', they had complicated barks like 'whuuugh!'
- and 'hwhoouf!'. No, it was that it hadn't in fact /barked/ at all. It had
-/said/ 'woof'.   'Could have bin worse, mister. I could have said "miaow".'
+There was silence for a while.
 
-  [Moving Pictures, by Terry Pratchett]
-%e passage
-%passage 4
-''Twas beauty killed the beast,' said the Dean, who liked to say things
-like that.   'No it wasn't,' said the Chair. 'It was it splatting into the
-ground like that.' 
+"Well, maybe I'm only No. 2," said Casanunda.  "But I try harder."
 
-  [Moving Pictures, by Terry Pratchett]
+  [Witches Abroad, by Terry Pratchett]
 %e passage
-%e title
-#
-#
-#
-%title Reaper Man (4)
-%passage 1
-No one is actually dead until the ripples they cause in the world die
-away...
+# pp. 285-286 (Greebo is still in human form; 'rationalise' is accurate)
+%passage 14
+Greebo leapt.
 
-  [Reaper Man, by Terry Pratchett]
-%e passage
-%passage 2
-Five exclamation marks, the sure sign of an insane mind.
+Cats are like witches.  They don't fight to kill, but to win.  There is a
+difference.  There's no point in killing an opponent.  That way, they won't
+know they've lost, and to be a real winner you have to have an opponent who
+is beaten and knows it.  There's no triumph over a corpse, but a beaten
+opponent, who will remain beaten every day for the remainder of their sad
+and wretched life, is something to treasure.
 
-  [Reaper Man, by Terry Pratchett]
-%e passage
-%passage 3
-Light thinks it travels faster than anything but it is wrong. No matter how
- fast light travels, it finds the darkness has always got there first, and
-is waiting for it. 
+Cats do not, of course, rationalise this far.  They just like to send
+someone limping off minus a tail and a few square inches of fur.
 
-  [Reaper Man, by Terry Pratchett]
-%e passage
-%passage 4
-"That's not fair, you know. If we knew when we were going to die, people
-would lead better lives." 
+Greebo's technique was unscientific and wouldn't have stood a chance against
+any decent swordsmanship, but on his side was the fact that it is almost
+impossible to develop decent swordsmanship when you seem to have run into a
+food mixer that is biting your ear off.
 
-IF PEOPLE KNEW WHEN THEY WERE GOING TO DIE, I THINK THEY PROBABLY WOULDN'T
-LIVE AT ALL. 
+The witches watched with interest.
 
-  [Reaper Man, by Terry Pratchett]
-%e passage
-%e title
-#
-#
-#
-%title Witches Abroad (1)
-%passage 1
-Vampires have risen from the dead, the grave and the crypt, but have never
-managed it from the cat.
+"I think we can leave him now," said Nanny.  "I think he's having fun."
 
   [Witches Abroad, by Terry Pratchett]
 %e passage
@@ -363,7 +2950,7 @@ sent, but their /spiritual/ home is in a hidden valley in the high Ramtops
 of the Discworld, where the books of history are kept.
 
 These aren't books in which the events of the past are pinned like so many
-butterflies to a cork.  These are the books from which history in derived.
+butterflies to a cork.  These are the books from which history is derived.
 There are more than twenty thousand of them, each one is ten feet high,
 bound in lead, and the letters are so small that they have to be read with
 a magnifying glass.
@@ -514,7 +3101,7 @@ in the street looking for a towel.  And then five years later they elected
 another one just like him, and really it was amazing how intelligent
 people kept on making the same mistakes.
 
-(1) Provided that we wasn't poor, foreign, nor disqualified by reason of
+(1) Provided that he wasn't poor, foreign, nor disqualified by reason of
 being mad, frivolous, or a woman.
 
   [Small Gods, by Terry Pratchett]
@@ -710,7 +3297,7 @@ There was a burst of octarine light.
 turned to Ponder Stibbons.  "Interestin' use of Stacklady's Morphic
 Resonator here, I hoped you noticed."
 
-Ponder lookd down.
+Ponder looked down.
 
 The chieftain had been turned into a pumpkin, although, in accordance with
 the rules of universal humor, he still had his hat on.
@@ -746,7 +3333,7 @@ that'd work for all of two seconds, wouldn't it?
 Her eye was drawn by some kind of horrible magic back to the room's
 garderobe, lurking behind its curtain.
 
-Margrat lifted the lid.  The shaft was definitely wide enough to admit a
+Magrat lifted the lid.  The shaft was definitely wide enough to admit a
 body.  Garderobes were notorious in that respect.  Several unpopular kings
 met their end, as it were, in the garderobe, at the hands of an assassin
 with good climbing ability, a spear, and a fundamental approach to politics.
@@ -762,7 +3349,7 @@ That was a portrait she'd never seen before.  She'd never walked down this
 far.  The idiot vapidity of the assembled queens had depressed her.  But
 this one...
 
-Ths one, somehow, reached out to her.
+This one, somehow, reached out to her.
 
 She stopped.
 
@@ -892,7 +3479,7 @@ metaphorical.  Just a doughnut.  One doughnut."
 
 "You only had to say."
 
-Harge brushed off his vest, gave Vimes a hurt look, and went back into
+Harga brushed off his vest, gave Vimes a hurt look, and went back into
 the kitchen.
 
   [Men at Arms, by Terry Pratchett]
@@ -999,7 +3586,7 @@ Sometimes it's better to light a flamethrower than curse the darkness.
 
 They stretched away in the candlelight, shelf on shelf of them, tiny
 little clown faces--as if a tribe of headhunters had suddenly developed
-a sophisicated sense of humor and a desire to make the world a better
+a sophisticated sense of humor and a desire to make the world a better
 place.
 
   [Men at Arms, by Terry Pratchett]
@@ -1167,7 +3754,7 @@ seemed to be a lot of rats around.  Lord Vetinari had listened carefully
 while the problem was explained, and had solved the thing with one
 memorable phrase which said a lot about him, about the folly of bounty
 offers, and about the natural instinct of Ankh-Morporkians in any
-situtation involving money:  "Tax the rat farms."
+situation involving money:  "Tax the rat farms."
 
   [Soul Music, by Terry Pratchett]
 %e passage
@@ -1292,7 +3879,7 @@ it is better organized.
 %e passage
 # p. 14
 %passage 4
-Many things went on at Unseen University and, regretably, teaching had to
+Many things went on at Unseen University and, regrettably, teaching had to
 be one of them.  The faculty had long ago confronted this fact and had
 perfected various devices for avoiding it.  But this was perfectly all
 right because, to be fair, so had the students.
@@ -1307,7 +3894,7 @@ Reader in Woolly Thinking(1)) that lectures had taken place /in essence/,
 so that was all right, too.
 
 And therefore education at the University mostly worked by the age-old
-method of putting a lot of young people in the vicinty of a lot of books
+method of putting a lot of young people in the vicinity of a lot of books
 and hoping that something would pass from one to the other, while the
 actual young people put themselves in the vicinity of inns and taverns
 for exactly the same reason.
@@ -1316,7 +3903,7 @@ for exactly the same reason.
 
   [Interesting Times, by Terry Pratchett]
 %e passage
-# p. 20 (speaker is Archchancellor Ridcully; sad, hopless person is Rincewind)
+# p. 20 (speaker is Archchancellor Ridcully; sad, hopeless person is Rincewind)
 %passage 5
 "Wizzard?" he said.  "What kind of sad, hopeless person needs to write
 WIZZARD on their hat?"
@@ -1616,7 +4203,7 @@ woman was a thin woman trying to get out,(1) so she'd named her Perdita.
 She was a good repository for all those thoughts that Agnes couldn't think
 on account of her wonderful personality.  Perdita would use black writing
 paper if she could get away with it, and would be beautifully pale instead
-of embarassingly flushed.  Perdita wanted to be an interestingly lost soul
+of embarrassingly flushed.  Perdita wanted to be an interestingly lost soul
 in plum-colored lipstick.  Just occasionally, though, Agnes thought
 Perdita was as dumb as she was.
 
@@ -1804,7 +4391,7 @@ years in the merchant navy and has recently fallen on hard times," and
 then unroll a lot of supercilious commentary about calluses and stance
 and the state of a man's boots, when /exactly the same/ comments could
 apply to a man who was wearing his old clothes because he'd been doing a
-spot of home bricklaying for a new barbecue pit, and had been tatooed
+spot of home bricklaying for a new barbecue pit, and had been tattooed
 once when he was drunk and seventeen(1) and in fact got seasick on a wet
 pavement.  What arrogance!  What an insult to the rich and chaotic variety
 of the human experience.
@@ -1940,7 +4527,7 @@ of course, to the bottom of the C.
 the science of this very specialized "concrete overshoe" form of waste
 disposal.  An unfortunate drawback of the process was the tendency for
 bits of the client to eventually detach and float to the surface, causing
-much comment among the general poplation.  Enough chicken wire, he pointed
+much comment among the general population.  Enough chicken wire, he pointed
 out, would solve that, while also allowing the ingress of crabs and fish
 going about their vital recycling activities.
 
@@ -2059,7 +4646,7 @@ the white and green symbolize a small parasitic plant?"
 "Exactly, Archchancellor," said the Senior Wrangler, who was now just
 hanging on.
 
-"Funny thing, that," said Ridcully, in the same thoughful tone of voice.
+"Funny thing, that," said Ridcully, in the same thoughtful tone of voice.
 "That statement is either so deep it would take a lifetime to fully
 comprehend every particle of its meaning, or it is a load of absolute
 tosh.  Which is it, I wonder?"
@@ -2159,7 +4746,7 @@ YES.  JUSTICE.  MERCY.  DUTY.  THAT SORT OF THING.
   [Hogfather, by Terry Pratchett]
 %e passage
 # p. 343 (Mr. Teatime [pronounced Teh-ah-tim-eh] has just been thwarted in
-#         his elabrate plot to lure and then kill Death)
+#         his elaborate plot to lure and then kill Death)
 %passage 10
 "What did he do it all for?" said Susan.  "I mean, why?  Money?  Power?"
 
@@ -2174,10 +4761,11 @@ Death.  OR THE FAME.  OR BECAUSE THEY SHOULDN'T.
 #
 %title Jingo (12)
 %passage 1
+# p. 206 (Harper Torch Edition; passage starts mid-paragraph)
 It was so much easier to blame it on Them.  It was bleakly depressing to
 think that They were Us.  If it was Them, then nothing was anyone's fault.
-If it was us, what did that make Me?  After all, I'm one of Us.  I must be.
-I've certainly never thought of myself as one of Them.  No one ever thinks
+If it was Us, what did that make Me?  After all, I'm one of Us.  I must be.
+I've certainly never thought of myself as one of Them.  /No one/ ever thinks
 of themselves as one of Them.  We're always one of Us.  It's Them that do
 the bad things.
 
@@ -2247,7 +4835,7 @@ please?  My clerk here will give you a list of the prime defaulters.'
 'Right, sir.  And if they resist, sir?' said Vimes, smiling nastily.
 
 'Oh, how can they resist, commander?  This is the will of our civic
-leaders.'  He took the paper his clerk proferred.  'Let me see, now.  Top
+leaders.'  He took the paper his clerk profferred.  'Let me see, now.  Top
 of the list--'
 
 Lord Selachii coughed hurriedly.  'Far too late for that sort of nonsense
@@ -2281,7 +4869,7 @@ graduate student at the University of What Some Bloke In the Pub Told Me.
 %passage 5
 "Hey, that's Reg Shoe!  He's a zombie.  He falls to bits all the time!"
 
-"Very big man in undead community, sir," said Carrott.
+"Very big man in the undead community, sir," said Carrot.
 
 "How come /he/ joined?"
 
@@ -2692,8 +5280,8 @@ comp-lic-ated documents."
 
   [Carpe Jugulum, by Terry Pratchett]
 %e passage
-# p. 336-337 (the plot is driven by the actions of a family of vampyres
-#             who do mostly cooperate with each other)
+# pp. 336-337 (the plot is driven by the actions of a family of vampyres
+#              who do mostly cooperate with each other)
 %passage 7
 Vampires are not naturally cooperative creatures.  It's not in their nature.
 Every other vampire is a rival for the next meal.  In fact, the ideal
@@ -2730,7 +5318,7 @@ A million dead people can't have been wrong, can they?
 %e passage
 # p. 233 (Harper Torch edition) [this is a footnote]
 %passage 2
-He'd noticed that sex bore some resemblance to cookery:  It facinated
+He'd noticed that sex bore some resemblance to cookery:  It fascinated
 people, they sometimes bought books full of complicated recipes and
 interesting pictures, and sometimes when they were really hungry they
 created vast banquets in their imagination--but at the end of the day
@@ -2741,7 +5329,7 @@ maybe had a slice of tomato.
 %e passage
 # pp. 80-81 (Harper Torch edition) [the pigeon is trained to carry messages]
 %passage 3
-Constable Shoe saluted, but a litle testily.  He'd been waiting rather a
+Constable Shoe saluted, but a little testily.  He'd been waiting rather a
 long time.
 
 "Afternoon, Sergeant--"
@@ -3007,22 +5595,22 @@ Day By His Wife.
   [Thief of Time, by Terry Pratchett]
 %e passage
 # p. 53 ('... with the chorus:', '"Do not act...' are separate paragraphs;
-#        'challanger' has been cowed after finding out that the little old
-#        man he challanged--for entering the dojo--is actually Lu-Tze)
+#        'challenger' has been cowed after finding out that the little old
+#        man he challenged--for entering the dojo--is actually Lu-Tze)
 %passage 3
 As Lobsang followed the ambling Lu-Tze, he heard the dojo master, who like
 all teachers never missed an opportunity to drive home a lesson, say:
 "Dojo!  What is Rule One?"
 
-Even the cowering challanger mumbled along with the chorus:
+Even the cowering challenger mumbled along with the chorus:
 
 "Do not act incautiously when confronting a little bald wrinkly smiling
 man!"
 
   [Thief of Time, by Terry Pratchett]
 %e passage
-# p. 74-75 (the novices didn't know that the little old man known as Sweeper
-#          is actually Lu-Tze; see passage 3 regarding Rule One)
+# pp. 74-75 (the novices didn't know that the little old man known as Sweeper
+#            is actually Lu-Tze; see passage 3 regarding Rule One)
 %passage 4
 One day a group of senior novices, for mischief, kicked over the little
 shrine that Lu-Tze kept beside his sleeping mat.
@@ -3214,7 +5802,7 @@ the list 'the man who arrived just before you'.
 # second paragraph is a bit "on the nose" but is too good to leave out
 %passage 2
 The reason for the story was a mix of many things.  There was humanity's
-desire to do forebidden deeds merely because they were forbidden.
+desire to do forbidden deeds merely because they were forbidden.
 There was its desire to find new horizons and kill the people who live
 beyond them.  There were the mysterious scrolls.  There was the cucumber.
 But mostly there was the knowledge that one day, it would all be over.
@@ -3322,13 +5910,231 @@ betray 'em, quick as a wink.  'Cos that's villaining.'
 %e title
 #
 #
+# _The_Amazing_Maurice_and_His_Educated_Rodents_ (sometimes spelled with
+# "his" uncapitalized--the book itself uses all uppercase on both the
+# cover and the title page so doesn't help resolve which is correct...)
+# was the first of six Discworld books marketed for "Young Adults" (at
+# least in the US), ages 12 to 16 give or take, so tended to be stocked
+# on different shelves from the rest of Discworld in book stores and
+# libraries.  In the UK, _The_Amazing_Maurice..._ won the Carnegie Medal
+# which is awarded for best children's book of the year.
+# (The other Young Adult Discworld books are the five Tiffany Aching ones.)
+#
+# _The_Amazing_Maurice..._ may well be the most serious Discworld book.
+# (Don't worry, it has lots of humor/humour in it....)
 #
-%title The Amazing Maurice and his Educated Rodents (1)
+%title The Amazing Maurice and His Educated Rodents (10)
+# p. 68 (Harperteen edition; _Mr._Bunnsy_Has_an_Adventure_ is a book
+#        within the book, and a brief quote is shown at the beginning
+#        of each chapter.  This one is from the start of chapter 4.)
 %passage 1
-The important thing about adventures, thought Mr Bunnsy, was that they
+The important thing about adventures, thought Mr. Bunnsy, was that they
 shouldn't be so long as to make you miss mealtimes.
 
-  [The Amazing Maurice and his Educated Rodents, by Terry Pratchett]
+  [The Amazing Maurice and His Educated Rodents, by Terry Pratchett]
+%e passage
+# p. 9 (passage starts mid-paragraph)
+%passage 2
+"Stealing from a thief isn't stealing, 'cos it cancels out."
+
+  [The Amazing Maurice and His Educated Rodents, by Terry Pratchett]
+%e passage
+# pp. 11-12 (rats became intelligent from eating wizards' trash just outside
+#            one of the walls of Unseen University; Maurice insists that he
+#            never did that, implying that he'd eaten some of the rats instead
+#            [never explicitly stated] before he became intelligent himself)
+%passage 3
+They said he was amazing.  The Amazing Maurice, they said.  He'd never
+meant to be amazing.  It just happened.
+
+He'd realized something was odd that day, just after lunch, when he'd
+looked into a reflection in a puddle and thought, /that's me/.  He'd never
+been /aware/ of himself before.  Of course it was hard to remember /how/
+he'd thought before becoming amazing.  It seemed to him that his mind had
+been just a kind of soup.
+
+And then there had been the rats, who lived under the rubbish heap in one
+corner of his territory.  He'd realized there was something educated
+about the rats when he'd jumped on one and it'd said, "Can we talk about
+this?" and part of his amazing new brain had told him you couldn't eat
+someone who could talk.  At least, not until you'd heard what it'd got
+to say.
+
+  [The Amazing Maurice and His Educated Rodents, by Terry Pratchett]
+%e passage
+# p. 32 (Maurice the cat, Keith the human boy, and the intelligent rat clan are
+#        in the town of Bad Blintz; people are queuing up for rationed food)
+%passage 4
+"Shall we line up too?" asked the kid.
+
+"I shouldn't think so," said Maurice carefully.
+
+"Why not?"
+
+"See those men on the door?  They look like the Watch.  They've got big
+truncheons.  And everyone's showing them a bit of paper as they go past.
+I don't like the look of that," said Maurice.  "That looks like
+/government/ to me."
+
+"We haven't done anything wrong," said the kid.  "Not here, anyway."
+
+"You never know, with governments," said Maurice.  "Just stay here kid.
+I'll take a look."
+
+  [The Amazing Maurice and His Educated Rodents, by Terry Pratchett]
+%e passage
+# p. 52 (speaker is Darktan, the traps expert; "Number One" platoon seems
+#        like an obvious joke here--missed deliberately or accidentally?)
+%passage 5
+"All right, Number Three platoon, you're on widdling duty," he said.  "Go
+and have a good drink."
+
+  [The Amazing Maurice and His Educated Rodents, by Terry Pratchett]
+%e passage
+# p. 110 (opening quote for chapter 6)
+%passage 6
+There were big adventures and small adventures, Mr. Bunnsy knew.  You
+didn't get told what size they were going to be before you started.
+Sometimes you could have a big adventure even when you were standing
+still.
+
+  [The Amazing Maurice and His Educated Rodents, by Terry Pratchett]
+%e passage
+# pp. 127-128 (searching for a secret door...)
+%passage 7
+Malicia leaned against the wall with incredible nonchalance.
+
+There was not a click.  A panel in the floor did not slide back.
+
+"Probably the wrong place," she said.  "I'll just rest my arm innocently
+on this coat hook."
+
+A sudden door in the wall completely failed to happen.
+
+"Of course, it'd help if there was an ornate candlestick," said Malicia.
+"They're always a surefire secret-passage lever.  Every adventurer knows
+that."
+
+"There isn't a candlestick," said Maurice.
+
+"I know.  Some people totally fail to have any /idea/ of how to design a
+proper secret passage," said Malicia.  She leaned against another piece
+of wall, which had no affect whatsoever.
+
+"I don't think you'll find it that way," said Keith, who was carefully
+examining a trap.
+
+"Oh?  Won't I?" said Malicia.  "Well at least I'm being /constructive/
+about things!  Where would you look, if you're such an expert?"
+
+"Why is there a rat hole in a rat catcher's shed?" said Keith.  "It smells
+of dead rats and wet dogs and poison.  I wouldn't come near this place,
+if I was a rat."
+
+Malicia glared at him.  Then her face wrapped itself in an expression of
+acute concentration, as if she was trying out several ideas in her head.
+
+"Ye-es," she said.  "That usually works, in stories.  It's often the stupid
+person who comes up with the good idea by accident."
+
+She crouched down and peered into the hole.
+
+"There's a sort of little lever," she said.  "I'll just give it a little
+push...."
+
+There was a /clonk/ under the floor, part of it swung back, and Keith
+dropped out of sight.
+
+"Oh, yes," said Malicia.  "I thought something like that would probably
+happen."
+
+  [The Amazing Maurice and His Educated Rodents, by Terry Pratchett]
+%e passage
+# p. 231 (passage ends mid-paragraph)
+%passage 8
+He had to admit that he was cleverer at plans than at underground
+navigation.  He wasn't exactly lost, because cats never get lost.  He
+merely didn't know where everything else was.
+
+  [The Amazing Maurice and His Educated Rodents, by Terry Pratchett]
+%e passage
+# pp. 298-300 (Keith has challanged the professional rat piper and offered
+#              to rid the town of rats for a much lower price; Sardines is
+#              one of the Educated Rodents, known for dancing all the time;
+#              "hwun/two/three/four/" is run-together "one /two/ three /four/";
+#              quite a long passage primarily for the 'a bit more grimy' gag)
+%passage 9
+[...]
+"But first I shall need to borrow a pipe," Keith went on.
+
+"You haven't got one?" asked the mayor.
+
+"It got broken."
+
+Corporal Knopf nudged the mayor.  "I've got a trombone from when I was in
+the army," he said.  "It won't take a moment to get it."
+
+The rat piper burst out laughing.
+
+"Doesn't that count?" asked the mayor, as Corporal Knopf hurried off.
+
+"What?  A trombone for charming rats?  No, no, let him try.  Can't blame
+a kid for trying.  Good with a trombone, are you?"
+
+"I don't know," said Keith.
+
+"What do you mean, you don't know?"
+
+"I meant I've never played one.  I'd be a lot happier with a flute,
+trumpet, piccolo, cornet, or Lancre bagpipe, but I've seen people playing
+the trombone, and it doesn't look too difficult.  It's only an overgrown
+trumpet, really."
+
+"Hah!" said the piper.  "This I'd like to see--but not hear."
+
+The Watch came running back, rubbing a battered trombone with his sleave
+and therefore making it just a bit more grimy.  Keith took it, wiped the
+mouthpiece, put it to his mouth, moved the slide a few times, and then
+blew one long note.
+
+"Seems to work," he said.  "I expect I can learn as I go along."  He gave
+the rat piper a brief smile.  "Do you want to go first?"
+
+"You won't charm one rat with that mess, kid," said the piper, "but I'm
+glad I'm here to see you try."
+
+Keith gave him a smile again, took a breath, and played.
+
+There was a tune there.  The instrument squeaked and wheezed, because
+Corporal Knopf had occasionally used the thing as a hammer, but there was
+a tune, quite fast, almost jaunty.  You could tap your feet to it.
+
+Someone tapped his feet to it.
+
+Sardines emerged from a crack in a nearby wall, going "hwun/two/three/four/"
+under his breath.  The crowd watched him dance ferociously across the
+cobbles until he disappeared into a drain.  Then they broke into applause.
+
+The piper looked at Keith.
+
+"Did that one have a /hat/ on?" he asked.
+
+"I didn't notice," said Keith.  "Your go."
+
+  [The Amazing Maurice and His Educated Rodents, by Terry Pratchett]
+%e passage
+# pp. 309-310
+%passage 10
+"You really /can/ talk?  You can think?" asked the mayor.
+
+Darktan looked up at him.  It had been a long night.  He didn't want to
+remember any of it.  And now it was going to be a longer, harder day.
+He took a deep breath.
+
+"Here's what I suggest," he said.  "You pretend that rats can think, and
+I'll promise to pretend that humans can think, too."
+
+  [The Amazing Maurice and His Educated Rodents, by Terry Pratchett]
 %e passage
 %e title
 #
@@ -4176,7 +6982,7 @@ pretty good sigh.  IT APPEARS THAT THE BUTLER DID IT.
 
 IT IS A MADE-UP STORY.  VERY STRANGE.  ALL ONE NEEDS TO DO IS TURN TO THE
 LAST PAGE AND THE ANSWER IS THERE.  WHAT, THEREFORE, IS THE POINT OF
-DELIBERATEDLY NOT KNOWING?
+DELIBERATELY NOT KNOWING?
 
 It sounded like gibberish to Vimes, so he ignored it.  Some of the aches
 had gone, although his head still hammered.  There was an empty feeling
@@ -4232,7 +7038,7 @@ favor.
 "I have been know to have the occasional 'little flutter,' sir."
 
 "Given, then, a contest between an invisible and very powerful quasidemonic
-/thing/ of pure vengence on the one hand, and the commander on the other,
+/thing/ of pure vengeance on the one hand, and the commander on the other,
 where would you wager, say... one dollar?"
 
 "I wouldn't, sir.  That looks like one that would go to the judges."
@@ -4284,10 +7090,10 @@ has anyone checked lately?
 %passage 3
 All witches are a bit odd.  Tiffany had got used to odd, so that odd seemed
 quite normal.  There was Miss Level, for example, who had two bodies,
-although one of them was imaginery.  Mistress Pullunder, who bred pedigreed
+although one of them was imaginary.  Mistress Pullunder, who bred pedigreed
 earthworms and gave them all names... well, she was hardly odd at all, just
 a bit peculiar, and anyway earthworms were quite interesting in a basically
-uninterestng kind of way.  And there had been Old Mother Dismass, who
+uninteresting kind of way.  And there had been Old Mother Dismass, who
 suffered from bouts of temporal confusion, which can be quite strange when
 it happens to a witch; her mouth never moved in time with her words, and
 sometimes her footsteps came down the stairs ten minutes before she did.
@@ -4322,9 +7128,9 @@ Treason than met the eye.
 
   [Wintersmith, by Terry Pratchett]
 %e passage
-# p. 53-54 (in Carpe Jugulum, most of the lore [for humans] about how to kill
-#           vampires had been written by long-lived/long-not-defunct vampires
-#           [meaning that it was deliberately full of inaccuracies...])
+# pp. 53-54 (in Carpe Jugulum, most of the lore [for humans] about how to kill
+#            vampires had been written by long-lived/long-not-defunct vampires
+#            [meaning that it was deliberately full of inaccuracies...])
 %passage 6
 It was in fact Miss Tick who had written /Witch Hunting for Dumb People/,
 and she made sure that copies of it found their way into those areas where
@@ -4340,7 +7146,7 @@ even underwater.
 
   [Wintersmith, by Terry Pratchett]
 %e passage
-# p. 55-56
+# pp. 55-56
 %passage 7
 Working quickly, she emptied her pockets and started a shamble.
 
@@ -4405,8 +7211,8 @@ dark art.  It was just so /hard/.
 
   [Wintersmith, by Terry Pratchett]
 %e passage
-# p. 126-127 (passage starts mid-paragraph;
-#             witches know in advance when they're going to die)
+# pp. 126-127 (passage starts mid-paragraph;
+#              witches know in advance when they're going to die)
 %passage 10
 "[...]  We shall hold the funeral tomorrow afternoon."
 
@@ -4433,8 +7239,8 @@ witches is an "argument."
 
   [Wintersmith, by Terry Pratchett]
 %e passage
-# p. 174-175  (passage starts mid-paragraph; last paragraph continues, but
-#         changes topic so abruptly Tiffany gasps; 'rumbustious' is accurate)
+# pp. 174-175 (passage starts mid-paragraph; last paragraph continues, but
+#          changes topic so abruptly Tiffany gasps; 'rumbustious' is accurate)
 %passage 12
 "[...]  And now I shall tell you something vitally important.  It is the
 secret of my long life."
@@ -4490,7 +7296,7 @@ as good as she ought to be.
 
   [Wintersmith, by Terry Pratchett]
 %e passage
-# p. 360-361 ('wurds' is accurate)
+# pp. 360-361 ('wurds' is accurate)
 %passage 15
 "An heroic effect, Mr. Anybody," said Granny.  "The first thing a hero must
 conquer is his fear, and when it comes to fightin', the Nac Mac Feegle
@@ -4501,7 +7307,7 @@ o' wurds!"
 
   [Wintersmith, by Terry Pratchett]
 %e passage
-# p. 398-399 ("Chumsfanleigh" is pronounced "Chuffley")
+# pp. 398-399 ("Chumsfanleigh" is pronounced "Chuffley")
 %passage 16
 At the back of the Feegles' chalk pit, more chalk had been carved out of
 the wall to make a tunnel about five feet high and perhaps as long.
@@ -4594,7 +7400,7 @@ within an inch of your life."
 only got two paragraphs in the /Tanty Bugle/!(1)  Two paragraphs, may I
 say, for a life of ingenious, inventive, and strictly nonviolent crime?
 I could have been an example to the youngsters!  Page one got hogged by
-the Dyslectic Alphabet Killer, and he only maanaged A and W!"
+the Dyslectic Alphabet Killer, and he only managed A and W!"
 
 "I confess the editor does appear to believe that it is not a proper crime
 unless someone is found in three alleys at once, but that is the price of
@@ -4615,7 +7421,7 @@ Moist winced at this.  "And if I /don't/ do what you say?"
 "Hmm?  Oh, you misunderstand me, Mr. Lipwig.  That is what will happen to
 you if you decline my offer.  If you accept it, you will survive on your
 wits against powerful and dangerous enemies, with every day presenting
-fresh challanges.  Someone may even try to kill you."
+fresh challenges.  Someone may even try to kill you."
 
 "What?  Why?"
 
@@ -4649,7 +7455,7 @@ It was from Spike!
 
 He read:
 
-    SUCCESS.  RETURNING DAY AFTER TOMMOROW.
+    SUCCESS.  RETURNING DAY AFTER TOMORROW.
     ALL WILL BE REVEALED.  S.
 
 Moist put it down carefully.
@@ -4941,7 +7747,7 @@ keen night vision to find.  He had already seen some luminous spoon ants
 carrying a fork, and, to his surprise, the forgotten mazes were home to
 that very rare indoorovore, the Uncommon Sock Eater.  There were some
 things living up in the pipes, too, which periodically murmured "Awk! Awk!"
-Who knew what strange monsters made there home here?
+Who knew what strange monsters made their home here?
 
   [Unseen Academicals, by Terry Pratchett]
 %e passage
@@ -4991,7 +7797,7 @@ pp'd at all.  Incidentally, how loud were his screams?"
 
   [Unseen Academicals, by Terry Pratchett]
 %e passage
-# p. 192-193 ('pants': underpants; 'football': soccer ;-)
+# pp. 192-193 ('pants': underpants; 'football': soccer ;-)
 %passage 9
 "You will arrange yourself into two teams, set up goals, and strive to win!
 No man will leave the field of play unless injured!  The hands are not to
@@ -5039,7 +7845,7 @@ raised his voice.  "Arrange yourselves into two teams and play football!"
 # p. 268 (passage starts mid-paragraph; Glenda is cleaning UU's Night Kitchen)
 %passage 10
 [...]  If you wanted a job done properly, you had to do it yourself.
-Juliet's verison of cleanliness was next to godliness, which was to say
+Juliet's version of cleanliness was next to godliness, which was to say
 it was erratic, past all understanding and seldom seen.
 
   [Unseen Academicals, by Terry Pratchett]
@@ -5263,17 +8069,259 @@ ag-rreeeed arr-angement, ye ken!"
 #
 #
 #
-%title Snuff (2)
+%title Snuff (16)
+# p. 168 (Harper edition; 'ax' is spelled without the 'e' there...)
 %passage 1
 They were crude weapons, to be sure, but a flint axe hitting your head does
-not need a degree in physics.  
+not need a degree in physics.
 
   [Snuff, by Terry Pratchett]
 %e passage
 %passage 2
-It is a strange thing to find yourself doing something you 
-have apparently always wanted to do, when in fact up until 
-that moment you had never known that you always wanted to do it...
+It is a strange thing to find yourself doing something you have apparently
+always wanted to do, when in fact up until that moment you had never known
+that you always wanted to do it...
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 2 (the subject is goblins)
+%passage 3
+At this point, Lord Vetinari, Patrician of Ankh-Morpork, stopped reading
+and stared at nothing.  After a few seconds, nothing was eclipsed by the
+form of Drumknott, his secretary (who, it must be said, had spent a career
+turning himself as much like nothing as anything).
+
+Drumknott said, "You look pensive, my lord," to which observation he
+appended a most delicate question mark, which gradually evaporated.
+
+"Awash with tears, Drumknott, awash with tears."
+
+Drumknott stopped dusting the impeccably shiny black lacquered desk.
+"Pastor Oats is a very persuasive writer, isn't he, sir...?"
+
+"Indeed he is, Drumknott, but the basic problem remains and it is this:
+humanity may come to terms with the dwarf, the troll and even the orc,
+terrifying though all these have proved to be at times, and you know why
+this is, Drumknott?"
+
+The secretary carefully folded the duster he had been using and looked at
+the ceiling.  "I would venture to suggest, my lord, that in their violence
+we recognize ourselves?"
+
+"Oh, well done, Drumknott, I shall make a cynic of you yet!  Predators
+respect other predators, do they not?  They may perhaps even respect the
+prey:  the lion may lie down with the lamb, even if only the lion is
+likely to get up again, but the lion will not lie down with the rat.
+Vermin, Drumknott, an entire race reduced to vermin!"
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 6
+%passage 4
+Vimes grunted.  "Where there are policemen there's crime, sergeant,
+remember that."
+
+"Yes, I do, sir, although I think it sounds better with a little reordering
+of the words."
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# pp. 46-47 (passage starts mid-paragraph and ends mid-paragraph; it's a
+#           long slog for a weak punchline...)
+%passage 5
+"[...]  The third earl, 'Mad' Jack Ramkin, had a brother called
+Woolsthorpe, probably for his sins.  He was something of a scholar and
+would have been sent to the university to become a wizard were it not for
+the fact that his brother let it be known that any male sibling of his who
+took up a profession that involved wearing a dress would be disinherited
+with a cleaver.
+
+"Nevertheless, young Woolsthorpe persevered in his studies in natural
+philosophy in the way a gentleman should, by digging into any suspicious-
+looking burial mounds he could find in the neighborhood, filling up his
+lizard press with as many rare species as he could collect, and drying
+samples of any flowers he could find before they became extinct.  The
+story runs that, on one warm summer day, he dozed off under an apple tree
+and was awakened when an apple fell on his head.  A lesser man, as his
+biographer put it, would have seen nothing untoward about this, but
+Woolsthorpe surmised that, since apples and practically everything else
+always fell down, then the world would eventually become dangerously
+unbalanced... unless there was another agency involved that natural
+philosophy had yet to discover.  He lost no time in dragging one of the
+footmen to the orchard and ordering him, on the pain of dismissal, to lie
+under the tree until an apple hit him on the head!  The possibility of
+this happening was increased by another footman who had been told by
+Woolsthorpe to shake the tree vigorously until the required apple fell.
+Woolsthorpe was ready to observe this from a distance.
+
+"Who can imagine his joy when the inevitable apple fell and a second apple
+was seen rising from the tree and disappearing at speed into the vaults of
+heaven, proving the hypothesis that what goes up must come down, provided
+that what goes down must come up, thus safeguarding the equilibrium of the
+Universe.  Regrettably, this only works with apples and, amazingly, only
+the apples on this one tree, /Malus equilibria/!  I hear that someone has
+worked out that the apples at the top of the tree fill with gas and fly up
+when the tree is disturbed so that it can set its seeds some way off.
+Wonderful thing, nature, shame the fruit tastes like dog's business,"
+Willikins added as Young Sam spat some out.  [...]
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 100
+%passage 6
+"Look, Willikins, I don't like to involve you in all this.  It's only a
+hunch, after all."
+
+Willikins waved this away.  "You wouldn't keep me out of it for a big
+clock, sir, because all this is tickling my fancy as well.  I shall lay
+out a selection of cutting edges for you in your dressing room, sir, and I
+myself will go up to the copse half an hour before you're due to be there,
+with my trusty bow and an assortment of favorite playthings.  It's nearly
+full moon, clear skies, there'll be shadows everywhere, and I'll be
+standing in the darkest one of them."
+
+Vimes looked at him for a moment and said, "Could I please amend that
+suggestion?  Could you not be there in the second darkest shadow one hour
+before midnight, to see who steps into the darkest shadow?"
+
+"Ah yes, that's why you command the watch, sir," said Willikins, and to
+Vimes's shock there was a hint of a tear in the man's voice.  "You're
+listening to the street, aren't you, sir, yes?"
+
+Vimes shrugged.  "No streets here, Willikins."
+
+Willikins shook his head.  "Once a street boy, always a street boy, sir.
+It comes with us, in the pinch.  Mothers go, fathers go--if we ever knew
+who they were--but the Street, well, the Street looks after us.  In the
+pinch it keeps us alive."
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 116 (passage ends mid-paragraph)
+%passage 7
+Well, we live and learn, Vimes thought, or perhaps more importantly, we
+learn and live.  [...]
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 153
+%passage 8
+In the country, there is always somebody watching you, he thought as they
+sped along.  Well, there was always somebody watching you in the city, too,
+but that was generally in the hope that you might drop dead and they could
+run off with your wallet.  They were never /interested/.  But here he
+thought he could feel many eyes on him.  Maybe they belonged to squirrels
+or badgers, or whatever the damn things were that Vimes heard at night;
+gorillas, possibly.
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# pp. 169-170
+%passage 9
+"Well, sir, it looks as though they're pleased to see us, yes?"
+
+Feeney's relief and hope should have been bottled and sold to despairing
+people everywhere.  Vimes just nodded, because the ranks were pulling
+apart, leaving a pathway of sorts, at the end of which there was,
+inarguably, a corpse.  It was a mild relief to see that it was a goblin
+corpse, but no corpse is good news, particularly when seen in a grimy low
+light and especially for the corpse.  And yet something inside him exulted
+and cried /Hallelujah!/, because here was a corpse and he was a copper
+and this was a crime and this place was smoky and dirty and full of
+suspicious-looking goblins and here was a /crime/.  His world.  Yes, here
+was /his/ world.
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 211
+%passage 10
+Vimes lay back in the bed, enjoying the wonderful sensation of gradually
+being eaten by the pillows, and said to Sybil, "Do the Rust family have a
+place down here?"
+
+Too late he reflected that this might be a bad move because she might well
+have told him all about it on one of those occasions when, so unusually for
+a married man, he was not paying much attention to what his wife was
+saying, and therefore he might be the cause of grumpiness in those
+precious, warm minutes before sleep.  All he could see of her right now
+was the very tip of her nose, as the pillows claimed her, but she mumbled,
+drowsily, "Oh, they bought Hangnail Manor ten years or so ago, after the
+Marquis of Fantailer murdered his wife with a pruning knife in the
+pineapple house.  Don't you remember?  You spent weeks searching the city
+for him.  In the end everybody seemed to think he'd gone off to Fourecks
+and disguised himself by not calling himself the Marquis of Fantailer."
+
+"Oh yes," said Vimes, "and I remember that a lot of his chums were quite
+indignant about the investigation!  They said he'd only done one murder,
+and it was his wife's fault for having the bad taste to die after just one
+little stab!"
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 212 (passage starts mid-paragraph and ends mid-paragraph)
+%passage 11
+[...] he had heard that writers spent all day in their dressing gowns
+drinking champagne.(1)  [...]
+
+(1) This is, of course, absolutely true.
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 217 (passage starts mid-paragraph and ends mid-paragraph)
+%passage 12
+"[...] and the Summoning Dark is /real/.  It's not all in your head,
+commander:  no matter what you hear, I sometimes hear it too.  Oh dear,
+you of all people must recognize a substition when you're possessed by it?
+It's the opposite of superstition:  it's real even if you don't believe
+in it.  [...]"
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 233
+%passage 13
+Vimes frowned.  He couldn't remember ever going into a church or a temple
+or one of the numerous other places of more or less spirituality for any
+other reason than the occasional requirements of the job.  These days he
+tended to go in for reasons of Sybil, i.e., his wife dragging him along
+so that he could be seen, and, if possible, seen remaining awake.
+
+No, the world of next worlds, afterlives, and purgatorial destinations
+simply did not fit into his head.  Whether you wanted it or not, you were
+born, you did the best you could, and then, whether you really wanted to
+or not, you died.  They were the only certainties, and so the best thing
+for a copper to do was to get on with the job.  And it was about time
+that Sam Vimes got back to doing his.
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 254 (passage starts mid-paragraph)
+%passage 14
+[...]  And maybe if I distinguish myself I can get a job in the city, so
+that my mum can live in a place where you don't lie awake at night
+listening to the mice fighting the cockroaches--hooray!(1)
+
+(1) Regrettably, Constable Upshot was overly hopeful:  in Ankh-Morpork the
+mice and cockroaches had decided to forget their differences and gang up
+on the humans.
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 403 (passage starts mid-paragraph)
+%passage 15
+"[...]  And I remember reading somewhere that you would arrest the gods
+for doing it wrong."
+
+Vimes shook his head.  "I'm sure I never said anything of the sort!  But
+law is order and order is law and it must be the highest thing.  The world
+runs on it, the heavens run on it and without order, lad, one second
+cannot follow another."
+
+  [Snuff, by Terry Pratchett]
+%e passage
+# p. 404 (footnote)
+%passage 16
+The sound of the gentle rattle of china cup on china saucer drives away
+all demons, a little-known fact.
 
   [Snuff, by Terry Pratchett]
 %e passage
@@ -5281,18 +8329,19 @@ that moment you had never known that you always wanted to do it...
 #
 #
 #
-%title Raising Steam (8)
+%title Raising Steam (13)
+# p. 281 (Anchor Books edition; passage starts mid-paragraph)
 %passage 1
-Yesterday you never thought about it and after today you 
-don't know what you would do without it. 
-
-That was what the technology was doing. 
+[...]  And yesterday you never thought about it and after today you don't
+know what you would do without it.  That was what the technology was doing.
 It was your slave but, in a sense, it might be the other way round.
 
   [Raising Steam, by Terry Pratchett]
 %e passage
+# p. 358 (passage starts mid-paragraph and ends mid-paragraph; quote is
+#         attributed to Lord Vetinari but he's not present in the scene)
 %passage 2
-If you take enough precautions, you never need to take precautions.
+"If you take enough precautions, you never need to take precautions."
 
   [Raising Steam, by Terry Pratchett]
 %e passage
@@ -5378,7 +8427,7 @@ There was a young goblin waiting there, rather nervous, clasping what
 looked like two wheels held together by not very much.  The wheels were
 spinning.
 
-Durmknott cleared his throat.  "Show his lordship your new invention,
+Drumknott cleared his throat.  "Show his lordship your new invention,
 Mister Of the Wheel the Spoke."
 
 (1) Frankly most palaces are just like this.  Their backsides do not bear
@@ -5386,27 +8435,219 @@ looking at.
 
   [Raising Steam, by Terry Pratchett]
 %e passage
+##
+# passages 9..13 added after 3.6.0's release
+##
+# pp. 20-21
+%passage 9
+Moist Von Lipwig had done some heavy work once and couldn't see any future
+in it, but he could look at it for hours, provided other people were doing
+it, of course, and clearly some of them liked what they were doing, and so
+he shrugged and felt happy that Crisp was happy being a handyman whilst
+Moist was happy not picking up anything that was heavier than a glass.
+After all, his work was unseen and depended on words, which were
+fortunately not very heavy and didn't need grease.  In his career as a
+crook they had served him well and now he felt somewhat smug at using them
+to the benefit of the citizenry.
+
+There was a difference between a banker and a crook, there really was, and
+although it was very, very teeny Moist felt that he should point out that
+it did exist and, besides, Lord Vetinari always had his eye on him.
+
+So everybody was happy and Moist went to work in very clean clothes and
+with a very clean conscience.
+
+  [Raising Steam, by Terry Pratchett]
+%e passage
+# p. 22
+%passage 10
+Harry, red-faced and impatient, looked over his desk and said to him, "Lad,
+time is money and I'm a busy man.  You told Nancy down on reception that
+you've got something I might like.  Now stop fidgeting and look me in the
+face square like.  If you're another chancer wanting to bamboozle me I'll
+have you down the Effing stairs(1) before you know it."
+
+(1) The wonderfully colored oak wood of the Effing Forest was much in
+demand for high-class joinery.
+
+  [Raising Steam, by Terry Pratchett]
+%e passage
+# p. 80
+%passage 11
+Moist knew about the zeitgeist, he tasted it in the wind, and sometimes it
+allowed him to play with it.  He understood it, and now it hinted at speed,
+escape, something wonderfully new, the very bones of the land awakening,
+and suddenly it seemed to cry out for motion, new horizons, faraway places,
+/anywhere that is not here/!  No doubt about it, the railway was going to
+turn coal into gold.
+
+  [Raising Steam, by Terry Pratchett]
+%e passage
+# p. 195 (passage starts mid-paragraph and ends mid-paragraph)
+%passage 12
+And the trouble with madness was that the mad didn't know they were mad.
+
+  [Raising Steam, by Terry Pratchett]
+%e passage
+# p. 284 (passage starts mid-paragraph; speaker is Cmdr Vimes of the Watch)
+%passage 13
+"[...]  That's the trouble, you see.  When you've had hatred on your tongue
+for such a long time, you don't know how to spit it out."
+
+  [Raising Steam, by Terry Pratchett]
+%e passage
 %e title
-%title The Shepherd's Crown (1)
+#
+#
+# Sir Terry Pratchett's final book, published posthumously.
+# The story is complete, but the length is substantially shorter than
+# other recent Discworld novels.  Presumably it would have been expanded
+# if he had had more time to work on it....
+#
+%title The Shepherd's Crown (7)
+# pp. 29-30 (Harper edition)
 %passage 1
-'It's an inconvenience, true enough, and I don't like it at all, but I
-know that you do it for everyone, Mister Death. Is there any other way?'
+"It's an inconvenience, true enough, and I don't like it at all, but I
+know that you do it for everyone, Mr. Death.  Is there any other way?"
+
+NO, THERE ISN'T, I'M AFRAID.  WE ARE ALL FLOATING IN THE WINDS OF TIME.
+BUT YOUR CANDLE, MISTRESS WEATHERWAX, WILL FLICKER FOR SOME TIME BEFORE
+IT GOES OUT--A LITTLE REWARD FOR A LIFE WELL LIVED.  FOR I CAN SEE THE
+BALANCE AND YOU HAVE LEFT THE WORLD MUCH BETTER THAN YOU FOUND IT, AND
+IF YOU ASK ME, said Death, NOBODY COULD DO ANY BETTER THAN THAT....
+
+  [The Shepherd's Crown, by Terry Pratchett]
+%e passage
+# p. 30 ('she' is Miss Tick, a travelling witch who finds new witches;
+#        'under water' is spelled as two words; 'ducking' is accurate)
+%passage 2
+She sighed.  It was such a shame when old customs disappeared.  A good
+witch-ducking was something she had liked doing in the bad old days--she
+had even /trained/ for it.  All those swimming lessons, and practice with
+knots at the Quirm College for Young Ladies.  She had been able to defeat
+the mobs under water if necessary.  Or at least work at breaking her own
+record for untying the simple knots they all thought worked on the nasty
+witch.
+
+Now, a bit of pond-dipping had become more like a hobby, and she had a
+nasty feeling that others were copying her after she passed through their
+villages.  She'd even heard talk of a swimming club being started in one
+small hamlet over by Ham-on-Rye.(1)
+
+(1) A popular idea among the young lads, since they felt that everyone--
+and "everyone" definitely included the young ladies--should swim without
+their clothes.
+
+  [The Shepherd's Crown, by Terry Pratchett]
+%e passage
+# p. 37 (passage starts mid-paragraph; 'she' is Tiffany Aching)
+%passage 3
+Not for the first time, she wondered how it was that cats seemed to be
+able to be in one place one moment, and then /almost at the same time/,
+reappear somewhere else.(1)
+
+(1) She did not know it, but a keen young philosopher in Ephebe had
+pondered exactly that same conumdrum, until he was found one morning--
+most of him, anyway--surrounded by a number of purring, and very well fed,
+cats.  No one had seemed keen to continue his experiments after that.
+
+  [The Shepherd's Crown, by Terry Pratchett]
+%e passage
+# pp. 112-113 (the footnote has a misprint of mismatched quotes: "Chuffley')
+%passage 4
+Roland de Chumsfanleigh,(1) the young Baron on the Chalk /did/ want to be
+like his father in many ways.  He knew the old man had been popular--what
+was known as an "old-school Baron," which meant that everyone knew what
+to expect and the guards polished up their armor and saluted, and did
+what was expected of /them/, while the Baron did what was expected of him,
+and pretty much left them alone.
+
+But his father had also been a bit of a bad-tempered bully at times.  And
+/that/ bit Roland wanted to forget about.  He particularly wanted to sound
+the right note when he called round to see Tiffany Aching at Home Farm.
+For they had once been good friends, and to Roland's alarm, Tiffany was
+thought of as a good friend by his wife Letitia.  Any man with sense was
+wise to be fearful of a wife's best friends.  For who knew what ... little
+secrets might be shared.  Roland, having been educated at home and with
+limited knowledge of the world outside the Chalk, feared that "little"
+might be /exactly/ the kind of comment Letitia might share with Tiffany.
+
+(1) Pronounced "Chuffley" under the strange rule that the more gentrified
+a family is, the more peculiar the pronunciation of their name becomes.
+Tiffany had once heard a high-born visitor named Ponsonby-Macklewright
+(/Pwt/) refer to Roland as /Chf/.  She wondered how they managed at dinner
+when /Pwt/ introduced /Chf/ to /Wm/ or /Hmpfh/.  Surely it could lead to
+misunderstandings?
+
+  [The Shepherd's Crown, by Terry Pratchett]
+%e passage
+# p. 158
+%passage 5
+He kicked the helmet of his chief, the Big Man of the clan, and shouted,
+"There's elves here!  I can smell it, ye ken!"
+
+And from every hole in turn, the clan of the Nac Mac Feegle poured out in
+their hundreds to deal with the ancient enemy, waving claymores and swords,
+yodeling their war cries:
+
+"Ach, stickit yer trakkans!"
 
-NO, THERE ISN'T, I'M AFRAID. WE ARE ALL FLOATING IN THE WINDS OF TIME. 
-BUT YOUR CANDLE, MISTRESS WEATHERWAX, WILL FLICKER FOR SOME TIME BEFORE 
-IT GOES OUT -- A LITTLE REWARD FOR A LIFE WELL LIVED. FOR I CAN SEE THE 
-BALANCE AND YOU HAVE LEFT THE WORLD MUCH BETTER THAN YOU FOUND IT, AND 
-IF YOU ASK ME, said Death, NOBODY COULD DO ANY BETTER THAN THAT. . . 
+"Nac Mac Feegle wha hae!"
+
+"Gae awa' wi' ye, yer bogle!"
+
+"Gi'e you sich a guid kickin'!"
+
+"Nae king!  Nae quin!  We will nae be fooled agin!"
+
+There is a concept known as a hustle and bustle, and the Feegles were very
+good at it, cheerfully getting in one another's way in the drive to be the
+first into battle, and it seemed as if each small warrior had a battle cry
+of his own--and he was very ready to fight anyone who tried to take it
+away from him.
+
+"How many elves?" asked Rob Anybody, trying to adjust his spog.
+
+There was a pause.
+
+"One," said Big Yan sheepishly.
+
+  [The Shepherd's Crown, by Terry Pratchett]
+%e passage
+# p. 159 (passage starts mid-paragraph. 'oor' is accurate)
+%passage 6
+"This elf is oor prisoner.  A hostage, ye ken.  That means ye are nae tae
+kill it until ye are told."  He ignored the grumbles from the clan.  "As
+tae the rest o' ye, tak guard around yon stones.  And if they come in
+force, show them what the Feegles can dae!"
+
+Daft Wullie said, "I can play the harmonica."
+
+Rob Anybody sighed.  "Aye, weel, I suppose that puts the willies up me,
+so wud likely keep them awa'."
+
+  [The Shepherd's Crown, by Terry Pratchett]
+%e passage
+# p. 202
+%passage 7
+Sometimes, Tiffany thought, I am so /fed up/ with being young.(1)
+
+(1) A thought that she would most certainly grow out of, assuming she
+survived long enough.
 
   [The Shepherd's Crown, by Terry Pratchett]
 %e passage
 %e title
+#
 %e section
+#
 #-----------------------------------------------------
 # Used for interaction with Death.
 #
+# Death Quotes are always one line, and '%e passage' can be omitted.
+#
 %section Death
-%title Death Quotes (10)
+%title Death Quotes (31)
 %passage 1
 WHERE THE FIRST PRIMAL CELL WAS, THERE WAS I ALSO. WHERE MAN IS, THERE AM I.  WHEN THE LAST LIFE CRAWLS UNDER FREEZING STARS, THERE WILL I BE.
 %e passage
@@ -5446,5 +8687,76 @@ THERE IS ALWAYS TIME FOR ANOTHER LAST MINUTE.
 MUSTARD IS ALWAYS TRICKY.
 %passage 10
 PICKLES OF ALL SORTS DON'T SEEM TO MAKE IT.  I'M SORRY.
+# The Colour of Magic, p. 68 (Signet edition)
+%passage 11
+IT WON'T HURT A BIT.
+# p. 177
+%passage 12
+SHALL WE GO?
+# p. 251 (speaker is actually a demon named 'Scrofula' filling in for Death)
+%passage 13
+I HAVE COME FOR THEE.
+# The Light Fantastic, p. 52 (Signet edition; quote has quotation marks but
+#                             including them here wouldn't fit with the rest;
+#                             Death is addressing an elderly wizard who went
+#                             to extreme measures to hide himself [from Death])
+%passage 14
+DARK IN HERE, ISN'T IT?
+# Equal Rites, p. 14 (Signet edition; second sentence continues
+#                     'said the deep, heavy voice...')
+%passage 15
+THERE IS NO GOING BACK.  THERE IS NO GOING BACK.
+# p. 15 (contradicts later descriptions of Death as existing outside of time;
+#        presumably it's just intended as a colloquial expression)
+%passage 16
+I HAVEN'T GOT ALL DAY, YOU KNOW.
+# p. 15 (same page)
+%passage 17
+LIFE IS FOR THE LIVING.
+# Mort, p. 148 (Signet edition)
+%passage 18
+NO-ONE EVER WANTED TO TALK TO ME BEFORE.
+# p. 149
+%passage 19
+I HAVEN'T GOT A SINGLE FRIEND.  EVEN CATS FIND ME AMUSING.
+# Sourcery, p. 12 (Signet edition)
+%passage 20
+YOU'RE ONLY PUTTING OFF THE INEVITABLE.
+# Wyrd Sisters, p. 11 (ROC edition)
+%passage 21
+I SAID WAS.  IT'S CALLED THE PAST TENSE.  YOU'LL SOON GET USED TO IT.
+# p. 13
+%passage 22
+DON'T LET IT UPSET YOU.
+# Pyramids, p. 57 (ROC edition)
+%passage 23
+I CAN SEE THAT YOU HAVE GOT A LOT TO THINK ABOUT.
+# Eric, p. 134 (Harper Torch edition)
+%passage 24
+PERHAPS IT'S TIME TO CALL IT A DAY.
+# Moving Pictures, p. 260 (ROC edition)
+%passage 25
+I KNOW WHEN EVERYONE'S HAD ENOUGH.
+# Reaper Man, p. 10 (ROC edition)
+%passage 26
+I HAVE ALWAYS DONE MY DUTY AS I SAW FIT.
+# p. 18
+%passage 27
+I AM NOT KNOWN FOR MY SENSE OF FUN.
+# p. 160
+%passage 28
+I MEAN THAT THERE IS A TIME FOR EVERYONE TO DIE.
+# p. 227
+%passage 29
+JUST BECAUSE SOMETHING IS A METAPHORE DOESN'T MEAN IT CAN'T BE REAL.
+# p. 334
+%passage 30
+I AM ALWAYS ALONE.  BUT JUST NOW I WANT TO BE ALONE BY MYSELF.
+# Witches Abroad, p. 298 (Death's explanation why he didn't come for zombie 12
+#                         years earlier:  YOU STOPPED LIVING.  YOU NEVER DIED.)
+%passage 31
+I HAD AN APPOINTMENT WITH YOU TONIGHT.
 %e title
 %e section
+#
+#eof
index 28284cf..ee61a2e 100644 (file)
@@ -1,23 +1,28 @@
 \83f\83o\83b\83O\83\82\81[\83h\81F
 
-^E  ==  \94é\96§\82Ì\83h\83A\82âã©\82ð\92²\82×\82é\81D
-^F  ==  \96\82\96@\82Ì\92n\90}\81D
-^G  ==  \89ö\95¨\82ð\91¢\82é\81D
-^I  ==  \8e\9d\82¿\95¨\82ð\8e¯\95Ê\82·\82é\81D
-^O  ==  \93Á\8eê\8aK\82Ì\88Ê\92u\82ð\92m\82é\81D
-^T  ==  \82»\82Ì\8aK\82Å\82Ì\8fu\8aÔ\88Ú\93®\81D
-^V  ==  \88á\82¤\8aK\82Ö\82Ì\8fu\8aÔ\88Ú\93®\81D
-^W  ==  \96]\82Ý\82ð\82©\82È\82¦\82é\81D
-^X  ==  \91®\90«\82ð\8c©\82é\81D
+^E  ==  \94é\96§\82Ì\83h\83A\82âã©\82ð\92²\82×\82é
+^F  ==  \96\82\96@\82Ì\92n\90}
+^G  ==  \89ö\95¨\82ð\91¢\82é
+^I  ==  \8e\9d\82¿\95¨\82ð\8e¯\95Ê\82·\82é
+^T  ==  \82»\82Ì\8aK\82Å\82Ì\8fu\8aÔ\88Ú\93®
+^V  ==  \88á\82¤\8aK\82Ö\82Ì\8fu\8aÔ\88Ú\93®; '?'\82Å\93Á\95Ê\82È\8ds\90æ\82Ö\82Ì\83\81\83j\83\85\81[
+^W  ==  \96]\82Ý\82ð\82©\82È\82¦\82é(\95¨\82©ã©\82©\88ê\95\94\82Ì\92n\8c`)
+^X  ==  \91®\90«\82ð\8c©\82é(\8ag\92£\82³\82ê\82½\8c[\96Ö)
 
-#levelchange == change experience level
-#lightsources == show mobile light sources
+#levelchange    == set hero's experience level
+#lightsources   == show mobile light sources
 #monpolycontrol == control monster polymorphs
-#panic == panic test
-#polyself == polymorph self
-#seenv == show seen vectors
-#stats == show memory statistics
-#timeout == look at timeout queue
-#vision == show vision array
-#wmode == show wall modes
-
+#panic          == panic test (warning: current game will be terminated)
+#polyself       == polymorph self
+#seenv          == show seen vectors
+#stats          == show memory statistics
+#terrain        == show current level (more options than in normal play)
+#timeout        == look at timeout queue and hero's timed intrinsics
+#vanquished     == disclose counts of dead monsters sorted in various ways
+#vision         == show vision array
+#wizintrinsic   == set selected intrinsic timeouts
+#wizmakemap     == recreate the current dungeon level
+#wizrumorcheck  == validate first and last rumor for true and false set
+#wizsmell       == smell a monster
+#wizwhere       == show dungeon placement of all special levels
+#wmode          == show wall modes
index 1e56a79..9b21196 100644 (file)
@@ -1,11 +1,28 @@
-.\" $NHDT-Branch: master $:$NHDT-Revision: 1.188 $ $NHDT-Date: 1449420465 2015/12/06 16:47:45 $
+.\" $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.264 $ $NHDT-Date: 1524690677 2018/04/25 21:11:17 $
+.\"
+.\" This is an excerpt from the 'roff' man page from the 'groff' package.
+.\" NetHack's Guidebook.mn currently does *not* adhere to these guidelines.
+.\"|||
+.\"| o Never include empty or blank lines in a roff document.  Instead,  use
+.\"|   the empty request (a line consisting of a dot only) or a line comment
+.\"|   .\" if a structuring element is needed.
+.\"| o Never start a line with whitespace because this can lead to unexpect-
+.\"|   ed  behavior.  Indented paragraphs can be constructed in a controlled
+.\"|   way by roff requests.
+.\"| o Start each sentence on a line of its own, for the spacing after a dot
+.\"|   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.
+.\"|||
+.\"
 .ds h0 "NetHack Guidebook
 .ds h1
 .ds h2 %
 .ds vr "NetHack 3.6
 .ds f0 "\*(vr
 .ds f1
-.ds f2 "December 7, 2015
+.ds f2 "April 27, 2018
+.
 .\" labeled paragraph start (should be part of tmac.n, but I don't want to
 .\" make changes to that file)
 .\" .PS word
@@ -26,7 +43,7 @@
 .br
 \\h'|-\\n(PYu'\\$1\\h'|-\\n(PXu'\ -\ \\c \" back up, output the label, then
 .                                      \" skip to width-of(" - ") before the
-.                                      \" normal indentation, output the " - " 
+.                                      \" normal indentation, output the " - "
 .                                      \" then attach the next line (the
 .                                      \" text) without stopping (\c: nroff
 .                                      \" section 4.2)
 .\"  the full width of the column, print " - " and the definition
 \\h'|\\n(CYu'\\fB\\$1\\fP\\h'|\\n(CZu'\ -\ \\$2
 ..
+.\" '.UX' is verbatim copy of tmac.n's '.ux' with the exception that
+.\" the trademark owner for "UNIX" has been updated.  (tmac.n contains
+.\" a comment asking that modified versions not be distributed, so we
+.\" are using this substitute instead of modifying that file.)
+.de UX                                 \" print "UNIX"
+.ie \\n(ux \\&\\$2\\s-1UNIX\\s0\\$1
+.el \{\
+.      nr ux +1                        \" mark footnote as dropped
+\\&\\$2\\s-1UNIX\\s0\\*(rg\\$1
+.      fn                              \" put out the footnote
+\\&\\*(rgUNIX is a registered trademark of The Open Group.
+.      ef                              \" short and sweet ...
+.\}
+..
+.
+.\" A note on some special characters:
+.\"                                    \(dq = double quote character
+.\"  - = hyphen                        \-   = minus sign
+.\"                                    \(em = M-sized dash
+.\"  ^ = small circumflex punctuation  \(ha = larger circumflex character
+.\"  ~ = small tilde punctuation       \(ti = larger tilde character
+.
+.
+.\" finally, start the actual Guidebook...
+.
 .mt
 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)
-.hu
-Preface - Version 3.6
-.pg
-This version of the game is special in a particular way.  Near the end of
-the development of 3.6, one of the significant inspirations for many of the 
-humorous and fun features found in the game, author \fITerry Pratchett\fP,
-passed away.  We have dedicated this version of the game in his memory.
 .hn 1
 Introduction
 .pg
-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 
+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 
+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?
-
+.
 .pg
 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.  
-
-.pg
-  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 morning, you 
-gather your gear, eat what may be your last meal outside, and enter 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.
+.
+.pg
+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 morning, you
+gather your gear, eat what may be your last meal outside, and enter the
 dungeon...
-
+.
 .hn 1
 What is going on here?
 .pg
@@ -244,7 +279,8 @@ 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.
-
+.
+.ft CR \" set font to constant-width Roman
 .TS S
 center tab(~);
 a.
@@ -265,9 +301,10 @@ Dlvl:1 $:0  HP:9(12) Pw:3(3) AC:10 Exp:1/19 T:257 Weak
 
 _
 .TE
+.ft \" revert to previous font
 .ce 1
 Figure 1
-
+.
 .hn 2
 The status lines (bottom)
 .pg
@@ -295,6 +332,9 @@ do other tasks requiring agility or manipulation of objects.
 .lp 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
+carrying capacity from your constitution no longer matters.
 .lp Intelligence
 Intelligence affects your ability to cast spells and read spellbooks.
 .lp Wisdom
@@ -310,7 +350,7 @@ coincide.  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.
-.lp "Dungeon Level
+.lp "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
@@ -318,7 +358,7 @@ reputed to be somewhere beneath the twentieth level.
 .lp "Gold  "
 The number of gold pieces you are openly carrying.  Gold which you have
 concealed in containers is not counted.
-.lp "Hit Points
+.lp "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
@@ -328,10 +368,10 @@ number your hit points can reach.
 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
+.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
-is quite possible to have negative armor class. 
+is quite possible to have negative armor class.
 .lp Experience
 Your current experience level and experience points.  As you
 adventure, you gain experience points.  At certain experience point
@@ -342,20 +382,43 @@ show only your experience level here.
 The number of turns elapsed so far, displayed if you have the
 .op time
 option set.
-.lp "Hunger status
-Your current hunger status, ranging from \fBSatiated\fP down to
-\fBFainting\fP.  If your hunger status is normal, it is not displayed.
-.pg
-Additional status flags may appear after the hunger status:  \fBConf\fP
-when you're confused, \fBFoodPois\fP or \fBIll\fP
-when sick, \fBBlind\fP when you can't
-see, \fBStun\fP when stunned, and \fBHallu\fP when hallucinating.
+.lp "Status  "
+Hunger:
+your current hunger status.
+Values are \fBSatiated\fP, \fBNot Hungry\fP (or \fBNormal\fP),
+\fBHungry\fP, \fBWeak\fP, and \fBFainting\fP.
+.\" not mentioned: Fainted
+Not shown when \fBNormal\fP.
+.lp ""
+Encumbrance:
+an indication of how what you are carrying affects your ability to move.
+Values are \fBUnencumbered\fP, \fBEncumbered\fP, \fBStressed\fP,
+\fBStrained\fP, \fBOvertaxed\fP, and \fBOverloaded\fP.
+Not shown when \fBUnencumbered\fP.
+.lp ""
+Fatal conditions:
+\fBStone\fP (aka \fBPetrifying\fP, turning to stone),
+\fBSlime\fP (turning into green slime),
+\fBStrngl\fP (being strangled),
+\fBFoodPois\fP (suffering from acute food poisoning),
+\fBTermIll\fP (suffering from a terminal illness).
+.lp ""
+Non-fatal conditions:
+\fBBlind\fP (can't see), \fBDeaf\fP (can't hear),
+\fBStun\fP (stunned), \fBConf\fP (confused), \fBHallu\fP (hallucinating).
+.lp ""
+Movement modifiers:
+\fBLev\fP (levitating), \fBFly\fP (flying), \fBRide\fP (riding).
+.lp ""
+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.
 .hn 2
 The message line (top)
 .pg
 The top line of the screen is reserved for messages that describe
 things that are impossible to represent visually.  If you see a
-``\fB--More--\fP'' on the top line, this means that NetHack has
+``\fB\-\-More\-\-\fP'' on the top line, this means that NetHack has
 another message 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.
@@ -372,7 +435,7 @@ 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:
-.lp "- and |
+.lp "\\- and | "
 The walls of a room, or an open door.  Or a grave (|).
 .lp .
 The floor of a room, ice, or a doorless doorway.
@@ -389,7 +452,7 @@ A closed door, or a spellbook containing a spell you may be able to learn.
 Your character or a human.
 .lp $
 A pile of gold.
-.lp ^
+.lp \(ha \" ^
 A trap (once you have detected it).
 .lp )
 A weapon.
@@ -407,7 +470,7 @@ A ring.
 A potion.
 .lp (
 A useful item (pick-axe, key, lamp...).
-.lp """
+.lp \(dq \" \(dq == double quote
 An amulet or a spider web.
 .lp *
 A gem or rock (possibly valuable, possibly worthless).
@@ -421,25 +484,27 @@ An altar, or an iron chain.
 A fountain.
 .lp }
 A pool of water or moat or a pool of lava.
-.lp "\e
+.lp \\\\
 An opulent throne.
-.lp "a-zA-Z and other symbols
+.lp "a-zA-Z and other symbols"
 Letters and certain other symbols represent the various inhabitants
 of the Mazes of Menace.  Watch out, they can be nasty and vicious.
 Sometimes, however, they can be helpful.
 .lp 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.
+monster.  Note that the monster could have moved.
+The `F' and `m' commands may be useful here.
 .pg
 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).
-
+.
 .hn 1
 Commands
 .pg
-Commands are initiated by typing one or two characters.  Some 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 direction, or an object to be used.  For those commands that
@@ -450,8 +515,8 @@ you are presented with will depend chiefly on how you have set the
 option.
 .pg
 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.
+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
@@ -472,11 +537,12 @@ ESC key.
 .pg
 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 commands for your reference:
+helpful texts.  Here are the default key bindings for your reference:
 .lp ?
 Help menu:  display one of several help texts available.
 .lp /
-Tell what a symbol represents.  You may choose to specify a location
+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 `.', `,', `;',
@@ -485,14 +551,31 @@ conditionally check for ``More info?'' depending upon whether the
 .op help
 option is on, and then you will be asked to pick another location;
 `,' will explain the symbol but skip any additional
-information; `;' will skip additional info and also not bother asking
+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.
-.pg
+.lp ""
+If the
+.op 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
+.op whatis_coord
+option controls whether the short description includes map coordinates.
+.lp ""
 Specifying a name rather than a location
 always gives any additional information available about that name.
+.lp ""
+You may also request a description of nearby monsters,
+all monsters currently displayed, nearby objects, or all objects.
+The
+.op whatis_coord
+option controls which format of map coordinate is included with their
+descriptions.
 .lp &
 Tell what a command does.
 .lp <
@@ -506,6 +589,9 @@ 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.''
 .sd
+.\" note: the two number pad layouts are separated by a tab on each line;
+.\"       converting those tabs to spaces will screw up the formatting;
+.\"       the '(if ... set)' line starts with <backslash><space><tab>
 .TS S
 center;
 c c.
@@ -514,24 +600,39 @@ y  k  u   7  8  9
 h- . -l        4- . -6
 / | \e / | \e
 b  j  n        1  2  3
-       (if \fBnumber_pad\fP is set)
+\      (if \fBnumber_pad\fP is set)
 .TE
 .ed
 .ce 1
 Figure 2
-
+.
 .lp [YUHJKLBN]
 Go in that direction until you hit a wall or run into something.
 .lp m[yuhjklbn]
 Prefix:  move without picking up objects or fighting (even if you remember
-a monster there)
+a monster there).
+.lp ""
+A few non-movement commands use the `m' prefix to request operating
+via menu (to temporarily override the
+.op 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).
+.lp ""
+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 adjacent monsters. The prefix will
+make ``#travel'' command show a menu of interesting targets in sight.
 .lp F[yuhjklbn]
-Prefix:  fight a monster (even if you only guess one is there)
+Prefix:  fight a monster (even if you only guess one is there).
 .lp M[yuhjklbn]
 Prefix:  move far, no pickup.
-.lp "g[yuhjklbn]
+.lp "g[yuhjklbn]"
 Prefix:  move until something interesting is found.
-.lp "G[yuhjklbn] or <CONTROL->[yuhjklbn]
+.lp "G[yuhjklbn] or <CONTROL->[yuhjklbn]"
 Prefix:  same as `g', but forking of corridors is not considered interesting.
 .lp _
 Travel to a map location via a shortest-path algorithm.
@@ -541,17 +642,20 @@ 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 
+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.
 .lp .
-Rest, do nothing for one turn.
+Wait or rest, do nothing for one turn.
 .lp a
 Apply (use) a tool (pick-axe, key, lamp...).
+.lp ""
+If used on a wand, that wand will be broken, releasing its magic in the
+process.  Confirmation is required.
 .lp A
 Remove one or more worn items, such as armor.
 .lp ""
-Use `T' (take off) to take off only one piece of armor 
+Use `T' (take off) to take off only one piece of armor
 or `R' (remove) to take off only one accessory.
 .lp ^A
 Redo the previous command.
@@ -574,40 +678,66 @@ In answer to the question
 .lp ""
 ``What kinds of things do you want to drop? [!%= BUCXaium]''
 .lp ""
-you should type zero or more object symbols possibly followed by 
+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.
-.sd
-.si
-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.
-.ei
-.ed
+.PS D%u
+.PL DB
+drop all objects known to be blessed.
+.PL DU
+drop all objects known to be uncursed.
+.PL DC
+drop all objects known to be cursed.
+.PL DX
+drop all objects of unknown B/U/C status.
+.PL Da
+drop all objects, without asking for confirmation.
+.PL Di
+examine your inventory before dropping anything.
+.PL Du
+drop only unpaid objects (when in a shop).
+.PL Dm
+use a menu to pick which object(s) to drop.
+.PL D%u
+drop only unpaid food.
+.PE
+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 multiple 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.)
 .lp ^D
 Kick something (usually a door).
 .lp e
 Eat food.
+.lp ""
+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
+anything off the floor.
 .\" Make sure Elbereth is not hyphenated below, the exact spelling matters
 .hw Elbereth
 .lp E
 Engrave a message on the floor.
 .sd
 .si
-E- - write in the dust with your fingers.  
+E- - write in the dust with your fingers.
 .ei
 .ed
 .lp ""
 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.  (This feature may be compiled out
-of the game, so your version might not have it.)
+often useful to give yourself a breather.
 .lp f
 Fire one of the objects placed in your quiver (or quiver sack, or that you
 have at the ready).  You may select
@@ -620,18 +750,24 @@ List your inventory (everything you're carrying).
 .lp I
 List selected parts of your inventory, usually be specifying the character
 for a particular set of objects, like `[' for armor or `!' for potions.
-.sd
-.si
-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 known;
-I$ - count your money.
-.ei
-.ed
+.PS IX
+.PL I*
+list all gems in inventory;
+.PL Iu
+list all unpaid items;
+.PL Ix
+list all used up items that are on your shopping bill;
+.PL IB
+list all items known to be blessed;
+.PL IU
+list all items known to be uncursed;
+.PL IC
+list all items known to be cursed;
+.PL IX
+list all items whose bless/curse status is known;
+.PL I$
+count your money.
+.PE
 .lp o
 Open a door.
 .lp O
@@ -645,6 +781,14 @@ 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.
+.lp ^O
+Show overview or show dungeon layout
+.lp ""
+In normal play and in explore mode, a shortcut for the ``#overview''
+extended command to list interesting dungeon levels visited.
+.lp ""
+In debug mode, an extra command which lists the placement of all special
+levels.
 .lp p
 Pay your shopping bill.
 .lp P
@@ -750,7 +894,7 @@ via the ``#twoweapon'' extended command.
 .lp ""
 (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 ``#explore''.)
+been moved to ``#exploremode''.)
 .lp ^X
 Display basic information about your character.
 .lp ""
@@ -776,7 +920,9 @@ Z. - to cast at yourself, use `.' for the direction.
 .ed
 .lp ^Z
 Suspend the game
-.ux " versions with job control only)." (
+.\" .UX: print "UNIX" now and a trademark footnote at bottom of current page;
+.\"  2nd arg (literal '(') _precedes_ it, 1st arg (quoted string) follows it
+.UX " versions with job control only)." (
 .lp :
 Look at what is here.
 .lp ;
@@ -789,15 +935,15 @@ May be preceded by `m' to force a selection menu.
 Toggle the
 .op autopickup
 option on and off.
-.lp ^
-Ask for the type of a trap you found earlier.
+.lp \(ha \" ^
+Ask for the type of an adjacent trap you found earlier.
 .lp )
 Tell what weapon you are wielding.
 .lp [
 Tell what armor you are wearing.
 .lp =
 Tell what rings you are wearing.
-.lp """
+.lp \(dq \" \(dq == double quote
 Tell what amulet you are wearing.
 .lp (
 Tell what tools you are using.
@@ -816,12 +962,14 @@ 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 finishes.  Sorting
-the whole list is temporary.  To make the most recent sort order persist
+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
+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.)
-.lp "\e
+.lp \\\\
 Show what types of objects have been discovered.
 .lp `
 Show discovered types for one class of objects.
@@ -830,6 +978,7 @@ Escape to a shell.
 .lp #
 Perform an extended command.
 .lp ""
+.pg
 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.
@@ -838,55 +987,171 @@ compiled with.
 .lp #adjust
 Adjust inventory letters (most useful when the
 .op fixinv
-option is ``on'').
+option is ``on''). Autocompletes. Default key is 'M-a'.
 .lp ""
 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 location when inventory listings
 are displayed.
+You can move to a currently empty slot, or if the destination is
+occupied \(em and won't merge \(em 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.
+.lp ""
+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 eligible.
+In either case, otherwise compatible stacks with a different name
+will not be merged.  This contrasts with using ``#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.
 .lp #annotate
 Allows you to specify one line of text to associate with the current
-dungeon level.  All levels with annotations are displayed by the
+dungeon level.
+All levels with annotations are displayed by the
 ``#overview'' command.
+Autocompletes.
+Default key is 'M-A', and '^N' if
+.op number_pad
+is on.
+.lp #apply
+Apply (use) a tool such as a pick-axe, a key, or a lamp. Default key is 'a'.
+.lp ""
+If the tool used acts on items on the floor, using the `m' prefix skips
+those items.
+.lp ""
+If used on a wand, that wand will be broken, releasing its magic in the
+process.  Confirmation is required.
+.lp #attributes
+Show your attributes. Default key is '^X'.
+.lp #autopickup
+Toggle the autopickup -option on/off. Default key is '@'.
+.lp #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'.
+.lp #cast
+Cast a spell. Default key is 'Z'.
 .lp #chat
-Talk to someone.
+Talk to someone. Default key is 'M-c'.
+.lp #close
+Close a door. Default key is 'c'.
 .lp #conduct
 List voluntary challenges you have maintained.
+Autocompletes.
+Default key is 'M-C'.
 .lp ""
 See the section below entitled ``Conduct'' for details.
 .lp "#dip "
-Dip an object into something.
+Dip an object into something. Autocompletes. Default key is 'M-d'.
+.lp #down
+Go down a staircase. Default key is '>'.
+.lp #drop
+Drop an item. Default key is 'd'.
+.lp #droptype
+Drop specific item types. Default key is 'D'.
+.lp "#eat "
+Eat something. Default key is 'e'.
+The `m' prefix skips eating items on the floor.
+.lp #engrave
+Engrave writing on the floor. Default key is 'E'.
 .lp #enhance
-Advance or check weapon and spell skills.
+Advance or check weapon and spell skills. Autocompletes. Default key is 'M-e'.
+.lp #exploremode
+Enter the explore mode.
+.lp #fire
+Fire ammunition from quiver. Default key is 'f'.
 .lp #force
-Force a lock.
+Force a lock. Autocompletes. Default key is 'M-f'.
+.lp #glance
+Show what type of thing a map symbol corresponds to. Default key is ';'.
+.lp #help
+Show the help menu. Default key is '?', and 'h' if
+.op number_pad
+is on.
+.lp #herecmdmenu
+Show a menu of possible actions in your current location.
+.lp #history
+Show long version and game history. Default key is 'V'.
+.lp #inventory
+Show your inventory. Default key is 'i'.
+.lp #inventtype
+Inventory specific item types. Default key is 'I'.
 .lp #invoke
-Invoke an object's special powers.
+Invoke an object's special powers. Autocompletes. Default key is 'M-i'.
 .lp #jump
 Jump to another location.
+Autocompletes.
+Default key is 'M-j', and 'j' if
+.op number_pad
+is on.
+.lp #kick
+Kick something.
+Default key is '^D', and 'k' if
+.op number_pad
+is on.
+.lp #known
+Show what object types have been discovered. Default key is '\\'.
+.lp #knownclass
+Show discovered types for one class of objects. Default key is '`'.
+.lp #levelchange
+Change your experience level. Autocompletes. Wizard-mode only.
+.lp #lightsources
+Show mobile light sources. Autocompletes. Wizard-mode only.
+.lp #look
+Look at what is here, under you. Default key is ':'.
 .lp #loot
-Loot a box or bag on the floor beneath you, or the saddle 
-from a steed standing next to you.
+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 'l' if
+.op number_pad
+is on.
+.lp #monpolycontrol
+Control monster polymorphs. Autocompletes. Wizard-mode only.
 .lp #monster
 Use a monster's special ability (when polymorphed into monster form).
+Autocompletes. Default key is 'M-m'.
 .lp #name
-Name a monster, an individual object, or a type of object.  Same as `C'.
+Name a monster, an individual object, or a type of object.  Same as #call.
+Autocompletes. Default keys are 'N', 'M-n', and 'M-N'.
 .lp #offer
-Offer a sacrifice to the gods.
+Offer a sacrifice to the gods. Autocompletes. Default key is 'M-o'.
+The `m' prefix skips offering items on the altar.
 .lp ""
 You'll need to find an altar to have any chance at success.
 Corpses of recently killed monsters are the fodder of choice.
+.lp #open
+Open a door. Default key is 'o'.
+.lp #options
+Show and change option settings. Default key is 'O'.
 .lp #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 dungeon branch) trigger an automatic annotation.
 If dungeon overview is chosen during end-of-game disclosure, every visited
-level will be included regardless of annotations.
+level will be included regardless of annotations. Autocompletes.
+Default keys are '^O', and 'M-O'.
+.lp #panic
+Test the panic routine. Autocompletes. Wizard-mode only.
+.lp "#pay "
+Pay your shopping bill. Default key is 'p'.
+.lp #pickup
+Pick up things at the current location. Default key is ','.
+The `m' prefix forces use of a menu.
+.lp #polyself
+Polymorph self. Autocompletes. Wizard-mode only.
 .lp #pray
-Pray to the gods for help.
+Pray to the gods for help. Autocompletes. Default key is 'M-p'.
 .lp ""
 Praying too soon after receiving prior help is a bad idea.
 (Hint: entering the dungeon alive is treated as having received help.
@@ -896,42 +1161,172 @@ option to make you confirm your intent before praying.  It is enabled
 by default, and you can reset the
 .op paranoid_confirmation
 option to disable it.
+.lp #prevmsg
+Show previously displayed game messages. Default key is '^P'.
+.lp #puton
+Put on an accessory (ring, amulet, etc). Default key is 'P'.
+.lp #quaff
+Quaff (drink) something. Default key is 'q'.
 .lp #quit
-Quit the program without saving your game.
+Quit the program without saving your game. Autocompletes. Default key is 'M-q'.
 .lp ""
 Since using this command by accident would throw away the current game,
 you are asked to confirm your intent before quitting.  By default a
 response of 'y' acknowledges that intent.  You can set the
 .op paranoid_confirmation
-option to require a response of "yes" instead.
+option to require a response of ``yes'' instead.
+.lp #quiver
+Select ammunition for quiver. Default key is 'Q'.
+.lp #read
+Read a scroll, a spellbook, or something else. Default key is 'r'.
+.lp #redraw
+Redraw the screen.
+Default key is '^R', and '^L' if
+.op number_pad
+is on.
+.lp #remove
+Remove an accessory (ring, amulet, etc). Default key is 'R'.
 .lp #ride
-Ride (or stop riding) a saddled creature.
+Ride (or stop riding) a saddled creature. Autocompletes. Default key is 'M-R'.
 .lp "#rub "
-Rub a lamp or a stone.
+Rub a lamp or a stone. Autocompletes. Default key is 'M-r'.
+.lp #save
+Save the game. Default key is 'S'.
+.lp #search
+Search for traps and secret doors around you. Default key is 's'.
+.lp #seeall
+Show all equipment in use. Default key is '*'.
+.lp #seeamulet
+Show the amulet currently worn. Default key is '\(dq'. \" double quote
+.lp #seearmor
+Show the armor currently worn. Default key is '['.
+.lp #seegold
+Count your gold. Default key is '$'.
+.lp #seenv
+Show seen vectors. Autocompletes. Wizard-mode only.
+.lp #seerings
+Show the ring(s) currently worn. Default key is '='.
+.lp #seespells
+List and reorder known spells. Default key is '+'.
+.lp #seetools
+Show the tools currently in use. Default key is '('.
+.lp #seetrap
+Show the type of an adjacent trap.
+Default key is '\(ha'.
+.lp #seeweapon
+Show the weapon currently wielded. Default key is ')'.
+.lp #shell
+Do a shell escape. Default key is '!'.
 .lp "#sit "
-Sit down.
+Sit down. Autocompletes. Default key is 'M-s'.
+.lp #stats
+Show memory statistics. Autocompletes. Wizard-mode only.
+.lp #suspend
+Suspend the game. Default key is '^Z'.
+.lp #swap
+Swap wielded and secondary weapons. Default key is 'x'.
+.lp #takeoff
+Take off one piece of armor. Default key is 'T'.
+.lp #takeoffall
+Remove all armor. Default key is 'A'.
+.lp #teleport
+Teleport around the level. Default key is '^T'.
 .lp #terrain
 Show bare map without displaying monsters, objects, or traps.
+Autocompletes.
+.lp #therecmdmenu
+Show a menu of possible actions in a location next to you.
+.lp #throw
+Throw something. Default key is 't'.
+.lp #timeout
+Look at the timeout queue. Autocompletes. Wizard-mode only.
 .lp "#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.
+.lp #travel
+Travel to a specific location on the map. Default key is '_'.
+Using the ``request menu'' prefix shows a menu of interesting targets in sight
+without asking to move the cursor. When picking a target with cursor and
+the
+.op autodescribe
+option is on, the top line will show ``(no travel path)'' if
+your character does not know of a path to that location.
 .lp #turn
-Turn undead.
+Turn undead away. Autocompletes. Default key is 'M-t'.
 .lp #twoweapon
-Toggle two-weapon combat on or off.
+Toggle two-weapon combat on or off. Autocompletes. Default keys
+are 'X', and 'M-2'.
 .lp ""
 Note that you must
 use suitable weapons for this type of combat, or it will
 be automatically turned off.
 .lp #untrap
 Untrap something (trap, door, or chest).
+Default key is 'M-u', and 'u' if
+.op number_pad
+is on.
 .lp ""
 In some circumstances it can also be used to rescue trapped monsters.
+.lp "#up  "
+Go up a staircase. Default key is '<'.
+.lp #vanquished
+List vanquished monsters. Autocompletes. Wizard-mode only.
 .lp #version
 Print compile time options for this version of NetHack.
+Autocompletes. Default key is 'M-v'.
+.lp #versionshort
+Show version string. Default key is 'v'.
+.lp #vision
+Show vision array. Autocompletes. Wizard-mode only.
+.lp #wait
+Rest one move while doing nothing. Default key is '.', and ' ' if
+rest_on_space is on.
+.lp #wear
+Wear a piece of armor. Default key is 'W'.
+.lp #whatdoes
+Tell what a key does. Default key is '&'.
+.lp #whatis
+Show what type of thing a symbol corresponds to. Default key is '/'.
+.lp #wield
+Wield a weapon. Default key is 'w'.
 .lp #wipe
-Wipe off your face.
+Wipe off your face. Autocompletes. Default key is 'M-w'.
+.lp #wizdebug_bury
+Bury objects under and around you. Autocompletes. Wizard-mode only.
+.lp #wizdebug_traveldisplay
+Toggle travel display. Autocompletes. Wizard-mode only.
+.lp #wizdetect
+Search a room. Autocompletes. Wizard-mode only. Default key is '^E'.
+.lp #wizgenesis
+Create a monster. Autocompletes. Wizard-mode only. Default key is '^G'.
+.lp #wizidentify
+Identify all items in inventory. Autocompletes. Wizard-mode only.
+Default key is '^I'.
+.lp #wizintrinsic
+Set intrinsic. Autocompletes. Wizard-mode only.
+.lp #wizlevelport
+Teleport to another level.
+Autocompletes.
+Wizard-mode only.
+Default key is '^V'.
+.lp #wizmap
+Map the level. Autocompletes. Wizard-mode only. Default key is '^F'.
+.lp #wizrumorcheck
+Verify rumor boundaries. Autocompletes. Wizard-mode only.
+.lp #wizsmell
+Smell monster. Autocompletes. Wizard-mode only.
+.lp #wizwhere
+Show locations of special levels. Autocompletes. Wizard-mode only.
+.lp #wizwish
+Wish for something. Autocompletes. Wizard-mode only. Default key is '^W'.
+.lp #wmode
+Show wall modes. Autocompletes. Wizard-mode only.
+.lp "#zap "
+Zap a wand. Default key is 'z'.
 .lp "#?   "
 Help menu:  get the list of available extended commands.
+.lp ""
 .pg
 If your keyboard has a meta key (which, when pressed in combination
 with another key, modifies it by setting the `meta' [8th, or `high']
@@ -946,11 +1341,13 @@ On other systems, if typing `Alt' plus another key transmits a
 two character sequence consisting of an \fBEscape\fP
 followed by the other key, you may set the
 .op altmeta
-option to have nethack combine them into meta+key.
+option to have NetHack combine them into meta+key.
 .lp M-?
 #? (not supported by all platforms)
 .lp M-2
-#twoweapon (unless the number_pad option is enabled)
+#twoweapon (unless the
+.op number_pad
+option is enabled)
 .lp M-a
 #adjust
 .lp M-A
@@ -999,31 +1396,29 @@ option to have nethack combine them into meta+key.
 #version
 .lp M-w
 #wipe
+.lp ""
 .pg
 If the
 .op number_pad
 option is on, some additional letter commands are available:
 .lp h
-Help menu:  display one of several help texts available, like ``?''.
+#help
 .lp j
-Jump to another location.  Same as ``#jump'' or ``M-j''.
+#jump
 .lp k
-Kick something (usually a door).  Same as `^D'.
+#kick
 .lp l
-Loot a box or bag on the floor beneath you, or the saddle 
-from a steed standing next to you.  Same as ``#loot'' or ``M-l''.
+#loot
 .lp N
-Name a monster, an individual object, or a type of object.  Same
-as ``#name'' (or ``M-n'') which is the same as the `C'
-command.
+#name
 .lp u
-Untrap a trap, door, or chest.  Same as ``#untrap'' or ``M-u''.
-
+#untrap
+.
 .hn 1
 Rooms and corridors
 .pg
 Rooms and corridors in the dungeon are either lit or dark.
-Any lit areas within your line of sight will be displayed;  
+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.
 .pg
@@ -1052,7 +1447,7 @@ 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.
 .hn 2
-Traps (`^')
+Traps (`\(ha')
 .pg
 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
@@ -1068,7 +1463,7 @@ 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.
 .hn 2
-Stairs (`<', `>')
+Stairs and ladders (`<', `>')
 .pg
 In general, each level in the dungeon will have a staircase going up
 (`<') to the previous level and another going down (`>') to the next
@@ -1096,8 +1491,6 @@ 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.
-.hn 2
-Ladders (`<', `>')
 .pg
 Ladders serve the same purpose as staircases, and the two types of
 inter-level connections are nearly indistinguishable during game play.
@@ -1149,10 +1542,10 @@ outside the shop.
 While the shopkeeper watches you like a hawk, he will generally ignore
 any other customers.
 .lp * 2
-If a shop is "closed for inventory", it will not open of its own accord.
+If a shop is ``closed for inventory'', it will not open of its own accord.
 .lp * 2
 Shops do not get restocked with new items, regardless of inventory depletion.
-
+.
 .hn 1
 Monsters
 .pg
@@ -1162,8 +1555,8 @@ help you locate them before they locate you (which some monsters can do
 very well).
 .pg
 The commands `/' and `;' may be used to obtain information about those
-monsters who are displayed on the screen.  The command ``#name'', or
-its synonym `C', allows you
+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.
@@ -1181,11 +1574,11 @@ you attack them.  Some of them are very dangerous when angered.
 Remember:  discretion is the better part of valor.
 .pg
 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 
+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
 .op paranoid_confirmation
-option to require a response of "yes" instead.
+option to require a response of ``yes'' instead.
 .pg
 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.
@@ -1222,16 +1615,24 @@ Steeds
 .pg
 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 
+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 
+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.
 .pg
-Riding skill is managed by the `#enhance' command.  See the section
+Riding skill is managed by the ``#enhance'' command.  See the section
 on Weapon proficiency for more information about that.
+.pg
+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.
+.pg
+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.
 .hn 2
 Bones levels
 .pg
@@ -1242,9 +1643,27 @@ 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.
-
+.
+.hn 2
+Persistence of Monsters
+.pg
+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.
+.pg
+However, if you encounter a monster which you can't see or sense \(em
+perhaps it is invisible and has just tapped you on the noggin \(em
+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.
+.
 .hn 1
-Objects 
+Objects
 .pg
 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
@@ -1253,7 +1672,7 @@ the object (unless you turn off the
 option (see below), or move with the `m' prefix (see above)), or
 manually by using the `,' command.
 .pg
-If you're carrying too many items, NetHack will tell you so and you won't 
+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.
@@ -1261,7 +1680,8 @@ 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 you are, the less the additional load will affect you.  There comes
+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
@@ -1287,7 +1707,7 @@ 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, or its synonym `C', for the same purpose at any time, to 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
@@ -1356,8 +1776,8 @@ 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 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
+monster's armor class \(em a general defense rating, not necessarily due to
+wearing of armor \(em is a factor too; also, some monsters are particularly
 vulnerable to certain types of weapons.
 .pg
 Many weapons can be wielded in one hand; some require both hands.
@@ -1412,7 +1832,7 @@ for `Q' runs out.
 .pg
 Some characters have the ability to fire a volley of multiple 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
+once \(em or hold several missiles in your hand \(em 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
@@ -1478,8 +1898,8 @@ 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
+one is considered secondary.  The most noticeable difference is
+after you stop \(em or before you begin, for that matter \(em 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.)
@@ -1517,7 +1937,7 @@ 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:
-
+.
 .TS S
 center;
 a n.
@@ -1532,6 +1952,7 @@ 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
@@ -1627,10 +2048,12 @@ The command to drink a potion is `q' (quaff).
 .hn 2
 Wands (`/')
 .pg
-Magic wands usually have multiple magical charges.  Some wands are
-directional\(emyou must give a direction in which to zap them.  You can also
+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 wands are nondirectional\(emthey
+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.
 .pg
@@ -1666,7 +2089,7 @@ Putting on a ring activates its magic.  You can wear only two
 rings, one on each ring finger.
 .pg
 Most rings also cause you to grow hungry more rapidly, the rate
-varying with the type of ring.  
+varying with the type of ring.
 .pg
 The commands to use rings are `P' (put on) and `R' (remove).
 .hn 2
@@ -1686,16 +2109,18 @@ energy and the time required in casting.
 .pg
 Casting a spell calls forth magical energies and focuses them with
 your naked mind.  Some of the magical energy released comes from within
-you, and casting several spells in a row may tire you.
+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 memory of each spell will dim, and you will need to relearn it.
 .pg
-Some spells are
-directional\(emyou must give a direction in which to cast them.  You can also
-cast them at yourself (just give a `.' or `s' for the direction). Be warned,
-however, for this is often unwise.  Other spells are nondirectional\(emthey
-don't require a direction.
+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 direction.
+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.
 .pg
 Just as weapons are divided into groups in which a character can become
 proficient (to varying degrees), spells are similarly grouped.
@@ -1771,6 +2196,9 @@ heavy.  It is rumored that some statues are not what they seem.
 .pg
 Very large humanoids (giants and their ilk) have been known to use boulders
 as weapons.
+.pg
+For some configurations of the program, statues are no longer shown as `\`'
+but by the letter representing the monster they depict instead.
 .hn 2
 Gold (`$')
 .pg
@@ -1778,7 +2206,31 @@ 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).
-
+.
+.hn 2
+Persistence of Objects
+.pg
+Normally, if you have seen an object at a particular map location and
+move to another location which 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 \(em
+perhaps a monster has picked it up or it has rotted away \(em
+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 and 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.
+.pg
+The situation is the same for a pile of objects, except that only the
+top item of the pile is displayed.
+The
+.op hilite_pile
+option can be enabled in order to show an item differently when is
+the top one of a pile.
+.
 .hn 1
 Conduct
 .pg
@@ -1887,7 +2339,7 @@ wish for any items is a challenge, as is a game without wishing for
 an artifact (even if the artifact 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.
-
+.
 .hn 1
 Options
 .pg
@@ -1899,18 +2351,167 @@ Setting the options
 .pg
 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 the
-NETHACKOPTIONS environment variable or in a configuration file.
+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 administrators.
 .hn 2
+Using a configuration file
+.pg
+.\" hw: don't hyphenate file names
+.hw .nethackrc defaults.nh nethack.exe nethackW.exe
+The default name of the configuration file varies on different
+operating systems.
+On DOS and Windows, it is ``defaults.nh''
+in the same folder as nethack.exe or nethackW.exe.
+On
+.UX ,
+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 file and
+can be created with any text editor.
+.pg
+Any line in the configuration file starting with `#' is treated as a comment.
+Empty lines are ignored.
+.pg
+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.
+.pg
+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:
+.lp OPTIONS
+There are two types of options, boolean and compound options.
+Boolean 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 multiple options
+in a single OPTIONS statement.
+.pg
+Example:
+.sd
+\fBOPTIONS=dogname:Fido\fP
+.\" '\(dq' == double quote; including a literal double quote here works
+.\"           for formatting but confuses Emacs' nroff-mode into thinking
+.\"           that the \fP is part of a string rather than a font toggle
+\fBOPTIONS=!legacy,autopickup,pickup_types:$\(dq=/!?+\fP
+.ed
+.lp 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.
+.lp LEVELDIR
+The location that in-progress level files are stored. Defaults to HACKDIR,
+must be writeable.
+.lp SAVEDIR
+The location where saved games are kept. Defaults to HACKDIR, must be
+writeable.
+.lp BONESDIR
+The location that bones files are kept. Defaults to HACKDIR, must be
+writeable.
+.lp LOCKDIR
+The location that file synchronization locks are stored. Defaults to
+HACKDIR, must be writeable.
+.lp TROUBLEDIR
+The location that a record of game aborts and self-diagnosed game problems
+is kept. Defaults to HACKDIR, must be writeable.
+.lp AUTOCOMPLETE
+Enable or disable an extended command autocompletion.
+Autocompletion has no effect for the X11 windowport.
+You can specify multiple autocompletions. To enable
+autocompletion, list the extended command. Prefix the
+command with ``!'' to disable the autocompletion
+for that command.
+.pg
+Example:
+.sd
+\fBAUTOCOMPLETE=zap,!annotate\fP
+.ed
+.lp AUTOPICKUP_EXCEPTION
+Set exceptions to the
+.op pickup_types
+option. See the ``Configuring Autopickup Exceptions'' section.
+.lp 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 ``Changing Key Bindings`` section for more information.
+.pg
+Example:
+.sd
+\fBBIND=^X:getpos.autodescribe\fP
+.ed
+.lp CHOOSE
+Chooses at random one of the comma-separated parameters as an active
+section name. Lines in other sections are ignored.
+.pg
+Example:
+.sd
+\fBOPTIONS=color\fP
+\fBCHOOSE=char A,char B\fP
+\fB[char A]\fP
+\fBOPTIONS=role:arc,race:dwa,align:law,gender:fem\fP
+\fB[char B]\fP
+\fBOPTIONS=role:wiz,race:elf,align:cha,gender:mal\fP
+.ed
+.lp MSGTYPE
+Change the way messages are shown in the top status line.
+See the ``Configuring Message Types`` section.
+.lp MENUCOLOR
+Highlight menu lines with different colors.
+See the ``Configuring Menu Colors`` section.
+.lp SYMBOLS
+Override one or more symbols in the symbols files.
+See the ``Modifying NetHack Symbols'' section.
+.pg
+Example:
+.sd
+\fBSYMBOLS=S_boulder:0\fP
+.ed
+.lp WIZKIT
+Wizard-mode extra items, in a text file containing item names,
+one per line, up to a maximum of 128 lines. Each line is processed
+by the function that handles wishing.
+.pg
+Example:
+.sd
+\fBWIZKIT=\(ti/wizkit.txt\fP \" \(ti == '~'
+.ed
+.lp SOUNDDIR
+Define the directory that contains the sound files.
+See the ``Configuring User Sounds'' section.
+.lp SOUND
+Define a sound mapping. See the ``Configuring User Sounds'' section.
+.pg
+Here is a short example of config file contents:
+.sd
+\fB# Set your character's role, race, gender, and alignment.\fP
+\fBOPTIONS=role:Valkyrie, race:Human, gender:female, align:lawful\fP
+\fB#\fP
+\fB# Turn on autopickup, and set automatically picked up object types\fP
+\fBOPTIONS=autopickup,pickup_types:$"=/!?+\fP
+\fB# Show colored text if possible\fP
+\fBOPTIONS=color\fP
+\fB# Show lit corridors differently\fP
+\fBOPTIONS=lit_corridor\fP
+\fB#\fP
+\fB# No startup splash screen. Windows GUI only.\fP
+\fBOPTIONS=!splash_screen\fP
+.ed
+.hn 2
 Using the NETHACKOPTIONS environment variable
 .pg
 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 
+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.
@@ -1927,28 +2528,9 @@ $ \fBNETHACKOPTIONS="autoquiver,!autopickup,name:Blue Meanie,fruit:papaya"\fP
 $ \fBexport NETHACKOPTIONS\fP
 .ed
 in \fIsh\fP or \fIksh\fP.
-.hn 2
-Using a configuration file
-.pg
-Any line in the configuration file starting with `#' is treated as a comment.
-Any line in the configuration file starting with ``OPTIONS='' may be
-filled out with options in the same syntax as in NETHACKOPTIONS.
-Any line starting with ``SYMBOLS=''
-is taken as defining the corresponding symbol
-in a different syntax, a sequence of decimal numbers giving 
-the character position in the current font to be used in displaying 
-each entry. Such a sequence can be continued to multiple lines by putting a `\e'
-at the end of each line to be continued.
-.pg
-Any line starting with ``AUTOPICKUP_EXCEPTION='' is taken
-as defining an exception to the 
-.op pickup_types
-option. 
-There is a section of this Guidebook that discusses that.
 .pg
-The default name of the configuration file varies on different
-operating systems, but NETHACKOPTIONS can also be set to
-the full name of a file you want to use (possibly preceded by an `@').
+NETHACKOPTIONS can also be set to the full name of a configuration file you
+want to use (possibly preceded by an `@').
 .hn 2
 Customization options
 .pg
@@ -1967,9 +2549,14 @@ Persistent.
 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 a `!' or ``no'' to the value, you can 
+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.
+.lp autodescribe
+Automatically describe the terrain under cursor when asked to get a location
+on the map.  The
+.op whatis_coord
+option controls whether the description includes map coordinates.
 .lp autodig
 Automatically dig if you are wielding a digging tool and moving into a place
 that can be dug (default false). Persistent.
@@ -1990,34 +2577,39 @@ 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. (default false)
+false, the `t' (throw) command is executed instead.
+Persistent. (default false)
 .lp blind
 Start the character permanently blind.  Persistent. (default false)
 .lp bones
 Allow saving and loading bones files.  Persistent. (default true)
 .lp boulder
-Set the character used to display boulders (default is rock class symbol).
+Set the character used to display boulders (default is the ``large rock''
+class symbol, `\`').
 .lp catname
 Name your starting cat (ex. ``catname:Morris'').
 Cannot be set with the `O' command.
 .lp character
-Pick your type of character (ex. ``character:Monk'');
-synonym for ``role''.  See ``name'' for an alternate method
-of specifying your role.  Normally only the first letter of
-the value is examined; the string ``random'' is an exception.
+Synonym for ``role'' to pick the type of your character
+(ex. ``character:Monk'').
+See
+.op role
+for more details.
 .lp checkpoint
 Save game state after each level change, for possible recovery after
 program crash (default on).  Persistent.
 .lp 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.
+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.
 .lp clicklook
 Allows looking at things on the screen by navigating the mouse
 over them and clicking the right mouse button (default off).
 .lp cmdassist
-Have the game provide some additional command assistance for 
+Have the game provide some additional command assistance for
 new players if it detects some anticipated mistakes (default on).
 .lp "confirm "
 Have user confirm attacks on pets, shopkeepers, and other
@@ -2051,6 +2643,20 @@ lets you refine how it behaves.  Here are the valid prefixes:
 .CC - "do not disclose it and do not prompt."
 .ei
 .ed
+The listing of vanquished monsters can be sorted,
+so there are two additional choices for `v':
+.sd
+.si
+.CC ? "prompt you and default to ask on the prompt;"
+.CC # "disclose it without prompting, ask for sort order."
+.ei
+.ed
+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.
+.lp ""
 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
@@ -2075,7 +2681,7 @@ Cannot be set with the `O' command.
 .lp extmenu
 Changes the extended commands interface to pop-up a menu of available commands.
 It is keystroke compatible with the traditional interface except that it does
-not require that you hit Enter. It is implemented only by the tty port 
+not require that you hit Enter. It is implemented only by the tty port
 (default off), when the game has been compiled to support tty graphics.
 .lp female
 An obsolete synonym for ``gender:female''.
@@ -2084,6 +2690,9 @@ Cannot be set with the `O' command.
 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.
+.lp force_invmenu
+Commands asking for an inventory item show a menu instead of
+a text query with possible menu letters. Default is off.
 .lp "fruit   "
 Name a fruit after something you enjoy eating (ex. ``fruit:mango'')
 (default ``slime mold'').  Basically a nostalgic whimsy that NetHack uses
@@ -2096,15 +2705,27 @@ 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 a `!' or ``no'' to the value, you can 
+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.
+.lp "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
+.op implicit_uncursed
+option is `off'.
 .lp "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 interrupted with the
 ``More info?'' prompt, but it also means that you might miss some
 interesting and/or important information.  Persistent.
+.lp 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.
 .lp hilite_pet
 Visually distinguish pets from similar animals (default off).
 The behavior of this option depends on the type of windowing you use.
@@ -2116,6 +2737,9 @@ 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.
+.lp 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.
 .lp horsename
 Name your starting horse (ex. ``horsename:Trigger'').
 Cannot be set with the `O' command.
@@ -2168,11 +2792,11 @@ Default '-'.
 .lp 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 '\e'.
+Default '\\'.
 .lp menu_first_page
 Menu character accelerator to jump to the first page in a menu.
 Implemented by the Amiga, Gem and tty ports.
-Default '^'.
+Default '\(ha'.
 .lp menu_headings
 Controls how the headings in a menu are highlighted.
 Values are 'none', 'bold', 'dim', 'underline', 'blink', or 'inverse'.
@@ -2184,7 +2808,7 @@ Default '@'.
 .lp 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 '~'.
+Default '\(ti'. \" ~
 .lp menu_last_page
 Menu character accelerator to jump to the last page in a menu.
 Implemented by the Amiga, Gem and tty ports.
@@ -2196,7 +2820,11 @@ Default '>'.
 .lp menu_objsyms
 Show object symbols in menu headings in menus where
 the object symbols act as menu accelerators (default off).
-.lp menu_previous_page 
+.lp 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)
+.lp menu_previous_page
 Menu character accelerator to goto the previous menu page.
 Implemented by the Amiga, Gem and tty ports.
 Default '<'.
@@ -2233,9 +2861,9 @@ defaults to `full'), or it can be negated (which defaults to `single').
 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
-.op "-A -B -C -H -K -M -P -Ra -Ro -S -T -V -W" ).
+.op "\-A \-B \-C \-H \-K \-M \-P \-Ra \-Ro \-S \-T \-V \-W" ).
 If
-.op "-@"
+.op "\-@"
 is used for the role, then a random one will be automatically chosen.
 Cannot be set with the `O' command.
 .lp "news    "
@@ -2270,42 +2898,48 @@ is the same as specifying 0.
 (Settings 2 and 4 are for compatibility with MSDOS 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 German keyboards which have the
+Setting -1 is to accommodate 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'').
 .lp packorder
-Specify the order to list object types in (default ``")[%?+!=/(*`0_'').
+.\" \(dq == double quote; literal '"' formats ok but confuses Emacs' nroff-mode
+Specify the order to list object types in (default ``\(dq)[%?+!=/(*`0_'').
 The value of this option should be a string containing the
 symbols for the various object types.  Any omitted types are filled in
 at the end from the previous order.
 .lp paranoid_confirmation
 A space separated list of specific situations where alternate
 prompting is desired.  The default is paranoid_confirmation:pray.
-.PS Confirm
+.PS Were-change
 .PL 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
+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
 .PL quit
-require "yes" rather than 'y' to confirm quitting
+require ``yes'' rather than 'y' to confirm quitting
 the game or switching into non-scoring explore mode;
 .PL die
-require "yes" rather than 'y' to confirm dying (not
+require ``yes'' rather than 'y' to confirm dying (not
 useful in normal play; applies to explore mode);
 .PL bones
-require "yes" rather than 'y' to confirm saving
+require ``yes'' rather than 'y' to confirm saving
 bones data when dying in debug mode;
 .PL attack
-require "yes" rather than 'y' to confirm attacking a peaceful monster;
+require ``yes'' rather than 'y' to confirm attacking a peaceful monster;
+.PL wand-break
+require ``yes'' rather than 'y' to confirm breaking a wand;
+.PL Were-change
+require ``yes'' rather than 'y' to confirm changing form due to lycanthropy
+when hero has polymorph control;
 .PL pray
 require 'y' to confirm an attempt to pray rather
 than immediately praying; on by default;
-.PL wand
-require "yes" rather than 'y' to confirm breaking a wand;
 .PL Remove
 require selection from inventory for 'R' and 'T'
 commands even when wearing just one applicable item.
+.PL all
+turn on all of the above.
 .PE
 By default, the pray choice is enabled, the others disabled.
 To disable it without setting
@@ -2339,18 +2973,20 @@ or match an autopickup exception.  Default is on.  Persistent.
 .lp pickup_types
 Specify the object types to be picked up when
 .op autopickup
-is on.  Default is all types.  You can use 
+is on.  Default is all types.  You can use
 .op autopickup_exception
 configuration file lines to further refine
 .op autopickup
 behavior.  Persistent.
 .lp 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.
+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.
 .lp playmode
 Values are `normal', `explore', or `debug'.
 Allows selection of explore mode (also known as discovery mode) or debug
@@ -2367,24 +3003,26 @@ Likewise for the `a' (apply) command if it causes the applied item to
 become wielded.  Persistent.
 .lp "race    "
 Selects your race (for example, ``race:human'').  Default is random.
-If you prefix a `!' or ``no'' to the value, you can 
+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.
 .lp rest_on_space
-Make the space bar a synonym for the `.' (rest) command (default off).
+Make the space bar a synonym for the `.' (#wait) command (default off).
 Persistent.
 .lp "role    "
 Pick your type of character (ex. ``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; `r' is an exception with ``Rogue'', ``Ranger'',
-and ``random'' values. If you prefix a `!' or ``no'' to the value, you can 
-exclude that role from being picked randomly.  Persistent.
+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.
 .lp 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.
 .lp rlecomp
-When writing out a save file, perform run length compression of the map. 
+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.
 .lp runmode
@@ -2403,7 +3041,7 @@ update the map after each step;
 like walk, but pause briefly after each step.
 .PE
 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 
+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.
 .lp safe_pet
@@ -2446,17 +3084,21 @@ Persistent.
 Display a sparkly effect when a monster (including yourself) is hit by an
 attack to which it is resistant (default on).  Persistent.
 .lp standout
-Boldface monsters and ``\fB--More--\fP'' (default off).  Persistent.
+Boldface monsters and ``\fB\-\-More\-\-\fP'' (default off).  Persistent.
 .lp statushilites
-Enable coloring of status fields (default off).
-See ``Configuring Status Hilites'' for futher information.
+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.
+.lp status_updates
+Allow updates to the status lines at the bottom of the screen (default true).
 .lp suppress_alert
 This option may be set to a NetHack version level to suppress
-alert notification messages about feature changes for that 
+alert notification messages about feature changes for that
 and prior versions (ex. ``suppress_alert:3.3.1'').
 .lp 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.
 .lp "time    "
 Show the elapsed game time in turns on bottom line (default off).  Persistent.
 .lp timed_delay
@@ -2478,13 +3120,62 @@ prevent the game from attempting unintended moves if you make inadvertent
 mouse clicks on the map window.  Persistent.
 .lp verbose
 Provide more commentary during the game (default on).  Persistent.
+.lp whatis_coord
+When using the `/' or `;' commands to look around on the map with
+.op autodescribe
+on, display coordinates after the description.
+Also works in other situations where you are asked to pick a location.
+.lp ""
+The possible settings are:
+.sd
+.si
+.CC c "compass ('east' or '3s' or '2n,4w');"
+.CC f "full compass ('east' or '3south' or '2north,4west');"
+.CC m "map <x,y> (map column x=0 is not used);"
+.CC s "screen [row,column] (row is offset to match tty usage);"
+.CC n "none (no coordinates shown) [default]."
+.ei
+.ed
+.lp ""
+The
+.op whatis_coord
+option is also used with
+the `/m', `/M', `/o', and `/O' sub-commands of `/',
+where the `none' setting is overridden with `map'.
+.lp 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.
+.lp ""
+.sd
+.si
+.CC n "no filtering [default]"
+.CC v "in view only"
+.CC a "in same area only"
+.ei
+.ed
+.lp ""
+The area-filter tries to be slightly predictive \(em if you're standing
+on a doorway,
+it will consider the area on the side of the door you were last moving towards.
+.lp ""
+Filtering can also be changed when getting a location with the
+``getpos.filter'' key.
+.lp 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)
+.lp 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)
 .lp windowtype
 Select which windowing system to use, such as ``tty'' or ``X11''
 (default depends on version).
 Cannot be set with the `O' command.
 .lp 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 
+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.
 .hn 2
 Window Port Customization options
@@ -2507,67 +3198,73 @@ Where to align or place the message window (top, bottom, left, or right)
 .lp align_status
 Where to align or place the status window (top, bottom, left, or right).
 .lp ascii_map
-NetHack should display an ascii character map if it can.
-.lp color              
-NetHack should display color if it can for different monsters, 
-objects, and dungeon features
-.lp eight_bit_tty      
-NetHack should pass eight-bit character values (for example, specified with the
+If NetHack can, it should display an ascii character map if it can.
+.lp color
+If NetHack can, it should display color if it can for different monsters,
+objects, and dungeon features.
+.lp eight_bit_tty
+If NetHack can, it should pass eight-bit character values (for example,
+specified with the
 .op traps
 option) straight through to your terminal (default off).
-.lp font_map   
-NetHack should use a font by the chosen name for the map window.
-.lp font_menu  
-NetHack should use a font by the chosen name for menu windows.
-.lp font_message       
-NetHack should use a font by the chosen name for the message window.
-.lp font_status        
-NetHack should use a font by the chosen name for the status window.
-.lp font_text  
-NetHack should use a font by the chosen name for text windows.
-.lp font_size_map      
-NetHack should use this size font for the map window.
-.lp font_size_menu     
-NetHack should use this size font for menu windows.
-.lp font_size_message 
-NetHack should use this size font for the message window.
+.lp font_map
+if NetHack can, it should use a font by the chosen name for the map window.
+.lp font_menu
+If NetHack can, it should use a font by the chosen name for menu windows.
+.lp font_message
+If NetHack can, it should use a font by the chosen name for the message window.
+.lp font_status
+If NetHack can, it should use a font by the chosen name for the status window.
+.lp font_text
+If NetHack can, it should use a font by the chosen name for text windows.
+.lp font_size_map
+If NetHack can, it should use this size font for the map window.
+.lp font_size_menu
+If NetHack can, it should use this size font for menu windows.
+.lp font_size_message
+If NetHack can, it should use this size font for the message window.
 .lp font_size_status
-NetHack should use this size font for the status window.
-.lp font_size_text     
-NetHack should use this size font for text windows.
+If NetHack can, it should use this size font for the status window.
+.lp font_size_text
+If NetHack can, it should use this size font for text windows.
 .lp fullscreen
-NetHack should try and display on the entire screen rather than in a window.
-.lp large_font 
-NetHack should use a large font.
-.lp map_mode   
-NetHack should display the map in the manner specified.
+If NetHack can, it should try and display on the entire screen rather than
+in a window.
+.lp large_font
+If NetHack can, it should use a large font.
+.lp map_mode
+If NetHack can, it should display the map in the manner specified.
 .lp mouse_support
 Allow use of the mouse for input and travel.
 .lp player_selection
-NetHack should pop up dialog boxes, or use prompts for character selection.
-.lp popup_dialog       
-NetHack should pop up dialog boxes for input.
+If NetHack can, it should pop up dialog boxes, or use prompts for character
+selection.
+.lp popup_dialog
+If NetHack can, it should pop up dialog boxes for input.
 .lp preload_tiles
-NetHack should preload tiles into memory.
+If NetHack can, it should preload tiles into memory.
 For example, in the protected mode MSDOS 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.
 .lp scroll_amount
-NetHack should scroll the display by this number of cells
+If NetHack can, it should scroll the display by this number of cells
 when the hero reaches the scroll_margin.
 .lp scroll_margin
-NetHack should scroll the display when the hero or cursor
+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.
 .lp selectsaved
-NetHack 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.
+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.
 .lp softkeyboard
-Display an onscreen keyboard.  Handhelds are most likely to support this option.
+Display an onscreen keyboard.
+Handhelds are most likely to support this option.
 .lp splash_screen
-NetHack should display an opening splash screen when it starts up (default yes).
-.lp tiled_map  
-NetHack should display a tiled map if it can.
+If NetHack can, it should display an opening splash screen when it starts
+up (default yes).
+.lp tiled_map
+If NetHack can, it should display a tiled map if it can.
 .lp tile_file
 Specify the name of an alternative tile file to override the default.
 .lp tile_height
@@ -2577,42 +3274,43 @@ Specify the preferred width of each tile in a tile capable port
 .lp use_darkgray
 Use bold black instead of blue for black glyphs (TTY only).
 .lp use_inverse
-NetHack should display inverse when the game specifies it.
+If NetHack can, it should display inverse when the game specifies it.
 .lp vary_msgcount
-NetHack should display this number of messages at a time in
+If NetHack can, it should display this number of messages at a time in
 the message window.
 .lp windowcolors
-NetHack should display windows with the specified foreground/background
-colors if it can.
+If NetHack can, it should display windows with the specified
+foreground/background colors if it can.
 .lp wraptext
-NetHack port should wrap long lines of text if they don't fit in 
+If NetHack can, it should wrap long lines of text if they don't fit in
 the visible area of the window.
 .hn 2
 Platform-specific Customization options
 .pg
-Here are explanations of options that are used by specific platforms or ports 
+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.
+The name of the handler is specified without the .dll extension and without
+any path information.
 Cannot be set with the `O' command.
 .lp altmeta
 On Amiga, this option controls whether typing `Alt' plus another key
 functions as a meta-shift for that key (default on).
 .lp 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
+set to tell NetHack to convert a two character sequence beginning with
 ESC into a meta-shifted version of the second character (default off).
 .lp ""
 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 \fBn\fP if the
+command \(em preceded by \fBn\fP if the
 .op 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.
+option is set \(em 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.
 .lp "BIOS    "
 Use BIOS calls to update the screen
 display quickly and to read the keyboard (allowing the use of arrow
@@ -2645,7 +3343,7 @@ Cannot be set with the `O' command.
 Set the video mode used (PC NetHack only).
 Values are `autodetect', `default', or `vga'.
 Setting `vga' (or `autodetect' with vga hardware present) will cause
-the game to display tiles. 
+the game to display tiles.
 Cannot be set with the `O' command.
 .lp videocolors
 Set the color palette for PC systems using NO_TERMS
@@ -2667,23 +3365,24 @@ Regular expressions are normally POSIX extended regular expressions. 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.
+patterns. This applies to Autopickup exceptions, Message types, Menu colors,
+and User sounds.
 .hn 2
 Configuring Autopickup Exceptions
 .pg
 You can further refine the behavior of the
 .op autopickup
-option beyond what is available through the 
+option beyond what is available through the
 .op pickup_types
-option. 
+option.
 .pg
-By placing 
+By placing
 .op autopickup_exception
 lines in your configuration
 file, you can define patterns to be checked when the game is about to
 autopickup something.
 .lp autopickup_exception
-Sets an exception to the 
+Sets an exception to the
 .op pickup_types
 option.
 The
@@ -2692,7 +3391,7 @@ 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.
 .lp ""
-In addition, some characters are treated specially if they occur as the first 
+In addition, some characters are treated specially if they occur as the first
 character in the pattern, specifically:
 .sd
 .si
@@ -2722,6 +3421,169 @@ 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.
 .hn 2
+Changing Key Bindings
+.pg
+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.
+.pg
+For example:
+.sd
+.si
+BIND=^X:getpos.autodescribe
+BIND={:menu_first_page
+BIND=v:loot
+.ei
+.ed
+.pg
+.lp "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 ``<esc>'', ``<enter>'', and ``<space>'' keys.
+.lp "Menu accelerator keys"
+The menu control or accelerator keys can also be rebound via OPTIONS-lines
+in the config file. You cannot bind object symbols into menu accelerators.
+.lp "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.
+.pg
+.lp count
+Prefix key to start a count, to repeat a command this many times.
+With
+.op number_pad
+only.
+Default is 'n'.
+.lp doinv
+Show inventory.
+With
+.op number_pad
+only.
+Default is '0'.
+.lp fight
+Prefix key to force fight a direction. Default is 'F'.
+.lp fight.numpad
+Prefix key to force fight a direction.
+With
+.op number_pad
+only.
+Default is '-'.
+.lp getdir.help
+When asked for a direction, the key to show the help. Default is '?'.
+.lp getdir.self
+When asked for a direction, the key to target yourself. Default is '.'.
+.lp getdir.self2
+When asked for a direction, the key to target yourself. Default is 's'.
+.lp getpos.autodescribe
+When asked for a location, the key to toggle autodescribe. Default is '#'.
+.lp getpos.all.next
+When asked for a location, the key to go to next closest interesting thing.
+Default is 'a'.
+.lp getpos.all.prev
+When asked for a location, the key to go to previous closest interesting
+thing.
+Default is 'A'.
+.lp getpos.door.next
+When asked for a location, the key to go to next closest door or doorway.
+Default is 'd'.
+.lp getpos.door.prev
+When asked for a location, the key to go to previous closest door or doorway.
+Default is 'D'.
+.lp getpos.help
+When asked for a location, the key to show help. Default is '?'.
+.lp getpos.mon.next
+When asked for a location, the key to go to next closest monster.
+Default is 'm'.
+.lp getpos.mon.prev
+When asked for a location, the key to go to previous closest monster.
+Default is 'M'.
+.lp getpos.obj.next
+When asked for a location, the key to go to next closest object.
+Default is 'o'.
+.lp getpos.obj.prev
+When asked for a location, the key to go to previous closest object.
+Default is 'O'.
+.lp 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 '!'.
+.lp 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 '*'.
+.lp 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 '\(dq'. \" double quote
+.lp getpos.pick
+When asked for a location, the key to choose the location, and possibly
+ask for more info.
+Default is '.'.
+.lp getpos.pick.once
+When asked for a location, the key to choose the location, and skip asking
+for more info.
+Default is ','.
+.lp 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.
+Default is ';'.
+.lp getpos.pick.verbose
+When asked for a location, the key to choose the location, and show more
+info without asking.
+Default is ':'.
+.lp getpos.self
+When asked for a location, the key to go to your location.
+Default is '@'.
+.lp getpos.unexplored.next
+When asked for a location, the key to go to next closest unexplored location.
+Default is 'x'.
+.lp getpos.unexplored.prev
+When asked for a location, the key to go to previous closest unexplored
+location.
+Default is 'X'.
+.lp getpos.valid
+When asked for a location, the key to go to show valid target locations.
+Default is '$'.
+.lp getpos.valid.next
+When asked for a location, the key to go to next closest valid location.
+Default is 'z'.
+.lp getpos.valid.prev
+When asked for a location, the key to go to previous closest valid location.
+Default is 'Z'.
+.lp nopickup
+Prefix key to move without picking up items. Default is 'm'.
+.lp redraw
+Key to redraw the screen. Default is '^R'.
+.lp redraw.numpad
+Key to redraw the screen.
+With
+.op number_pad
+only.
+Default is '^L'.
+.lp repeat
+Key to repeat previous command. Default is '^A'.
+.lp reqmenu
+Prefix key to request menu from some commands. Default is 'm'.
+.lp run
+Prefix key to run towards a direction. Default is 'G'.
+.lp run.nopickup
+Prefix key to run towards a direction without picking up items on the way.
+Default is 'M'.
+.lp run.numpad
+Prefix key to run towards a direction.
+With
+.op number_pad
+only.
+Default is '5'.
+.lp rush
+Prefix key to rush towards a direction. Default is 'g'.
+.hn 2
 Configuring Message Types
 .pg
 You can change the way the messages are shown in the message area, when
@@ -2732,7 +3594,7 @@ look like this:
 .si
 MSGTYPE=type "pattern"
 .ei
-.PS "message type"
+.PS "pattern"
 .PL type
 how the message should be shown;
 .PL pattern
@@ -2742,14 +3604,16 @@ the pattern to match.
 The pattern should be a regular expression.
 .lp ""
 Allowed types are:
-.sd
-.si
-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.
-.ei
-.ed
+.PS "norep"
+.PL show
+show message normally;
+.PL hide
+never show the message;
+.PL stop
+wait for user with more-prompt;
+.PL norep
+show the message once, but not again if no other message is shown in between.
+.PE
 .lp ""
 Here's an example of message types using NetHack's internal
 pattern matching facility:
@@ -2759,9 +3623,11 @@ MSGTYPE=stop "You feel hungry."
 MSGTYPE=hide "You displaced *."
 .ei
 .ed
-specifies that whenever a message "You feel hungry" is shown,
+specifies that whenever a message ``You feel hungry'' is shown,
 the user is prompted with more-prompt, and a message matching
-"You displaced <something>." is not shown at all.
+``You displaced <something>.'' is not shown at all.
+.\" historical trivia:  "You displaced Fido." was the sort of message you
+.\" got when swapping places with your pet, but that was changed long ago...
 .lp ""
 The order of the defined MSGTYPE-lines is important; the last matching
 rule is used. Put the general case first, exceptions below them.
@@ -2806,23 +3672,23 @@ MENUCOLOR="* cursed *"=red
 MENUCOLOR="* cursed *(being worn)"=red&underline
 .ei
 .ed
-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)"
+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 multiple MENUCOLOR entries in your config file,
 and the last MENUCOLOR-line in your config file that matches
 a menu line will be used for the line.
 .pg
 Note that if you intend to have one or more color specifications match
-" uncursed ", you will probably want to turn the
+`` uncursed '', you will probably want to turn the
 .op implicit_uncursed
 option off so that all items known to be uncursed are actually
 displayed with the ``uncursed'' description.
 .hn 2
 Configuring User Sounds
 .pg
-Some platforms allow you to define sound files to be played when a message 
+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.
@@ -2851,20 +3717,25 @@ The pattern should be a POSIX extended regular expression.
 Configuring Status Hilites
 .pg
 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 
+If so, you can customize your game display by setting thresholds to
 change the color or appearance of fields in the status display.
 .pg
+The format for defining status colors is:
+.si
+.lp "OPTION=hilite_status: field-name/behavior/color&attributes"
+.ei
+.pg
 For example, the following line in your config file will cause
 the hitpoints field to display in the color red if your hitpoints
 drop to or below a threshold of 30%:
 .si
-.lp "OPTION=hilite_status: hitpoints/30%/red/normal"
+.lp "OPTION=hilite_status: hitpoints/<30%/red/normal"
 .ei
 .pg
 For another example, the following line in your config file will cause
 wisdom to be displayed red if it drops and green if it rises.
 .si
-.lp "OPTION=hilite_status: wisdom/updown/red/green"
+.lp "OPTION=hilite_status: wisdom/down/red/up/green"
 .ei
 .pg
 You can adjust the display of the following status fields:
@@ -2883,21 +3754,76 @@ experience      condition
 .\"TABLE_END  Do not delete this line.
 .TE
 .lp ""
+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.
+.lp ""
+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 condition.
+.lp ""
+Allowed behaviors are "always", "up", "down", "changed", a
+percentage or absolute number threshold, or a text to match against.
+.si
+.lp "*"
+"always" will set the default attributes for that field.
+.lp "*"
+"up" and "down" set the field attributes for when the field
+value changes upwards or downwards. This attribute times out after
+statushilites turns.
+.lp "*"
+"changed" sets the field attribute for when the field value
+changes. This attribute times out after statushilites turns.
+.lp "*"
+percentage sets the field attribute when the field value
+matches the percentage. If the percentage is prefixed with '<'
+or '>', it also matches when value is below or above the percentage.
+Only valid for `power' and `hitpoints' fields.
+.lp "*"
+absolute value sets the attribute when the field value
+matches that number. If the number is prefixed with '<'
+or '>', it also matches when value is below or above.
+.lp "*"
+text match sets the attribute when the field value
+matches the text. Text matches can only be used for `alignment',
+`carrying-capacity', and `dungeon-level'.
+.ei
+.lp ""
 Allowed colors are black, red, green, brown, blue, magenta, cyan, gray,
 orange, lightgreen, yellow, lightblue, lightmagenta, lightcyan, and white.
 .lp ""
-Allowed attributes are bold, inverse, normal.
+Allowed attributes are bold, inverse, underline, blink, dim, and normal.
 Note that the platform used may interpret the attributes any way it
 wants.
 .lp ""
-Behaviours can occur based on percentage thresholds, updown, or absolute values.
 The in-game options menu can help you determine the correct syntax for a
 config file.
 .lp ""
-The whole feature can be disabled by setting option statushilites off.
+The whole feature  can  be  disabled  by  setting  option
+statushilites to 0.
+.lp ""
+Example hilites:
+.sd
+.si
+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
+.ei
+.ed
 .pg
 .hn 2
-Modifying NetHack Symbols 
+Modifying NetHack Symbols
 .pg
 NetHack can load entire symbol sets from the symbol file.
 .pg
@@ -2910,51 +3836,55 @@ Set the name of the symbol set that you want to load for display
 on the rogue level.
 .pg
 You can also override one or more symbols using the SYMBOLS config
-file option. Symbols are specified as name:value pairs. Note that
+file option. Symbols are specified as name:value pairs.
+Note that
 NetHack escape-processes the value string in conventional C fashion.
-This means that \e is a prefix to take the following character literally. Thus
-\e needs to be represented as \e\e.
-The special escape form
-\em switches on the meta bit in the symbol value, and the \e^ prefix causes the
-following character to be treated as a control
-character.
+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 \(ha prefix causes the following character to be treated as a
+control character.
 .pg
 .TS S
 center;
 c s s
 c1 l1 l.
 .\"TABLE_START
-NetHack Symbols
+.\" because description is wide, centered title seems off, so pad it a bit
+.\" note that each backslash precedes one space of padding (including the
+.\" last one; in other words, there's a trailing space here)
+NetHack Symbols\ \ \ \ \ \ \ 
 Default        Symbol Name     Description
 \_     \_      \_
-       S_air   (air)
+\      S_air   (air)
 \&_    S_altar (altar)
-"      S_amulet        (amulet)
+\(dq   S_amulet        (amulet)
 A      S_angel (angelic being)
 a      S_ant   (ant or other insect)
-^      S_anti_magic_trap       (anti-magic field)
+\(ha   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)
+\(ha   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)
+\(ha   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)
+\`     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_dart_trap     (dart trap)
+\-     S_crwall        (wall)
+#      S_darkroom      (dark room)
+\(ha   S_dart_trap     (dart trap)
 &      S_demon (major demon)
 *      S_digbeam       (dig beam)
 >      S_dnladder      (ladder down)
@@ -2964,134 +3894,136 @@ D     S_dragon        (dragon)
 ;      S_eel   (sea monster)
 E      S_elemental     (elemental)
 /      S_explode1      (explosion top left)
-     S_explode2      (explosion top center)
-`\e'   S_explode3      (explosion top right)
+\-     S_explode2      (explosion top center)
+\\     S_explode3      (explosion top right)
 |      S_explode4      (explosion middle left)
-       S_explode5      (explosion middle center)
+\      S_explode5      (explosion middle center)
 |      S_explode6      (explosion middle right)
-`\e'   S_explode7      (explosion bottom left)
-     S_explode8      (explosion bottom center)
+\\     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)
+\(ha   S_falling_rock_trap     (falling rock trap)
 f      S_feline        (cat or other feline)
-^      S_fire_trap     (fire trap)
+\(ha   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)
+\      S_ghost (ghost)
 H      S_giant (giant humanoid)
 G      S_gnome (gnome)
 '      S_golem (golem)
 |      S_grave (grave)
 g      S_gremlin       (gremlin)
--      S_hbeam (wall)
+\-     S_hbeam (horizontal beam [zap animation])
 #      S_hcdbridge     (horizontal raised drawbridge)
-+      S_hcdoor        (closed door)
-     S_hodbridge     (horizontal lowered drawbridge)
-|      S_hodoor        (open door)
-^      S_hole  (hole)
++      S_hcdoor        (closed door in horizontal wall)
+\.     S_hodbridge     (horizontal lowered drawbridge)
+|      S_hodoor        (open door in horizontal wall)
+\(ha   S_hole  (hole)
 @      S_human (human or elf)
 h      S_humanoid      (humanoid)
-     S_hwall (horizontal wall)
-     S_ice   (ice)
+\-     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)
+\(ha   S_land_mine     (land mine)
 }      S_lava  (molten lava)
 l      S_leprechaun    (leprechaun)
-^      S_level_teleporter      (level teleporter)
+\(ha   S_level_teleporter      (level teleporter)
 L      S_lich  (lich)
 y      S_light (light)
 #      S_litcorr       (lit corridor)
 :      S_lizard        (lizard)
-`\e'   S_lslant        (wall)
-^      S_magic_portal  (magic portal)
-^      S_magic_trap    (magic trap)
+\\     S_lslant        (diagonal beam [zap animation])
+\(ha   S_magic_portal  (magic portal)
+\(ha   S_magic_trap    (magic trap)
 m      S_mimic (mimic)
 ]      S_mimic_def     (mimic)
 M      S_mummy (mummy)
 N      S_naga  (naga)
-.      S_ndoor (doorway)
+\.     S_ndoor (doorway witout door)
 n      S_nymph (nymph)
 O      S_ogre  (ogre)
 o      S_orc   (orc)
 p      S_piercer       (piercer)
-^      S_pit   (pit)
+\(ha   S_pit   (pit)
 #      S_poisoncloud   (poison cloud)
-^      S_polymorph_trap        (polymorph trap)
+\(ha   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)
+\`     S_rock  (boulder or statue)
 r      S_rodent        (rodent)
-^      S_rolling_boulder_trap  (rolling boulder trap)
-     S_room  (floor of a room)
-/      S_rslant        (wall)
-^      S_rust_trap     (rust trap)
+\(ha   S_rolling_boulder_trap  (rolling boulder trap)
+\.     S_room  (floor of a room)
+/      S_rslant        (diagonal beam [zap animation])
+\(ha   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)
+\(ha   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)
+\(ha   S_spiked_pit    (spiked pit)
+\(ha   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 (dark part of a room)
--      S_sw_bc (swallow bottom center)
-`\e'   S_sw_bl (swallow bottom left)
+\(ha   S_statue_trap   (statue trap)
+\      S_stone (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_tc (swallow top center)
 /      S_sw_tl (swallow top left)
-`\e'   S_sw_tr (swallow top right)
-     S_tdwall        (wall)
-^      S_teleportation_trap    (teleportation trap)
-\      S_throne        (opulent throne)
-     S_tlcorn        (top left corner)
+\\     S_sw_tr (swallow top right)
+\-     S_tdwall        (wall)
+\(ha   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)
+\(ha   S_trap_door     (trap door)
 t      S_trapper       (trapper or lurker above)
-     S_trcorn        (top right corner)
+\-     S_trcorn        (top right corner)
 #      S_tree  (tree)
 T      S_troll (troll)
 |      S_trwall        (wall)
-     S_tuwall        (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 (wall)
+|      S_vbeam (vertical beam [zap animation])
 #      S_vcdbridge     (vertical raised drawbridge)
-+      S_vcdoor        (closed door)
-     S_venom (splash of venom)
-^      S_vibrating_square      (vibrating square)
-     S_vodbridge     (vertical lowered drawbridge)
--      S_vodoor        (open door)
++      S_vcdoor        (closed door in vertical wall)
+\.     S_venom (splash of venom)
+\(ha   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)
+\(dq   S_web   (web)
 w      S_worm  (worm)
-~      S_worm_tail     (long worm tail)
+\(ti   S_worm_tail     (long worm tail)
 W      S_wraith        (wraith)
 x      S_xan   (xan or other mythical/fantastic insect)
 X      S_xorn  (xorn)
@@ -3101,6 +4033,13 @@ z        S_zruty (zruty)
 .\"TABLE_END  Do not delete this line.
 .TE
 .pg
+There is one additional class of object, described as ``strange object'',
+which will occasionally be the shape taken on by mimics and shown as `]'
+for maps displayed as text characters.
+Although the displayed character is the same as the default value for
+`S_mimic_def', it is a different symbol and there is no corresponding
+`S_strange_object' symbol nor any way to assign an alternate value for it.
+.pg
 .hn 2
 Configuring NetHack for Play by the Blind
 .pg
@@ -3120,27 +4059,58 @@ 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.
 .pg
+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.
+.pg
 While it is not difficult for experienced users to edit the \fBdefaults.nh\fP
 file to accomplish this, novices may find this task somewhat daunting.
-Included within the ``symbols'' file of all official distributions of NetHack 
+Included within the ``symbols'' file of all official distributions of NetHack
 is a symset called \fBNHAccess\fP.  Selecting 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 \fBSYMBOLS=\fP 
-in your configuration file to better suit your preferences. 
+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 \fBSYMBOLS=\fP
+in your configuration file to better suit your preferences.
 The most crucial settings to make the game accessible are:
 .pg
 .lp symset:NHAccess
 Load a symbol set appropriate for use by blind players.
 .lp roguesymset:NHAccess
-Load a symbol set for the rogue level that is appropriate for 
+Load a symbol set for the rogue level that is appropriate for
 use by blind players.
 .lp menustyle:traditional
 This will assist in the interface to speech synthesizers.
+.lp nomenu_overlay
+Show menus on a cleared screen and aligned to the left edge.
 .lp 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
+If this is the case, disable the
+.op number_pad
+option and use the traditional
 Rogue-like commands.
+.lp autodescribe
+Automatically describe the terrain under the cursor when targeting.
+.lp mention_walls
+Give feedback messages when walking towards a wall or when travel command
+was interrupted.
+.lp whatis_coord:compass
+When targeting with cursor, describe the cursor position with coordinates
+relative to your character.
+.lp 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.
+.lp whatis_moveskip
+When targeting with cursor and using fast-move, skip the same glyphs instead
+of moving 8 units at a time.
+.lp 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.
 .hn 2
 Global Configuration for System Administrators
 .pg
@@ -3153,55 +4123,81 @@ 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).
 .pg
+.\"  '\ =\ Word'  follow each option name with space+equals+space+first
+.\"               word of sentence in a way that won't have spaces inserted
+.\"               there if that line is padded from left to right;
+.\"               essentially, "OPTION = Word" becomes one token as far
+.\"               as filling and justifying are concerned
 .lp
-WIZARDS
-A space-separated list of user names who are allowed to play in wizard
+WIZARDS\ =\ A space-separated list of user names who are allowed to
+play in wizard
 mode (the debugging mode, not the magic-using role).  A value of a single
 asterisk (*) allows anyone to start a game in wizard mode.
 .lp
-SHELLERS
-A list of users who are allowed to use the shell escape command (!).  The
-syntax is the same as WIZARDS.
+SHELLERS\ =\ A list of users who are allowed to use the shell
+escape command (!).  The syntax is the same as WIZARDS.
 .lp
-EXPLORERS
-A list of users who are allowed to use the explore mode.  The
+EXPLORERS\ =\ A list of users who are allowed to use the explore mode.  The
 syntax is the same as WIZARDS.
 .lp
-MAXPLAYERS
-Limit the maximum number of games that can be running at the same time.
+MAXPLAYERS\ =\ Limit the maximum number of games that can be running
+at the same time.
 .lp
-SUPPORT
-A string explaining how to get local support (no default value).
+SUPPORT\ =\ A string explaining how to get local support (no default value).
 .lp
-RECOVER
-A string explaining how to recover a game on this system (no default value).
+RECOVER\ =\ A string explaining how to recover a game on this system
+(no default value).
 .lp
-SEDUCE
-0 or 1 to disable or enable, respectively, the SEDUCE option (see the source
-for details on this function).
+SEDUCE\ =\ 0 or 1 to disable or enable, respectively, the SEDUCE option.
+When disabled, incubi and succubi behave like nymphs.
 .lp
-CHECK_SAVE_UID
-0 or 1 to disable or enable, respectively, the UID checking for savefiles.
+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.
+.lp
+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).
 .pg
 The following options affect the score file:
 .pg
 .lp
-PERSMAX
-Maximum number of entries for one person.
+PERSMAX\ =\ Maximum number of entries for one person.
+.lp
+ENTRYMAX\ =\ Maximum number of entries in the score file.
 .lp
-ENTRYMAX
-Maximum number of entries in the score file.
+POINTSMIN\ =\ Minimum number of points to get an entry in the score file.
 .lp
-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, respectively,
+to identify unique people for the score file.
 .lp
-PERS_IS_UID
-0 or 1 to use user names or numeric userids, respectively, 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).
 .lp
-MAX_STATUENAME_RANK
-Maximum number of score file entries to use for random statue names
-(default is 10).
+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 following placeholders:
+.\" note: %M is not an entry in the table, but 'M' is the widest letter
+.PS %M
+.PL %%
+literal '%'
+.PL %v
+version (eg. "3.6.1-0")
+.PL %u
+game UID
+.PL %t
+game start time, UNIX timestamp format
+.PL %T
+current time, UNIX timestamp format
+.PL %d
+game start time, YYYYMMDDhhmmss format
+.PL %D
+current time, YYYYMMDDhhmmss format
+.PL %n
+player name
+.PL %N
+first character of player name
+.PE
+.
 .hn 1
 Scoring
 .pg
@@ -3224,8 +4220,8 @@ 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.
 .pg
 If you just want to see what the current top players/games list is, you
-can type \fBnethack -s all\fP on most versions.
-
+can type \fBnethack \-s all\fP on most versions.
+.
 .hn 1
 Explore mode
 .pg
@@ -3237,7 +4233,7 @@ paltry cost of not getting on the high score list.
 .pg
 There are two ways of enabling explore mode.  One is to start the game
 with the
-.op -X
+.op \-X
 command-line switch or with the
 .op playmode:explore
 option.  The other is to issue the ``#exploremode'' extended command while
@@ -3254,7 +4250,7 @@ brief description.  It is intended for tracking down problems within the
 program rather than to provide 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
-.op -D
+.op \-D
 command-line switch or with the
 .op playmode:debug
 option.
@@ -3266,12 +4262,12 @@ there's no connection between ``wizard mode'' and the Wizard role).
 And on any system, the program might have been configured to omit debug
 mode entirely.  Attempting to start a game in debug mode when not allowed
 or not available will result in falling back to explore mode instead.
-
+.
 .hn
 Credits
 .pg
-The original \fIhack\fP game was modeled on the Berkeley 
-.ux
+The original \fIhack\fP game was modeled on the Berkeley
+.UX
 \fIrogue\fP game.  Large portions of this paper were shamelessly
 cribbed from \fIA Guide to the Dungeons of Doom\fP, by Michael C. Toy
 and Kenneth C. R. C. Arnold.  Small portions were adapted from
@@ -3279,7 +4275,7 @@ and Kenneth C. R. C. Arnold.  Small portions were adapted from
 .pg
 NetHack is the product of literally dozens of people's work.
 Main events in the course of the game development are described below:
-
+.
 .pg
 \fBJay Fenlason\fP wrote the original Hack, with help from
 \fBKenny Woodland\fP, \fBMike Thome\fP and \fBJon Payne\fP.
@@ -3287,7 +4283,7 @@ Main events in the course of the game development are described below:
 \fBAndries Brouwer\fP 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
-.ux
+.UX
 machines to the Usenet.
 .pg
 \fBDon G. Kneller\fP ported Hack 1.0.3 to Microsoft C and MS-DOS, producing PC
@@ -3392,29 +4388,31 @@ DevTeam and incorporated 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.
 .pg
-The 3.3 development team, consisting of \fBMichael Allison\fP, \fBKen Arromdee\fP, 
-\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBSteve Creps\fP, \fBKevin Darcy\fP, 
-\fBTimo Hakulinen\fP, \fBKevin Hugo\fP, \fBSteve Linhart\fP, \fBKen Lorber\fP, 
-\fBDean Luick\fP, \fBPat Rankin\fP, \fBEric Smith\fP, \fBMike Stephenson\fP, 
-\fBJanet Walz\fP, and \fBPaul Winner\fP, released 3.3.0 in 
+The 3.3 development team, consisting of
+\fBMichael Allison\fP, \fBKen Arromdee\fP,
+\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBSteve Creps\fP, \fBKevin Darcy\fP,
+\fBTimo Hakulinen\fP, \fBKevin Hugo\fP, \fBSteve Linhart\fP, \fBKen Lorber\fP,
+\fBDean Luick\fP, \fBPat Rankin\fP, \fBEric Smith\fP, \fBMike Stephenson\fP,
+\fBJanet Walz\fP, and \fBPaul Winner\fP, released 3.3.0 in
 December 1999 and 3.3.1 in August of 2000.
 .pg
-Version 3.3 offered many firsts. It was the first version to separate 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, 
+Version 3.3 offered many firsts. It was the first version to separate 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 listing all the bugs that had been discovered.  Despite 
+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.
 .pg
 The 3.4 development team initially consisted of
 \fBMichael Allison\fP, \fBKen Arromdee\fP,
 \fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBKevin Hugo\fP, \fBKen Lorber\fP,
-\fBDean Luick\fP, \fBPat Rankin\fP, \fBMike Stephenson\fP, 
-\fBJanet Walz\fP, and \fBPaul Winner\fP, with \fB Warwick Allison\fP joining 
+\fBDean Luick\fP, \fBPat Rankin\fP, \fBMike Stephenson\fP,
+\fBJanet Walz\fP, and \fBPaul Winner\fP, with \fB Warwick Allison\fP joining
 just before the release of NetHack 3.4.0 in March 2002.
 .pg
 As with version 3.3, various people contributed to the game as a whole as
@@ -3428,46 +4426,38 @@ and \fBYitzhak Sapir\fP provided encouragement.
 \fBDean Luick\fP, \fBMark Modrall\fP, and \fBKevin Hugo\fP maintained and enhanced the
 Macintosh port of 3.4.
 .pg
-\fBMichael Allison\fP, \fBDavid Cohrs\fP, \fBAlex Kompel\fP, \fBDion Nicolaas\fP, and 
-\fBYitzhak Sapir\fP maintained and enhanced 3.4 for the Microsoft Windows platform.
-\fBAlex Kompel\fP contributed a new graphical interface for the Windows port. 
+\fBMichael Allison\fP, \fBDavid Cohrs\fP, \fBAlex Kompel\fP,
+\fBDion Nicolaas\fP, and
+\fBYitzhak Sapir\fP maintained and enhanced 3.4 for the Microsoft Windows
+platform.
+\fBAlex Kompel\fP contributed a new graphical interface for the Windows port.
 \fBAlex Kompel\fP also contributed a Windows CE port for 3.4.1.
 .pg
 \fBRon Van Iwaarden\fP 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 
+early 2006. A great many thanks to Ron for keeping NetHack alive on OS/2
 all these years.
 .pg
-\fBJanne Salmijarvi\fP and \fBTeemu Suikki\fP maintained and 
-enhanced the Amiga port of 3.4 after \fBJanne Salmijarvi\fP resurrected 
+\fBJanne Salmijarvi\fP and \fBTeemu Suikki\fP maintained and
+enhanced the Amiga port of 3.4 after \fBJanne Salmijarvi\fP resurrected
 it for 3.3.1.
 .pg
-\fBChristian ``Marvin'' Bressler\fP maintained 3.4 for the Atari after he 
+\fBChristian ``Marvin'' Bressler\fP maintained 3.4 for the Atari after he
 resurrected it for 3.3.1.
 .pg
-The release of NetHack 3.4.3 in December 2003 marked the beginning of a 
+The release of NetHack 3.4.3 in December 2003 marked the beginning 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 
-devteam 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 
-\fBDerek S. Ray\fP, unnethack by \fBPatric Mueller\fP, nitrohack and its 
-successors originally by \fBDaniel Thaler\fP and then by \fBAlex Smith\fP, 
-and Dynahack by \fBTung Nguyen\fP. Some of those variants continue to be 
+provided continued enjoyment by the community for more than a decade. The
+devteam 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
+\fBDerek S. Ray\fP, unnethack by \fBPatric Mueller\fP, nitrohack and its
+successors originally by \fBDaniel Thaler\fP and then by \fBAlex Smith\fP,
+and Dynahack by \fBTung Nguyen\fP. Some of those variants continue to be
 developed, maintained, and enjoyed by the community to this day.
 .pg
-At the beginning of development for what would eventually get released
-as 3.6.0, the development team consisted of \fBWarwick Allison\fP, 
-\fBMichael Allison\fP, \fBKen Arromdee\fP,
-\fBDavid Cohrs\fP, \fBJessie Collet\fP, 
-\fBKen Lorber\fP, \fBDean Luick\fP, \fBPat Rankin\fP, 
-\fBMike Stephenson\fP, \fBJanet Walz\fP, and \fBPaul Winner\fP.
-Leading up to the release of 3.6.0 in early 2015, new members
-\fBSean Hunt\fP, \fBPasi Kallinen\fP, and \fBDerek S. Ray\fP
-joined the NetHack development team.
-.pg
-In September 2014, an interim snapshot of the code under development was 
-released publicly by other parties. Since that code was a work-in-progress 
+In September 2014, an interim snapshot of the code under development 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
@@ -3475,89 +4465,123 @@ was posted on the devteam'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.
 .pg
-In November 2014, preparation began for the release of NetHack 3.6. The 3.6
-version merges work done by the development team since the previous release
-with some of the beloved community patches. Many bugs were fixed and a
-large amount of code was restructured.
+In January 2015, preparation began for the release of NetHack 3.6.
+.pg
+At the beginning of development for what would eventually get released
+as 3.6.0, the development team consisted of \fBWarwick Allison\fP,
+\fBMichael Allison\fP, \fBKen Arromdee\fP,
+\fBDavid Cohrs\fP, \fBJessie Collet\fP,
+\fBKen Lorber\fP, \fBDean Luick\fP, \fBPat Rankin\fP,
+\fBMike Stephenson\fP, \fBJanet Walz\fP, and \fBPaul Winner\fP.
+In early 2015, ahead of the release of 3.6.0, new members
+\fBSean Hunt\fP, \fBPasi Kallinen\fP, and \fBDerek S. Ray\fP
+joined the NetHack development team.
+.pg
+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.
+.pg
+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.
+.pg
+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 development team at the time of release of 3.6.1 consisted of
+\fBWarwick Allison\fP, \fBMichael Allison\fP, \fBKen Arromdee\fP,
+\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBPasi Kallinen\fP,
+\fBKen Lorber\fP, \fBDean Luick\fP, \fBPatric Mueller\fP,
+\fBPat Rankin\fP, \fBDerek S. Ray\fP, \fBAlex Smith\fP,
+\fBMike Stephenson\fP, \fBJanet Walz\fP, and \fBPaul Winner\fP.
+.pg
+The development team, as well as \fBSteve VanDevender\fP and
+\fBKevin Smolkowski\fP, ensured that NetHack 3.6 continued to operate on
+various
+.UX
+flavors and maintained the X11 interface.
+.pg
+\fBKen Lorber\fP, \fBHaoyang Wang\fP, \fBPat Rankin\fP, and \fBDean Luick\fP
+maintained the port of NetHack 3.6 for Mac OSX.
 .pg
-\fBThe development team, as well as \fBSteve VanDevender\fP and 
-\fBKevin Smolkowski\fP ensured that NetHack 3.6.0 continued to operate on 
-various Unix flavors and maintained the X11 interface. 
+\fBMichael Allison\fP, \fBDavid Cohrs\fP, \fBBarton House\fP,
+\fBPasi Kallinen\fP, \fBAlex Kompel\fP, \fBDion Nicolaas\fP,
+\fBDerek S. Ray\fP and \fBYitzhak Sapir\fP maintained the port of
+NetHack 3.6 for Microsoft Windows.
 .pg
-\fBKen Lorber\fP, \fBHaoyang Wang\fP, \fBPat Rankin\fP, and \fBDean Luick\fP 
-maintained the port of NetHack 3.6.0 for Mac.
+\fBPat Rankin\fP attempted to keep the VMS port running for NetHack 3.6.1,
+hindered by limited access. \fBKevin Smolkowski\fP 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.
 .pg
-\fBMichael Allison\fP, \fBDerek S. Ray\fP, \fBYitzhak Sapir\fP, 
-\fBAlex Kompel\fP, and \fBDion Nicolaas\fP maintained the port of 
-NetHack 3.6.0 for Microsoft Windows.
+\fBRay Chason\fP resurrected the msdos port for 3.6.1 and contributed the
+necessary updates to the community at large.
 .pg
 The official NetHack web site is maintained by \fBKen Lorber\fP at http://www.nethack.org/.
 .pg
-SHOUT-OUTS
+.hn 2
+SPECIAL THANKS
 .pg
-The devteam would like to give a special "shout-out" to thank the generous 
-people primarily responsible for the public NetHack servers available for 
-playing the game at nethack.alt.org and devnull.net. In addition to providing 
-a way for the public to play a game of NetHack from almost anywhere, they 
-have hosted annual NetHack tournaments for many, many years. 
-.pg 
-On behalf of the NetHack community, thank you very much to 
-\fBM. Drew Streib\fP, \fBPasi Kallinen\fP and \fBRobin Bandy\fP.
+On behalf of the NetHack community, thank you very much once
+again to \fBM. Drew Streib\fP, \fBPasi Kallinen\fP and \fBRobin Bandy\fP
+for providing public NetHack servers at nethack.alt.org and devnull.net
+and/or for hosting annual NetHack tournaments.
 .pg
-                          - - - - - - - - - -
+.ce
+- - - - - - - - - -\ \ \ \ \" when centered, the dashes look a little too far
+.                          \" to the right, so pad them with a few spaces
 .pg
 From time to time, some depraved individual out there in netland sends a
 particularly intriguing modification to help out with the game.  The Gods of
 the Dungeon sometimes make note of the names of the worst of these miscreants
 in this, the list of Dungeoneers:
-
+.
 .TS S
 center;
 c c c.
 .\"TABLE_START
-Adam Aronow    Janet Walz      Nathan Eady
-Alex Kompel    Janne Salmijarvi        Norm Meluch
+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
-Ari Huttunen   John Kallen     Paul Winner
-Barton House   John Rupley     Pierre Martineau
-Benson I. Margulies    John S. Bien    Ralf Brown
-Bill Dyer      Johnny Lee      Ray Chason
-Boudewijn Waijers      Jon W{tte       Richard Addison
-Bruce Cox      Jonathan Handler        Richard Beigel
-Bruce Holloway Joshua Delahunty        Richard P. Hughey
-Bruce Mewborne Keizo Yamamoto  Rob Menke
-Carl Schelin   Ken Arnold      Robin Bandy
-Chris Russo    Ken Arromdee    Robin Johnson
-David Cohrs    Ken Lorber      Roderick Schertler
-David Damerell Ken Washikita   Roland McGrath
-David Gentzel  Kevin Darcy     Ron Van Iwaarden
-David Hairston Kevin Hugo      Ronnen Miller
-Dean Luick     Kevin Sitze     Ross Brown
-Del Lamb       Kevin Smolkowski        Sascha Wostmann
-Derek S. Ray   Kevin Sweet     Scott Bigham
-Deron Meranda  Lars Huttar     Scott R. Turner
-Dion Nicolaas  Leon Arnott     Sean Hunt
-Dylan O'Donnell        M. Drew Streib  Stephen Spackman
-Eric Backus    Malcolm Ryan    Stefan Thielscher
-Eric Hendrickson       Mark Gooderum   Stephen White
-Eric R. Smith  Mark Modrall    Steve Creps
-Eric S. Raymond        Marvin Bressler Steve Linhart
-Erik Andersen  Matthew Day     Steve VanDevender
-Frederick Roeber       Merlyn LeRoy    Teemu Suikki
-Gil Neiger     Michael Allison Tim Lennan
-Greg Laskin    Michael Feir    Timo Hakulinen
-Greg Olson     Michael Hamel   Tom Almy
-Gregg Wonderly Michael Sokolov Tom West
-Hao-yang Wang  Mike Engber     Warren Cheung
-Helge Hafting  Mike Gallop     Warwick Allison
-Irina Rempt-Drijfhout  Mike Passaretti Yitzhak Sapir
-Izchak Miller  Mike Stephenson
-J. Ali Harlow  Mikko Juola
+Ari Huttunen   John Kallen     Patric Mueller
+Barton House   John Rupley     Paul Winner
+Benson I. Margulies    John S. Bien    Pierre Martineau
+Bill Dyer      Johnny Lee      Ralf Brown
+Boudewijn Waijers      Jon W{tte       Ray Chason
+Bruce Cox      Jonathan Handler        Richard Addison
+Bruce Holloway Joshua Delahunty        Richard Beigel
+Bruce Mewborne Keizo Yamamoto  Richard P. Hughey
+Carl Schelin   Ken Arnold      Rob Menke
+Chris Russo    Ken Arromdee    Robin Bandy
+David Cohrs    Ken Lorber      Robin Johnson
+David Damerell Ken Washikita   Roderick Schertler
+David Gentzel  Kevin Darcy     Roland McGrath
+David Hairston Kevin Hugo      Ron Van Iwaarden
+Dean Luick     Kevin Sitze     Ronnen Miller
+Del Lamb       Kevin Smolkowski        Ross Brown
+Derek S. Ray   Kevin Sweet     Sascha Wostmann
+Deron Meranda  Lars Huttar     Scott Bigham
+Dion Nicolaas  Leon Arnott     Scott R. Turner
+Dylan O'Donnell        M. Drew Streib  Sean Hunt
+Eric Backus    Malcolm Ryan    Stephen Spackman
+Eric Hendrickson       Mark Gooderum   Stefan Thielscher
+Eric R. Smith  Mark Modrall    Stephen White
+Eric S. Raymond        Marvin Bressler Steve Creps
+Erik Andersen  Matthew Day     Steve Linhart
+Frederick Roeber       Merlyn LeRoy    Steve VanDevender
+Gil Neiger     Michael Allison Teemu Suikki
+Greg Laskin    Michael Feir    Tim Lennan
+Greg Olson     Michael Hamel   Timo Hakulinen
+Gregg Wonderly Michael Sokolov Tom Almy
+Hao-yang Wang  Mike Engber     Tom West
+Helge Hafting  Mike Gallop     Warren Cheung
+Irina Rempt-Drijfhout  Mike Passaretti Warwick Allison
+Izchak Miller  Mike Stephenson Yitzhak Sapir
 .\"TABLE_END  Do not delete this line.
 .TE
-
+.pg
 .\"Microsoft and MS-DOS are registered trademarks of Microsoft Corporation.
 .\"Lattice is a trademark of Lattice, Inc.
 .\"Atari and 1040ST are trademarks of Atari, Inc.
index 7a06034..2cbc606 100644 (file)
@@ -1,5 +1,5 @@
 \documentstyle[titlepage,longtable]{article}
-% NetHack 3.6  Guidebook.tex $NHDT-Date: 1431192762 2015/05/09 17:32:42 $  $NHDT-Branch: master $:$NHDT-Revision: 1.60 $ */
+% NetHack 3.6  Guidebook.tex $NHDT-Date: 1431192762 2015/12/16 17:32:42 $  $NHDT-Branch: master $:$NHDT-Revision: 1.60 $ */
 %+% we're still limping along in LaTeX 2.09 compatibility mode
 %-%\documentclass{article}
 %-%\usepackage{hyperref} % before longtable
 %.au
 \author{Original version - Eric S. Raymond\\
 (Edited and expanded for 3.6 by Mike Stephenson and others)}
-\date{December 7, 2015}
+\date{April 27, 2018}
 
 \maketitle
 
-%.hn 1
-\section{Preface - Version 3.6}
-%.pg
-This version of the game is special in a particular way.  Near the end of 
-the development of 3.6, one of the significant inspirations for many of the 
-humorous and fun features found in the game, author {\it Terry Pratchett}, 
-passed away.  We have dedicated this version of the game in his memory.
-
 %.pg
 %.hn 1
 \section{Introduction}
 
 %.pg
 
-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 
+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 
+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?
 %.pg
 
@@ -88,23 +80,23 @@ 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.  
-
-%.pg
-\nd 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 morning, you 
-gather your gear, eat what may be your last meal outside, and enter 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.
+
+%.pg
+\nd 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 morning, you
+gather your gear, eat what may be your last meal outside, and enter the
 dungeon\ldots
 
 %.hn 1
@@ -113,7 +105,7 @@ dungeon\ldots
 %.pg
 You have just begun a game of {\it NetHack}.  Your goal is to grab as much
 treasure as you can, retrieve the Amulet of Yendor, and escape the
-Mazes of Menace alive.  
+Mazes of Menace alive.
 
 %.pg
 Your abilities and strengths for dealing with the hazards of adventure
@@ -245,8 +237,8 @@ The armor and weapons fashioned by the Orcs are typically of inferior quality.
 %.hn 1
 \section{What do all those things on the screen mean?}
 %.pg
-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, 
+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.
 
 %.pg
@@ -346,6 +338,9 @@ do other tasks requiring agility or manipulation of objects.
 \item[\bb{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
+carrying capacity from your constitution no longer matters.
 %.lp
 \item[\bb{Intelligence}]
 Intelligence affects your ability to cast spells and read spellbooks.
@@ -405,16 +400,42 @@ show only your experience level here.
 The number of turns elapsed so far, displayed if you have the
 {\it time\/} option set.
 %.lp
-\item[\bb{Hunger Status}]
-Your current hunger status, ranging from %
-{\it Satiated\/} down to {\it Fainting}.  If your hunger status is normal,
-it is not displayed.
-%.pg
-Additional status flags may appear after the hunger status:
-{\it Conf\/} when you're confused, {\it FoodPois\/} or {\it Ill\/}
-when sick, {\it Blind\/}
-when you can't see, {\it Stun\/} when stunned, and {\it Hallu\/} when
-hallucinating.
+\item[\bb{Status}]
+Hunger:
+your current hunger status.
+Values are {\it Satiated}, {\it Not~Hungry\/} (or {\it Normal\/}),
+{\it Hungry}, {\it Weak}, and {\it Fainting}.
+%.\" not mentioned: Fainted
+Not shown when {\it Normal}.
+
+%.lp ""
+Encumbrance:
+an indication of how what you are carrying affects your ability to move.
+Values are {\it Unencumbered}, {\it Encumbered}, {\it Stressed},
+{\it Strained}, {\it Overtaxed}, and {\it Overloaded}.
+Not shown when {\it Unencumbered}.
+
+%.lp ""
+Fatal~conditions:
+{\it Stone\/} (aka {\it Petrifying}, turning to stone),
+{\it Slime\/} (turning into green slime),
+{\it Strngl\/} (being strangled),
+{\it FoodPois\/} (suffering from acute food poisoning),
+{\it TermIll\/} (suffering from a terminal illness).
+
+%.lp ""
+Non-fatal~conditions:
+{\it Blind\/} (can't see), {\it Deaf\/} (can't hear),
+{\it Stun\/} (stunned), {\it Conf\/} (confused), {\it Hallu\/} (hallucinating).
+
+%.lp ""
+Movement~modifiers:
+{\it Lev\/} (levitating), {\it Fly\/} (flying), {\it Ride\/} (riding).
+
+%.lp ""
+Other conditions and modifiers exist, but there isn't enough room to
+display them with the other status fields.  The `{\tt \^{}X}' command shows
+all relevant status conditions.
 \elist
 
 %.hn 2
@@ -529,8 +550,8 @@ Sometimes, however, they can be helpful.
 %.lp
 \item[\tb{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.
+monster.  Note that the monster could have moved.
+The `{\tt F}' and `{\tt m}' commands may be useful here.
 
 \elist
 %.pg
@@ -542,13 +563,15 @@ more info).
 \section{Commands}
 
 %.pg
-Commands are initiated by typing one or two characters.  Some 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 ``{\tt search}'', do not require that any more information be collected
 by {\it NetHack\/}.  Other commands might require additional information, for
 example a direction, or an object to be used.  For those commands that
-require additional information, {\it 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
+require additional information, {\it 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
 `{\it menustyle\/}'
 option.
 
@@ -578,7 +601,7 @@ greater control (see below).  To cancel a count or a prefix, press the
 %.pg
 The list of commands is rather long, but it can be read at any time
 during the game through the `{\tt ?}' command, which accesses a menu of
-helpful texts.  Here are the commands for your reference:
+helpful texts.  Here are the default key bindings for your reference:
 
 \blist{}
 %.lp
@@ -586,24 +609,44 @@ helpful texts.  Here are the commands for your reference:
 Help menu:  display one of several help texts available.
 %.lp
 \item[\tb{/}]
-Tell what a symbol represents.  You may choose to specify a location
+The {\tt 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 `{\tt .}', `{\tt ,}', `{\tt ;}',
 or `{\tt :}'.  `{\tt .}' will explain the symbol at the chosen location,
+information, then let you pick another location;
 conditionally check for ``{\tt More info?}'' depending upon whether the
-{\it help\/}
+`{\it help\/}'
 option is on, and then you will be asked to pick another location;
 `{\tt ,}' will explain the symbol but skip any additional
-information; `{\tt ;}' will skip additional info and also not bother asking
+`{\tt ;}' will skip additional info and also not bother asking
 you to choose another location to examine; `{\tt :}' will show additional
 info, if any, without asking for confirmation.  When picking a location,
 pressing the {\tt ESC} key will terminate this command, or pressing `{\tt ?}'
 will give a brief reminder about how it works.
 
-%.pg
+%.lp ""
+If the
+{\it autodescribe\/}
+option is on, a short description of what you see at each location is
+shown as you move the cursor.  Typing `{\tt \#}' while picking a location will
+toggle that option on or off.
+The
+{\it whatis\verb+_+coord\/}
+option controls whether the short description includes map coordinates.
+
+%.lp ""
 Specifying a name rather than a location
 always gives any additional information available about that name.
+
+%.lp ""
+You may also request a description of nearby monsters,
+all monsters currently displayed, nearby objects, or all objects.
+The
+{\it whatis\verb+_+coord\/}
+option controls which format of map coordinate is included with their
+descriptions.
 %.lp
 \item[\tb{\&}]
 Tell what a command does.
@@ -641,10 +684,25 @@ Go in that direction until you hit a wall or run into something.
 %.lp
 \item[\tb{m[yuhjklbn]}]
 Prefix:  move without picking up objects or fighting (even if you remember
-a monster there)
+a monster there).\\
+%.lp ""
+A few non-movement commands use the `{\tt m}' prefix to request operating
+via menu (to temporarily override the
+{\it menustyle:Traditional\/}
+option).
+Primarily useful for `{\tt ,}' (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 `{\tt m}' at that prompt).\\
+%.lp ""
+A few other commands (eat food, offer sacrifice, apply tinning-kit) use
+the `{\tt m}' prefix to skip checking for applicable objects on the floor
+and go straight to checking inventory,
+or (for ``{\tt \#loot}'' to remove a saddle),
+skip containers and go straight to adjacent monsters. The prefix will
+make ``{\tt \#travel}'' command show a menu of interesting targets in sight.
 %.lp
 \item[\tb{F[yuhjklbn]}]
-Prefix:  fight a monster (even if you only guess one is there)
+Prefix:  fight a monster (even if you only guess one is there).
 %.lp
 \item[\tb{M[yuhjklbn]}]
 Prefix:  Move far, no pickup.
@@ -662,22 +720,25 @@ Travel to a map location via a shortest-path algorithm.\\
 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 
+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 
+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.
 %.lp
 \item[\tb{.}]
-Rest, do nothing for one turn.
+Wait or rest, do nothing for one turn.
 %.lp
 \item[\tb{a}]
-Apply (use) a tool (pick-axe, key, lamp \ldots).
+Apply (use) a tool (pick-axe, key, lamp \ldots).\\
+%.lp ""
+If used on a wand, that wand will be broken, releasing its magic in the
+process.  Confirmation is required.
 %.lp
 \item[\tb{A}]
 Remove one or more worn items, such as armor.\\
 %.lp ""
-Use `{\tt T}' (take off) to take off only one piece of armor 
+Use `{\tt T}' (take off) to take off only one piece of armor
 or `{\tt R}' (remove) to take off only one accessory.
 %.lp
 \item[\tb{\^{}A}]
@@ -726,7 +787,12 @@ the bless\-ed/\-un\-curs\-ed/\-curs\-ed groups may be typed.\\
 Kick something (usually a door).
 %.lp
 \item[\tb{e}]
-Eat food.
+Eat food.\\
+%.lp ""
+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 `{\tt e}' with the `{\tt m}' prefix to bypass attempting to eat
+anything off the floor.
 %.lp
 % Make sure Elbereth is not hyphenated below, the exact spelling matters.
 % (Only specified here to parallel Guidebook.mn; use of \tt font implicity
@@ -742,8 +808,7 @@ Engrave a message on the floor.\\
 %.lp ""
 Engraving the word ``{\tt 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.  (This feature may be compiled out
-of the game, so your version might not have it.)
+often useful to give yourself a breather.
 %.lp
 \item[\tb{f}]
 Fire one of the objects placed in your quiver (or quiver sack, or that you
@@ -786,6 +851,15 @@ The available options
 are listed later in this Guidebook.  Options are usually set before the
 game rather than with the `{\tt O}' command; see the section on options below.
 %.lp
+\item[\tb{\^{}O}]
+Show overview or show dungeon layout\\
+%.lp ""
+In normal play and in explore mode, a shortcut for the ``{\tt \#overview}''
+extended command to list interesting dungeon levels visited.\\
+%.lp ""
+In debug mode, an extra command which lists the placement of all special
+levels.
+%.lp
 \item[\tb{p}]
 Pay your shopping bill.
 %.lp
@@ -802,7 +876,7 @@ choices but will accept an accessory and attempt to put that on.)
 Repeat previous message.\\
 %.lp ""
 Subsequent {\tt \^{}P}'s repeat earlier messages.
-The behavior can be varied via the {\it msg\verb+_+window} option.
+The behavior can be varied via the {\it msg\verb+_+window\/} option.
 %.lp
 \item[\tb{q}]
 Quaff (drink) something (potion, water, etc).
@@ -904,10 +978,11 @@ the exchange still takes place.
 \item[\tb{X}]
 Toggle two-weapon combat, if your character can do it.  Also available
 via the ``{\tt \#twoweapon}'' extended command.\\
-+.lp ""
-+(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 ``{\tt \#explore}''.)
+%.lp ""
+
+(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 ``{\tt \#exploremode}''.)
 %.lp
 \item[\tb{\^{}X}]
 Display basic information about your character.\\
@@ -953,7 +1028,7 @@ May be preceded by `{\tt m}' to force a selection menu.
 Toggle the {\it autopickup\/} option on and off.
 %.lp
 \item[\tb{\^{}}]
-Ask for the type of a trap you found earlier.
+Ask for the type of an adjacent trap you found earlier.
 %.lp
 \item[\tb{)}]
 Tell what weapon you are wielding.
@@ -1014,69 +1089,202 @@ the game was compiled with.
 \item[\tb{\#adjust}]
 Adjust inventory letters (most useful when the
 {\it fixinv\/}
-option is ``on'').\\
+option is ``on''). Autocompletes. Default key is '{\tt M-a}'.\\
 %.lp ""
 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 location 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.
 ``{\tt \#adjust}'' can also be used to split a stack of objects; when
-choosing the item to adjust, enter a count prior to its letter.
+choosing the item to adjust, enter a count prior to its letter.\\
+%.lp ""
+Adjusting without a count used to collect all compatible stacks when
+moving to the destination.  That behavior has been changed; to gather
+compatible stacks, ``{\tt \#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 eligible.
+In either case, otherwise compatible stacks with a different name
+will not be merged.  This contrasts with using ``{\tt \#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.
 %.lp
 \item[\tb{\#annotate}]
 Allows you to specify one line of text to associate with the current
 dungeon level.  All levels with annotations are displayed by the
-``{\tt \#overview}'' command.
+``{\tt \#overview}'' command. Autocompletes. Default key is '{\tt M-A}',
+and '{\tt \^{}N}' if {\it number\verb+_+pad\/} is on.
+%.lp
+\item[\tb{\#apply}]
+Apply (use) a tool such as a pick-axe, a key, or a lamp.
+Default key is '{\tt a}'.\\
+If the tool used acts on items on the floor, using the `{\tt m}' prefix
+skips those items.\\
+%.lp ""
+If used on a wand, that wand will be broken, releasing its magic in the
+process.  Confirmation is required.
+%.lp
+\item[\tb{\#attributes}]
+Show your attributes. Default key is '{\tt \^{}X}'.\\
+%.lp
+\item[\tb{\#autopickup}]
+Toggle the {\it autopickup\/} -option. Default key is '{\tt @}'.\\
+%.lp
+\item[\tb{\#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 ``{\tt \#annotate}''). Default key is '{\tt C}'.
+%.lp
+\item[\tb{\#cast}]
+Cast a spell. Default key is '{\tt Z}'.\\
 %.lp
 \item[\tb{\#chat}]
-Talk to someone.
+Talk to someone. Default key is '{\tt M-c}'.\\
+%.lp
+\item[\tb{\#close}]
+Close a door. Default key is '{\tt c}'.\\
 %.lp
 \item[\tb{\#conduct}]
-List voluntary challenges you have maintained.\\
+List voluntary challenges you have maintained. Autocompletes.
+Default key is '{\tt M-C}'.\\
 %.lp ""
 See the section below entitled ``Conduct'' for details.
 %.lp
 \item[\tb{\#dip}]
-Dip an object into something.
+Dip an object into something. Autocompletes. Default key is '{\tt M-d}'.
+%.lp
+\item[\tb{\#down}]
+Go down a staircase. Default key is '{\tt >}'.
+%.lp
+\item[\tb{\#drop}]
+Drop an item. Default key is '{\tt d}'.
+%.lp
+\item[\tb{\#droptype}]
+Drop specific item types. Default key is '{\tt D}'.
+%.lp
+\item[\tb{\#eat}]
+Eat something. Default key is '{\tt e}'.
+The `{\tt m}' prefix skips eating items on the floor.
+%.lp
+\item[\tb{\#engrave}]
+Engrave writing on the floor. Default key is '{\tt E}'.
 %.lp
 \item[\tb{\#enhance}]
-Advance or check weapon and spell skills.
+Advance or check weapon and spell skills. Autocompletes.
+Default key is '{\tt M-e}'.
+%.lp
+\item[\tb{\#exploremode}]
+Enter the explore mode.
+%.lp
+\item[\tb{\#fire}]
+Fire ammunition from quiver. Default key is '{\tt f}'.
 %.lp
 \item[\tb{\#force}]
-Force a lock.
+Force a lock. Autocompletes. Default key is '{\tt M-f}'.
+%.lp
+\item[\tb{\#glance}]
+Show what type of thing a map symbol corresponds to. Default key is '{\tt ;}'.
+%.lp
+\item[\tb{\#help}]
+Show the help menu. Default key is '{\tt ?}', and '{\tt h}' if {\it number\verb+_+pad\/} is on.
+%.lp
+\item[\tb{\#herecmdmenu}]
+Show a menu of possible actions in your current location.
+%.lp
+\item[\tb{\#history}]
+Show long version and game history. Default key is '{\tt V}'.
+%.lp
+\item[\tb{\#inventory}]
+Show your inventory. Default key is '{\tt i}'.
+%.lp
+\item[\tb{\#inventtype}]
+Inventory specific item types. Default key is '{\tt I}'.
 %.lp
 \item[\tb{\#invoke}]
-Invoke an object's special powers.
+Invoke an object's special powers. Autocompletes. Default key is '{\tt M-i}'.
 %.lp
 \item[\tb{\#jump}]
-Jump to another location.
+Jump to another location. Autocompletes. Default key is '{\tt M-j}', and '{\tt j}' if {\it number\verb+_+pad\/} is on.
+%.lp
+\item[\tb{\#kick}]
+Kick something. Default key is '{\tt \^{}D}', and '{\tt k}' if {\it number\verb+_+pad\/} is on.
+%.lp
+\item[\tb{\#known}]
+Show what object types have been discovered. Default key is '{\tt $\backslash$}'.
+%.lp
+\item[\tb{\#knownclass}]
+Show discovered types for one class of objects. Default key is '{\tt `}'.
+%.lp
+\item[\tb{\#levelchange}]
+Change your experience level. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#lightsources}]
+Show mobile light sources. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#look}]
+Look at what is here, under you. Default key is '{\tt :}'.
 %.lp
 \item[\tb{\#loot}]
-Loot a box or bag on the floor beneath you, or the saddle 
-from a steed standing next to you.
+Loot a box or bag on the floor beneath you, or the saddle
+from a steed standing next to you. Autocompletes.
+Default key is '{\tt M-l}', and '{\tt l}' if {\it number\verb+_+pad\/} is on.
+Precede with the `{\tt m}' prefix to skip containers at your location
+and go directly to removing a saddle.
+%.lp
+\item[\tb{\#monpolycontrol}]
+Control monster polymorphs. Autocompletes. Wizard-mode only.
 %.lp
 \item[\tb{\#monster}]
 Use a monster's special ability (when polymorphed into monster form).
+Autocompletes. Default key is '{\tt M-m}'.
 %.lp
 \item[\tb{\#name}]
-Name a monster, an individual object, or a type of object.  Same as `{\tt C}'.
+Name a monster, an individual object, or a type of object.  Same as `{\tt \#call}'.
+Autocompletes. Default keys are '{\tt N}', '{\tt M-n}', and '{\tt M-N}'.
 %.lp
 \item[\tb{\#offer}]
-Offer a sacrifice to the gods.\\
+Offer a sacrifice to the gods. Autocompletes. Default key is '{\tt M-o}'.\\
+The `{\tt m}' prefix skips offering items on the altar.
 %.lp ""
 You'll need to find an altar to have any chance at success.
 Corpses of recently killed monsters are the fodder of choice.
 %.lp
+\item[\tb{\#open}]
+Open a door. Default key is '{\tt o}'.
+%.lp
+\item[\tb{\#options}]
+Show and change option settings. Default key is '{\tt O}'.
+%.lp
 \item[\tb{\#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 dungeon branch) trigger an automatic annotation.
 If dungeon overview is chosen during end-of-game disclosure, every visited
-level will be included regardless of annotations.
+level will be included regardless of annotations. Autocompletes.
+Default keys are '{\tt \^{}O}', and '{\tt M-O}'.
+%.lp
+\item[\tb{\#panic}]
+Test the panic routine. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#pay}]
+Pay your shopping bill. Default key is '{\tt p}'.
+%.lp
+\item[\tb{\#pickup}]
+Pick up things at the current location. Default key is '{\tt ,}'.
+The `{\tt m}' prefix forces use of a menu.
+%.lp
+\item[\tb{\#polyself}]
+Polymorph self. Autocompletes. Wizard-mode only.
 %.lp
 \item[\tb{\#pray}]
-Pray to the gods for help.\\
+Pray to the gods for help. Autocompletes. Default key is '{\tt M-p}'.\\
 %.lp ""
 Praying too soon after receiving prior help is a bad idea.
 (Hint: entering the dungeon alive is treated as having received help.
@@ -1087,8 +1295,18 @@ by default, and you can reset the
 {\it paranoid\verb+_+confirmation\/}
 option to disable it.
 %.lp
+\item[\tb{\#prevmsg}]
+Show previously displayed game messages. Default key is '{\tt \^{}P}'.
+%.lp
+\item[\tb{\#puton}]
+Put on an accessory (ring, amulet, etc). Default key is '{\tt P}'.
+%.lp
+\item[\tb{\#quaff}]
+Quaff (drink) something. Default key is '{\tt q}'.
+%.lp
 \item[\tb{\#quit}]
-Quit the program without saving your game.\\
+Quit the program without saving your game. Autocompletes.
+Default key is '{\tt M-q}'.
 %.lp ""
 Since using this command by accident would throw away the current game,
 you are asked to confirm your intent before quitting.  By default a
@@ -1096,40 +1314,202 @@ response of `{\tt y}' acknowledges that intent.  You can set the
 {\it paranoid\verb+_+confirmation\/}
 option to require a response of ``{\tt yes}'' instead.
 %.lp
+\item[\tb{\#quiver}]
+Select ammunition for quiver. Default key is '{\tt Q}'.
+%.lp
+\item[\tb{\#read}]
+Read a scroll, a spellbook, or something else. Default key is '{\tt r}'.
+%.lp
+\item[\tb{\#redraw}]
+Redraw the screen. Default key is '{\tt \^{}R}', and '{\tt \^{}L}' if {\it number\verb+_+pad\/} is on.
+%.lp
+\item[\tb{\#remove}]
+Remove an accessory (ring, amulet, etc). Default key is '{\tt R}'.
+%.lp
 \item[\tb{\#ride}]
-Ride (or stop riding) a saddled creature.
+Ride (or stop riding) a saddled creature. Autocompletes.
+Default key is '{\tt M-R}'.
 %.lp
 \item[\tb{\#rub}]
-Rub a lamp or a stone.
+Rub a lamp or a stone. Autocompletes. Default key is '{\tt M-r}'.
+%.lp
+\item[\tb{\#save}]
+Save the game. Default key is '{\tt S}'.
+%.lp
+\item[\tb{\#search}]
+Search for traps and secret doors around you. Default key is '{\tt s}'.
+%.lp
+\item[\tb{\#seeall}]
+Show all equipment in use. Default key is '{\tt *}'.
+%.lp
+\item[\tb{\#seeamulet}]
+Show the amulet currently worn. Default key is '{\tt "}'.
+%.lp
+\item[\tb{\#seearmor}]
+Show the armor currently worn. Default key is '{\tt [}'.
+%.lp
+\item[\tb{\#seegold}]
+Count your gold. Default key is '{\tt \$}'.
+%.lp
+\item[\tb{\#seenv}]
+Show seen vectors. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#seerings}]
+Show the ring(s) currently worn. Default key is '{\tt =}'.
+%.lp
+\item[\tb{\#seespells}]
+List and reorder known spells. Default key is '{\tt +}'.
+%.lp
+\item[\tb{\#seetools}]
+Show the tools currently in use. Default key is '{\tt (}'.
+%.lp
+\item[\tb{\#seetrap}]
+Show the type of an adjacent trap. Default key is '{\tt \^{}}'.
+%.lp
+\item[\tb{\#seeweapon}]
+Show the weapon currently wielded. Default key is '{\tt )}'.
+%.lp
+\item[\tb{\#shell}]
+Do a shell escape. Default key is '{\tt !}'.
 %.lp
 \item[\tb{\#sit}]
-Sit down.
+Sit down. Autocompletes. Default key is '{\tt M-s}'.
+%.lp
+\item[\tb{\#stats}]
+Show memory statistics. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#suspend}]
+Suspend the game. Default key is '{\tt \^{}Z}'.
+%.lp
+\item[\tb{\#swap}]
+Swap wielded and secondary weapons. Default key is '{\tt x}'.
+%.lp
+\item[\tb{\#takeoff}]
+Take off one piece of armor. Default key is '{\tt T}'.
+%.lp
+\item[\tb{\#takeoffall}]
+Remove all armor. Default key is '{\tt A}'.
+%.lp
+\item[\tb{\#teleport}]
+Teleport around the level. Default key is '{\tt \^{}T}'.
 %.lp
 \item[\tb{\#terrain}]
 Show bare map without displaying monsters, objects, or traps.
+Autocompletes.
+%.lp
+\item[\tb{\#therecmdmenu}]
+Show a menu of possible actions in a location next to you.
+%.lp
+\item[\tb{\#throw}]
+Throw something. Default key is '{\tt t}'.
+%.lp
+\item[\tb{\#timeout}]
+Look at the timeout queue. Autocompletes. Wizard-mode only.
+%.lp
 \item[\tb{\#tip}]
 Tip over a container (bag or box) to pour out its contents.
+Autocompletes. Default key is '{\tt M-T}'.
+The `{\tt m}' prefix makes the command use a menu.
+%.lp
+\item[\tb{\#travel}]
+Travel to a specific location on the map. Default key is '{\tt _}'.
+Using the ``request menu'' prefix shows a menu of interesting targets in sight
+without asking to move the cursor. When picking a target with cursor and
+the {\it autodescribe\/}-option is on, the top line will show "(no travel path)" if
+your character does not know of a path to that location.
 %.lp
 \item[\tb{\#turn}]
-Turn undead.
+Turn undead away. Autocompletes. Default key is '{\tt M-t}'.
 %.lp
 \item[\tb{\#twoweapon}]
-Toggle two-weapon combat on or off.\\
+Toggle two-weapon combat on or off. Autocompletes. Default keys are '{\tt X}',
+and '{\tt M-2}'.
 %.lp ""
 Note that you must
 use suitable weapons for this type of combat, or it will
 be automatically turned off.
 %.lp
 \item[\tb{\#untrap}]
-Untrap something (trap, door, or chest).\\
+Untrap something (trap, door, or chest). Default key is '{\tt M-u}', and '{\tt u}' if {\it number\verb+_+pad\/} is on.
 %.lp ""
 In some circumstancs it can also be used to rescue trapped monsters.
 %.lp
+\item[\tb{\#up}]
+Go up a staircase. Default key is '{\tt <}'.
+%.lp
+\item[\tb{\#vanquished}]
+List vanquished monsters. Autocompletes. Wizard-mode only.
+%.lp
 \item[\tb{\#version}]
-Print compile time options for this version of {\it NetHack}.
+Print compile time options for this version of {\it NetHack\/}.
+Autocompletes. Default key is '{\tt M-v}'.
+%.lp
+\item[\tb{\#versionshort}]
+Show version string. Default key is '{\tt v}'.
+%.lp
+\item[\tb{\#vision}]
+Show vision array. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#wait}]
+Rest one move while doing nothing. Default key is '{\tt .}', and '{\tt{ }}' if {\it rest\verb+_+on\verb+_+space\/} is on.
+%.lp
+\item[\tb{\#wear}]
+Wear a piece of armor. Default key is '{\tt W}'.
+%.lp
+\item[\tb{\#whatdoes}]
+Tell what a key does. Default key is '{\tt \&}'.
+%.lp
+\item[\tb{\#whatis}]
+Show what type of thing a symbol corresponds to. Default key is '{\tt /}'.
+%.lp
+\item[\tb{\#wield}]
+Wield a weapon. Default key is '{\tt w}'.
 %.lp
 \item[\tb{\#wipe}]
-Wipe off your face.
+Wipe off your face. Autocompletes. Default key is '{\tt M-w}'.
+%.lp
+\item[\tb{\#wizdebug\verb+_+bury}]
+Bury objects under and around you. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#wizdebug\verb+_+traveldisplay}]
+Toggle travel display. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#wizdetect}]
+Search a room. Autocompletes. Wizard-mode only. Default key is '{\tt \^{}E}'.
+%.lp
+\item[\tb{\#wizgenesis}]
+Create a monster. Autocompletes. Wizard-mode only. Default key is '{\tt \^{}G}'.
+%.lp
+\item[\tb{\#wizidentify}]
+Identify all items in inventory. Autocompletes. Wizard-mode only.
+Default key is '{\tt \^{}I}'.
+%.lp
+\item[\tb{\#wizintrinsic}]
+Set intrinsic. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#wizlevelport}]
+Teleport to another level. Autocompletes. Wizard-mode only. Default key is '{\tt \^{}V}'.
+%.lp
+\item[\tb{\#wizmap}]
+Map the level. Autocompletes. Wizard-mode only. Default key is '{\tt \^{}F}'.
+%.lp
+\item[\tb{\#wizrumorcheck}]
+Verify rumor boundaries. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#wizsmell}]
+Smell monster. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#wizwhere}]
+Show locations of special levels. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#wizwish}]
+Wish for something. Autocompletes. Wizard-mode only. Default key is '{\tt \^{}W}'.
+%.lp
+\item[\tb{\#wmode}]
+Show wall modes. Autocompletes. Wizard-mode only.
+%.lp
+\item[\tb{\#zap}]
+Zap a wand. Default key is '{\tt z}'.
 %.lp
 \item[\tb{\#?}]
 Help menu:  get the list of available extended commands.
@@ -1146,9 +1526,9 @@ on the {\it Amiga\/}, set the {\it altmeta\/} option to get this behavior.
 On other systems, if typing `Alt' plus another key transmits a
 two character sequence consisting of an {\tt Escape}
 followed by the other key, you may set the {\it altmeta\/}
-option to have nethack combine them into meta\+key.
+option to have {\it NetHack\/} combine them into meta\+key.
 \blist{}
-%.lp 
+%.lp
 \item[\tb{M-?}]
 {\tt\#?} (not supported by all platforms)
 %.lp
@@ -1232,28 +1612,24 @@ option to have nethack combine them into meta\+key.
 \nd If the {\it number\verb+_+pad\/} option is on, some additional letter commands
 are available:
 \blist{}
-%.lp 
+%.lp
 \item[\tb{h}]
-Help menu:  display one of several help texts available, like ``{\tt ?}''.
+{\tt\#help}
 %.lp
 \item[\tb{j}]
-Jump to another location.  Same as ``{\tt \#jump}'' or ``{\tt M-j}''.
+{\tt\#jump}
 %.lp
 \item[\tb{k}]
-Kick something (usually a door).  Same as `{\tt \^{}D}'.
+{\tt\#kick}
 %.lp
 \item[\tb{l}]
-Loot a box or bag on the floor beneath you, or the saddle 
-from a steed standing next to you.  Same as ``{\tt \#loot}'' or ``{\tt M-l}''.
+{\tt\#loot}
 %.lp
 \item[\tb{N}]
-Name an object or type of object.  Same as ``{\tt \#name}'' or ``{\tt M-n}''.
-Name a monster, an individual object, or a type of object.  Same
-as ``{\tt \#name}'' (or ``{\tt M-n}'') which is the same as the `{\tt C}'
-command.
+{\tt\#name}
 %.lp
 \item[\tb{u}]
-Untrap a trap, door, or chest.  Same as ``{\tt \#untrap}'' or ``{\tt M-u}''.
+{\tt\#untrap}
 \elist
 
 %.hn 1
@@ -1262,7 +1638,7 @@ Untrap a trap, door, or chest.  Same as ``{\tt \#untrap}'' or ``{\tt M-u}''.
 %.pg
 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. 
+dark areas are only displayed if they are within one space of you.
 Walls and corridors remain on the map as you explore them.
 
 %.pg
@@ -1316,7 +1692,8 @@ 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.
 
-\subsection*{Stairs (`{\tt <}', `{\tt >}')}
+%.hn 2
+\subsection*{Stairs and ladders (`{\tt <}', `{\tt >}')}
 
 %.pg
 In general, each level in the dungeon will have a staircase going up
@@ -1340,7 +1717,7 @@ 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.
+
 %.pg
 Ordinarily when you climb a set of stairs, you will arrive on the
 corresponding staircase at your destination.  However, pets (see below)
@@ -1349,8 +1726,6 @@ 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.
 
-\subsection*{Ladders (`{\tt <}', `{\tt >}')}
-
 %.pg
 Ladders serve the same purpose as staircases, and the two types of
 inter-level connections are nearly indistinguishable during game play.
@@ -1434,8 +1809,8 @@ very well).
 %.pg
 The commands `{\tt /}' and `{\tt ;}' may be used to obtain information
 about those
-monsters who are displayed on the screen.  The command ``{\tt \#name}'', or
-its synonym `{\tt C}', allows you
+monsters who are displayed on the screen.  The command ``{\tt \#name}''
+(by default bound to `{\tt 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.
@@ -1457,7 +1832,7 @@ Remember:  discretion is the better part of valor.
 
 %.pg
 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 
+moving into its location, you'll be asked to confirm your intent.  By
 default an answer of `{\tt y}' acknowledges that intent,
 which can be error prone if you're using `{\tt y}' to move.  You can set the
 {\it paranoid\verb+_+confirmation\/}
@@ -1509,15 +1884,25 @@ 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 `{\tt \#ride}' command.  Lead
+easily climb in and out of the saddle with the ``{\tt \#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.
 
 %.pg
-Riding skill is managed by the `{\tt \#enhance}' command.  See the section
+Riding skill is managed by the ``{\tt \#enhance}'' command.  See the section
 on Weapon proficiency for more information about that.
 
+%.pg
+Use the `{\tt 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.
+
+%.pg
+Use the ``{\tt \#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.
+
 %.hn 2
 \subsection*{Bones levels}
 
@@ -1530,12 +1915,32 @@ 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.
 
+%.hn 2
+\subsection*{Persistence of Monsters}
+
+%.pg
+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.
+
+%.pg
+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.
+
 %.hn 1
 \section{Objects}
 
 %.pg
 When you find something in the dungeon, it is common to want to pick
-it up.  In {\it NetHack}, this is accomplished automatically by walking over
+it up.  In {\it NetHack\/}, this is accomplished automatically by walking over
 the object (unless you turn off the {\it autopickup\/}
 option (see below), or move with the `{\tt m}' prefix (see above)), or
 manually by using the `{\tt ,}' command.
@@ -1547,14 +1952,15 @@ 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 you are, the less the additional load will affect you.  There comes
+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.
 %.pg
-NetHack will tell you how badly you have loaded yourself.  The symbols
+{\it NetHack\/} will tell you how badly you have loaded yourself.  The symbols
 `Burdened', `Stressed', `Strained', `Overtaxed' and `Overloaded' are
 displayed on the bottom line display to indicate your condition.
 
@@ -1576,7 +1982,7 @@ When you use one of these objects, if its effect is obvious, {\it 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 ``{\tt \#name}''
-command, or its synonym `{\tt C}', for the same purpose at any time, to 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 ``{\tt \#name}'' on an object which has already been named,
 specifying a space as the value will remove the prior name instead
@@ -1793,7 +2199,7 @@ To wield two weapons, you need to use the ``{\tt \#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   
+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
@@ -1845,10 +2251,10 @@ 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 &                   & studded leather armor & 7\\
-ring mail              & 7 &                   & orcish ring mail      & 8\\
-leather armor          & 8 &                   & leather jacket        & 9\\
-no armor               & 10
+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\\
 \end{tabular}
 \end{center}
 
@@ -1963,11 +2369,13 @@ The command to drink a potion is `{\tt q}' (quaff).
 \subsection*{Wands (`{\tt /}')}
 
 %.pg
-Magic wands usually have multiple magical charges.  Some wands are
-directional---you must give a direction in which to zap them.  You can also
+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 `{\tt .}' or `{\tt s}' for the direction).
-Be warned, however, for this is often unwise.  Other wands are
-nondirectional---they don't require a direction.  The number of charges in a
+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.
 
 %.pg
@@ -2035,17 +2443,19 @@ energy and the time required in casting.
 %.pg
 Casting a spell calls forth magical energies and focuses them with
 your naked mind.  Some of the magical energy released comes from within
-you, and casting several spells in a row may tire you.
+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 memory of each spell will dim, and you will need to relearn it.
 
 %.pg
-Some spells are
-directional---you must give a direction in which to cast them.  You can also
-cast them at yourself (just give a `{\tt .}' or `{\tt s}' for the direction).
-Be warned, however, for this is often unwise.  Other spells are
-nondirectional---they don't require a direction.
+Some spells require a direction in which to cast them, similar to wands.
+To cast one at yourself, just give a `{\tt .}' or `{\tt s}' for the direction.
+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.
 
 %.pg
 Just as weapons are divided into groups in which a character can become
@@ -2141,6 +2551,11 @@ 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.
 
+%.pg
+For some configurations of the program, statues are no longer shown
+as `{\tt `}'
+but by the letter representing the monster they depict instead.
+
 %.hn 2
 \subsection*{Gold (`{\tt \$}')}
 
@@ -2150,6 +2565,32 @@ There are a number
 of monsters in the dungeon that may be influenced by the amount of gold
 you are carrying (shopkeepers aside).
 
+%.hn 2
+\subsection*{Persistence of Objects}
+
+%.pg
+Normally, if you have seen an object at a particular map location and
+move to another location which 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 and 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.
+
+%.pg
+The situation is the same for a pile of objects, except that only the
+top item of the pile is displayed.
+The
+{\it hilite\verb+_+pile\/}
+option can be enabled in order to show an item differently when is
+the top one of a pile.
+
 %.hn 1
 \section{Conduct}
 
@@ -2285,13 +2726,201 @@ behaves.
 %.pg
 Options may be set in a number of ways.  Within the game, the `{\tt O}'
 command allows you to view all options and change most of them.
-You can also set options automatically by placing them in the
-``NETHACKOPTIONS'' environment variable or in a configuration file.
+You can also set options automatically by placing them in a configuration
+file, or in the ``NETHACKOPTIONS'' environment variable.
 Some versions of {\it NetHack\/} also have front-end programs that allow
-you to set options before starting the game or a global configuration 
+you to set options before starting the game or a global configuration
 for system administrators.
 
 %.hn 2
+\subsection*{Using a configuration file}
+
+%.pg
+The default name of the configuration file varies on different
+operating systems. On DOS and Windows, it is \mbox{``defaults.nh''}
+in the same folder as \mbox{{\it nethack.exe\/}} or \mbox{{\it nethackW.exe\/}}. 
+On Unix, Linux and Mac OS X it is \mbox{``.nethackrc''} in the user's home 
+directory. The file may not exist, but it is a normal ASCII text file and
+can be created with any text editor.
+
+%.pg
+Any line in the configuration file starting with `{\tt \#}' is treated as a comment.
+Empty lines are ignored.
+
+%.pg
+Any line beginning with `{\tt [}' and ending in `{\tt ]}' 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.
+
+%.pg
+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:
+
+%.lp
+\blist{}
+\item[\bb{OPTIONS}]
+There are two types of options, boolean and compound options.
+Boolean 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 multiple options
+in a single OPTIONS statement.
+
+%.pg
+Example:
+%.sd
+\begin{verbatim}
+    OPTIONS=dogname:Fido
+    OPTIONS=!legacy,autopickup,pickup_types:$"=/!?+
+\end{verbatim}
+%.ed
+
+%.lp
+\item[\bb{HACKDIR}]
+Default location of files {\it NetHack\/} needs. On Windows HACKDIR
+defaults to the location of the {\it NetHack.exe\/} or {\it NetHackw.exe\/} file
+so setting HACKDIR to override that is not usually necessary or recommended.
+%.lp
+\item[\bb{LEVELDIR}]
+The location that in-progress level files are stored. Defaults to HACKDIR,
+must be writeable.
+%.lp
+\item[\bb{SAVEDIR}]
+The location where saved games are kept. Defaults to HACKDIR, must be
+writeable.
+%.lp
+\item[\bb{BONESDIR}]
+The location that bones files are kept. Defaults to HACKDIR, must be
+writeable.
+%.lp
+\item[\bb{LOCKDIR}]
+The location that file synchronization locks are stored. Defaults to
+HACKDIR, must be writeable.
+%.lp
+\item[\bb{TROUBLEDIR}]
+The location that a record of game aborts and self-diagnosed game problems
+is kept. Defaults to HACKDIR, must be writeable.
+%.lp
+\item[\bb{AUTOCOMPLETE}]
+Enable or disable an extended command autocompletion.
+Autocompletion has no effect for the X11 windowport.
+You can specify multiple autocompletions. To enable
+autocompletion, list the extended command. Prefix the
+command with ``{{\tt !}}'' to disable the autocompletion
+for that command.
+
+%.pg
+Example:
+%.sd
+\begin{verbatim}
+    AUTOCOMPLETE=zap,!annotate
+\end{verbatim}
+%.ed
+
+%.lp
+\item[\bb{AUTOPICKUP\_EXCEPTION}]
+Set exceptions to the {{\it pickup\_types\/}}
+option. See the ``Configuring Autopickup Exceptions'' section.
+%.lp
+\item[\bb{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 ``Changing Key Bindings`` section for more information.
+
+%.pg
+Example:
+%.sd
+\begin{verbatim}
+   BIND=^X:getpos.autodescribe
+\end{verbatim}
+%.ed
+
+%.lp
+\item[\bb{CHOOSE}]
+Chooses at random one of the comma-separated parameters as an active
+section name. Lines in other sections are ignored.
+
+%.pg
+Example:
+%.sd
+\begin{verbatim}
+   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
+\end{verbatim}
+%.ed
+
+%.lp
+\item[\bb{MSGTYPE}]
+Change the way messages are shown in the top status line.
+See the ``Configuring Message Types`` section.
+%.lp
+\item[\bb{MENUCOLOR}]
+Highlight menu lines with different colors.
+See the ``Configuring Menu Colors`` section.
+%.lp
+\item[\bb{SYMBOLS}]
+Override one or more symbols in the symbols files.
+See the ``Modifying {\it NetHack\/} Symbols'' section.
+%.pg
+Example:
+%.sd
+\begin{verbatim}
+    SYMBOLS=S_boulder:0
+\end{verbatim}
+%.ed
+
+%.lp
+\item[\bb{WIZKIT}]
+Wizard-mode extra items, in a text file containing item names,
+one per line, up to a maximum of 128 lines. Each line is processed
+by the function that handles wishing.
+%.pg
+Example:
+%.sd
+\begin{verbatim}
+    WIZKIT=~/wizkit.txt
+\end{verbatim}
+%.ed
+%.lp
+\item[\bb{SOUNDDIR}]
+Define the directory that contains the sound files.
+See the ``Configuring User Sounds'' section.
+%.lp
+\item[\bb{SOUND}]
+Define a sound mapping. See the ``Configuring User Sounds'' section.
+\elist
+
+%.pg
+Here is a short example of config file contents:
+%.sd
+\begin{verbatim}
+    # Set your character's role, race, gender, and alignment.
+    OPTIONS=role:Valkyrie, race:Human, gender:female, align:lawful
+
+    # Turn on autopickup, and set automatically picked up object types
+    OPTIONS=autopickup,pickup_types:$"=/!?+
+    # Show colored text if possible
+    OPTIONS=color
+    # Show lit corridors differently
+    OPTIONS=lit_corridor
+
+    # No startup splash screen. Windows GUI only.
+    OPTIONS=!splash_screen
+\end{verbatim}
+%.ed
+
+%.hn 2
 \subsection*{Using the NETHACKOPTIONS environment variable}
 
 %.pg
@@ -2325,29 +2954,9 @@ and the {\it fruit\/} is set to ``papaya'', you would enter the command
 
 \nd in {\it sh\/} or {\it ksh}.
 
-%.hn 2
-\subsection*{Using a configuration file}
-
-%.pg
-Any line in the configuration file starting with `{\tt \#}' is treated as a comment.
-Any line in the configuration file starting with ``{\tt OPTIONS=}'' may be
-filled out with options in the same syntax as in NETHACKOPTIONS.
-Any line starting with ``{\tt SYMBOLS=}''
-is taken as defining the corresponding {\it symbol}
-in a different syntax, a sequence of decimal numbers giving 
-the character position in the current font to be used in displaying 
-each entry. Such a sequence can be continued to multiple lines by putting a
-`{\tt \verb+\+}' at the end of each line to be continued.
-
-%.pg
-Any line starting with ``{\tt AUTOPICKUP\verb+_+EXCEPTION=}'' 
-is taken as defining an exception to the ``{\tt pickup\verb+_+types}'' option.
-There is a section of this Guidebook that discusses that.
-
 %.pg
-The default name of the configuration file varies on different
-operating systems, but NETHACKOPTIONS can also be set to
-the full name of a file you want to use (possibly preceded by an `{\tt @}').
+NETHACKOPTIONS can also be set to the full name of a configuration file you
+want to use (possibly preceded by an `{\tt @}').
 
 %.hn 2
 \subsection*{Customization options}
@@ -2373,10 +2982,16 @@ Persistent.
 Your starting alignment ({\tt align:lawful}, {\tt align:neutral},
 or {\tt align:chaotic}).  You may specify just the first letter.
 The default is to randomly pick an appropriate alignment.
-If you prefix `{\tt !}' or ``{\tt no}'' to the value, you can 
+If you prefix the value with `{\tt !}' or ``{\tt no}'', you will
 exclude that alignment from being picked randomly.
 Cannot be set with the `{\tt O}' command.  Persistent.
 %.lp
+\item[\ib{autodescribe}]
+Automatically describe the terrain under cursor when asked to get a location
+on the map.  The
+{\it whatis\verb+_+coord\/}
+option controls whether the description includes map coordinates.
+%.lp
 \item[\ib{autodig}]
 Automatically dig if you are wielding a digging tool and moving into a place
 that can be dug (default false).  Persistent.
@@ -2407,7 +3022,8 @@ Start the character permanently blind.  Persistent. (default false)
 Allow saving and loading bones files.  Persistent.  (default true)
 %.lp
 \item[\ib{boulder}]
-Set the character used to display boulders (default is rock class symbol).
+Set the character used to display boulders (default is the ``large rock''
+class symbol, `{\tt `}').
 %.lp
 \item[\ib{catname}]
 Name your starting cat (ex.\ ``{\tt catname:Morris}'').
@@ -2415,9 +3031,7 @@ Cannot be set with the `{\tt O}' command.
 %.lp character
 \item[\ib{character}]
 Pick your type of character (ex.\ ``{\tt character:Monk}'');
-synonym for ``{\it role\/}''.  See ``{\it name\/}'' for an alternate method
-of specifying your role.  Normally only the first letter of
-the value is examined; the string ``{\tt random}'' is an exception.
+synonym for ``{\it role\/}''.  See {\it role\/} for more details.
 %.lp
 \item[\ib{checkpoint}]
 Save game state after each level change, for possible recovery after
@@ -2426,7 +3040,9 @@ program crash (default on).  Persistent.
 \item[\ib{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.
+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.
 %.lp
 \item[\ib{clicklook}]
@@ -2434,7 +3050,7 @@ Allows looking at things on the screen by navigating the mouse
 over them and clicking the right mouse button (default off).
 %.lp
 \item[\ib{cmdassist}]
-Have the game provide some additional command assistance for new 
+Have the game provide some additional command assistance for new
 players if it detects some anticipated mistakes (default on).
 %.lp
 \item[\ib{confirm}]
@@ -2475,6 +3091,22 @@ lets you refine how it behaves.  Here are the valid prefixes:
 %.ei
 %.ed
 
+The listing of vanquished monsters can be sorted,
+so there are two additional choices for `{\tt v}':
+%.sd
+%.si
+{\tt ?} --- prompt you and default to ask on the prompt;\\
+{\tt\#} --- disclose it without prompting, ask for sort order.
+%.ei
+%.ed
+
+Asking refers to picking one of the orderings from a menu.
+The `{\tt +}' disclose without prompting choice,
+or being prompted and answering `{\tt y}' rather than `{\tt a}',
+will default to showing monsters in the traditional order,
+from high level to low level.
+.lp ""
+
 %.lp ""
 (ex.\ ``{\tt disclose:yi na +v -g o}'')
 The example sets
@@ -2487,7 +3119,7 @@ The example sets
 
 %.lp ""
 Note that the vanquished monsters list includes all monsters killed by
-traps and each other as well as by you. 
+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.
 %.lp
@@ -2498,7 +3130,7 @@ Cannot be set with the `{\tt O}' command.
 \item[\ib{extmenu}]
 Changes the extended commands interface to pop-up a menu of available commands.
 It is keystroke compatible with the traditional interface except that it does
-not require that you hit Enter.  It is implemented only by the tty port 
+not require that you hit Enter.  It is implemented only by the tty port
 (default off), when the game has been compiled to support tty graphics.
 %.lp
 \item[\ib{female}]
@@ -2510,23 +3142,34 @@ 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.
 %.lp
+\item[\ib{force\_invmenu}]
+Commands asking for an inventory item show a menu instead of
+a text query with possible menu letters. Default is off.
+%.lp
 \item[\ib{fruit}]
 Name a fruit after something you enjoy eating (ex.\ ``{\tt fruit:mango}'')
 (default ``{\tt slime mold}''). Basically a nostalgic whimsy that
 {\it 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 {\it NetHack}, so don't use those.
-%.Ip
+melons already exist in {\it NetHack\/}, so don't use those.
+%.lp
 \item[\ib{gender}]
 Your starting gender ({\tt gender:male} or {\tt gender:female}).
 You may specify just the first letter.  Although you can
 still denote your gender using the ``{\tt male}'' and ``{\tt female}''
 options, the ``{\tt gender}'' option will take precedence.
 The default is to randomly pick an appropriate gender.
-If you prefix `{\tt !}' or ``{\tt no}'' to the value, you can 
-exclude that gender from being picked randomly. 
+If you prefix the value with `{\tt !}' or ``{\tt no}'', you will
+exclude that gender from being picked randomly.
 Cannot be set with the `{\tt O}' command.  Persistent.
 %.lp
+\item[\ib{goldX}]
+When filtering objects based on bless/curse state (BUCX), whether to
+treat gold pieces as {\tt X} (unknown bless/curse state, when `on')
+or {\tt 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 {\it implicit\verb+_+uncursed\/} option is `off'.
+%.lp
 \item[\ib{help}]
 If more information is available for an object looked at
 with the `{\tt /}' command, ask if you want to see it (default on).
@@ -2534,6 +3177,11 @@ Turning help off makes just looking at things faster, since you aren't
 interrupted with the ``{\tt More info?}'' prompt, but it also means that you
 might miss some interesting and/or important information.  Persistent.
 %.lp
+\item[\ib{herecmd\verb+_+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.
+%.lp
 \item[\ib{hilite\verb+_+pet}]
 Visually distinguish pets from similar animals (default off).
 The behavior of this option depends on the type of windowing you use.
@@ -2551,6 +3199,10 @@ on the top of the pile.
 Name your starting horse (ex.\ ``{\tt horsename:Trigger}'').
 Cannot be set with the `{\tt O}' command.
 %.lp
+\item[\ib{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.
+%.lp
 \item[\ib{ignintr}]
 Ignore interrupt signals, including breaks (default off).  Persistent.
 %.lp
@@ -2638,6 +3290,10 @@ Default `\verb+>+'.
 \item[\ib{menu\verb+_+objsyms}]
 Show object symbols in menu headings in menus where
 the object symbols act as menu accelerators (default off).
+\item[\ib{menu\verb+_+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)
 \item[\ib{menu\verb+_+previous\verb+_+page}]
 Menu character accelerator to goto the previous menu page.
 Implemented by the Amiga, Gem and tty ports.
@@ -2674,7 +3330,7 @@ Allows you to change the way recalled messages are displayed.
 
 For backward compatibility, no value needs to be specified (which
 defaults to {\it full\/}), or it can be negated (which defaults
-to {\it single\/}). 
+to {\it single\/}).
 %.lp
 \item[\ib{name}]
 Set your character's name (defaults to your user name).  You can also
@@ -2721,7 +3377,7 @@ is the same as specifying {\tt 0}.
 (Settings {\tt 2} and {\tt 4} are for compatibility with MSDOS or old PC Hack;
 in addition to the different behavior for `{\tt 5}', `{\tt Alt-5}' acts as `{\tt G}'
 and `{\tt Alt-0}' acts as `{\tt I}'.
-Setting {\tt -1} is to accommodate some German keyboards which have the
+Setting {\tt -1} is to accommodate some QWERTZ keyboards which have the
 location of the `{\tt y}' and `{\tt z}' keys swapped.)
 When moving by numbers, to enter a count prefix for those commands
 which accept one (such as ``{\tt 12s}'' to search twelve times), precede it
@@ -2739,7 +3395,7 @@ prompting is desired.  The default is ``{\it paranoid\verb+_+confirmation:pray}'
 %.sd
 %.si
 \newlength{\pcwidth}
-\settowidth{\pcwidth}{\tt Confirm}
+\settowidth{\pcwidth}{\tt Were-change}
 \addtolength{\pcwidth}{\labelsep}
 \blist{\leftmargin \pcwidth \topsep 1mm \itemsep 0mm}
 \item[{\tt Confirm}]
@@ -2758,14 +3414,21 @@ bones data when dying in debug mode
 \item[{\tt attack~}]
 require ``{\tt yes}'' rather than `{\tt y}' to confirm attacking
 a peaceful monster;
+\item[{\tt wand-break}]
+require ``{\tt yes}'' rather than `{\tt y}' to confirm breaking
+a wand;
+\item[{\tt Were-change}]
+require ``{\tt yes}'' rather than `{\tt y}' to confirm changing form
+due to lycanthropy
+when hero has polymorph control;
 \item[{\tt pray~~~}]
 require `{\tt y}' to confirm an attempt to pray rather
 than immediately praying; on by default;
-\item[{\tt wand}]
-require ``{\tt yes}'' rather than `{\tt y}' to confirm breaking
-a wand;
-\item[{\tt Remove~}] require selection from inventory for `{\tt R}' and `{\tt T}'
+\item[{\tt Remove~}] require selection from inventory for `{\tt R}'
+and `{\tt T}'
 commands even when wearing just one applicable item.
+\item[{\tt all~~~~}]
+turn on all of the above.
 \elist
 %.ei
 %.ed
@@ -2798,12 +3461,14 @@ or overLoaded), you will be asked if you want to continue.
 %.lp
 \item[\ib{pickup\verb+_+thrown}]
 If this option is on and ``{\it autopickup\/}'' is also on, try to pick up
-things that you threw, even if they aren't in ``{\it pickup\verb+_+types\/}'' or
+things that you threw, even if they aren't in
+``{\it pickup\verb+_+types\/}'' or
 match an autopickup exception.  Default is on.  Persistent.
 %.lp
 \item[\ib{pickup\verb+_+types}]
-Specify the object types to be picked up when ``{\it autopickup\/}'' 
-is on.  Default is all types.  You can use ``{\it autopickup\verb+_+exception\/}''
+Specify the object types to be picked up when ``{\it autopickup\/}''
+is on.  Default is all types.  You can use
+``{\it autopickup\verb+_+exception\/}''
 configuration file lines to further refine ``{\it autopickup\/}'' behavior.
 Persistent.
 %.lp
@@ -2833,12 +3498,12 @@ become wielded.  Persistent.
 %.Ip
 \item[\ib{race}]
 Selects your race (for example, ``{\tt race:human}'').  Default is random.
-If you prefix `{\tt !}' or ``{\tt no}'' to the value, you can 
-exclude that race from being picked randomly. 
+If you prefix the value with `{\tt !}' or ``{\tt no}'', you will
+exclude that race from being picked randomly.
 Cannot be set with the `{\tt O}' command.  Persistent.
 %.lp
 \item[\ib{rest\verb+_+on\verb+_+space}]
-Make the space bar a synonym for the `{\tt .}' (rest) command (default off).
+Make the space bar a synonym for the `{\tt .}' (\#wait) command (default off).
 Persistent.
 %.lp
 \item[\ib{role}]
@@ -2846,9 +3511,10 @@ Pick your type of character (ex.\ ``{\tt role:Samurai}'');
 synonym for ``{\it character\/}''.  See ``{\it name\/}'' for an alternate method
 of specifying your role.  Normally only the first letter of the
 value is examined; `r' is an exception with ``{\tt Rogue}'', {\tt Ranger}'',
-and ``{\tt random}'' values. If you prefix `{\tt !}' or ``{\tt no}'' to the 
-value, you can exclude that role from being picked randomly.
-Persistent.
+and ``{\tt random}'' values.
+If you prefix the value with `{\tt !}' or ``{\tt no}'', you will
+exclude that role from being picked randomly.
+Cannot be set with the `{\tt O}' command.  Persistent.
 %.lp
 \item[\ib{roguesymset}]
 This option may be used to select one of the named symbol sets found within
@@ -2877,7 +3543,7 @@ The possible values are:
 %.ed
 
 This option only affects the game's screen display, not the actual
-results of moving.  The default is {\it run\/}; versions prior to 3.4.1 
+results of moving.  The default is {\it run\/}; versions prior to 3.4.1
 used {\it teleport\/} only.  Whether or not the effect is noticeable will
 depend upon the window port used or on the type of terminal.  Persistent.
 %.lp
@@ -2933,17 +3599,22 @@ attack to which it is resistant (default on).  Persistent.
 Boldface monsters and ``{\tt --More--}'' (default off).  Persistent.
 %.lp
 \item[\ib{statushilites}]
-Enable coloring of status fields (default off).
+Controls how many turns status hilite behaviors highlight
+the field. If negated or set to zero, disables status hiliting.
 See ``{\it Configuring Status Hilites\/}'' for further information.
 %.lp
+\item[\ib{status\verb+_+updates}]
+Allow updates to the status lines at the bottom of the screen (default true).
+%.lp
 \item[\ib{suppress\verb+_+alert}]
-This option may be set to a NetHack version level to suppress
-alert notification messages about feature changes for that 
+This option may be set to a {\it NetHack\/} version level to suppress
+alert notification messages about feature changes for that
 and prior versions (ex.\ ``{\tt suppress\verb+_+alert:3.3.1}'')
 %.lp
 \item[\ib{symset}]
 This option may be used to select one of the named symbol sets found within
 {\tt symbols} to alter the symbols displayed on the screen.
+Use ``{\tt symset:default}'' to explicitly select the default symbols.
 %.lp
 \item[\ib{time}]
 Show the elapsed game time in turns on bottom line (default off).  Persistent.
@@ -2959,9 +3630,9 @@ program.)  Persistent.
 Draw a tombstone graphic upon your death (default on).  Persistent.
 %.lp
 \item[\ib{toptenwin}]
-Put the ending display in a NetHack window instead of on stdout (default off).
+Put the ending display in a {\it 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 window, but it no longer leaves
+of {\it 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.
 %.lp
 \item[\ib{travel}]
@@ -2972,14 +3643,73 @@ mouse clicks on the map window.  Persistent.
 \item[\ib{verbose}]
 Provide more commentary during the game (default on).  Persistent.
 %.lp
+\item[\ib{whatis\verb+_+coord}]
+When using the `{\tt /}' or `{\tt ;}' commands to look around on the map with
+``{\tt autodescribe}''
+on, display coordinates after the description.
+Also works in other situations where you are asked to pick a location.
+
+%.lp ""
+The possible settings are:
+
+%.sd
+%.si
+{\tt c} --- \verb#compass ('east' or '3s' or '2n,4w')#;\\
+{\tt f} --- \verb#full compass ('east' or '3south' or '2north,4west')#;\\
+{\tt m} --- \verb#map <x,y> (map column x=0 is not used)#;\\
+{\tt s} --- \verb#screen [row,column] (row is offset to match tty usage)#;\\
+{\tt n} --- \verb#none (no coordinates shown) [default]#.
+%.ei
+%.ed
+
+%.lp ""
+The
+{\it whatis\verb+_+coord\/}
+option is also used with
+the `{\tt /m}', `{\tt /M}', `{\tt /o}', and `{\tt /O}' sub-commands
+of `{\tt /}',
+where the `{\it none\/}' setting is overridden with `{\it map}'.
+%.lp
+\item[\ib{whatis\verb+_+filter}]
+When getting a location on the map, and using the keys to cycle through
+next and previous targets, allows filtering the possible targets.
+(default none)
+%.lp ""
+The possible settings are:
+
+%.sd
+%.si
+{\tt n} --- \verb#no filtering#;\\
+{\tt v} --- \verb#in view only#;\\
+{\tt a} --- \verb#in same area (room, corridor, etc)#.
+%.ei
+%.ed
+%.lp ""
+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.
+%.lp ""
+Filtering can also be changed when getting a location with the ``getpos.filter''
+key.
+%.lp
+\item[\ib{whatis\verb+_+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)
+%.lp
+\item[\ib{whatis\verb+_+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)
+%.lp
 \item[\ib{windowtype}]
 Select which windowing system to use, such as ``{\tt tty}'' or ``{\tt X11}''
 (default depends on version).
 Cannot be set with the `{\tt O}' command.
 %.lp
 \item[\ib{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 
+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.
 \elist
 
@@ -2992,10 +3722,10 @@ 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 
-config file, and if the window port is capable of adjusting 
+here.  You can safely add any of these options to your
+config 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 
+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
@@ -3010,91 +3740,94 @@ with the `{\tt O}' command.
  Where to align or place the status window (top, bottom, left, or right).
 %.lp
 \item[\ib{ascii\verb+_+map}]
-NetHack should display an ascii map if it can.
+If {\it NetHack\/} can, it should display an ascii map.
 %.lp
 \item[\ib{color}]
-NetHack should display color if it can for different monsters, 
-objects, and dungeon features
+If {\it NetHack\/} can, it should display color for different monsters,
+objects, and dungeon features.
+
 %.lp
 \item[\ib{eight\verb+_+bit\verb+_+tty}]
-Pass eight-bit character values (for example, specified with the {\it
-traps \/} option) straight through to your terminal (default off).
+Pass eight-bit character values (for example, specified with the
+{\it traps \/} option) straight through to your terminal (default off).
 %.lp
 \item[\ib{font\verb+_+map}]
-NetHack should use a font by the chosen name for the map window.
+If {\it NetHack\/} can, it should use a font by the chosen name for the
+map window.
 %.lp
 \item[\ib{font\verb+_+menu}]
-NetHack should use a font by the chosen name for menu windows.
+If {\it NetHack\/} can, it should use a font by the chosen name for menu
+windows.
 %.lp
 \item[\ib{font\verb+_+message}]
-NetHack should use a font by the chosen name for the message window.
+If {\it NetHack\/} can, it should use a font by the chosen name for the message window.
 %.lp
 \item[\ib{font\verb+_+status}]
-NetHack should use a font by the chosen name for the status window.
+If {\it NetHack\/} can, it should use a font by the chosen name for the status window.
 %.lp
 \item[\ib{font\verb+_+text}]
-NetHack should use a font by the chosen name for text windows.
+If {\it NetHack\/} can, it should use a font by the chosen name for text windows.
 %.lp
 \item[\ib{font\verb+_+size\verb+_+map}]
-NetHack should use this size font for the map window.
+If {\it NetHack\/} can, it should use this size font for the map window.
 %.lp
 \item[\ib{font\verb+_+size\verb+_+menu}]
-NetHack should use this size font for menu windows.
+If {\it NetHack\/} can, it  should use this size font for menu windows.
 %.lp
 \item[\ib{font\verb+_+size\verb+_+message}]
-NetHack should use this size font for the message window.
+If {\it NetHack\/} can, it should use this size font for the message window.
 %.lp
 \item[\ib{font\verb+_+size\verb+_+status}]
-NetHack should use this size font for the status window.
+If {\it NetHack\/} can, it should use this size font for the status window.
 %.lp
 \item[\ib{font\verb+_+size\verb+_+text}]
-NetHack should use this size font for text windows.
+If {\it NetHack\/} can, it should use this size font for text windows.
 %.lp
 \item[\ib{fullscreen}]
-NetHack should try and display on the entire screen rather than in a window.
+If {\it NetHack\/} can, it should try and display on the entire screen rather than in a window.
 %.lp
 \item[\ib{large\verb+_+font}]
-NetHack should use a large font.
+If {\it NetHack\/} can, it should use a large font.
 %.lp
 \item[\ib{map\verb+_+mode}]
-NetHack should display the map in the manner specified.
+If {\it NetHack\/} can, it should display the map in the manner specified.
 %.lp
 \item[\ib{mouse\verb+_+support}]
 Allow use of the mouse for input and travel.
 %.lp
 \item[\ib{player\verb+_+selection}]
-NetHack should pop up dialog boxes or use prompts for character selection.
+If {\it NetHack\/} can, it should pop up dialog boxes or use prompts for character selection.
 %.lp
 \item[\ib{popup\verb+_+dialog}]
-NetHack should pop up dialog boxes for input.
+If {\it NetHack\/} can, it should pop up dialog boxes for input.
 %.lp
 \item[\ib{preload\verb+_+tiles}]
-NetHack should preload tiles into memory.
+If {\it NetHack\/} can, it should preload tiles into memory.
 For example, in the protected mode MSDOS 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 `{\tt O}' command.
 %.lp
 \item[\ib{scroll\verb+_+amount}]
-NetHack should scroll the display by this number of cells
+If {\it NetHack\/} can, it should scroll the display by this number of cells
 when the hero reaches the scroll\verb+_+margin.
 %.lp
 \item[\ib{scroll\verb+_+margin}]
-NetHack should scroll the display when the hero or cursor
+If {\it NetHack\/} can, it should scroll the display when the hero or cursor
 is this number of cells away from the edge of the window.
 %.lp
 \item[\ib{selectsaved}]
-NetHack should display a menu of existing saved games for the player to
+If {\it 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.
 %.lp
 \item[\ib{softkeyboard}]
-Display an onscreen keyboard.  Handhelds are most likely to support this option.
+If {\it NetHack\/} can, it should display an onscreen keyboard.  Handhelds are most likely to support this option.
 %.lp
 \item[\ib{splash\verb+_+screen}]
-NetHack should display an opening splash screen when it starts up (default yes).
+If {\it NetHack\/} can, it should display an opening splash screen when it starts up (default yes).
 %.lp
 \item[\ib{tiled\verb+_+map}]
-NetHack should display a tiled map if it can.
+If {\it NetHack\/} can, it should display a tiled map if it can.
 %.lp
 \item[\ib{tile\verb+_+file}]
 Specify the name of an alternative tile file to override the default.
@@ -3109,25 +3842,26 @@ Specify the preferred width of each tile in a tile capable port
 Use bold black instead of blue for black glyphs (TTY only).
 %.lp
 \item[\ib{use\verb+_+inverse}]
-NetHack should display inverse when the game specifies it.
+If {\it NetHack\/} can, it should display inverse when the game specifies it.
 %.lp
 \item[\ib{vary\verb+_+msgcount}]
-NetHack should display this number of messages at a time in the message window.
+If {\it NetHack\/} can, it should display this number of messages at a time
+in the message window.
 %.lp
 \item[\ib{windowcolors}]
-NetHack should display windows with the specified foreground/background 
-colors if it can.
+If {\it NetHack\/} can, it should display windows with the specified
+foreground/background colors if it can.
 %.lp
 \item[\ib{wraptext}]
-NetHack port should wrap long lines of text if they don't fit in 
-the visible area of the window.
+If {\it NetHack\/} can, it should wrap long lines of text if they don't fit
+in the visible area of the window.
 \elist
 
 %.hn 2
 \subsection*{Platform-specific Customization options}
 
 %.pg
-Here are explanations of options that are used by specific platforms 
+Here are explanations of options that are used by specific platforms
 or ports to customize and change the port behavior.
 
 \blist{}
@@ -3144,7 +3878,7 @@ functions as a meta-shift for that key (default on).
 %.lp
 \item[\ib{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
+set to tell {\it NetHack\/} to convert a two character sequence beginning with
 ESC into a meta-shifted version of the second character (default off).
 
 %.lp ""
@@ -3152,7 +3886,7 @@ 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 {\tt n} if the {\it number\verb+_+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
+abort the count by typing ESC will leave {\it 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.
 %.lp
@@ -3160,20 +3894,20 @@ finish cancelling such a count.  At other prompts a single ESC suffices.
 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, {\it OS/2, PC\/ {\rm and} ST NetHack\/} only).
-%.lp 
+%.lp
 \item[\ib{flush}]
 (default off, {\it Amiga NetHack \/} only).
-%.lp 
+%.lp
 \item[\ib{Macgraphics}]
 (default on, {\it Mac NetHack \/} only).
-%.lp 
+%.lp
 \item[\ib{page\verb+_+wait}]
 (default off, {\it Mac NetHack \/} only).
 %.lp
 \item[\ib{rawio}]
 Force raw (non-cbreak) mode for faster output and more
 bulletproof input (MS-DOS sometimes treats `{\tt \^{}P}' as a printer toggle
-without it) (default off, {\it OS/2, PC\/ {\rm and} ST NetHack\/} only).  
+without it) (default off, {\it OS/2, PC\/ {\rm and} ST NetHack\/} only).
 Note:  DEC Rainbows hang if this is turned on.
 Cannot be set with the `{\tt O}' command.
 %.lp
@@ -3184,17 +3918,18 @@ Cannot be set with the `{\tt O}' command.
 \item[\ib{subkeyvalue}]
 ({\it 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.
+returns to {\it NetHack\/} to help compensate for international keyboard
+issues.
 OPTIONS=subkeyvalue:171/92
-will return 92 to NetHack, if 171 was originally going to be returned.
+will return 92 to {\it NetHack\/}, if 171 was originally going to be returned.
 You can use multiple subkeyvalue statements in the config file if needed.
 Cannot be set with the `{\tt O}' command.
 %.lp
 \item[\ib{video}]
 Set the video mode used ({\it PC\/ NetHack\/} only).
-Values are {\it autodetect\/}, {\it default\/}, or {\it vga\/}. 
-Setting {\it vga\/} (or {\it autodetect\/} with vga hardware present) will cause
-the game to display tiles. 
+Values are {\it autodetect\/}, {\it default\/}, or {\it vga\/}.
+Setting {\it vga\/} (or {\it autodetect\/} with vga hardware present) will
+cause the game to display tiles.
 Cannot be set with the `{\tt O}' command.
 %.lp
 \item[\ib{videocolors}]
@@ -3220,10 +3955,11 @@ Cannot be set with the `{\tt O}' command.
 
 %.pg
 Regular expressions are normally POSIX extended regular expressions. It is
-possible to compile NetHack without regular expression support on a platform where
+possible to compile {\it 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.
+platform, if your {\it NetHack\/} was built this way, patterns are instead glob
+patterns. This applies to Autopickup exceptions, Message types, Menu colors,
+and User sounds.
 
 %.hn 2
 \subsection*{Configuring Autopickup Exceptions}
@@ -3245,7 +3981,7 @@ The {\it autopickup\verb+_+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.
 
-In addition, some characters are treated specially if they occur as the first 
+In addition, some characters are treated specially if they occur as the first
 character in the pattern, specifically:
 
 %.sd
@@ -3278,6 +4014,169 @@ The last example results in the exclusion of items known to be cursed from
 autopickup.
 
 %.lp
+
+%.hn 2
+\subsection*{Changing Key Bindings}
+
+%.pg
+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 (``{\tt x}''),
+a control key (``{\tt \^{}X}'', ``{\tt C-x}''), a meta key (``{\tt M-x}''),
+or a three-digit decimal ASCII code.
+
+%.pg
+For example:
+
+\begin{verbatim}
+    BIND=^X:getpos.autodescribe
+    BIND={:menu_first_page
+    BIND=v:loot
+\end{verbatim}
+
+\blist{}
+%.lp "Extended command keys"
+\item[\tb{Extended command keys}]
+You can bind multiple keys to the same extended command. Unbind a key by
+using ``{\tt nothing}'' as the extended command to bind to. You can also bind
+the ``{\tt <esc>}'', ``{\tt <enter>}'', and ``{\tt <space>}'' keys.
+
+%.lp "Menu accelerator keys"
+\item[\tb{Menu accelerator keys}]
+The menu control or accelerator keys can also be rebound via OPTIONS-lines
+in the config file. You cannot bind object symbols into menu accelerators.
+
+%.lp "Special command keys"
+\item[\tb{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.
+
+%.pg
+\blist{}
+%.lp
+\item{\bb{count}}
+Prefix key to start a count, to repeat a command this many times. With {\it number\verb+_+pad\/} only. Default is ``{\tt n}''.
+%.lp
+\item{\bb{doinv}}
+Show inventory. With {\it number\verb+_+pad\/} only. Default is ``{\tt 0}''.
+%.lp
+\item{\bb{fight}}
+Prefix key to force fight a direction. Default is ``{\tt F}''.
+%.lp
+\item{\bb{fight.numpad}}
+Prefix key to force fight a direction. With {\it number\verb+_+pad\/} only. Default is ``{\tt -}''.
+%.lp
+\item{\bb{getdir.help}}
+When asked for a direction, the key to show the help. Default is ``{\tt ?}''.
+%.lp
+\item{\bb{getdir.self}}
+When asked for a direction, the key to target yourself. Default is ``{\tt .}''.
+%.lp
+\item{\bb{getdir.self2}}
+When asked for a direction, the key to target yourself. Default is ``{\tt s}''.
+%.lp
+\item{\bb{getpos.autodescribe}}
+When asked for a location, the key to toggle {\it autodescribe\/}. Default is ``{\tt \#}''.
+%.lp
+\item{\bb{getpos.all.next}}
+When asked for a location, the key to go to next closest interesting thing. Default is ``{\tt a}''.
+%.lp
+\item{\bb{getpos.all.prev}}
+When asked for a location, the key to go to previous closest interesting thing. Default is ``{\tt A}''.
+%.lp
+\item{\bb{getpos.door.next}}
+When asked for a location, the key to go to next closest door or doorway. Default is ``{\tt d}''.
+%.lp
+\item{\bb{getpos.door.prev}}
+When asked for a location, the key to go to previous closest door or doorway. Default is ``{\tt D}''.
+%.lp
+\item{\bb{getpos.help}}
+When asked for a location, the key to show help. Default is ``{\tt ?}''.
+%.lp
+\item{\bb{getpos.mon.next}}
+When asked for a location, the key to go to next closest monster. Default is ``{\tt m}''.
+%.lp
+\item{\bb{getpos.mon.prev}}
+When asked for a location, the key to go to previous closest monster. Default is ``{\tt M}''.
+%.lp
+\item{\bb{getpos.obj.next}}
+When asked for a location, the key to go to next closest object. Default is ``{\tt o}''.
+%.lp
+\item{\bb{getpos.obj.prev}}
+When asked for a location, the key to go to previous closest object. Default is ``{\tt O}''.
+%.lp
+\item{\bb{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 '{\tt !}'.
+%.lp
+\item{\bb{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 ``{\tt *}''.
+%.lp
+\item{\bb{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 '{\tt "}'.
+%.lp
+\item{\bb{getpos.pick}}
+When asked for a location, the key to choose the location, and possibly ask for more info. Default is ``{\tt .}''.
+%.lp
+\item{\bb{getpos.pick.once}}
+When asked for a location, the key to choose the location, and skip asking for more info. Default is ``{\tt ,}''.
+%.lp
+\item{\bb{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. Default is ``{\tt ;}''.
+%.lp
+\item{\bb{getpos.pick.verbose}}
+When asked for a location, the key to choose the location, and show more info without asking. Default is ``{\tt :}''.
+%.lp
+\item{\bb{getpos.self}}
+When asked for a location, the key to go to your location. Default is ``{\tt @}''.
+%.lp
+\item{\bb{getpos.unexplored.next}}
+When asked for a location, the key to go to next closest unexplored location. Default is ``{\tt x}''.
+%.lp
+\item{\bb{getpos.unexplored.prev}}
+When asked for a location, the key to go to previous closest unexplored location. Default is ``{\tt X}''.
+%.lp
+\item{\bb{getpos.valid}}
+When asked for a location, the key to go to show valid target locations. Default is ``{\tt \$}''.
+%.lp
+\item{\bb{getpos.valid.next}}
+When asked for a location, the key to go to next closest valid location. Default is ``{\tt z}''.
+%.lp
+\item{\bb{getpos.valid.prev}}
+When asked for a location, the key to go to previous closest valid location. Default is ``{\tt Z}''.
+%.lp
+\item{\bb{nopickup}}
+Prefix key to move without picking up items. Default is ``{\tt m}''.
+%.lp
+\item{\bb{redraw}}
+Key to redraw the screen. Default is ``{\tt \^{}R}''.
+%.lp
+\item{\bb{redraw.numpad}}
+Key to redraw the screen. With {\it number\verb+_+pad\/} only. Default is ``{\tt \^{}L}''.
+%.lp
+\item{\bb{repeat}}
+Key to repeat previous command. Default is ``{\tt \^{}A}''.
+%.lp
+\item{\bb{reqmenu}}
+Prefix key to request menu from some commands. Default is ``{\tt m}''.
+%.lp
+\item{\bb{run}}
+Prefix key to run towards a direction. Default is ``{\tt G}''.
+%.lp
+\item{\bb{run.nopickup}}
+Prefix key to run towards a direction without picking up items on the way. Default is ``{\tt M}''.
+%.lp
+\item{\bb{run.numpad}}
+Prefix key to run towards a direction. With {\it number\verb+_+pad\/} only. Default is ``{\tt 5}''.
+%.lp
+\item{\bb{rush}}
+Prefix key to rush towards a direction. Default is ``{\tt g}''.
+\elist
+\elist
+
+
 %.hn 2
 \subsection*{Configuring Message Types}
 
@@ -3310,7 +4209,7 @@ the pattern to match. The pattern should be a regular expression.
 \elist
 
 %.lp ""
-Here's an example of message types using NetHack's internal
+Here's an example of message types using {\it NetHack's\/} internal
 pattern matching facility:
 
 \begin{verbatim}
@@ -3374,7 +4273,7 @@ Note that the platform used may interpret the attributes any way it
 wants.
 
 %.lp ""
-Here's an example of menu colors using NetHack's internal
+Here's an example of menu colors using {\it NetHack's\/} internal
 pattern matching facility:
 
 \begin{verbatim}
@@ -3403,7 +4302,7 @@ displayed with the ``uncursed'' description.
 \subsection*{Configuring User Sounds}
 
 %.pg
-Some platforms allow you to define sound files to be played when a message 
+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.
@@ -3439,21 +4338,26 @@ The pattern should be a regular expression.
 \subsection*{Configuring Status Hilites}
 
 %.pg
-Your copy of NetHack may have been compiled with support for {\it Status Hilites}.
-If so, you can customize your game display by setting thresholds to 
+Your copy of {\it NetHack\/} may have been compiled with support for {\it 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.
-
+%.pg
+The format for defining status colors is:
+\begin{verbatim}
+    OPTION=hilite_status: field-name/behavior/color&attributes
+\end{verbatim}
+%.pg
 For example, the following line in your config file will cause
 the hitpoints field to display in the color red if your hitpoints
 drop to or below a threshold of 30%:
 \begin{verbatim}
-    OPTION=hilite_status: hitpoints/30%/red/normal
+    OPTION=hilite_status: hitpoints/<30%/red/normal
 \end{verbatim}
 %.pg
 For another example, the following line in your config file will cause
 wisdom to be displayed red if it drops and green if it rises.
 \begin{verbatim}
-    OPTION=hilite_status: wisdom/updown/red/green
+    OPTION=hilite_status: wisdom/down/red/up/green
 \end{verbatim}
 You can adjust the display of the following status fields:
 %.sd
@@ -3472,6 +4376,56 @@ experience & condition\\
 \end{tabular}
 \end{center}
 %.ed
+%.lp ""
+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.
+
+%.lp ""
+Instead of a behavior, `condition' takes the following condition flags:
+{\it stone}, {\it slime}, {\it strngl}, {\it foodpois}, {\it termill},
+{\it blind}, {\it deaf}, {\it stun}, {\it conf}, {\it hallu},
+{\it lev}, {\it fly}, and {\it 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 condition.
+
+%.lp ""
+Allowed behaviors are "always", "up", "down", "changed", a
+percentage or absolute number threshold, or a text to match against.
+
+\blist{}
+%.lp "*"
+\item{\bb{}}
+"always" will set the default attributes for that field.
+%.lp "*"
+\item{\bb{}}
+"up" and "down" set the field attributes for when the field
+value changes upwards or downwards. This attribute times out after
+statushilites turns.
+%.lp "*"
+\item{\bb{}}
+"changed" sets the field attribute for when the field value
+changes. This attribute times out after statushilites turns.
+%.lp "*"
+\item{\bb{}}
+percentage sets the field attribute when the field value
+matches the percentage. If the percentage is prefixed with `{\tt <}'
+or `{\tt >}', it also matches when value is below or above the percentage.
+Only valid for `power' and `hitpoints' fields.
+%.lp "*"
+\item{\bb{}}
+absolute value sets the attribute when the field value
+matches that number. If the number is prefixed with `{\tt <}'
+or `{\tt >}', it also matches when value is below or above.
+%.lp "*"
+\item{\bb{}}
+text match sets the attribute when the field value
+matches the text. Text matches can only be used for `alignment',
+`carrying-capacity', and `dungeon-level'.
+%.ei
+\elist
 
 %.lp ""
 Allowed colors are {\it black}, {\it red}, {\it green}, {\it brown},
@@ -3480,22 +4434,42 @@ Allowed colors are {\it black}, {\it red}, {\it green}, {\it brown},
 {\it lightcyan}, and {\it white}.
 
 %.lp ""
-Behaviours can occur based on percentage thresholds, updown, or absolute values.
-The in-game options menu can help you determine the correct syntax for a 
+Allowed attributes are {\it bold}, {\it inverse}, {\it underline},
+{\it blink}, {\it dim}, and {\it normal}.
+Note that the platform used may interpret the attributes any way it
+wants.
+
+%.lp ""
+The in-game options menu can help you determine the correct syntax for a
 config file.
 
 %.lp ""
-The whole feature can be disable by setting option {\it statushilites} off.
+The whole feature can be disable by setting option {\it statushilites} to 0.
+
+%.lp ""
+Example hilites:
+\begin{verbatim}
+    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
+\end{verbatim}
 
 %.lp
 %.hn 2
-\subsection*{Modifying NetHack Symbols}
+\subsection*{Modifying {\it NetHack\/} Symbols}
 
 %.pg
-NetHack can load entire symbol sets from the symbol file.
+{\it NetHack\/} can load entire symbol sets from the symbol file.
 
 %.pg
-The options that are used to select a particular symbol set from the 
+The options that are used to select a particular symbol set from the
 symbol file are:
 
 \blist{}
@@ -3506,16 +4480,16 @@ Set the name of the symbol set that you want to load.
 
 %.lp
 \item[\ib{roguesymset}]
-Set the name of the symbol set that you want to load for display 
+Set the name of the symbol set that you want to load for display
 on the rogue level.
 \elist
 
-You can also override one or more symbols using the {\it SYMBOLS\/} config 
-file option. Symbols are specified as {\it name:value\/} pairs. Note that 
+You can also override one or more symbols using the {\it SYMBOLS\/} config
+file option. Symbols are specified as {\it name:value\/} pairs. Note that
 {\it NetHack\/} escape-processes the {\it value\/} string in conventional C
 fashion.  This means that `\verb+\+' is a prefix to take the following
 character literally.  Thus `\verb+\+' needs to be represented as `\verb+\\+'.
-The special escape form
+The special prefix
 `\verb+\m+' switches on the meta bit in the symbol value, and the
 `{\tt \^{}}' prefix causes the following character to be treated as a control
 character.
@@ -3524,11 +4498,11 @@ character.
 \small
 \begin{longtable}{lll}
 \caption[]{NetHack Symbols}\\
-Default  & Symbol Name                & Description\\
+Default                      & Symbol Name                & Description\\
 \hline \hline
 \endhead
 \verb@ @ & S\verb+_+air                     &  (air)\\
-\verb@_@ & S\verb+_+altar                   &  (altar)\\
+\_ & S\verb+_+altar                   &        (altar)\\
 \verb@"@ & S\verb+_+amulet                  &  (amulet)\\
 \verb@A@ & S\verb+_+angel                   &  (angelic being)\\
 \verb@a@ & S\verb+_+ant                     &  (ant or other insect)\\
@@ -3537,7 +4511,7 @@ Default  & Symbol Name                & Description\\
 \verb@[@ & S\verb+_+armour                  &  (suit or piece of armor)\\
 \verb@^@ & S\verb+_+arrow\verb+_+trap             &    (arrow trap)\\
 \verb@0@ & S\verb+_+ball                    &  (iron ball)\\
-\verb@#@ & S\verb+_+bars                    &  (iron bars)\\
+\# & S\verb+_+bars                    &        (iron bars)\\
 \verb@B@ & S\verb+_+bat                     &  (bat or bird)\\
 \verb@^@ & S\verb+_+bear\verb+_+trap              &    (bear trap)\\
 \verb@-@ & S\verb+_+blcorn                  &  (bottom left corner)\\
@@ -3549,11 +4523,12 @@ Default  & Symbol Name                & Description\\
 \verb@-@ & S\verb+_+brcorn                  &  (bottom right corner)\\
 \verb@C@ & S\verb+_+centaur                 &  (centaur)\\
 \verb@_@ & S\verb+_+chain                   &  (iron chain)\\
-\verb@#@ & S\verb+_+cloud                   &  (cloud)\\
+\# & S\verb+_+cloud                   &        (cloud)\\
 \verb@c@ & S\verb+_+cockatrice              &  (cockatrice)\\
-\verb@$@ & S\verb+_+coin                    &  (pile of coins)\\
-\verb@#@ & S\verb+_+corr                    &  (corridor)\\
+\$ & S\verb+_+coin                    &        (pile of coins)\\
+\# & S\verb+_+corr                    &        (corridor)\\
 \verb@-@ & S\verb+_+crwall                  &  (wall)\\
+\verb@-@ & S\verb+_+darkroom                &  (dark room)\\
 \verb@^@ & S\verb+_+dart\verb+_+trap              &    (dart trap)\\
 \verb@&@ & S\verb+_+demon                   &  (major demon)\\
 \verb@*@ & S\verb+_+digbeam                 &  (dig beam)\\
@@ -3577,8 +4552,8 @@ Default  & Symbol Name                & Description\\
 \verb@f@ & S\verb+_+feline                  &  (cat or other feline)\\
 \verb@^@ & S\verb+_+fire\verb+_+trap              &    (fire trap)\\
 \verb@!@ & S\verb+_+flashbeam               &  (flash beam)\\
-\verb@%@ & S\verb+_+food                    &  (piece of food)\\
-\verb@{@ & S\verb+_+fountain                &  (fountain)\\
+\% & S\verb+_+food                    &        (piece of food)\\
+\{ & S\verb+_+fountain                &        (fountain)\\
 \verb@F@ & S\verb+_+fungus                  &  (fungus or mold)\\
 \verb@*@ & S\verb+_+gem                     &  (gem or rock)\\
 \verb@ @ & S\verb+_+ghost                   &  (ghost)\\
@@ -3588,16 +4563,17 @@ Default  & Symbol Name                & Description\\
 \verb@|@ & S\verb+_+grave                   &  (grave)\\
 \verb@g@ & S\verb+_+gremlin                 &  (gremlin)\\
 \verb@-@ & S\verb+_+hbeam                   &  (wall)\\
-\verb@#@ & S\verb+_+hcdbridge               &  (horizontal raised drawbridge)\\
+\# & S\verb+_+hcdbridge               &        (horizontal raised drawbridge)\\
 \verb@+@ & S\verb+_+hcdoor                  &  (closed door)\\
 \verb@.@ & S\verb+_+hodbridge               &  (horizontal lowered drawbridge)\\
 \verb@|@ & S\verb+_+hodoor                  &  (open door)\\
-\verb@^@ & S\verb+_+hole                    &  (hole)\\
+\verb\^\ & S\verb+_+hole                    &  (hole)\\
 \verb~@~ & S\verb+_+human                   &  (human or elf)\\
 \verb@h@ & S\verb+_+humanoid                &  (humanoid)\\
 \verb@-@ & S\verb+_+hwall                   &  (horizontal wall)\\
 \verb@.@ & S\verb+_+ice                     &  (ice)\\
 \verb@i@ & S\verb+_+imp                     &  (imp or minor demon)\\
+\verb@I@ & S\verb+_+invisible               &  (invisible monster)\\
 \verb@J@ & S\verb+_+jabberwock              &  (jabberwock)\\
 \verb@j@ & S\verb+_+jelly                   &  (jelly)\\
 \verb@k@ & S\verb+_+kobold                  &  (kobold)\\
@@ -3608,7 +4584,7 @@ Default  & Symbol Name                & Description\\
 \verb@^@ & S\verb+_+level\verb+_+teleporter       &    (level teleporter)\\
 \verb@L@ & S\verb+_+lich                    &  (lich)\\
 \verb@y@ & S\verb+_+light                   &  (light)\\
-\verb@#@ & S\verb+_+litcorr                 &  (lit corridor)\\
+\# & S\verb+_+litcorr                 &        (lit corridor)\\
 \verb@:@ & S\verb+_+lizard                  &  (lizard)\\
 \verb@\@ & S\verb+_+lslant                  &  (wall)\\
 \verb@^@ & S\verb+_+magic\verb+_+portal           &    (magic portal)\\
@@ -3623,7 +4599,7 @@ Default  & Symbol Name                & Description\\
 \verb@o@ & S\verb+_+orc                     &  (orc)\\
 \verb@p@ & S\verb+_+piercer                 &  (piercer)\\
 \verb@^@ & S\verb+_+pit                     &  (pit)\\
-\verb@#@ & S\verb+_+poisoncloud             &  (poison cloud)\\
+\# & S\verb+_+poisoncloud             &        (poison cloud)\\
 \verb@^@ & S\verb+_+polymorph\verb+_+trap         &    (polymorph trap)\\
 \verb@}@ & S\verb+_+pool                    &  (water)\\
 \verb@!@ & S\verb+_+potion                  &  (potion)\\
@@ -3639,18 +4615,19 @@ Default  & Symbol Name                & Description\\
 \verb@^@ & S\verb+_+rust\verb+_+trap              &    (rust trap)\\
 \verb@R@ & S\verb+_+rustmonst               &  (rust monster or disenchanter)\\
 \verb@?@ & S\verb+_+scroll                  &  (scroll)\\
-\verb@#@ & S\verb+_+sink                    &  (sink)\\
+\# & S\verb+_+sink                    &        (sink)\\
 \verb@^@ & S\verb+_+sleeping\verb+_+gas\verb+_+trap     &      (sleeping gas trap)\\
 \verb@S@ & S\verb+_+snake                   &  (snake)\\
 \verb@s@ & S\verb+_+spider                  &  (arachnid or centipede)\\
 \verb@^@ & S\verb+_+spiked\verb+_+pit             &    (spiked pit)\\
 \verb@^@ & S\verb+_+squeaky\verb+_+board          &    (squeaky board)\\
 \verb@0@ & S\verb+_+ss1                     &  (magic shield 1 of 4)\\
-\verb@#@ & S\verb+_+ss2                     &  (magic shield 2 of 4)\\
+\# & S\verb+_+ss2                     &        (magic shield 2 of 4)\\
 \verb+@+ & S\verb+_+ss3                     &  (magic shield 3 of 4)\\
 \verb@*@ & S\verb+_+ss4                     &  (magic shield 4 of 4)\\
 \verb@^@ & S\verb+_+statue\verb+_+trap            &    (statue trap)\\
 \verb@ @ & S\verb+_+stone                   &  (dark part of a room)\\
+\verb@]@ & S\verb+_+strange\verb+_+obj      &  (strange object)\\
 \verb@-@ & S\verb+_+sw\verb+_+bc                  &    (swallow bottom center)\\
 \verb@\@ & S\verb+_+sw\verb+_+bl                  &    (swallow bottom left)\\
 \verb@/@ & S\verb+_+sw\verb+_+br                  &    (swallow bottom right   )\\
@@ -3668,7 +4645,7 @@ Default  & Symbol Name                & Description\\
 \verb@^@ & S\verb+_+trap\verb+_+door              &    (trap door)\\
 \verb@t@ & S\verb+_+trapper                 &  (trapper or lurker above)\\
 \verb@-@ & S\verb+_+trcorn                  &  (top right corner)\\
-\verb@#@ & S\verb+_+tree                    &  (tree)\\
+\# & S\verb+_+tree                    &        (tree)\\
 \verb@T@ & S\verb+_+troll                   &  (troll)\\
 \verb@|@ & S\verb+_+trwall                  &  (wall)\\
 \verb@-@ & S\verb+_+tuwall                  &  (wall)\\
@@ -3678,7 +4655,7 @@ Default  & Symbol Name                & Description\\
 \verb@<@ & S\verb+_+upstair                 &  (staircase up)\\
 \verb@V@ & S\verb+_+vampire                 &  (vampire)\\
 \verb@|@ & S\verb+_+vbeam                   &  (wall)\\
-\verb@#@ & S\verb+_+vcdbridge               &  (vertical raised drawbridge)\\
+\# & S\verb+_+vcdbridge               &        (vertical raised drawbridge)\\
 \verb@+@ & S\verb+_+vcdoor                  &  (closed door)\\
 \verb@.@ & S\verb+_+venom                   &  (splash of venom)\\
 \verb@^@ & S\verb+_+vibrating\verb+_+square       &    (vibrating square)\\
@@ -3701,13 +4678,25 @@ Default  & Symbol Name                & Description\\
 \end{longtable}%
 }
 
-%.lp
+%.pg
+There is one additional class of object, described as ``strange object'',
+which will occasionally be the shape taken on by mimics and shown as
+`{\tt \verb+]+}'
+for maps displayed as text characters.
+Although the displayed character is the same as the default value for
+`S\verb+_+mimic\verb+_+def', it is a different symbol and there is no
+corresponding
+`S\verb+_+strange\verb+_+object' symbol nor any way to assign an
+alternate value for it.
+
+%.pg
 %.hn 2
-\subsection*{Configuring NetHack for Play by the Blind}
+\subsection*{Configuring {\it NetHack\/} for Play by the Blind}
 
 %.pg
-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
+{\it NetHack\/} can be set up to use only standard ASCII characters for making
+maps of the dungeons. This makes the MS-DOS versions of {\it 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
@@ -3722,14 +4711,23 @@ 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.
 %.pg
+{\it 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 {\it NetHack\/}
+has been compiled with the capability. When compiling {\it NetHack\/} from source
+on Linux and other POSIX systems, define {\it MSGHANDLER\/} to enable it. To use
+the capability, set the environment variable {\it NETHACK\_MSGHANDLER\/} to an
+executable, which will be executed with the game message as the program's
+only parameter.
+%.pg
 While it is not difficult for experienced users to edit the {\it defaults.nh\/}
 file to accomplish this, novices may find this task somewhat daunting.
-Included within the symbol file of all official distributions of NetHack 
+Included within the symbol file of all official distributions of {\it NetHack\/}
 is a symset called {\it NHAccess\/}.  Selecting 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 {\it SYMBOLS=\/} 
-in your configuration file to better suit your preferences. 
+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 {\it SYMBOLS=\/}
+in your configuration file to better suit your preferences.
 The most crucial settings to make the game accessible are:
 %.pg
 \blist{}
@@ -3738,28 +4736,55 @@ The most crucial settings to make the game accessible are:
 Load a symbol set appropriate for use by blind players.
 %.lp
 \item[\ib{roguesymset:NHAccess}]
-Load a symbol set for the rogue level that is appropriate for 
+Load a symbol set for the rogue level that is appropriate for
 use by blind players.
 %.lp
 \item[\ib{menustyle:traditional}]
 This will assist in the interface to speech synthesizers.
 %.lp
+\item[\ib{nomenu\verb+_+overlay}]
+Show menus on a cleared screen and aligned to the left edge.
+%.lp
 \item[\ib{number\verb+_+pad}]
 A lot of speech access programs use the number-pad to review the screen.
-If this is the case, disable the number\verb+_+pad option and use the traditional
-Rogue-like commands.
+If this is the case, disable the number\verb+_+pad option and use the
+traditional Rogue-like commands.
+%.lp
+\item[\ib{autodescribe}]
+Automatically describe the terrain under the cursor when targeting.
+%.lp
+\item[\ib{mention\verb+_+walls}]
+Give feedback messages when walking towards a wall or when travel command
+was interrupted.
+%.lp
+\item[\ib{whatis\verb+_+coord:compass}]
+When targeting with cursor, describe the cursor position with coordinates
+relative to your character.
+%.lp
+\item[\ib{whatis\verb+_+filter:area}]
+When targeting with cursor, filter possible locations so only those in
+the same area (eg. same room, or same corridor) are considered.
+%.lp
+\item[\ib{whatis\verb+_+moveskip}]
+When targeting with cursor and using fast-move, skip the same glyphs instead
+of moving 8 units at a time.
+%.lp
+\item[\ib{nostatus\verb+_+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 {\tt \#attributes} command.
 \elist
 
 %.hn2
 \subsection*{Global Configuration for System Administrators}
 
 %.pg
-If NetHack is compiled with the SYSCF option, a system administrator
-should set up a global configuration; this is a file in the 
+If {\it NetHack\/} is compiled with the SYSCF option, a system administrator
+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 other {\it 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).
@@ -3773,7 +4798,7 @@ mode (the debugging mode, not the magic-useing role). A value of a single
 asterisk (*) allows anyone to start a game in wizard mode.
 %.lp
 \item[\ib{SHELLERS}]
-A list of users who are allowed to use the shell escape command (!).
+A list of users who are allowed to use the shell escape command (`{\tt !}').
 The syntax is the same as WIZARDS.
 %.lp
 \item[\ib{EXPLORERS}]
@@ -3781,7 +4806,7 @@ A list of users who are allowed to use the explore mode.
 The syntax is the same as WIZARDS.
 %.lp
 \item[\ib{MAXPLAYERS}]
-Limit the maximum number of games taht can be running at the same time.
+Limit the maximum number of games that can be running at the same time.
 %.lp
 \item[\ib{SUPPORT}]
 A string explainign how to get local support (no default value).
@@ -3793,6 +4818,10 @@ A string explaining how to recover a game on this system (no default value).
 0 or 1 to disable or enable, respectively, the SEDUCE option (see the source)
 for details on this function.
 %.lp
+\item[\ib{CHECK\verb+_+PLNAME}]
+Setting this to 1 will make the EXPLORERS, WIZARDS, and SHELLERS check
+for the player name instead of the user's login name.
+%.lp
 \item[\ib{CHECK\verb+_+SAVE\verb+_+UID}]
 0 or 1 to disable or enable, respectively, the UID checking for savefiles.
 \elist
@@ -3814,6 +4843,24 @@ Minimum number of points to get an entry in the score file.
 \item[\ib{PERS\verb+_+IS\verb+_+UID}]
 0 or 1 to use user names or numeric userids, respectively, to identify
 unique people for the score file
+%.lp
+\item[\ib{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 following placeholders:
+%.sd
+%.si
+{\tt \%\%}  --- literal `{\tt \%}'\\
+{\tt \%v}  --- version (eg. "3.6.1-0")\\
+{\tt \%u}  --- game UID\\
+{\tt \%t}  --- game start time, UNIX timestamp format\\
+{\tt \%T}  --- current time, UNIX timestamp format\\
+{\tt \%d}  --- game start time, YYYYMMDDhhmmss format\\
+{\tt \%D}  --- current time, YYYYMMDDhhmmss format\\
+{\tt \%n}  --- player name\\
+{\tt \%N}  --- first character of player name
+%.ei
+%.ed
 \elist
 
 %.hn 1
@@ -4008,7 +5055,7 @@ was responsible for the VMS version of {\it NetHack\/} 3.1.
 \medskip
 \nd {\it Dean Luick}, with help from {\it David Cohrs}, developed {\it NetHack\/}
 3.1 for X11.
-{\it Warwick Allison} wrote a tiled version of NetHack for the Atari;
+{\it Warwick Allison} wrote a tiled version of {\it NetHack\/} for the Atari;
 he later contributed the tiles to the DevTeam and tile support was
 then added to other platforms.
 
@@ -4046,7 +5093,7 @@ Working independently, {\it Stephen White} wrote {\it NetHack Plus}.
 and his own {\it NetHack$--$} to produce {\it SLASH}.
 {\it Larry Stewart-Zerba} and {\it Warwick Allison} improved the spell
 casting system with the Wizard Patch.
-{\it Warwick Allison} also ported NetHack to use the Qt interface.
+{\it Warwick Allison} also ported {\it NetHack\/} to use the Qt interface.
 
 %.pg
 \medskip
@@ -4054,7 +5101,7 @@ casting system with the Wizard Patch.
 to produce {\it Slash'em\/}, and
 with the help of {\it Kevin Hugo}, added more features.
 Kevin later joined the
-DevTeam and incorporated the best of these ideas into NetHack 3.3.
+DevTeam and incorporated the best of these ideas into {\it NetHack\/} 3.3.
 
 %.pg
 \medskip
@@ -4063,34 +5110,34 @@ simultaneously with 3.3.0 in December 1999 just in time for the Year 2000.
 
 %.pg
 \medskip
-The 3.3 development team, consisting of {\it Michael Allison}, {\it Ken Arromdee}, 
-{\it David Cohrs}, {\it Jessie Collet}, {\it Steve Creps}, {\it Kevin Darcy}, 
-{\it Timo Hakulinen}, {\it Kevin Hugo}, {\it Steve Linhart}, {\it Ken Lorber}, 
-{\it Dean Luick}, {\it Pat Rankin}, {\it Eric Smith}, {\it Mike Stephenson}, 
-{\it Janet Walz}, and {\it Paul Winner}, released 3.3.0 in 
+The 3.3 development team, consisting of {\it Michael Allison}, {\it Ken Arromdee},
+{\it David Cohrs}, {\it Jessie Collet}, {\it Steve Creps}, {\it Kevin Darcy},
+{\it Timo Hakulinen}, {\it Kevin Hugo}, {\it Steve Linhart}, {\it Ken Lorber},
+{\it Dean Luick}, {\it Pat Rankin}, {\it Eric Smith}, {\it Mike Stephenson},
+{\it Janet Walz}, and {\it Paul Winner}, released 3.3.0 in
 December 1999 and 3.3.1 in August of 2000.
 
 %.pg
 \medskip
-Version 3.3 offered many firsts. It was the first version to separate 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, 
+Version 3.3 offered many firsts. It was the first version to separate 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 listing all the bugs that had been discovered.  Despite 
+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.
 
 %.pg
 \medskip
-The 3.4 development team initially consisted of 
+The 3.4 development team initially consisted of
 {\it Michael Allison}, {\it Ken Arromdee},
 {\it David Cohrs}, {\it Jessie Collet}, {\it Kevin Hugo}, {\it Ken Lorber},
-{\it Dean Luick}, {\it Pat Rankin}, {\it Mike Stephenson}, 
-{\it Janet Walz}, and {\it Paul Winner}, with {\it  Warwick Allison} joining 
-just before the release of NetHack 3.4.0 in March 2002.
+{\it Dean Luick}, {\it Pat Rankin}, {\it Mike Stephenson},
+{\it Janet Walz}, and {\it Paul Winner}, with {\it  Warwick Allison} joining
+just before the release of {\it NetHack\/} 3.4.0 in March 2002.
 
 %.pg
 \medskip
@@ -4104,7 +5151,8 @@ runs on:
 
 %.pg
 \medskip
-\nd {\it Michael Allison} maintained NetHack 3.4 for the MS-DOS platform.
+\nd {\it Michael Allison} maintained {\it NetHack\/} 3.4 for the MS-DOS
+platform.
 {\it Paul Winner} and {\it Yitzhak Sapir} provided encouragement.
 
 %.pg
@@ -4114,17 +5162,20 @@ enhanced the Macintosh port of 3.4.
 
 %.pg
 \medskip
-\nd {\it Michael Allison}, {\it David Cohrs}, {\it Alex Kompel}, {\it Dion Nicolaas}, and 
-{\it Yitzhak Sapir} maintained and enhanced 3.4 for the Microsoft Windows platform.
-{\it Alex Kompel} contributed a new graphical interface for the Windows port. 
+\nd {\it Michael Allison}, {\it David Cohrs}, {\it Alex Kompel},
+{\it Dion Nicolaas}, and
+{\it Yitzhak Sapir} maintained and enhanced 3.4 for the Microsoft Windows
+platform.
+{\it Alex Kompel} contributed a new graphical interface for the Windows port.
 {\it Alex Kompel} also contributed a Windows CE port for 3.4.1.
 
 %.pg
 \medskip
-\nd {\it Ron Van Iwaarden} was the sole maintainer of NetHack for OS/2 the past
+\nd {\it Ron Van Iwaarden} was the sole maintainer of {\it 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.
+early 2006. A great many thanks to Ron for keeping {\it NetHack\/} alive on
+OS/2 all these years.
 
 %.pg
 \medskip
@@ -4139,67 +5190,102 @@ resurrected it for 3.3.1.
 
 %.pg
 \medskip
-The release of NetHack 3.4.3 in December 2003 marked the beginning 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 
-devteam 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 continue to be developed, 
-maintained, and enjoyed by the community to this day.
+The release of {\it NetHack\/} 3.4.3 in December 2003 marked the beginning 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
+devteam 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 {\it NetHack\/} community. Notably sporkhack by
+Derek S. Ray, {\it unnethack\/} by Patric Mueller, {\it nitrohack\/} and its
+successors originally by Daniel Thaler and then by Alex Smith, and
+{\it Dynahack\/} by Tung Nguyen. Some of those variants continue to be
+developed, maintained, and enjoyed by the community to this day.
+
+%.pg
+\medskip
+In September 2014, an interim snapshot of the code under development 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 {\it NetHack\/} release. An
+announcement was posted on the devteam's official {\it 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.
+
+%.pg
+\medskip
+In January 2015, preparation began for the release of NetHack 3.6.
 
 %.pg
 \medskip
 At the beginning of development for what would eventually get released
-as 3.6.0, the development team consisted of {\it Warwick Allison}, 
+as 3.6.0, the development team consisted of {\it Warwick Allison},
 {\it Michael Allison}, {\it Ken Arromdee},
-{\it David Cohrs}, {\it Jessie Collet}, 
-{\it Ken Lorber}, {\it Dean Luick}, {\it Pat Rankin}, 
+{\it David Cohrs}, {\it Jessie Collet},
+{\it Ken Lorber}, {\it Dean Luick}, {\it Pat Rankin},
 {\it Mike Stephenson}, {\it Janet Walz}, and {\it Paul Winner}.
-Leading up to the release of 3.6.0 in early 2015, new members
+In early 2015, ahead of the release of 3.6.0, new members
 {\it Sean Hunt}, {\it Pasi Kallinen}, and {\it Derek S. Ray}
-joined the NetHack development team.
+joined the {\it NetHack\/} development team.
 
 %.pg
 \medskip
-In September 2014, an interim snapshot of the code under development 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 devteam'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.
+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. {\it NetHack\/} 3.6.0 introduced 
+a tribute to him.
+
+%.pg
+\medskip
+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.
+
+%.pg
+\medskip
+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 development team at the 
+time of release of 3.6.1 consisted of 
+{\it Warwick Allison}, {\it Michael Allison}, {\it Ken Arromdee}, 
+{\it David Cohrs}, {\it Jessie Collet},
+{\it Pasi Kallinen}, {\it Ken Lorber}, {\it Dean Luick},
+{\it Patric Mueller}, {\it Pat Rankin}, {\it Derek S. Ray},
+{\it Alex Smith}, {\it Mike Stephenson}, {\it Janet Walz}, and
+{\it Paul Winner}.
 
 %.pg
 \medskip
-In November 2014, preparation began for the release of NetHack 3.6. The 3.6
-version merges work done by the development team since the previous release 
-with some of the beloved community patches. Many bugs were fixed and a 
-large amount of code was restructured.
+The development team, as well as {\it Steve VanDevender} and
+{\it Kevin Smolkowski}, ensured that {\it NetHack\/} 3.6 continued to
+operate on various Unix flavors and maintained the X11 interface.
 
+%.pg
+\medskip
+{\it Ken Lorber}, {\it Haoyang Wang}, {\it Pat Rankin}, and {\it Dean Luick}
+maintained the port of {\it NetHack\/} 3.6 for Mac OSX.
 
 %.pg
 \medskip
-The development team, as well as {\it Steve VanDevender} and 
-{\it Kevin Smolkowski} ensured that NetHack 3.6.0 continued to operate on 
-various Unix flavors and maintained the X11 interface. 
+{\it Michael Allison}, {\it David Cohrs}, {\it Barton House},
+{\it Pasi Kallinen}, {\it Alex Kompel}, {\it Dion Nicolaas},
+{\it Derek S. Ray} and  {\it Yitzhak Sapir}
+maintained the port of  {\it NetHack\/} 3.6 for Microsoft Windows.
 
 %.pg
-{\it Ken Lorber}, {\it Haoyang Wang}, {\it Pat Rankin}, and {\it Dean Luick} 
-maintained the port of NetHack 3.6.0 for Mac.
+\medskip
+{\it Pat Rankin} attempted to keep the VMS port running for NetHack 3.6.1,
+hindered by limited access.  {it 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.
 
 %.pg
 \medskip
-{\it Michael Allison}, {\it Derek S. Ray}, {\it Yitzhak Sapir}, 
-{\it Alex Kompel}, and {\it Dion Nicolaas} maintained the port of 
-NetHack 3.6.0 for Microsoft Windows.
+{\it Ray Chason}  resurrected the msdos port for 3.6.1 and contributed the
+necessary updates to the community at large.
 
 %.pg
 \medskip
-\nd The official NetHack web site is maintained by {\it Ken Lorber} at 
+\nd The official {\it NetHack\/} web site is maintained by {\it Ken Lorber} at
 {\catcode`\#=11
 \special{html:<a href="http://www.nethack.org/">}}
 http:{\tt /}{\tt /}www.nethack.org{\tt /}.
@@ -4209,16 +5295,13 @@ http:{\tt /}{\tt /}www.nethack.org{\tt /}.
 %.pg
 %.hn 2
 
-\subsection*{Shout Outs}
-\nd The devteam would like to give a special "shout-out" to thank the generous 
-people primarily responsible for the public NetHack servers available for 
-playing the game at nethack.alt.org and devnull.net. In addition to providing 
-a way for the public to play a game of NetHack from almost anywhere, they 
-have hosted annual NetHack tournaments for many, many years. 
-%.pg 
-\nd On behalf of the NetHack community, thank you very much to 
-{\it M. Drew Streib}, {\it Pasi Kallinen} and {\it Robin Bandy}.
+\subsection*{Special Thanks}
+\nd On behalf of the {\it NetHack\/} community, thank you very much once
+again to {\it M. Drew Streib}, {\it Pasi Kallinen} and {\it Robin Bandy} for
+providing public {\it NetHack\/} servers at  {\it nethack.alt.org\/} and
+{\it devnull.net\/} and/or for hosting annual {\it NetHack\/} tournaments.
 \clearpage
+
 %.hn
 \section*{Dungeoneers}
 %.pg
@@ -4230,36 +5313,46 @@ in this, the list of Dungeoneers:
 \begin{center}
 \begin{tabular}{llll}
 %TABLE_START
-Adam Aronow & Frederick Roeber & Kevin Smolkowski & Richard Beigel\\
-Alex Kompel & Gil Neiger & Kevin Sweet & Richard P. Hughey\\
-Andreas Dorn & Greg Laskin & Lars Huttar & Rob Menke\\
-Andy Church & Greg Olson & Leon Arnott & Robin Bandy\\
-Andy Swanson & Gregg Wonderly & M. Drew Streib & Robin Johnson\\
-Ari Huttunen & Hao-yang Wang & Malcolm Ryan & Roderick Schertler\\
-Barton House & Helge Hafting & Mark Gooderum & Roland McGrath\\
-Benson I. Margulies & Irina Rempt-Drijfhout & Mark Modrall & Ron Van Iwaarden\\
-Bill Dyer & Izchak Miller & Marvin Bressler & Ronnen Miller\\
-Boudewijn Waijers & J. Ali Harlow & Matthew Day & Ross Brown\\
-Bruce Cox & Janet Walz & Merlyn LeRoy & Sascha Wostmann\\
-Bruce Holloway & Janne Salmij\"{a}rvi & Michael Allison & Scott Bigham\\
-Bruce Mewborne & Jean-Christophe Collet & Michael Feir & Scott R. Turner\\
-Carl Schelin & Jeff Bailey & Michael Hamel & Sean Hunt\\
-Chris Russo & Jochen Erwied & Michael Sokolov & Stephen Spackman\\
-David Cohrs & John Kallen & Mike Engber & Stefan Thielscher\\
-David Damerell & John Rupley & Mike Gallop & Stephen White\\
-David Gentzel & John S. Bien & Mike Passaretti & Steve Creps\\
-David Hairston & Johnny Lee & Mike Stephenson & Steve Linhart\\
-Dean Luick & Jon W\{tte & Mikko Juola & Steve VanDevender\\
-Del Lamb & Jonathan Handler & Nathan Eady & Teemu Suikki\\
-Derek S. Ray & Joshua Delahunty & Norm Meluch & Tim Lennan\\
-Deron Meranda & Keizo Yamamoto & Olaf Seibert & Timo Hakulinen\\
-Dion Nicolaas & Ken Arnold & Pasi Kallinen & Tom Almy\\
-Dylan O'Donnell & Ken Arromdee & Pat Rankin & Tom West\\
-Eric Backus & Ken Lorber & Paul Winner & Warren Cheung\\
-Eric Hendrickson & Ken Washikita & Pierre Martineau & Warwick Allison\\
-Eric R. Smith & Kevin Darcy & Ralf Brown & Yitzhak Sapir\\
-Eric S. Raymond & Kevin Hugo & Ray Chason\\
-Erik Andersen & Kevin Sitze & Richard Addison
+Adam Aronow & J. Ali Harlow & Mikko Juola\\
+Alex Kompel & Janet Walz & Nathan Eady\\
+Alex Smith & Janne Salmij\"{a}rvi & Norm Meluch\\
+Andreas Dorn & Jean-Christophe Collet & Olaf Seibert\\
+Andy Church & Jeff Bailey & Pasi Kallinen\\
+Andy Swanson & Jochen Erwied & Pat Rankin\\
+Ari Huttunen & John Kallen & Patric Mueller\\
+Barton House & John Rupley & Paul Winner\\
+Benson I. Margulies & John S. Bien & Pierre Martineau\\
+Bill Dyer & Johnny Lee & Ralf Brown\\
+Boudewijn Waijers & Jon W\{tte & Ray Chason\\
+Bruce Cox & Jonathan Handler & Richard Addison\\
+Bruce Holloway & Joshua Delahunty & Richard Beigel\\
+Bruce Mewborne & Keizo Yamamoto & Richard P. Hughey\\
+Carl Schelin & Ken Arnold & Rob Menke\\
+Chris Russo & Ken Arromdee & Robin Bandy\\
+David Cohrs & Ken Lorber & Robin Johnson\\
+David Damerell & Ken Washikita & Roderick Schertler\\
+David Gentzel & Kevin Darcy & Roland McGrath\\
+David Hairston & Kevin Hugo & Ron Van Iwaarden\\
+Dean Luick & Kevin Sitze & Ronnen Miller\\
+Del Lamb & Kevin Smolkowski & Ross Brown\\
+Derek S. Ray & Kevin Sweet & Sascha Wostmann\\
+Deron Meranda & Lars Huttar & Scott Bigham\\
+Dion Nicolaas & Leon Arnott & Scott R. Turner\\
+Dylan O'Donnell & M. Drew Streib & Sean Hunt\\
+Eric Backus & Malcolm Ryan & Stephen Spackman\\
+Eric Hendrickson & Mark Gooderum & Stefan Thielscher\\
+Eric R. Smith & Mark Modrall & Stephen White\\
+Eric S. Raymond & Marvin Bressler & Steve Creps\\
+Erik Andersen & Matthew Day & Steve Linhart\\
+Frederick Roeber & Merlyn LeRoy & Steve VanDevender\\
+Gil Neiger & Michael Allison & Teemu Suikki\\
+Greg Laskin & Michael Feir & Tim Lennan\\
+Greg Olson & Michael Hamel & Timo Hakulinen\\
+Gregg Wonderly & Michael Sokolov & Tom Almy\\
+Hao-yang Wang & Mike Engber & Tom West\\
+Helge Hafting & Mike Gallop & Warren Cheung\\
+Irina Rempt-Drijfhout & Mike Passaretti & Warwick Allison\\
+Izchak Miller & Mike Stephenson & Yitzhak Sapir
 %TABLE_END  Do not delete this line.
 \end{tabular}
 \end{center}
index a4f7f68..c95b18b 100644 (file)
 
 
 
-          Preface - Version 3.6
-
-               This  version  of  the  game is special in a particular way.
-          Near the end of the development of 3.6, one  of  the  significant
-          inspirations  for  many of the humorous and fun features found in
-          the game, author Terry Pratchett, passed away.  We have dedicated
-          this version of the game in his memory.
-
           1.  Introduction
 
                Recently,  you  have  begun to find yourself unfulfilled and
@@ -48,7 +40,6 @@
           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
           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.
 
 
-          NetHack Guidebook                                               1
 
 
+          NetHack Guidebook                                               1
 
 
 
-          NetHack Guidebook                                               2
 
 
+          NetHack Guidebook                                               2
 
-          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
+               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
@@ -87,7 +78,6 @@
           ing, you gather your gear, eat what may be your  last  meal  out-
           side, and enter the dungeon...
 
-
           2.  What is going on here?
 
                You have just begun a game of NetHack.  Your goal is to grab
           them  to  move  quickly  and sneak up on the local nasties.  They
           start equipped with the tools for a proper scientific expedition.
 
-               Barbarians  are  warriors out of the hinterland, hardened to
+               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.
 
-               Cavemen  and  Cavewomen start with exceptional strength but,
+               Cavemen and Cavewomen start with exceptional  strength  but,
           unfortunately, with neolithic weapons.
 
-               Healers are wise in medicine and apothecary.  They know  the
-          herbs  and  simples  that  can restore vitality, ease pain, anes-
+               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
+          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.
 
-               Knights  are  distinguished  from  the  common skirmisher by
-          their devotion to the ideals of chivalry and  by  the  surpassing
+               Knights are distinguished  from  the  common  skirmisher  by
+          their  devotion  to  the ideals of chivalry and by the surpassing
           excellence of their armor.
 
                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
+          without weapons as with.  They wear no armor but make up  for  it
           with increased mobility.
 
+               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.
 
+               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.
 
-          NetHack 3.6                                      December 7, 2015
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
-          NetHack Guidebook                                               3
 
 
+          NetHack Guidebook                                               3
 
-               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.
 
-               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,
+               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
+               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
+               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.
 
-               Valkyries are hardy warrior women.  Their upbringing in  the
-          harsh  Northlands  makes  them strong, inures them to extremes of
+               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.
 
-               Wizards start out with a knowledge of magic, a selection  of
-          magical  items,  and a particular affinity for dweomercraft.  Al-
+               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.
 
                You may also choose the race of your character:
 
                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
+          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.
 
-               Elves are agile, quick, and perceptive; very little of  what
-          goes  on  will escape an Elf.  The quality of Elven craftsmanship
+               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.
 
-               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
+               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.
 
                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
+          and  are  thus  the norm to which other races are often compared.
+          Although they have no special abilities, they can succeed in  any
           role.
 
-               Orcs are a cruel and barbaric race that  hate  every  living
-          thing  (including other orcs).  Above all others, Orcs hate Elves
+               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.
 
+          3.  What do all those things on the screen mean?
 
-          NetHack 3.6                                      December 7, 2015
+               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                                        April 27, 2018
 
 
-          NetHack Guidebook                                               4
 
 
 
-          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.
+          NetHack Guidebook                                               4
 
-          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.
 
-               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-
+               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
+          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
+          tance  of  Braille  readers or speech synthesisers.  Instructions
+          for configuring NetHack for the blind are included later in  this
           document.
 
                NetHack generates a new dungeon every time you play it; even
-          the  authors  still find it an entertaining and exciting game de-
+          the authors still find it an entertaining and exciting  game  de-
           spite having won several times.
 
-               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
+               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-
+          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-
+          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
+          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.
 
-               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 3.6                                      December 7, 2015
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
 
+          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.
           --------------------------------------------------------------------
            The bat bites!
 
           --------------------------------------------------------------------
                                       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
+               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):
                experience level, see below).
 
           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
+               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.
+               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
+               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
+               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.
 
-          Intelligence
-               Intelligence affects your ability to cast  spells  and  read
 
 
-          NetHack 3.6                                      December 7, 2015
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
 
+          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
                spellbooks.
 
           Wisdom
 
           Charisma
                Charisma affects how certain creatures react toward you.  In
-               particular,  it can affect the prices shopkeepers offer you.
+               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
+               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
+               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-
+               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
+               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  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
+               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
+               friendly  creatures.   The  lower  this  number is, the more
 
 
-          NetHack 3.6                                      December 7, 2015
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
 
+               effective the armor; it is quite possible to  have  negative
+               armor 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
                here.
 
           Time
-               The  number  of  turns elapsed so far, displayed if you have
+               The number of turns elapsed so far, displayed  if  you  have
                the time option set.
 
-          Hunger status
-               Your current hunger status, ranging from  Satiated  down  to
-               Fainting.   If  your hunger status is normal, it is not dis-
-               played.
+          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).
 
-               Additional status flags may appear after the hunger  status:
-          Conf  when you're confused, FoodPois or Ill when sick, Blind when
-          you can't see, Stun when stunned, and Hallu when hallucinating.
+               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
-          another  message  to  display on the screen, but it wants to make
-          certain that you've read the one that is there  first.   To  read
+          scribe things that are impossible to represent visually.  If  you
+          see  a  ``--More--'' on the top line, this means that NetHack has
+          another message 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
+               To change how and what messages are  shown  on  the  message
           line, see ``Configuring Message Types`` and the verbose option.
 
+
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                               8
+
+
+
           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
+               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 floor of a room, ice, or a doorless doorway.
 
-          #    A corridor, or iron bars, or a tree, or possibly  a  kitchen
+          #    A  corridor,  or iron bars, or a tree, or possibly a kitchen
                sink (if your dungeon has sinks), or a drawbridge.
 
           >    Stairs down: a way to the next level.
 
           <    Stairs up: a way to the previous level.
 
-          +    A  closed door, or a spellbook containing a spell you may be
+          +    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 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                               8
-
-
-
           ^    A trap (once you have detected it).
 
           )    A weapon.
 
           0    An iron ball.
 
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                               9
+
+
+
           _    An altar, or an iron chain.
 
           {    A fountain.
           \    An opulent throne.
 
           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
+               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.
 
           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.
+               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  are  initiated  by  typing  one or two characters.
-          Some commands, like ``search'', do not require that any more  in-
-          formation  be collected by NetHack.  Other commands might require
-          additional information, for example a direction, or an object  to
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                               9
-
-
-
-          be used.  For those commands that require additional information,
-          NetHack will present you with either a menu of choices or with  a
-          command  line  prompt requesting information.  Which you are pre-
-          sented with will depend chiefly on how you have set the menustyle
-          option.
-
-               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 unexpect-
+               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.
+
+               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  unexpect-
           ed.  Typing a `*' lists your entire inventory, so you can see the
-          inventory  letters  of every object you're carrying.  Finally, if
+          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.
 
-               You  can  put  a  number before some commands to repeat them
-          that many times; for example, ``10s'' will search ten times.   If
+               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 addi-
-          tion, movement commands can be prefixed for greater control  (see
+          count,  so  the  example  above  would be typed ``n10s'' instead.
+          Commands for which counts make no sense ignore  them.   In  addi-
+          tion,  movement commands can be prefixed for greater control (see
           below).  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 commands for your refer-
-          ence:
-
-          ?    Help menu:  display one of several help texts available.
 
-          /    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 par-
-               ticular  spot  on the map and then pressing one of `.', `,',
-               `;', or `:'.  `.' will explain the symbol at the chosen  lo-
-               cation, conditionally check for ``More info?'' depending up-
-               on 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; `;'  will  skip  additional
-               info  and also not bother asking you to choose another loca-
-               tion 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  press-
-               ing `?'  will give a brief reminder about how it works.
-
-               Specifying  a  name  rather than a location always gives any
-          additional information available about that name.
 
-          &    Tell what a command does.
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack Guidebook                                              10
 
 
 
+               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:
 
-          NetHack Guidebook                                              10
+          ?    Help menu:  display one of several help texts available.
 
+          /    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 op-
+               tion is on, and then you will be asked to pick another loca-
+               tion;  `,'  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 asking for confirmation.  When picking
+               a location, pressing the ESC key will  terminate  this  com-
+               mand,  or pressing `?'  will give a brief reminder about how
+               it works.
+
+               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.
+
+               Specifying a name rather than a location  always  gives  any
+               additional information available about that name.
+
+               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).
                cause   you  to  fight  monsters;  the  others  (below)  are
                ``safe.''
 
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              11
+
+
+
                                     y  k  u          7  8  9
                                      \ | /            \ | /
                                     h- . -l          4- . -6
 
                                          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)
+               if you remember a monster there).
+
+               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).
+
+               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
+               ``#travel'' command show a menu of  interesting  targets  in
+               sight.
 
           F[yuhjklbn]
-               Prefix:  fight a monster (even if  you  only  guess  one  is
-               there)
+               Prefix:   fight  a  monster  (even  if you only guess one is
+               there).
 
           M[yuhjklbn]
                Prefix:  move far, no pickup.
                Prefix:  move until something interesting is found.
 
           G[yuhjklbn] or <CONTROL->[yuhjklbn]
-               Prefix:   same  as `g', but forking of corridors is not con-
+               Prefix:  same as `g', but forking of corridors is  not  con-
                sidered interesting.
 
           _    Travel to a map location via a shortest-path algorithm.
 
-               The shortest path is computed over map  locations  the  hero
-               knows  about  (e.g. seen or previously traversed).  If there
+               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
+               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-
 
 
-          NetHack 3.6                                      December 7, 2015
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
-          NetHack Guidebook                                              11
+          NetHack Guidebook                                              12
 
 
 
-               position.
+               click takes place on a location other than the current posi-
+               tion.
 
-          .    Rest, do nothing for one turn.
+          .    Wait or rest, do nothing for one turn.
 
           a    Apply (use) a tool (pick-axe, key, lamp...).
 
+               If used on a wand, that wand will be broken,  releasing  its
+               magic in the process.  Confirmation is required.
+
           A    Remove one or more worn items, such as armor.
 
                Use  `T'  (take  off) to take off only one piece of armor or
 
                ``What kinds of things do you want to drop? [!%= BUCXaium]''
 
-               you should type zero or more object  symbols  possibly  fol-
+               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
+               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.
+               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.
 
-          ^D   Kick something (usually a door).
+               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
 
-          e    Eat food.
 
-          E    Engrave a message on the floor.
+          NetHack 3.6                                        April 27, 2018
 
-                    E- - write in the dust with your fingers.
 
 
-          NetHack 3.6                                      December 7, 2015
 
 
+          NetHack Guidebook                                              13
 
 
 
-          NetHack Guidebook                                              12
+               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).
+
+          e    Eat food.
+
+               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.
 
+          E    Engrave a message on the floor.
+
+                    E- - write in the dust with your fingers.
 
                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.
-               (This feature may be compiled out of the game, so your  ver-
-               sion might not have it.)
+               it out); this is often useful to give yourself a breather.
 
           f    Fire  one  of  the  objects placed in your quiver (or quiver
                sack, or that you have at the ready).  You may select  ammu-
                the  character for a particular set of objects, like `[' for
                armor or `!' for potions.
 
-                    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 known;
-                    I$ - count your money.
+               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 known;
+               I$ - count your money.
 
           o    Open a door.
 
           O    Set options.
 
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              14
+
+
+
                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-
                fore the game rather than with the `O' command; see the sec-
                tion on options below.
 
+          ^O   Show overview or show dungeon layout
+
+               In normal play and in  explore  mode,  a  shortcut  for  the
+               ``#overview''  extended  command to list interesting dungeon
+               levels visited.
+
+               In debug mode, an extra command which lists the placement of
+               all special levels.
+
           p    Pay your shopping bill.
 
           P    Put on an accessory (ring, amulet, or blindfold).
 
                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.
+               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.)
 
           ^P   Repeat previous message.
 
+               Subsequent ^P's repeat earlier messages.  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 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.
 
-          NetHack 3.6                                      December 7, 2015
-
+               (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).
 
+               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.
 
-          NetHack Guidebook                                              13
 
 
+          NetHack 3.6                                        April 27, 2018
 
-               Subsequent  ^P's  repeat earlier messages.  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  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.
 
-               (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.
+          NetHack Guidebook                                              15
 
-          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
+               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.)
 
           ^R   Redraw the screen.
 
-          s    Search  for  secret  doors and traps around you.  It usually
+          s    Search for secret doors and traps around  you.   It  usually
                takes several tries to find something.
 
-          S    Save (and suspend) the game.  The game will be restored  au-
+          S    Save  (and suspend) the game.  The game will be restored au-
                tomatically the next time you play.
 
           t    Throw an object or shoot a projectile.
 
           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,
+               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
+               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'
+               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
+               es but will accept an item of armor and attempt to  take  it
                off.)
 
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              14
-
-
-
           ^T   Teleport, if you have the ability.
 
           v    Display version number.
 
                     w- - wield nothing, use your bare hands.
 
-               Some characters can wield two weapons at once; use  the  `X'
+               Some  characters  can wield two weapons at once; use the `X'
                command (or the ``#twoweapon'' extended command) to do so.
 
           W    Wear armor.
 
-               This  command may also be used to put on an accessory (ring,
-               amulet, or blindfold).  The prompt for which inventory  item
+               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-
+               It lists accessories as the inventory choices but  will  ac-
                cept an item of armor and attempt to wear it.)
 
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              16
+
+
+
           x    Exchange your wielded weapon with the item in your alternate
                weapon slot.
 
                The latter is used as your secondary weapon when engaging in
-               two-weapon combat.  Note that if one of these slots is  emp-
+               two-weapon  combat.  Note that if one of these slots is emp-
                ty, the exchange still takes place.
 
           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
+               (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 ``#explore''.)
+               mode", which has now been moved to ``#exploremode''.)
 
           ^X   Display basic information about your character.
 
-               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-
+               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
+               several additional things which don't appear in  the  normal
                status display due to space considerations.
 
           z    Zap a wand.
 
                     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.
+
+          ;    Show what type of thing a visible symbol corresponds to.
 
+          ,    Pick up some things from the floor beneath you.
 
-          NetHack 3.6                                      December 7, 2015
+               May be preceded by `m' to force a selection menu.
 
+          @    Toggle the autopickup option on and off.
 
+          ^    Ask for the type of an adjacent trap you found earlier.
 
+          )    Tell what weapon you are wielding.
 
+          [    Tell what armor you are wearing.
 
-          NetHack Guidebook                                              15
 
 
+          __________
+          (R)UNIX is a registered trademark of The Open Group.
 
-          ^Z   Suspend the game (UNIX(R) versions with job control only).
 
-          :    Look at what is here.
+          NetHack 3.6                                        April 27, 2018
 
-          ;    Show what type of thing a visible symbol corresponds to.
 
-          ,    Pick up some things from the floor beneath you.
 
-               May be preceded by `m' to force a selection menu.
 
-          @    Toggle the autopickup option on and off.
 
-          ^    Ask for the type of a trap you found earlier.
+          NetHack Guidebook                                              17
 
-          )    Tell what weapon you are wielding.
 
-          [    Tell what armor you are wearing.
 
           =    Tell what rings you are wearing.
 
                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
+               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.)
 
 
           !    Escape to a shell.
 
+          #    Perform an extended command.
 
 
-          __________
-          (R)UNIX is a registered trademark of AT&T.
 
+               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.
 
-          NetHack 3.6                                      December 7, 2015
+          #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.
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
-          NetHack Guidebook                                              16
 
 
 
-          #    Perform an extended command.
+          NetHack Guidebook                                              18
 
-               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
-               commands.   What  extended commands are available depends on
-               what features the game was compiled with.
 
-          #adjust
-               Adjust inventory letters (most useful when the fixinv option
-               is ``on'').
 
-               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.   ``#ad-
-               just''  can  also  be used to split a stack of objects; when
-               choosing the item to adjust, enter a count prior to its let-
-               ter.
+               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  as-
+               signed, 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 el-
+               igible.  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  de-
+               ciding whether to merge with the destination stack.
 
           #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.
+               played  by  the  ``#overview'' command.  Autocompletes.  De-
+               fault key is 'M-A', and '^N' if number_pad is on.
+
+          #apply
+               Apply (use) a tool such as a pick-axe, a key, or a lamp. De-
+               fault key is 'a'.
+
+               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'.
+
+          #autopickup
+               Toggle the autopickup -option on/off. Default key is '@'.
+
+          #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'.
+
+          #cast
+               Cast a spell. Default key is 'Z'.
 
           #chat
-               Talk to someone.
+               Talk to someone. Default key is 'M-c'.
+
+          #close
+               Close a door. Default key is 'c'.
+
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              19
+
+
 
           #conduct
-               List voluntary challenges you have maintained.
+               List voluntary challenges  you  have  maintained.   Autocom-
+               pletes.  Default key is 'M-C'.
 
                See the section below entitled ``Conduct'' for details.
 
           #dip
-               Dip an object into something.
+               Dip  an object into something. Autocompletes. Default key is
+               'M-d'.
+
+          #down
+               Go down a staircase. Default key is '>'.
+
+          #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.
+
+          #engrave
+               Engrave writing on the floor. Default key is 'E'.
 
           #enhance
-               Advance or check weapon and spell skills.
+               Advance or check weapon and spell skills. Autocompletes. De-
+               fault key is 'M-e'.
+
+          #exploremode
+               Enter the explore mode.
+
+          #fire
+               Fire ammunition from quiver. Default key is 'f'.
 
           #force
-               Force a lock.
+               Force a lock. Autocompletes. Default key is 'M-f'.
+
+          #glance
+               Show what type of thing a map symbol corresponds to. Default
+               key is ';'.
+
+          #help
+               Show  the  help  menu.  Default  key is '?', and 'h' if num-
+               ber_pad is on.
+
+          #herecmdmenu
+               Show a menu of possible actions in your current location.
+
+          #history
+               Show long version and game history. Default key is 'V'.
+
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              20
+
+
+
+          #inventory
+               Show your inventory. Default key is 'i'.
+
+          #inventtype
+               Inventory specific item types. Default key is 'I'.
 
           #invoke
-               Invoke an object's special powers.
+               Invoke an object's special  powers.  Autocompletes.  Default
+               key is 'M-i'.
 
           #jump
-               Jump to another location.
+               Jump  to  another  location.  Autocompletes.  Default key is
+               'M-j', and 'j' if number_pad is on.
+
+          #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 '`'.
+
+          #levelchange
+               Change your experience level. Autocompletes. Wizard-mode on-
+               ly.
+
+          #lightsources
+               Show mobile light sources. Autocompletes. Wizard-mode only.
+
+          #look
+               Look at what is here, under you. Default key is ':'.
 
           #loot
-               Loot  a  box  or bag on the floor beneath you, or the saddle
-               from a steed standing next to you.
+               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
+               'l' if number_pad is on.
+
+          #monpolycontrol
+               Control monster polymorphs. Autocompletes. Wizard-mode only.
 
           #monster
                Use a monster's special ability (when polymorphed into  mon-
-               ster form).
+               ster form).  Autocompletes. Default key is 'M-m'.
 
+          #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'.
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              17
 
+          NetHack Guidebook                                              21
 
 
-          #name
-               Name  a  monster, an individual object, or a type of object.
-               Same as `C'.
 
           #offer
-               Offer a sacrifice to the gods.
+               Offer a sacrifice to the gods. Autocompletes. Default key is
+               'M-o'.  The `m' prefix skips offering items on the altar.
 
                You'll need to find an altar to have any chance at  success.
                Corpses  of  recently  killed  monsters  are  the  fodder of
                choice.
 
+          #open
+               Open a door. Default key is 'o'.
+
+          #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
                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.
+               ited level will be included regardless of annotations. Auto-
+               completes.  Default keys are '^O', and 'M-O'.
+
+          #panic
+               Test the panic routine. Autocompletes. Wizard-mode only.
+
+          #pay
+               Pay your shopping bill. Default key is 'p'.
+
+          #pickup
+               Pick  up things at the current location. Default key is ','.
+               The `m' prefix forces use of a menu.
+
+          #polyself
+               Polymorph self. Autocompletes. Wizard-mode only.
 
           #pray
-               Pray to the gods for help.
+               Pray to the gods for help. Autocompletes. Default key is 'M-
+               p'.
 
-               Praying too soon after receiving prior help is a  bad  idea.
-               (Hint:  entering  the dungeon alive is treated as having re-
+               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
+               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.
 
+          #prevmsg
+               Show previously displayed  game  messages.  Default  key  is
+               '^P'.
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              22
+
+
+
+          #puton
+               Put on an accessory (ring, amulet, etc). Default key is 'P'.
+
+          #quaff
+               Quaff (drink) something. Default key is 'q'.
+
           #quit
-               Quit the program without saving your game.
+               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.   By  default  a response of 'y' acknowledges that
+               Since using this command by accident would  throw  away  the
+               current  game,  you  are asked to confirm your intent before
+               quitting.  By default a response of  'y'  acknowledges  that
                intent.  You can set the paranoid_confirmation option to re-
-               quire a response of "yes" instead.
+               quire a response of ``yes'' instead.
+
+          #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 '^L' if num-
+               ber_pad is on.
+
+          #remove
+               Remove an accessory (ring, amulet, etc). Default key is 'R'.
 
           #ride
-               Ride (or stop riding) a saddled creature.
+               Ride (or stop riding) a saddled creature. Autocompletes. De-
+               fault key is 'M-R'.
 
           #rub
-               Rub a lamp or a stone.
+               Rub a lamp or a stone. Autocompletes. Default key is 'M-r'.
+
+          #save
+               Save the game. Default key is 'S'.
+
+          #search
+               Search for traps and secret doors around you. Default key is
+               's'.
+
+          #seeall
+               Show all equipment in use. Default key is '*'.
+
+          #seeamulet
+               Show the amulet currently worn. Default key is '"'.
+
+          #seearmor
+               Show the armor currently worn. Default key is '['.
+
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              23
+
+
+
+          #seegold
+               Count your gold. Default key is '$'.
+
+          #seenv
+               Show seen vectors. Autocompletes. Wizard-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 '('.
+
+          #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 '!'.
 
           #sit
-               Sit down.
+               Sit down. Autocompletes. Default key is 'M-s'.
+
+          #stats
+               Show memory statistics. Autocompletes. Wizard-mode only.
+
+          #suspend
+               Suspend the game. Default key is '^Z'.
+
+          #swap
+               Swap wielded and secondary weapons. Default key is 'x'.
+
+          #takeoff
+               Take off one piece of armor. Default key is 'T'.
+
+          #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.
+               Show bare  map  without  displaying  monsters,  objects,  or
+               traps.  Autocompletes.
 
+          #therecmdmenu
+               Show a menu of possible actions in a location next to you.
 
+          #throw
+               Throw something. Default key is 't'.
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              18
+
+          NetHack Guidebook                                              24
+
 
 
+          #timeout
+               Look at the timeout queue. Autocompletes. Wizard-mode only.
 
           #tip
-               Tip over a container (bag or box) to pour out its  contents.
+               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  in-
+               teresting  targets  in sight without asking to move the cur-
+               sor. 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.
 
           #turn
-               Turn undead.
+               Turn undead away. Autocompletes. Default key is 'M-t'.
 
           #twoweapon
-               Toggle two-weapon combat on or off.
+               Toggle two-weapon combat on or off.  Autocompletes.  Default
+               keys are 'X', and 'M-2'.
 
                Note  that  you  must  use suitable weapons for this type of
                combat, or it will be automatically turned off.
 
           #untrap
-               Untrap something (trap, door, or chest).
+               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
+               In  some circumstances it can also be used to rescue trapped
                monsters.
 
+          #up
+               Go up a staircase. Default key is '<'.
+
+          #vanquished
+               List vanquished monsters. Autocompletes. Wizard-mode only.
+
           #version
-               Print compile time options for this version of NetHack.
+               Print compile time options for this version of NetHack.  Au-
+               tocompletes. Default key is 'M-v'.
+
+          #versionshort
+               Show version string. Default key is 'v'.
+
+          #vision
+               Show vision array. Autocompletes. Wizard-mode only.
+
+          #wait
+               Rest one move while doing nothing. Default key is '.', and '
+               ' if rest_on_space is on.
+
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              25
+
+
+
+          #wear
+               Wear a piece of armor. Default key is 'W'.
+
+          #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'.
 
           #wipe
-               Wipe off your face.
+               Wipe off your face. Autocompletes. Default key is 'M-w'.
+
+          #wizdebug_bury
+               Bury  objects  under  and around you. Autocompletes. Wizard-
+               mode only.
+
+          #wizdebug_traveldisplay
+               Toggle travel display. Autocompletes. Wizard-mode only.
+
+          #wizdetect
+               Search a room. Autocompletes. Wizard-mode only. Default  key
+               is '^E'.
+
+          #wizgenesis
+               Create  a  monster. Autocompletes. Wizard-mode only. Default
+               key is '^G'.
+
+          #wizidentify
+               Identify all items in inventory. Autocompletes.  Wizard-mode
+               only.  Default key is '^I'.
+
+          #wizintrinsic
+               Set intrinsic. Autocompletes. Wizard-mode only.
+
+          #wizlevelport
+               Teleport  to another level.  Autocompletes.  Wizard-mode on-
+               ly.  Default key is '^V'.
+
+          #wizmap
+               Map the level. Autocompletes. Wizard-mode only. Default  key
+               is '^F'.
+
+          #wizrumorcheck
+               Verify rumor boundaries. Autocompletes. Wizard-mode only.
+
+          #wizsmell
+               Smell monster. Autocompletes. Wizard-mode only.
+
+          #wizwhere
+               Show locations of special levels. Autocompletes. Wizard-mode
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              26
+
+
+
+               only.
+
+          #wizwish
+               Wish for something. Autocompletes. Wizard-mode only. Default
+               key is '^W'.
+
+          #wmode
+               Show wall modes. Autocompletes. Wizard-mode only.
+
+          #zap
+               Zap a wand. Default key is 'z'.
 
           #?
                Help menu:  get the list of available extended commands.
 
+
+
                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
           set the altmeta option to get this behavior.  On  other  systems,
           if  typing  `Alt'  plus another key transmits a two character se-
           quence consisting of an Escape followed by the other key, you may
-          set  the  altmeta  option  to  have  nethack  combine  them  into
+          set  the  altmeta  option  to  have  NetHack  combine  them  into
           meta+key.
 
           M-?  #? (not supported by all platforms)
 
           M-e  #enhance
 
+          M-f  #force
 
+          M-i  #invoke
 
-          NetHack 3.6                                      December 7, 2015
+          M-j  #jump
 
+          M-l  #loot
 
+          M-m  #monster
 
 
 
-          NetHack Guidebook                                              19
+          NetHack 3.6                                        April 27, 2018
 
 
 
-          M-f  #force
 
-          M-i  #invoke
 
-          M-j  #jump
+          NetHack Guidebook                                              27
 
-          M-l  #loot
 
-          M-m  #monster
 
           M-n  #name
 
 
           M-w  #wipe
 
+
+
                If the number_pad option is on, some additional letter  com-
           mands are available:
 
-          h    Help  menu:   display  one  of several help texts available,
-               like ``?''.
+          h    #help
 
-          j    Jump to another location.  Same as ``#jump'' or ``M-j''.
+          j    #jump
 
-          k    Kick something (usually a door).  Same as `^D'.
+          k    #kick
 
-          l    Loot a box or bag on the floor beneath you,  or  the  saddle
-               from  a  steed  standing  next to you.  Same as ``#loot'' or
-               ``M-l''.
+          l    #loot
 
-          N    Name a monster, an individual object, or a type  of  object.
-               Same  as ``#name'' (or ``M-n'') which is the same as the `C'
-               command.
+          N    #name
 
+          u    #untrap
 
+          5.  Rooms and corridors
 
-          NetHack 3.6                                      December 7, 2015
+               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.
 
+               Secret corridors are hidden.  You can find them with the `s'
+          (search) command.
 
 
 
 
-          NetHack Guidebook                                              20
+          NetHack 3.6                                        April 27, 2018
 
 
 
-          u    Untrap a trap, door, or chest.  Same as ``#untrap'' or  ``M-
-               u''.
 
 
-          5.  Rooms and corridors
+          NetHack Guidebook                                              28
 
-               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.
 
-               Secret corridors are hidden.  You can find them with the `s'
-          (search) command.
 
           5.1.  Doorways
 
           tional  rules  of Sokoban.  Some allowances are permitted in case
           the player gets stuck; however, they will lower your luck.
 
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              21
-
-
-
-          5.3.  Stairs (`<', `>')
+          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 (`>')
           choose  to  do so), you'll need to climb back up to the main dun-
           geon.
 
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              29
+
+
+
                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
           climb.  When that occurs, the pet or other monster will arrive on
           the staircase and you will end up nearby.
 
-          5.4.  Ladders (`<', `>')
-
                Ladders serve the same purpose as staircases,  and  the  two
           types  of  inter-level  connections  are nearly indistinguishable
           during game play.
 
-          5.5.  Shops and shopping
+          5.4.  Shops and shopping
 
                Occasionally you will run across a room  with  a  shopkeeper
           near  the  door  and  many items lying on the floor.  You can buy
           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
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              22
-
-
-
           the shop).
 
                If you drop something in a shop by accident, the  shopkeeper
           dungeon, don't bother trying to use it in shops; shopkeepers will
           not accept it.)
 
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              30
+
+
+
                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-
           any  unpaid  items which have been used up, along with other shop
           fees, if any.
 
-          5.5.1.  Shop idiosyncracies
+          5.4.1.  Shop idiosyncracies
 
                Several aspects of shop behavior might be unexpected.
 
           * The price of a given item can vary due to a variety of factors.
 
-          * A  shopkeeper treats the spot immediately inside the door as if
+          * 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
+          * 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
 
-               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
+               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'', or its synonym `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  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
+          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.
 
-          NetHack 3.6                                      December 7, 2015
 
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
-          NetHack Guidebook                                              23
 
 
 
-               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.
+          NetHack Guidebook                                              31
 
-          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.
 
                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.
+          ``yes'' instead.
 
                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
           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  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.
+
 
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              24
 
+          NetHack Guidebook                                              32
 
 
-          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.
+
+               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.
 
-               Riding skill is managed by the `#enhance' command.  See  the
-          section on Weapon proficiency for more information about that.
+               Use the ``#loot'' command while adjacent to a saddled  crea-
+          ture to try to remove the saddle from that creature.  If success-
+          ful, it will be transferred to your inventory.
 
           6.4.  Bones levels
 
-               You  may encounter the shades and corpses of other adventur-
+               You may encounter the shades and corpses of other  adventur-
           ers (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.
+          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.
 
           7.  Objects
 
           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 de-
-          pends on your strength and your constitution.  The  stronger  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  car-
-          rying  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.
+          of  that  object  to  your  load.   The amount that you can carry
 
-               NetHack  will  tell  you how badly you have loaded yourself.
-          The symbols `Burdened', `Stressed', `Strained',  `Overtaxed'  and
-          `Overloaded' are displayed on the bottom line display to indicate
-          your condition.
 
+          NetHack 3.6                                        April 27, 2018
 
-          NetHack 3.6                                      December 7, 2015
 
 
 
 
+          NetHack Guidebook                                              33
 
-          NetHack Guidebook                                              25
 
 
+          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 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.
+
+               NetHack  will  tell  you how badly you have loaded yourself.
+          The symbols `Burdened', `Stressed', `Strained',  `Overtaxed'  and
+          `Overloaded' are displayed on the bottom line display to indicate
+          your condition.
 
                When you pick up an object, it is assigned an inventory let-
           ter.   Many commands that operate on objects must ask you to find
           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, or its synonym `C', 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.
+          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
 
 
                Objects which are neither cursed nor blessed are referred to
           as  uncursed.   They  could just as easily have been described as
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              34
+
+
+
           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.
                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
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              26
-
-
-
           ``cursed'', ``uncursed'' or ``blessed'' in the description of the
           item.  In some cases ``uncursed'' will be omitted as being redun-
           dant when enough other information  is  displayed.   The  implic-
           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
+          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.
 
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              35
+
+
+
                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
           curs a penalty in the chance to hit your target compared to using
           just one weapon at a time.
 
-
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              27
-
-
-
                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
           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
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              36
+
+
+
           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
           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
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              28
-
-
-
-          others can still continue beyond that spot.
+          in the same direction; if the first ones kill a monster, the oth-
+          ers can still continue beyond that spot.
 
           7.2.2.  Weapon proficiency
 
           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
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              37
+
+
+
           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
           (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
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              29
-
-
-
-          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 designat-
-          ed as alternate weapon.)
+          after  you stop -- or before you begin, for that matter -- wield-
+          ing two weapons at once.  The primary is your wielded weapon  and
+          the  secondary is just an item in your inventory that's been des-
+          ignated 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
           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
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              38
+
+
+
                              plate mail                3
                              crystal plate mail        3
                              bronze plate mail         4
                              chain mail                5
                              orcish chain mail         6
                              scale mail                6
+                             dragon scales             7
                              studded leather armor     7
                              ring mail                 7
                              orcish ring mail          8
-
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              30
-
-
-
                              leather armor             8
                              leather jacket            9
                              no armor                 10
           any ``plusses'' it provides.  Cursed pieces of armor usually have
           negative 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-
+               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
+          The  `A'  command  can  also be used to take off armor as well as
           other worn items.
 
           7.4.  Food (`%')
 
-               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
+               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 usu-
-          ally  stay  fresh, but ice boxes are heavy, and tins take a while
+          ally 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
+          give  you special powers when you eat them.  A good rule of thumb
           is ``you are what you eat.''
 
-               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 name one food item after something you like  to  eat
-          with the fruit option.
 
-               The command to eat food is `e'.
+          NetHack 3.6                                        April 27, 2018
 
-          7.5.  Scrolls (`?')
 
-               Scrolls  are labeled with various titles, probably chosen by
-          ancient wizards for their amusement value (ex.  ``READ  ME,''  or
 
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack Guidebook                                              39
 
 
 
+               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.
 
-          NetHack Guidebook                                              31
+               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 (ex. ``READ ME,'' or
           ``THANX MAUD'' backwards).  Scrolls disappear after you read them
           (except for blank ones, without magic spells on them).
 
-               One of the most useful of these is the scroll  of  identify,
+               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
+          is  cursed  or  blessed, and how many uses it has left.  Some ob-
+          jects 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 NetHack where  mail  is
-          randomly  generated internal to the game, these environment vari-
-          ables are ignored.  You can disable the mail  daemon  by  turning
+          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 NetHack where mail is
+          randomly generated internal to the game, these environment  vari-
+          ables  are  ignored.   You can disable the mail daemon by turning
           off the mail option.
 
                The command to read a scroll is `r'.
 
           7.6.  Potions (`!')
 
-               Potions  are distinguished by the color of the liquid inside
+               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
+               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
+          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 (`/')
 
-               Magic wands usually have  multiple  magical  charges.   Some
-          wands  are directional--you must give 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 wands are nondirectional--they 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
 
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              32
+
+          NetHack Guidebook                                              40
+
 
 
+          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.
 
                In a truly desperate situation, when your back is up against
           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 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,
+               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
+               Putting  on  a  ring activates its magic.  You can wear only
           two rings, one on each ring finger.
 
-               Most  rings  also cause you to grow hungry more rapidly, the
+               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).
           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, and casting several spells in  a  row  may
-          tire  you.  Casting of spells also requires practice.  With prac-
-          tice, your skill in each category of spell casting will  improve.
-          Over  time,  however, your memory of each spell will dim, and you
-          will need to relearn it.
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
-          NetHack 3.6                                      December 7, 2015
-
 
 
 
+          NetHack Guidebook                                              41
 
-          NetHack Guidebook                                              33
 
 
+               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.
 
-               Some spells are directional--you must give  a  direction  in
-          which  to  cast  them.   You can also cast them at yourself (just
-          give a `.' or `s' for the direction).  Be  warned,  however,  for
-          this  is  often  unwise.   Other  spells are nondirectional--they
-          don't require a direction.
+               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.
+
+               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
+          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
+          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
+          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
+          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,
+               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-
+          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-
+          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.
 
                The command to use tools 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  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.
 
-               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.
 
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
-          NetHack 3.6                                      December 7, 2015
 
 
+          NetHack Guidebook                                              42
 
 
 
-          NetHack Guidebook                                              34
+          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 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.
 
+               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 (`"')
 
-               Amulets  are very similar to rings, and often more powerful.
+               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.
 
                Only one amulet may be worn at a time, around your neck.
 
-               The  commands  to use amulets are the same as for rings, `P'
+               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.
+               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
+          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 (``')
 
-               Statues and boulders are not particularly  useful,  and  are
-          generally  heavy.   It  is rumored that some statues are not what
+               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
+               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.
+
+
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              43
+
+
+
           7.14.  Gold (`$')
 
-               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
+               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).
 
+          7.15.  Persistence of Objects
+
+               Normally, if you have seen an object at a particular map lo-
+          cation and move to another location which 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  ex-
+          ception  is  that if the object gets covered by the ``remembered,
+          unseen monster'' marker and 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.
+
+               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 is
+          the top one of a pile.
 
           8.  Conduct
 
           is  unusual  for  players  to adhere to challenges the first time
           they win the game.
 
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              35
-
-
-
                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
           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
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              44
+
+
+
           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
                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
-
+          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.
 
-          NetHack 3.6                                      December 7, 2015
+               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.
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
-          NetHack Guidebook                                              36
 
 
+          NetHack Guidebook                                              45
 
-          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.
 
-               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.
 
                In  NetHack,  a  pacifist  refuses to cause the death of any
           other monster (i.e. if you would get experience for  the  death).
           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  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.
+
+          9.2.  Using a configuration file
 
+               The default name of the configuration file varies on differ-
+          ent operating systems.  On DOS and Windows, it is ``defaults.nh''
+          in the same folder as nethack.exe or nethackW.exe.  On UNIX, Lin-
+          ux, and Mac  OS  X  it  is  ``.nethackrc''  in  the  user's  home
 
 
+          NetHack 3.6                                        April 27, 2018
 
-          NetHack 3.6                                      December 7, 2015
 
 
 
 
+          NetHack Guidebook                                              46
 
-          NetHack Guidebook                                              37
 
 
+          directory.  The file may not exist, but it is a normal ASCII text
+          file and can be created with any text editor.
 
-          9.1.  Setting the options
+               Any line in the configuration  file  starting  with  `#'  is
+          treated as a comment.  Empty lines are ignored.
 
-               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
-          the NETHACKOPTIONS environment variable  or  in  a  configuration
-          file.  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.
+               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  se-
+          lect that section.  Section names are case insensitive.
+
+               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. Here is a list
+          of allowed statements:
 
-          9.2.  Using the NETHACKOPTIONS environment variable
+          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 in a single OPTIONS
+            statement.
 
-               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
+               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  neces-
+            sary or recommended.
+
+          LEVELDIR
+            The  location that in-progress level files are stored. Defaults
+            to HACKDIR, must be writeable.
+
+          SAVEDIR
+            The location where saved games are kept. Defaults  to  HACKDIR,
+            must be writeable.
+
+          BONESDIR
+            The  location  that  bones files are kept. Defaults to HACKDIR,
+            must be writeable.
+
+          LOCKDIR
+            The  location  that  file  synchronization  locks  are  stored.
+            Defaults to HACKDIR, must be writeable.
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              47
+
+
+
+          TROUBLEDIR
+            The  location  that  a record of game aborts and self-diagnosed
+            game problems is kept. Defaults to HACKDIR, must be writeable.
+
+          AUTOCOMPLETE
+            Enable or disable an extended command autocompletion.  Autocom-
+            pletion  has no effect for the X11 windowport.  You can specify
+            multiple autocompletions. To enable  autocompletion,  list  the
+            extended  command. Prefix the command with ``!'' to disable the
+            autocompletion for that command.
+
+               Example:
+
+               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
+
+          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
+
+          MSGTYPE
+            Change  the way messages are shown in the top status line.  See
+            the ``Configuring Message Types`` section.
+
+          MENUCOLOR
+            Highlight menu lines with different colors.  See the  ``Config-
+            uring Menu Colors`` section.
+
+          SYMBOLS
+            Override  one  or  more  symbols in the symbols files.  See the
+            ``Modifying NetHack Symbols'' section.
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              48
+
+
+
+               Example:
+
+               SYMBOLS=S_boulder:0
+
+          WIZKIT
+            Wizard-mode extra items, in a text file containing item  names,
+            one  per  line, up to a maximum of 128 lines. Each line is pro-
+            cessed by the function that handles wishing.
+
+               Example:
+
+               WIZKIT=~/wizkit.txt
+
+          SOUNDDIR
+            Define the directory that contains the sound  files.   See  the
+            ``Configuring User Sounds'' section.
+
+          SOUND
+            Define  a  sound  mapping.  See the ``Configuring User Sounds''
+            section.
+
+               Here is a short example of config file contents:
+
+               # Set your character's role, race, gender, and alignment.
+               OPTIONS=role:Valkyrie, race:Human, gender:female, align:lawful
+               #
+               # Turn on autopickup, and set automatically picked up object types
+               OPTIONS=autopickup,pickup_types:$"=/!?+
+               # Show colored text if possible
+               OPTIONS=color
+               # Show lit corridors differently
+               OPTIONS=lit_corridor
+               #
+               # No startup splash screen. Windows GUI only.
+               OPTIONS=!splash_screen
+
+          9.3.  Using the NETHACKOPTIONS environment variable
+
+               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
+          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.
 
                For example, to set up an environment variable so that ``au-
-          toquiver''  is  on,  ``autopickup''  is  off,  the name is set to
-          ``Blue Meanie'', and the fruit is set to  ``papaya'',  you  would
+          toquiver'' is on, ``autopickup'' is  off,  the  name  is  set  to
+          ``Blue  Meanie'',  and  the fruit is set to ``papaya'', you would
           enter the command
 
                % setenv NETHACKOPTIONS "autoquiver,\!autopickup,name:Blue Meanie,fruit:papaya"
 
-          in  csh  (note the need to escape the ! since it's special to the
-          shell), or
-
-               $ NETHACKOPTIONS="autoquiver,!autopickup,name:Blue Meanie,fruit:papaya"
-               $ export NETHACKOPTIONS
-
-          in sh or ksh.
 
-          9.3.  Using a configuration file
 
-               Any line in the configuration  file  starting  with  `#'  is
-          treated  as a comment.  Any line in the configuration file start-
-          ing with ``OPTIONS='' may be filled out with options in the  same
-          syntax as in NETHACKOPTIONS.  Any line starting with ``SYMBOLS=''
-          is taken as defining the corresponding symbol in a different syn-
-          tax,  a sequence of decimal numbers giving the character position
-          in the current font to be used in displaying each entry.  Such  a
-          sequence  can  be continued to multiple lines by putting a `\' at
-          the end of each line to be continued.
-
-               Any line starting with ``AUTOPICKUP_EXCEPTION='' is taken as
-          defining  an  exception  to  the pickup_types option.  There is a
-          section of this Guidebook that discusses that.
+          NetHack 3.6                                        April 27, 2018
 
-               The default name of the configuration file varies on differ-
-          ent  operating systems, but NETHACKOPTIONS can also be set to the
 
 
-          NetHack 3.6                                      December 7, 2015
 
 
+          NetHack Guidebook                                              49
 
 
 
-          NetHack Guidebook                                              38
+          in csh (note the need to escape the ! since it's special  to  the
+          shell), or
 
+               $ NETHACKOPTIONS="autoquiver,!autopickup,name:Blue Meanie,fruit:papaya"
+               $ export NETHACKOPTIONS
 
+          in sh or ksh.
 
-          full name of a file you want to  use  (possibly  preceded  by  an
-          `@').
+               NETHACKOPTIONS can also be set to the full name of a config-
+          uration file you want to use (possibly preceded by an `@').
 
           9.4.  Customization options
 
                Here are explanations of what the various options do.  Char-
-          acter strings that are too long may be truncated.   Some  of  the
+          acter  strings  that  are too long may be truncated.  Some of the
           options listed may be inactive in your dungeon.
 
-               Some  options  are  persistent,  and  are saved and reloaded
+               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.
 
           acoustics
-            Enable  messages  about what your character hears (default on).
+            Enable messages about what your character hears  (default  on).
             Note that this has nothing to do with your computer's audio ca-
             pabilities.  Persistent.
 
           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 a `!' or ``no'' to  the  value,  you  can  exclude  that
-            alignment  from  being picked randomly.  Cannot be set with the
+            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.
 
+          autodescribe
+            Automatically  describe  the terrain under cursor when asked to
+            get a location on the map.  The  whatis_coord  option  controls
+            whether the description includes map coordinates.
+
           autodig
             Automatically dig if you are wielding a digging tool and moving
             into a place that can be dug (default false). Persistent.
             tent.
 
           autopickup
-            Automatically pick up things onto which you move (default  on).
+            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 with an empty quiver (or  quiver  sack  or  have
-            nothing  at the ready).  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.  Persis-
-            tent. (default false)
+            This option controls what happens  when  you  attempt  the  `f'
+            (fire)  command  with  an  empty quiver (or quiver sack or have
 
-          blind
-            Start the character permanently  blind.   Persistent.  (default
-            false)
 
+          NetHack 3.6                                        April 27, 2018
 
 
-          NetHack 3.6                                      December 7, 2015
 
 
 
+          NetHack Guidebook                                              50
 
 
-          NetHack Guidebook                                              39
 
+            nothing at the ready).  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.   Persis-
+            tent. (default false)
 
+          blind
+            Start  the  character  permanently blind.  Persistent. (default
+            false)
 
           bones
-            Allow  saving  and  loading  bones files.  Persistent. (default
+            Allow saving and loading  bones  files.   Persistent.  (default
             true)
 
           boulder
-            Set the character used to display  boulders  (default  is  rock
-            class symbol).
+            Set  the  character  used  to  display boulders (default is the
+            ``large rock'' class symbol, ``').
 
           catname
             Name your starting cat (ex. ``catname:Morris'').  Cannot be set
             with the `O' command.
 
           character
-            Pick your type of character (ex.  ``character:Monk'');  synonym
-            for ``role''.  See ``name'' for an alternate method of specify-
-            ing your role.  Normally only the first letter of the value  is
-            examined; the string ``random'' is an exception.
+            Synonym  for  ``role''  to pick the type of your character (ex.
+            ``character:Monk'').  See role for more details.
 
           checkpoint
-            Save  game state after each level change, for possible recovery
+            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.
-            Only applies when MFLOPPY was defined during compilation.
+            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.
 
           clicklook
-            Allows  looking at things on the screen by navigating the mouse
+            Allows looking at things on the screen by navigating the  mouse
             over them and clicking the right mouse button (default off).
 
           cmdassist
-            Have the game provide some additional  command  assistance  for
-            new  players  if  it detects some anticipated mistakes (default
+            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
+            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 off).  Persis-
-            tent.
-
-          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:
-
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
-          NetHack 3.6                                      December 7, 2015
 
 
 
+          NetHack Guidebook                                              51
 
 
-          NetHack Guidebook                                              40
 
+          dark_room
+            Show out-of-sight areas of lit rooms  (default  off).   Persis-
+            tent.
 
+          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:
 
                  i - disclose your inventory;
                  a - disclose your attributes;
                  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
+            Each  disclosure  possibility  can  optionally be preceded by a
+            prefix which lets you refine how  it  behaves.   Here  are  the
             valid prefixes:
 
                  y - prompt you and default to yes on the prompt;
                  + - disclose it without prompting;
                  - - do not disclose it and do not prompt.
 
+            The  listing of vanquished monsters can be sorted, so there are
+            two additional choices for `v':
+
+                 ? - prompt you and default to ask on the prompt;
+                 # - disclose it without prompting, ask for sort order.
+
+            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.
+
             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
+            Order  of  the  disclosure  categories does not matter, program
             display for end-of-game disclosure follows a set sequence.
 
-            (ex.  ``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  de-
+            (ex. ``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 de-
             fault to no, and overview to disclose without prompting.
 
-            Note  that  the  vanquished monsters list includes all monsters
+            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.
 
-          dogname
-            Name your starting dog (ex. ``dogname:Fang'').  Cannot  be  set
-            with the `O' command.
 
-          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 only by the tty  port  (default  off),
-            when the game has been compiled to support tty graphics.
 
-          female
-            An  obsolete synonym for ``gender:female''.  Cannot be set with
-            the `O' command.
+          NetHack 3.6                                        April 27, 2018
 
-          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.
 
-          fruit
-            Name  a  fruit  after   something   you   enjoy   eating   (ex.
 
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack Guidebook                                              52
 
 
 
+          dogname
+            Name  your  starting dog (ex. ``dogname:Fang'').  Cannot be set
+            with the `O' command.
 
-          NetHack Guidebook                                              41
+          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 only by the tty port (default off),
+            when the game has been compiled to support tty graphics.
+
+          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 inventory letters.  Persistent.
 
+          force_invmenu
+            Commands  asking for an inventory item show a menu instead of a
+            text query with possible menu letters. Default is off.
 
-            ``fruit:mango'') (default ``slime mold'').  Basically a nostal-
-            gic 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.
+          fruit
+            Name a fruit after something you enjoy eating (ex. ``fruit:man-
+            go'')  (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.
 
           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 ran-
-            domly  pick  an  appropriate  gender.   If  you prefix a `!' or
-            ``no'' to the value, you can exclude  that  gender  from  being
-            picked  randomly.  Cannot be set with the `O' command.  Persis-
-            tent.
+            domly 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.
+
+          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
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              53
+
+
+
             means that you might miss some interesting and/or important in-
             formation.  Persistent.
 
+          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.
+
           hilite_pet
             Visually  distinguish  pets from similar animals (default off).
             The behavior of this option depends on the  type  of  windowing
             inverse video is often used; with tiles, generally  displays  a
             small plus-symbol beside the object on the top of the pile.
 
+          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.
+
           horsename
             Name  your  starting horse (ex. ``horsename:Trigger'').  Cannot
             be set with the `O' command.
             Display an introductory message when starting the game (default
             on).  Persistent.
 
+          lit_corridor
+            Show corridor squares seen by night vision or  a  light  source
+            held by your character as lit (default off).  Persistent.
 
+          lootabc
+            Use  the old `a', `b', and `c' keyboard shortcuts when looting,
+            rather than the mnemonics `o',  `i',  and  `b'  (default  off).
+            Persistent.
 
-
-          NetHack 3.6                                      December 7, 2015
+          mail
+            Enable mail delivery during the game (default on).  Persistent.
 
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
-          NetHack Guidebook                                              42
 
 
 
-          lit_corridor
-            Show  corridor  squares  seen by night vision or a light source
-            held by your character as lit (default off).  Persistent.
+          NetHack Guidebook                                              54
 
-          lootabc
-            Use the old `a', `b', and `c' keyboard shortcuts when  looting,
-            rather  than  the  mnemonics  `o',  `i', and `b' (default off).
-            Persistent.
 
-          mail
-            Enable mail delivery during the game (default on).  Persistent.
 
           male
             An  obsolete  synonym  for ``gender:male''.  Cannot be set with
             Implemented 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.  De-
+            Menu  character  accelerator to deselect all items on this page
+            of a menu.  Implemented by the Amiga, Gem and tty  ports.   De-
             fault '\'.
 
           menu_first_page
             Implemented by the Amiga, Gem and tty ports.  Default '^'.
 
           menu_headings
-            Controls  how  the  headings in a menu are highlighted.  Values
+            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 3.6                                      December 7, 2015
+          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
+            '~'.
 
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
-          NetHack Guidebook                                              43
 
 
 
-            are 'none', 'bold', 'dim', 'underline', 'blink', or  'inverse'.
-            Not all ports can actually display all types.
+          NetHack Guidebook                                              55
 
-          menu_invert_all
-            Menu  character accelerator to invert all items in a menu.  Im-
-            plemented 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.
+            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-
+            Menu character accelerator to goto the next menu page.   Imple-
             mented by the Amiga, Gem and tty ports.  Default '>'.
 
           menu_objsyms
-            Show object symbols in menu headings in menus where the  object
+            Show  object symbols in menu headings in menus where the object
             symbols 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.  (de-
+            fault on)
+
           menu_previous_page
             Menu character accelerator to goto the previous menu page.  Im-
             plemented by the Amiga, Gem and tty ports.  Default '<'.
 
           menu_search
-            Menu character accelerator to search for a menu  item.   Imple-
+            Menu  character  accelerator to search for a menu item.  Imple-
             mented by the Amiga, Gem, X11 and tty ports.  Default ':'.
 
           menu_select_all
-            Menu  character accelerator to select all items in a menu.  Im-
+            Menu character accelerator to select all items in a menu.   Im-
             plemented 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
+            Menu  character accelerator to select all items on this page of
+            a menu.  Implemented by the Amiga, Gem and tty ports.   Default
             ','.
 
           msghistory
-            The number of top line messages to save (and  recall  with  ^P)
+            The  number  of  top line messages to save (and recall with ^P)
             (default 20).  Cannot be set with the `O' command.
 
           msg_window
-            Allows  you  to change the way recalled messages are displayed.
-            (It is currently implemented for tty only.)  The possible  val-
+            Allows you to change the way recalled messages  are  displayed.
+            (It  is currently implemented for tty only.)  The possible val-
             ues are:
 
                  s - single message (default; only choice prior to 3.4.0);
                  f - full window, oldest message first;
                  r - full window reversed, newest message first.
 
+            For backward compatibility, no  value  needs  to  be  specified
+            (which  defaults  to  `full'),  or  it  can  be  negated (which
+            defaults to `single').
+
+          name
+            Set your character's name (defaults to your  user  name).   You
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              44
 
+          NetHack Guidebook                                              56
 
 
-                 For backward compatibility, no value needs to be specified
-                 (which defaults to `full'), or it can  be  negated  (which
-                 defaults to `single').
 
-          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
+            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
+            -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.
 
           news
             0.  (Settings 2 and 4 are for compatibility with MSDOS  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  German keyboards which have the location of the `y'
+            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'
 
           paranoid_confirmation
             A  space  separated list of specific situations where alternate
+            prompting  is  desired.   The  default  is   paranoid_confirma-
+            tion:pray.
 
+            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
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              45
 
+          NetHack Guidebook                                              57
 
 
-            prompting  is  desired.   The  default  is   paranoid_confirma-
-            tion:pray.
 
-            Confirm - for any prompts which are set to require "yes" rather
-                      than 'y', also require "no" to reject instead of  ac-
-                      cepting 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;
-            pray    - require 'y' to confirm an attempt to pray rather than
-                      immediately praying; on by default;
-            wand    - require "yes" rather than 'y' to confirm  breaking  a
-                      wand;
-            Remove  - require selection from inventory for 'R' and 'T' com-
-                      mands even when wearing just one applicable item.
-
-            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  set-
+            quit        - require  ``yes'' rather than 'y' to confirm quit-
+                          ting the game or switching into  non-scoring  ex-
+                          plore 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  at-
+                          tacking a peaceful monster;
+            wand-break  - require ``yes'' rather than 'y' to confirm break-
+                          ing a wand;
+            Were-change - require ``yes'' rather than 'y' to confirm chang-
+                          ing  form  due to lycanthropy when hero has poly-
+                          morph 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.
+            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
+            ``paranoid_confirmation:none''.   To keep it enabled while set-
             ting 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-
+            If  true,  always  display  your current inventory in a window.
+            This only makes sense for windowing system interfaces that  im-
             plement this feature.  Persistent.
 
           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'',
+            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 ig-
-            nored.   For example, ``horse'' will only be honored when play-
+            nored.  For example, ``horse'' will only be honored when  play-
             ing a knight.  Cannot be set with the `O' command.
 
           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.
+            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.
 
           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
+            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.
 
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              46
+
+          NetHack Guidebook                                              58
 
 
 
+          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.
 
           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.
+            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 ob-
+            jects.  A value of 0 means ``no limit'' (always  list  the  ob-
+            jects);  a  value  of  1 effectively means ``never show the ob-
+            jects'' since the pile size will always be at least  that  big;
+            default value is 5.  Persistent.
 
           playmode
-            Values are `normal', `explore', or `debug'.   Allows  selection
-            of  explore  mode  (also known as discovery mode) or debug mode
+            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
+            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-
+            entirely.   Requesting  it when not allowed or not possible re-
             sults 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).   Likewise  for  the `a' (apply) command if it causes the
+            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.
 
           race
-            Selects your race (for example,  ``race:human'').   Default  is
-            random.   If  you  prefix a `!' or ``no'' to the value, you can
-            exclude that race from being picked randomly.   Cannot  be  set
+            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.
 
           rest_on_space
-            Make  the  space  bar a synonym for the `.' (rest) command (de-
+            Make the space bar a synonym for the `.' (#wait)  command  (de-
             fault off).  Persistent.
 
           role
             Pick your type of character (ex. ``role:Samurai''); synonym for
-            ``character''.   See ``name'' for an alternate method of speci-
-            fying 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 a `!'  or  ``no''  to  the
-            value,  you  can  exclude that role from being picked randomly.
-            Persistent.
+            ``character''.  See ``name'' for an alternate method of  speci-
+            fying  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.
 
           roguesymset
-            This option may be used to select one of the named symbol  sets
-            found  within ``symbols'' to alter the symbols displayed on the
+            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.
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
-          NetHack 3.6                                      December 7, 2015
-
 
 
 
-
-          NetHack Guidebook                                              47
+          NetHack Guidebook                                              59
 
 
 
           rlecomp
             When writing out a save file, perform run length compression of
-            the  map.  Not all ports support run length compression. It has
+            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
-            control+direction and so forth, or via the  travel  command  or
+            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:
 
             teleport - update the map after movement has finished;
             crawl    - like walk, but pause briefly after each step.
 
             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
+            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.
 
           safe_pet
-            Prevent  you from (knowingly) attacking your pets (default on).
+            Prevent you from (knowingly) attacking your pets (default  on).
             Persistent.
 
           scores
-            Control what parts of the score list you are shown at  the  end
-            (ex.   ``scores:5  top  scores/4 around my score/own scores'').
-            Only the first letter of each category (`t', `a',  or  `o')  is
+            Control  what  parts of the score list you are shown at the end
+            (ex.  ``scores:5 top scores/4 around  my  score/own  scores'').
+            Only  the  first  letter of each category (`t', `a', or `o') is
             necessary.  Persistent.
 
           showexp
             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
+            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
 
           sortloot
             Controls the sorting behavior of the pickup lists for inventory
-            and  #loot commands and some others.  Persistent.  The possible
+            and #loot commands and some others.  Persistent.  The  possible
             values are:
 
 
 
-          NetHack 3.6                                      December 7, 2015
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
-          NetHack Guidebook                                              48
+          NetHack Guidebook                                              60
 
 
 
             full - always sort the lists;
-            loot - only sort the lists that don't  use  inventory  letters,
+            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 (de-
+            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-
+            hit by an attack to which it is resistant (default  on).   Per-
             sistent.
 
           standout
-            Boldface monsters and ``--More--'' (default off).   Persistent.
+            Boldface monsters and ``--More--'' (default off).  Persistent.
 
           statushilites
-            Enable  coloring of status fields (default off).  See ``Config-
-            uring Status Hilites'' for futher information.
+            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.
+
+          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
           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.
+            screen.  Use ``symset:default'' to explicitly  select  the  de-
+            fault symbols.
 
           time
-            Show the elapsed game time in turns  on  bottom  line  (default
+            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
+            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
             default is on if configured into the program.)  Persistent.
 
           tombstone
 
           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.
-
 
 
+          NetHack 3.6                                        April 27, 2018
 
-          NetHack 3.6                                      December 7, 2015
 
 
 
 
+          NetHack Guidebook                                              61
 
-          NetHack Guidebook                                              49
 
 
+            (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
+            will prevent the game from attempting unintended moves  if  you
             make inadvertent mouse clicks on the map window.  Persistent.
 
           verbose
-            Provide more commentary during the game (default on).   Persis-
+            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 <x,y> (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'.
+
+          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.
+
+            Filtering  can also be changed when getting a location with the
+            ``getpos.filter'' key.
+
+          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)
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              62
+
+
+
+          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
-            Select  which  windowing  system  to  use,  such  as ``tty'' or
-            ``X11'' (default depends on version).  Cannot be set  with  the
+            Select which windowing  system  to  use,  such  as  ``tty''  or
+            ``X11''  (default  depends on version).  Cannot be set with the
             `O' command.
 
           zerocomp
-            When  writing out a save file, perform zero-comp compression of
-            the contents. Not all ports support zero-comp  compression.  It
+            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
+               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
-          config 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  sup-
-          ported  by the window port that you are currently using by check-
-          ing to see if it shows up in the Options list.  Some options  are
-          dynamic  and  can  be specified during the game with the `O' com-
+          truncated.   Not  all  window  ports will adjust for all settings
+          listed here.  You can safely add any of  these  options  to  your
+          config  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 sup-
+          ported by the window port that you are currently using by  check-
+          ing  to see if it shows up in the Options list.  Some options are
+          dynamic and can be specified during the game with  the  `O'  com-
           mand.
 
           align_message
-            Where to align or place the message window (top, bottom,  left,
+            Where  to align or place the message window (top, bottom, left,
             or right)
 
           align_status
-            Where  to  align or place the status window (top, bottom, left,
+            Where to align or place the status window (top,  bottom,  left,
             or right).
 
           ascii_map
-            NetHack should display an ascii character map if it can.
+            If  NetHack can, it should display an ascii character map if it
+            can.
 
           color
-            NetHack should display color if it can for different  monsters,
-            objects, and dungeon features
+            If NetHack can, it should display color if it can for different
+            monsters, objects, and dungeon features.
 
           eight_bit_tty
-            NetHack  should  pass  eight-bit character values (for example,
-            specified with the traps option) straight through to your  ter-
-            minal (default off).
-
+            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                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              50
 
+          NetHack Guidebook                                              63
 
 
-          font_map
-            NetHack  should  use a font by the chosen name for the map win-
-            dow.
 
           font_menu
-            NetHack should use a font by the chosen name for menu  windows.
+            If NetHack can, it should use a font by  the  chosen  name  for
+            menu windows.
 
           font_message
-            NetHack  should  use  a font by the chosen name for the message
-            window.
+            If NetHack can, it should use a font by the chosen name for the
+            message window.
 
           font_status
-            NetHack should use a font by the chosen  name  for  the  status
-            window.
+            If NetHack can, it should use a font by the chosen name for the
+            status window.
 
           font_text
-            NetHack  should use a font by the chosen name for text windows.
+            If  NetHack  can,  it  should use a font by the chosen name for
+            text windows.
 
           font_size_map
-            NetHack should use this size font for the map window.
+            If NetHack can, it should use this size font for the  map  win-
+            dow.
 
           font_size_menu
-            NetHack should use this size font for menu windows.
+            If NetHack can, it should use this size font for menu windows.
 
           font_size_message
-            NetHack should use this size font for the message window.
+            If  NetHack  can,  it should use this size font for the message
+            window.
 
           font_size_status
-            NetHack should use this size font for the status window.
+            If NetHack can, it should use this size  font  for  the  status
+            window.
 
           font_size_text
-            NetHack should use this size font for text windows.
+            If NetHack can, it should use this size font for text windows.
 
           fullscreen
-            NetHack should try and display on the entire screen rather than
-            in a window.
+            If  NetHack can, it should try and display on the entire screen
+            rather than in a window.
 
           large_font
-            NetHack should use a large font.
+            If NetHack can, it should use a large font.
 
           map_mode
-            NetHack should display the map in the manner specified.
+            If NetHack can, it should display the map in the manner  speci-
+            fied.
 
           mouse_support
             Allow use of the mouse for input and travel.
 
           player_selection
-            NetHack  should pop up dialog boxes, or use prompts for charac-
-            ter selection.
+            If  NetHack  can, it should pop up dialog boxes, or use prompts
+            for character selection.
 
           popup_dialog
-            NetHack should pop up dialog boxes for input.
-
+            If NetHack can, it should pop up dialog boxes for input.
 
 
+          NetHack 3.6                                        April 27, 2018
 
-          NetHack 3.6                                      December 7, 2015
 
 
 
 
-
-          NetHack Guidebook                                              51
+          NetHack Guidebook                                              64
 
 
 
           preload_tiles
-            NetHack should preload tiles into memory.  For example, in  the
-            protected  mode  MSDOS  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. (de-
-            fault on).  Cannot be set with the `O' command.
+            If NetHack can, it should preload tiles into memory.  For exam-
+            ple, in the protected mode MSDOS version, control whether tiles
+            get pre-loaded into RAM at the start of the game.  Doing so en-
+            hances  performance of the tile graphics, but uses more memory.
+            (default on).  Cannot be set with the `O' command.
 
           scroll_amount
-            NetHack should scroll the display by this number of cells  when
-            the hero reaches the scroll_margin.
+            If NetHack can, it should scroll the display by this number  of
+            cells when the hero reaches the scroll_margin.
 
           scroll_margin
-            NetHack  should  scroll  the display when the hero or cursor is
-            this number of cells away from the edge of the window.
+            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
-            NetHack 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.
+            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
+            Display  an  onscreen  keyboard.   Handhelds are most likely to
             support this option.
 
           splash_screen
-            NetHack  should display an opening splash screen when it starts
-            up (default yes).
+            If NetHack can, it should display an opening splash screen when
+            it starts up (default yes).
 
           tiled_map
-            NetHack should display a tiled map if it can.
+            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
+            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
+            Specify the preferred height of each tile  in  a  tile  capable
             port.
 
           tile_width
             Use bold black instead of blue for black glyphs (TTY only).
 
           use_inverse
-            NetHack should display inverse when the game specifies it.
+            If  NetHack can, it should display inverse when the game speci-
+            fies it.
 
           vary_msgcount
-            NetHack should display this number of messages at a time in the
-            message window.
+            If NetHack can, it should display this number of messages at  a
+            time in the message window.
 
-          windowcolors
-            NetHack   should   display   windows   with    the    specified
 
 
-          NetHack 3.6                                      December 7, 2015
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
-          NetHack Guidebook                                              52
+          NetHack Guidebook                                              65
 
 
 
+          windowcolors
+            If  NetHack  can,  it should display windows with the specified
             foreground/background colors if it can.
 
           wraptext
-            NetHack  port  should wrap long lines of text if they don't fit
-            in the visible area of the window.
+            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
+               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
+            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.
 
 
           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
+            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
+            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 sec-
-            ond ESC to finish cancelling such a count.  At other prompts  a
-            single ESC suffices.
+            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.
 
           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,
+            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).
 
           flush
           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
 
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              53
+
+          NetHack Guidebook                                              66
 
 
 
-            without it) (default off,  OS/2,  PC,  and  ST  NetHack  only).
-            Note:   DEC  Rainbows hang if this is turned on.  Cannot be set
+          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
             mand.
 
           subkeyvalue
-            (Win32  tty  NetHack  only).  May be used to alter the value of
+            (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-
+            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 config 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
+            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'
+            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
+            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
 
-               Regular  expressions are normally POSIX extended regular ex-
-          pressions. It is possible to compile NetHack without regular  ex-
-          pression  support on a platform where there is no regular expres-
-          sion library. While this is not true of any modern  platform,  if
-          your  NetHack  was built this way, patterns are instead glob pat-
-          terns.
+               Regular expressions are normally POSIX extended regular  ex-
+          pressions.  It is possible to compile NetHack without regular ex-
+          pression support on a platform where there is no regular  expres-
+          sion  library.  While this is not true of any modern platform, if
+          your NetHack was built this way, patterns are instead  glob  pat-
+          terns. This applies to Autopickup exceptions, Message types, Menu
+          colors, and User sounds.
 
-          9.8.  Configuring Autopickup Exceptions
 
-               You can further refine the behavior of the autopickup option
-          beyond what is available through the pickup_types option.
 
-               By  placing autopickup_exception lines in your configuration
-          file, you can define patterns to be  checked  when  the  game  is
 
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              54
+
+          NetHack Guidebook                                              67
+
 
 
+          9.8.  Configuring Autopickup Exceptions
+
+               You can further refine the behavior of the autopickup option
+          beyond what is available through the pickup_types option.
 
+               By  placing autopickup_exception lines in your configuration
+          file, you can define patterns to be  checked  when  the  game  is
           about to autopickup something.
 
           autopickup_exception
           any  corpse from autopickup.  The last example results in the ex-
           clusion of items known to be cursed from autopickup.
 
-          9.9.  Configuring Message Types
+          9.9.  Changing Key Bindings
 
-               You can change the way the messages are shown in the message
-          area, when the message matches a user-defined pattern.
+               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.
 
-               In general, the config file entries to configure the message
-          types look like this: MSGTYPE=type "pattern"
+               For example:
 
-          type         - how the message should be shown;
-          pattern      - the pattern to match.
+               BIND=^X:getpos.autodescribe
+               BIND={:menu_first_page
+               BIND=v:loot
 
-            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.
+          NetHack 3.6                                        April 27, 2018
 
-            Here's an example of message  types  using  NetHack's  internal
-            pattern matching facility:
 
 
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack Guidebook                                              68
 
 
 
+          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 ``<esc>'', ``<enter>'',  and  ``<space>''
+            keys.
 
-          NetHack Guidebook                                              55
+          Menu accelerator keys
+            The  menu  control  or accelerator keys can also be rebound via
+            OPTIONS-lines in the config file. You cannot bind  object  sym-
+            bols 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 com-
+            mands 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'.
+
+          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 '.'.
+
+          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.  De-
+            fault is '#'.
+
+          getpos.all.next
+            When asked for a location, the key to go to next closest inter-
+            esting thing.  Default is 'a'.
+
+          getpos.all.prev
+            When asked for a location, the key to go  to  previous  closest
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              69
+
+
+
+            interesting thing.  Default is 'A'.
+
+          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
+            '?'.
+
+          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 '!'.
+
+          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. Tog-
+            gles between no filtering, in view only, and in the  same  area
+            only.  Default is '"'.
+
+          getpos.pick
+            When  asked for a location, the key to choose the location, and
+            possibly 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 ','.
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              70
+
+
+
+          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 ';'.
+
+          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.  De-
+            fault is '@'.
+
+          getpos.unexplored.next
+            When  asked for a location, the key to go to next closest unex-
+            plored location.  Default is 'x'.
+
+          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'.
 
+          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'.
+
+          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
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              71
+
+
+
+            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'.
+
+          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 config file entries to configure 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.
+
+            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:
 
                  MSGTYPE=stop "You feel hungry."
                  MSGTYPE=hide "You displaced *."
 
-            specifies  that  whenever a message "You feel hungry" is shown,
+            specifies that whenever a message ``You feel hungry'' is shown,
             the user is prompted with more-prompt, and a  message  matching
-            "You displaced <something>." is not shown at all.
+            ``You displaced <something>.'' is not shown at all.
 
             The  order  of the defined MSGTYPE-lines is important; the last
             matching rule is used. Put the general case  first,  exceptions
             below them.
 
-          9.10.  Configuring Menu Colors
+          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
                In  general,  the  config file entries to configure the menu
           color mappings look like this:
 
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              72
+
+
+
                MENUCOLOR="pattern"=color&attribute
 
                  pattern    - the pattern to match;
                  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 under-
+            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
             file,  and  the  last  MENUCOLOR-line  in your config file that
+            matches a menu line will be used for the line.
 
+               Note that if you intend to have one or more color specifica-
+          tions  match  ``  uncursed '', you will probably want to turn the
+          implicit_uncursed option off so that all items known  to  be  un-
+          cursed are actually displayed with the ``uncursed'' description.
 
-          NetHack 3.6                                      December 7, 2015
-
-
-
+          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.
 
-          NetHack Guidebook                                              56
+               The following config file entries are  relevant  to  mapping
+          user sounds to messages:
 
+          SOUNDDIR
+            The directory that houses the sound files to be played.
 
 
-            matches a menu line will be used for the line.
 
-               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.
+          NetHack 3.6                                        April 27, 2018
 
-          9.11.  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 config file entries are  relevant  to  mapping
-          user sounds to messages:
 
-          SOUNDDIR
-            The directory that houses the sound files to be played.
+
+          NetHack Guidebook                                              73
+
+
 
           SOUND
             An  entry  that  maps  a sound file to a user-specified message
 
             The pattern should be a POSIX extended regular expression.
 
-          9.12.  Configuring Status Hilites
+          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
+          ``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.
 
-               For example, the following line in  your  config  file  will
-          cause  the  hitpoints  field  to display in the color red if your
+               The format for defining status colors is:
+
+               OPTION=hilite_status: field-name/behavior/color&attributes
+
+               For  example,  the  following  line in your config file will
+          cause the hitpoints field to display in the  color  red  if  your
           hitpoints drop to or below a threshold of 30%:
 
-               OPTION=hilite_status: hitpoints/30%/red/normal
+               OPTION=hilite_status: hitpoints/<30%/red/normal
 
-               For another example, the following line in your config  file
+               For  another example, the following line in your config file
           will cause wisdom to be displayed red if it drops and green if it
           rises.
 
-               OPTION=hilite_status: wisdom/updown/red/green
+               OPTION=hilite_status: wisdom/down/red/up/green
 
                You can adjust the display of the following status fields:
+                      title             strength         dexterity
+                  constitution        intelligence        wisdom
+                    charisma           alignment           score
+                carrying-capacity         gold             power
+                    power-max       experience-level    armor-class
+                       HD                 time            hunger
+                    hitpoints        hitpoints-max     dungeon-level
+                   experience          condition
 
+            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,
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              57
 
+          NetHack Guidebook                                              74
 
 
-                      title             strength         dexterity
-                  constitution        intelligence        wisdom
-                    charisma           alignment           score
-                carrying-capacity         gold             power
-                    power-max       experience-level    armor-class
-                       HD                 time            hunger
-                    hitpoints        hitpoints-max     dungeon-level
-                   experience          condition
+
+            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.
+
+            Allowed behaviors are "always", "up", "down", "changed", a per-
+            centage  or  absolute  number  threshold,  or  a  text to match
+            against.
+
+               * "always" will set the default attributes for that field.
+
+               * "up" and "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 val-
+                 ue  changes.  This attribute times out after statushilites
+                 turns.
+
+               * percentage sets the field attribute when the  field  value
+                 matches the percentage. If the percentage is prefixed with
+                 '<' or '>', it also matches when value is below  or  above
+                 the  percentage.   Only  valid for `power' and `hitpoints'
+                 fields.
+
+               * absolute value sets the attribute  when  the  field  value
+                 matches that number. If the number is prefixed with '<' or
+                 '>', it also matches when value is below or above.
+
+               * text match sets the attribute when the field value matches
+                 the  text.  Text matches can only be used for `alignment',
+                 `carrying-capacity', and `dungeon-level'.
 
             Allowed colors are black, red,  green,  brown,  blue,  magenta,
             cyan,  gray, orange, lightgreen, yellow, lightblue, lightmagen-
             ta, lightcyan, and white.
 
-            Allowed attributes are bold, inverse, normal.   Note  that  the
-            platform used may interpret the attributes any way it wants.
+            Allowed attributes are bold, inverse,  underline,  blink,  dim,
+            and  normal.  Note that the platform used may interpret the at-
+            tributes any way it wants.
+
+            The in-game options menu can help  you  determine  the  correct
+            syntax for a config file.
+
+            The  whole feature  can  be  disabled  by  setting  option sta-
+            tushilites to 0.
+
+            Example hilites:
+
+
+
+
+
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
 
-            Behaviours can occur based on percentage thresholds, updown, or
-            absolute values.  The in-game options menu can help you  deter-
-            mine the correct syntax for a config file.
 
-            The  whole  feature  can  be  disabled  by  setting option sta-
-            tushilites off.
 
-          9.13.  Modifying NetHack Symbols
+          NetHack Guidebook                                              75
+
+
+
+                 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.
 
           config  file  option.  Symbols are specified as name:value pairs.
           Note that NetHack escape-processes the value  string  in  conven-
           tional C fashion.  This means that \ is a prefix to take the fol-
-          lowing character literally. Thus \ needs to be represented as \\.
-          The special escape 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.
+          lowing 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
+                                  NetHack Symbols
           Default Symbol Name            Description
           ------------------------------------------------------------------------
                   S_air                  (air)
              _    S_altar                (altar)
              "    S_amulet               (amulet)
              A    S_angel                (angelic being)
-
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              58
-
-
-
              a    S_ant                  (ant or other insect)
              ^    S_anti_magic_trap      (anti-magic field)
              [    S_armor                (suit or piece of armor)
              -    S_blcorn               (bottom left corner)
              b    S_blob                 (blob)
              +    S_book                 (spellbook)
+
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              76
+
+
+
              )    S_boomleft             (boomerang open left)
              (    S_boomright            (boomerang open right)
              `    S_boulder              (boulder)
              $    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)
              E    S_elemental            (elemental)
              /    S_explode1             (explosion top left)
              -    S_explode2             (explosion top center)
-            `\'   S_explode3             (explosion top right)
+             \    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_explode7             (explosion bottom left)
              -    S_explode8             (explosion bottom center)
              /    S_explode9             (explosion bottom right)
              e    S_eye                  (eye or sphere)
                   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                                      December 7, 2015
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
-          NetHack Guidebook                                              59
+          NetHack Guidebook                                              77
 
 
 
-             '    S_golem                (golem)
-             |    S_grave                (grave)
-             g    S_gremlin              (gremlin)
-             -    S_hbeam                (wall)
-             #    S_hcdbridge            (horizontal raised drawbridge)
-             +    S_hcdoor               (closed door)
-             |    S_hodoor               (open door)
-             ^    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)
              y    S_light                (light)
              #    S_litcorr              (lit corridor)
              :    S_lizard               (lizard)
-            `\'   S_lslant               (wall)
+             \    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 witout door)
              n    S_nymph                (nymph)
              O    S_ogre                 (ogre)
              o    S_orc                  (orc)
              `    S_rock                 (boulder or statue)
              r    S_rodent               (rodent)
              ^    S_rolling_boulder_trap (rolling boulder trap)
-             /    S_rslant               (wall)
+             .    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                                      December 7, 2015
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
-          NetHack Guidebook                                              60
+          NetHack Guidebook                                              78
 
 
 
-             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                (dark part of a room)
+             ]    S_strange_obj          (strange object)
              -    S_sw_bc                (swallow bottom center)
-            `\'   S_sw_bl                (swallow bottom left)
+             \    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_sw_tr                (swallow top right)
              -    S_tdwall               (wall)
              ^    S_teleportation_trap   (teleportation trap)
-                  S_throne               (opulent throne)
+             \    S_throne               (opulent throne)
              -    S_tlcorn               (top left corner)
              |    S_tlwall               (wall)
              (    S_tool                 (useful item (pick-axe key lamp...))
              <    S_upladder             (ladder up)
              <    S_upstair              (staircase up)
              V    S_vampire              (vampire)
-             |    S_vbeam                (wall)
+             |    S_vbeam                (vertical beam [zap animation])
              #    S_vcdbridge            (vertical raised drawbridge)
-             +    S_vcdoor               (closed door)
+             +    S_vcdoor               (closed door in vertical wall)
+             .    S_venom                (splash of venom)
              ^    S_vibrating_square     (vibrating square)
-             -    S_vodoor               (open door)
+             .    S_vodbridge            (vertical lowered drawbridge)
+             -    S_vodoor               (open door in vertical wall)
              v    S_vortex               (vortex)
              |    S_vwall                (vertical wall)
              /    S_wand                 (wand)
              x    S_xan                  (xan or other mythical/fantastic insect)
              X    S_xorn                 (xorn)
              Y    S_yeti                 (apelike creature)
+             Z    S_zombie               (zombie)
+             z    S_zruty                (zruty)
 
 
 
-          NetHack 3.6                                      December 7, 2015
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
-          NetHack Guidebook                                              61
 
+          NetHack Guidebook                                              79
 
 
-             Z    S_zombie               (zombie)
-             z    S_zruty                (zruty)
 
-          9.14.  Configuring NetHack for Play by the Blind
+               There  is  one  additional  class  of  object,  described as
+          ``strange object'', which will occasionally be the shape taken on
+          by mimics and shown as `]' for maps displayed as text characters.
+          Although the displayed character is the same as the default value
+          for  `S_mimic_def', it is a different symbol and there is no cor-
+          responding `S_strange_object' symbol nor any way to assign an al-
+          ternate value for it.
+
+          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
           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.
+
                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
 
           roguesymset:NHAccess
             Load a symbol set for the rogue level that is  appropriate  for
+
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              80
+
+
+
             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.
 
-          9.15.  Global Configuration for System Administrators
-
-               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
-
-
-          NetHack 3.6                                      December 7, 2015
-
+          autodescribe
+            Automatically  describe  the terrain under the cursor when tar-
+            geting.
 
+          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
+            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 Guidebook                                              62
+          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.
 
+          9.16.  Global Configuration for System Administrators
 
+               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).
 
-            WIZARDS A space-separated list of user names who are allowed to
-            play  in  wizard  mode (the debugging mode, not the magic-using
+            WIZARDS = A space-separated list of user names who are  allowed
+            to play in wizard mode (the debugging mode, not the magic-using
             role).  A value of a single asterisk (*) allows anyone to start
             a game in wizard mode.
 
-            SHELLERS  A  list of users who are allowed to use the shell es-
+
+          NetHack 3.6                                        April 27, 2018
+
+
+
+
+
+          NetHack Guidebook                                              81
+
+
+
+            SHELLERS = A list of users who are allowed to use the shell es-
             cape command (!).  The syntax is the same as WIZARDS.
 
-            EXPLORERS A list of users who are allowed to  use  the  explore
+            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-
+            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-
+            SUPPORT = A string explaining how to get local support (no  de-
             fault value).
 
-            RECOVER  A string explaining how to recover a game on this sys-
-            tem (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 (see the source for details on this function).
+            SEDUCE = 0 or 1 to disable or enable, respectively, the  SEDUCE
+            option.  When disabled, incubi and succubi behave like nymphs.
 
-            CHECK_SAVE_UID  0  or 1 to disable or enable, respectively, the
-            UID checking for savefiles.
+            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:
 
-            PERSMAX Maximum number of entries for one person.
+            PERSMAX Maximum number of entries for one person.
 
-            ENTRYMAX Maximum number of entries in the score file.
+            ENTRYMAX Maximum number of entries in the score file.
 
-            POINTSMIN Minimum number of points to get an entry 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, re-
+            PERS_IS_UID = 0  or 1 to use user names or numeric userids, re-
             spectively, 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).
+            MAX_STATUENAME_RANK = Maximum number of score file  entries  to
+            use for random statue names (default is 10).
 
-          10.  Scoring
+            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:
 
-               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
+            %% - literal '%'
+            %v - version (eg. "3.6.1-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
 
 
-          NetHack 3.6                                      December 7, 2015
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
-          NetHack Guidebook                                              63
+          NetHack Guidebook                                              82
+
+
 
+            %n - player name
+            %N - first character of player name
 
+          10.  Scoring
 
-          proper place under your current name.  How many scores  are  kept
+               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
+               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
+          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
+          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
+               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
+               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''
+          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
+          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
+               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
+          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.  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  ex-
-          pected  to  figure out how to use it themselves.  It is initiated
-          by starting the game with the -D command-line switch or with  the
+          from  this  brief  description.  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 ex-
+          pected 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).   And  on  any system, the program might have been
-          configured to omit debug mode entirely.  Attempting  to  start  a
-          game  in debug mode when not allowed or not available will result
-          in falling back to explore mode instead.
 
+          NetHack 3.6                                        April 27, 2018
 
-          NetHack 3.6                                      December 7, 2015
 
 
 
 
+          NetHack Guidebook                                              83
 
-          NetHack Guidebook                                              64
 
 
+               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).  And on any system, the  program  might  have  been
+          configured  to  omit  debug mode entirely.  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
+               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
+          Main events in the course of the game development  are  described
           below:
 
-
-               Jay Fenlason wrote the original Hack, with help  from  Kenny
+               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
+          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.
 
-               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-
+               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
+               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.
+          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
                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 development team which now included Ken Ar-
-          romdee, David Cohrs, Jean-Christophe Collet,  Kevin  Darcy,  Matt
-          Day,  Timo Hakulinen, Steve Linhart, Dean Luick, Pat Rankin, Eric
 
+          NetHack 3.6                                        April 27, 2018
 
-          NetHack 3.6                                      December 7, 2015
 
 
 
 
+          NetHack Guidebook                                              84
 
-          NetHack Guidebook                                              65
 
 
+          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 development team which now included Ken Ar-
+          romdee, 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
           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
 
 
-          NetHack 3.6                                      December 7, 2015
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
-          NetHack Guidebook                                              66
+          NetHack Guidebook                                              85
+
 
 
+               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.
 
 
                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
 
+          NetHack 3.6                                        April 27, 2018
 
-          NetHack 3.6                                      December 7, 2015
 
 
 
 
+          NetHack Guidebook                                              86
 
-          NetHack Guidebook                                              67
 
 
+               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.
 
-          Windows CE port for 3.4.1.
+               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
           Tung  Nguyen.  Some  of  those variants continue to be developed,
           maintained, and enjoyed by the community to this day.
 
-               At the beginning of development for  what  would  eventually
-          get  released as 3.6.0, the development team consisted of Warwick
-          Allison, Michael Allison, Ken Arromdee, David Cohrs, Jessie  Col-
-          let,  Ken  Lorber, Dean Luick, Pat Rankin, Mike Stephenson, Janet
-          Walz, and Paul Winner.  Leading up to the  release  of  3.6.0  in
-          early  2015,  new  members Sean Hunt, Pasi Kallinen, and Derek S.
-          Ray joined the NetHack development team.
-
                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
           fect,  stating  that  there would never be a 3.4.4, 3.5, or 3.5.0
           official release version.
 
-               In November 2014,  preparation  began  for  the  release  of
-          NetHack  3.6. The 3.6 version merges work done by the development
-          team since the previous release with some of the beloved communi-
-          ty  patches.  Many bugs were fixed and a large amount of code was
-          restructured.
-
-               The development team, as well as Steve VanDevender and Kevin
-          Smolkowski  ensured  that  NetHack  3.6.0 continued to operate on
-          various Unix flavors and maintained the X11 interface.
-
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              68
-
-
-
-               Ken Lorber, Haoyang Wang, Pat Rankin, and Dean  Luick  main-
-          tained the port of NetHack 3.6.0 for Mac.
-
-               Michael  Allison,  Derek S. Ray, Yitzhak Sapir, Alex Kompel,
-          and Dion Nicolaas maintained the port of NetHack  3.6.0  for  Mi-
-          crosoft Windows.
-
-               The official NetHack web site is maintained by Ken Lorber at
-          http://www.nethack.org/.
-
-               SHOUT-OUTS
-
-               The devteam would like to  give  a  special  "shout-out"  to
-          thank  the  generous  people primarily responsible for the public
-          NetHack servers available for playing the game at nethack.alt.org
-          and devnull.net. In addition to providing a way for the public to
-          play a game of NetHack from almost anywhere, they have hosted an-
-          nual NetHack tournaments for many, many years.
-
-               On  behalf  of the NetHack community, thank you very much to
-          M. Drew Streib, Pasi Kallinen and Robin Bandy.
-
-                    - - - - - - - - - -
-
-               From time to time, some depraved  individual  out  there  in
-          netland  sends a particularly intriguing modification to help out
-          with the game.  The Gods of the Dungeon sometimes  make  note  of
-          the  names  of the worst of these miscreants in this, the list of
-          Dungeoneers:
-
-               Adam Aronow              Janet Walz            Nathan Eady
-               Alex Kompel           Janne Salmijarvi         Norm Meluch
-              Andreas Dorn        Jean-Christophe Collet      Olaf Seibert
-               Andy Church             Jeff Bailey           Pasi Kallinen
-              Andy Swanson            Jochen Erwied            Pat Rankin
-              Ari Huttunen             John Kallen            Paul Winner
-              Barton House             John Rupley          Pierre Martineau
-           Benson I. Margulies         John S. Bien            Ralf Brown
-                Bill Dyer               Johnny Lee             Ray Chason
-            Boudewijn Waijers           Jon W{tte           Richard Addison
-                Bruce Cox            Jonathan Handler        Richard Beigel
-             Bruce Holloway          Joshua Delahunty      Richard P. Hughey
-             Bruce Mewborne           Keizo Yamamoto           Rob Menke
-              Carl Schelin              Ken Arnold            Robin Bandy
-               Chris Russo             Ken Arromdee          Robin Johnson
-               David Cohrs              Ken Lorber         Roderick Schertler
-             David Damerell           Ken Washikita          Roland McGrath
-              David Gentzel            Kevin Darcy          Ron Van Iwaarden
-             David Hairston             Kevin Hugo           Ronnen Miller
-               Dean Luick              Kevin Sitze             Ross Brown
-                Del Lamb             Kevin Smolkowski       Sascha Wostmann
-              Derek S. Ray             Kevin Sweet            Scott Bigham
-              Deron Meranda            Lars Huttar          Scott R. Turner
-
-
-
-          NetHack 3.6                                      December 7, 2015
-
-
-
-
-
-          NetHack Guidebook                                              69
-
-
-
-              Dion Nicolaas            Leon Arnott             Sean Hunt
-             Dylan O'Donnell          M. Drew Streib        Stephen Spackman
-               Eric Backus             Malcolm Ryan        Stefan Thielscher
-            Eric Hendrickson          Mark Gooderum          Stephen White
-              Eric R. Smith            Mark Modrall           Steve Creps
-             Eric S. Raymond         Marvin Bressler         Steve Linhart
-              Erik Andersen            Matthew Day         Steve VanDevender
-            Frederick Roeber           Merlyn LeRoy           Teemu Suikki
-               Gil Neiger            Michael Allison           Tim Lennan
-               Greg Laskin             Michael Feir          Timo Hakulinen
-               Greg Olson             Michael Hamel             Tom Almy
-             Gregg Wonderly          Michael Sokolov            Tom West
-              Hao-yang Wang            Mike Engber           Warren Cheung
-              Helge Hafting            Mike Gallop          Warwick Allison
-          Irina Rempt-Drijfhout      Mike Passaretti         Yitzhak Sapir
-              Izchak Miller          Mike Stephenson
-              J. Ali Harlow            Mikko Juola
-
-          Brand and product names are trademarks or  registered  trademarks
-          of their respective holders.
-
+               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 development team consisted of  Warwick
+          Allison,  Michael Allison, Ken Arromdee, David Cohrs, Jessie Col-
+          let, Ken Lorber, Dean Luick, Pat Rankin, Mike  Stephenson,  Janet
+          Walz,  and  Paul  Winner.  In early 2015, ahead of the release of
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
+          NetHack Guidebook                                              87
 
 
 
+          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.
 
+               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 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.
 
+               The development team, as well as Steve VanDevender and Kevin
+          Smolkowski, ensured that NetHack 3.6 continued to operate on var-
+          ious 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, Barton House,  Pasi  Kallinen,
+          Alex  Kompel, Dion Nicolaas, Derek S. Ray and Yitzhak Sapir main-
+          tained the port of NetHack 3.6 for Microsoft Windows.
 
+               Pat Rankin attempted  to  keep  the  VMS  port  running  for
+          NetHack  3.6.1,  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.
 
+               Ray Chason resurrected the msdos port for 3.6.1 and contrib-
+          uted the necessary updates to the community at large.
 
+               The official NetHack web site is maintained by Ken Lorber at
+          http://www.nethack.org/.
 
+          12.1.  SPECIAL THANKS
 
+               On behalf of the NetHack community, thank you very much once
+          again  to  M. Drew Streib, Pasi Kallinen and Robin Bandy for pro-
+          viding public NetHack servers at nethack.alt.org and  devnull.net
+          and/or for hosting annual NetHack tournaments.
 
+                                 - - - - - - - - - -
 
 
 
 
+          NetHack 3.6                                        April 27, 2018
 
 
 
 
 
+          NetHack Guidebook                                              88
 
 
 
-          NetHack 3.6                                      December 7, 2015
+               From  time  to  time,  some depraved individual out there in
+          netland sends a particularly intriguing modification to help  out
+          with  the  game.   The Gods of the Dungeon sometimes make 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
+              Ari Huttunen             John Kallen           Patric Mueller
+              Barton House             John Rupley            Paul Winner
+           Benson I. Margulies         John S. Bien         Pierre Martineau
+                Bill Dyer               Johnny Lee             Ralf Brown
+            Boudewijn Waijers           Jon W{tte              Ray Chason
+                Bruce Cox            Jonathan Handler       Richard Addison
+             Bruce Holloway          Joshua Delahunty        Richard Beigel
+             Bruce Mewborne           Keizo Yamamoto       Richard P. Hughey
+              Carl Schelin              Ken Arnold             Rob Menke
+               Chris Russo             Ken Arromdee           Robin Bandy
+               David Cohrs              Ken Lorber           Robin Johnson
+             David Damerell           Ken Washikita        Roderick Schertler
+              David Gentzel            Kevin Darcy           Roland McGrath
+             David Hairston             Kevin Hugo          Ron Van Iwaarden
+               Dean Luick              Kevin Sitze           Ronnen Miller
+                Del Lamb             Kevin Smolkowski          Ross Brown
+              Derek S. Ray             Kevin Sweet          Sascha Wostmann
+              Deron Meranda            Lars Huttar            Scott Bigham
+              Dion Nicolaas            Leon Arnott          Scott R. Turner
+             Dylan O'Donnell          M. Drew Streib           Sean Hunt
+               Eric Backus             Malcolm Ryan         Stephen Spackman
+            Eric Hendrickson          Mark Gooderum        Stefan Thielscher
+              Eric R. Smith            Mark Modrall          Stephen White
+             Eric S. Raymond         Marvin Bressler          Steve Creps
+              Erik Andersen            Matthew Day           Steve Linhart
+            Frederick Roeber           Merlyn LeRoy        Steve VanDevender
+               Gil Neiger            Michael Allison          Teemu Suikki
+               Greg Laskin             Michael Feir            Tim Lennan
+               Greg Olson             Michael Hamel          Timo Hakulinen
+             Gregg Wonderly          Michael Sokolov            Tom Almy
+              Hao-yang Wang            Mike Engber              Tom West
+              Helge Hafting            Mike Gallop           Warren Cheung
+          Irina Rempt-Drijfhout      Mike Passaretti        Warwick Allison
+              Izchak Miller          Mike Stephenson         Yitzhak Sapir
+
+               Brand  and product names are trademarks or registered trade-
+          marks of their respective holders.
+
+
+
+
+
+
+
+
+          NetHack 3.6                                        April 27, 2018
 
 
 
diff --git a/doc/config.nh b/doc/config.nh
new file mode 100644 (file)
index 0000000..4ceeca6
--- /dev/null
@@ -0,0 +1,530 @@
+# NetHack 3.6  config.nh       $NHDT-Date: 1524689547 2018/04/25 20:52:27 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
+# Copyright (c) 2016 by Pasi Kallinen
+# NetHack may be freely redistributed.  See license for details.
+# Sample config file for NetHack 3.6
+#
+# A '#' at the beginning of a line means the rest of the line is a comment.
+#
+# Some options must be set in this file, other options can be toggled while
+# playing.
+#
+# Copy the contents of this file into
+# * defaults.nh, same folder as nethack.exe or nethackW.exe (DOS, Windows)
+# * ~/.nethackrc (Unix, linux, Mac OS X)
+# * "NetHack Defaults" on pre-OSX Mac and BeOS
+# * NetHack.cnf on Amiga, Atari, OS/2, and VMS
+#
+# To change the configuration, comment out the unwanted lines, and
+# uncomment the configuration you want.
+#
+# There are two types of options, boolean and compound options.
+# Boolean 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.
+#
+# For more information about the options, see the Guidebook.
+
+
+# Set your character's name.
+#OPTIONS=name:Janet
+
+# Set your character's role, race, gender, and alignment
+#OPTIONS=role:Valkyrie, race:Human, gender:female, align:lawful
+
+# Set the default dog, cat, and horse names, and your fruit
+#OPTIONS=dogname:Fido
+#OPTIONS=catname:Morris
+#OPTIONS=horsename:Silver
+#OPTIONS=fruit:guava
+
+# Turn on autopickup, and set object types which are picked up automatically
+# Both are persistent.
+#OPTIONS=autopickup,pickup_types:$"=/!?+
+# Automatically pick up items you threw. Persistent.
+#OPTIONS=pickup_thrown
+# 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. Persistent.
+#OPTIONS=pickup_burden:u
+
+
+# Enable messages about what your character hears
+#OPTIONS=acoustics
+
+# Causes NetHack's top level command loop to treat two character sequence
+# "ESC c" as M-c, for terminals or emulators which send "ESC c" when Alt+c
+# is pressed.
+#OPTIONS=altmeta
+
+# NetHack should display an ascii character map if it can.
+#OPTIONS=ascii_map
+
+# Automatically describe the terrain under cursor when asked to
+# get a location on the map.
+#OPTIONS=autodescribe
+
+# Automatically dig if walking into a wall and you're wielding a digging
+# implement or can otherwise dig through the wall.
+#OPTIONS=autodig
+
+# Automatically try to open doors when walking into them
+#OPTIONS=autoopen
+
+# Let NetHack fill your quiver or make ready some suitable weapon,
+# when firing with empty quiver or nothing at the ready.
+#OPTIONS=autoquiver
+
+# Conduct/Role-playing: blind from birth or "zen"
+#OPTIONS=blind
+# Conduct/Role-playing: starts with no worn armor.
+# Wearing any armor will make you lose this conduct
+#OPTIONS=nudist
+
+# Disable loading and saving of bones files
+#OPTIONS=!bones
+
+# Save game state after each level change, for possible recovery
+# after program crash
+#OPTIONS=checkpoint
+
+# Allows looking at things on the screen by navigating the mouse
+# over them and clicking the right mouse button
+#OPTIONS=clicklook
+
+# Show assistance when you mistype a command
+#OPTIONS=cmdassist
+
+# Display color if possible for different monsters, objects,
+# and dungeon features
+#OPTIONS=color
+
+# Have user confirm attacks on pets, shopkeepers, and other
+# peaceable creatures (default on).
+#OPTIONS=confirm
+
+# Highlight out-of-sight room floors with different color or glyph
+#OPTIONS=dark_room
+
+# Controls what information the program reveals when the game ends.
+#OPTIONS=disclose:+i +a +v +g +c +o
+
+# NetHack should pass eight-bit character values straight through
+# to your terminal (default off).
+#OPTIONS=eight_bit_tty
+
+# Change the extended commands interface to pop-up a menu of
+# available commands.
+#OPTIONS=extmenu
+
+# Objects will try to keep their inventory letters
+#OPTIONS=fixinv
+
+# Try and display on the entire screen rather than in a window.
+#OPTIONS=fullscreen
+
+# If more information is available for an object looked at with
+# the '/' command, ask if you want to see it (default on).
+#OPTIONS=help
+
+# Hilight pets with a heart symbol (Windows, X11), or inverse attribute (TTY)
+#OPTIONS=hilite_pet
+
+# Visually distinguish piles of objects from individual objects
+#OPTIONS=hilite_pile
+
+# Always show the "uncursed" for inventory objects. Useful for MENUCOLORs
+#OPTIONS=implicit_uncursed
+
+# Do not show the legacy intro text at game start
+#OPTIONS=!legacy
+
+# Show lit corridors differently
+#OPTIONS=lit_corridor
+
+# Use the old 'a', 'b', and 'c' keyboard shortcuts when looting,
+# rather than the mnemonics 'o', 'i', and 'b' (default off).
+#OPTIONS=lootabc
+
+# Don't deliver email in-game
+#OPTIONS=!mail
+
+# Mention in the message line when walking at a wall. Useful for blind players.
+#OPTIONS=mention_walls
+
+# How menus are shown. Values are 'traditional', 'combination',
+# 'full', or 'partial'
+#OPTIONS=menustyle:full
+
+# Set menu accelerator keys
+#OPTIONS=menu_deselect_all:-
+#OPTIONS=menu_deselect_page:\
+#OPTIONS=menu_first_page:^
+#OPTIONS=menu_invert_all:@
+#OPTIONS=menu_invert_page:~
+#OPTIONS=menu_last_page:|
+#OPTIONS=menu_next_page:>
+#OPTIONS=menu_previous_page:<
+#OPTIONS=menu_search::
+#OPTIONS=menu_select_all:.
+#OPTIONS=menu_select_page:,
+
+# Controls how the headings in a menu are highlighted.
+# Values are 'none', 'bold', 'dim', 'underline', 'blink', or 'inverse'.
+# Default is 'inverse'
+#OPTIONS=menu_headings:inverse
+
+# Show object symbols in menus in the item class lines where that object symbol
+# acts as an accelerator key to select items of that class.
+#OPTIONS=menu_objsyms
+
+# Do not clear the screen before drawing menus, and align menus to right
+#OPTIONS=menu_overlay
+
+# Set the number of messages saved into message history (^P -command)
+#OPTIONS=msghistory:50
+
+# Allows you to change the way recalled messages are displayed.
+# The possible values are:
+# '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
+# Default is 's'. TTY only.
+#OPTIONS=msg_window:s
+
+# Allow use of the mouse for input and travel.
+#OPTIONS=mouse_support
+
+# Read the NetHack news file, if present (default on).
+#OPTIONS=news
+
+# Send padding nulls to the terminal (default on).
+#OPTIONS=null
+
+# Use number pad or vi-keys for movement?
+# number_pad option can have an optional value of 0 (off), 1 (on),
+# or 2 (on,legacy-mode) which causes 5='g', alt-5='G', alt-0='I'
+# -1 (use vi-keys, but swap z and y, for qwertz keyboards)
+#OPTIONS=number_pad:2
+
+# Set the order in which item classes appear in your inventory
+#OPTIONS=packorder:")[%?+/=!(*0_`
+
+# A space separated list of specific situations where alternate
+# prompting is desired.  The default is paranoid_confirmation:pray.
+#OPTIONS=paranoid_confirmation:confirm quit die bones attack pray remove
+
+# Always show the inventory window? X11 and Windows GUI only.
+#OPTIONS=perm_invent
+
+# 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".
+#OPTIONS=pettype:cat
+
+# Threshold when item pile under you is shown in a popup list. Persistent.
+#OPTIONS=pile_limit:5
+
+# Game mode
+# Values are 'normal', 'explore', or 'debug'.
+#OPTIONS=playmode:normal
+
+# Preload tiles into memory. MSDOS only.
+#OPTIONS=preload_tiles
+
+# When wielding a weapon, move your previous weapon to other hand
+#OPTIONS=pushweapon
+
+# Space key acts as a wait.
+#OPTIONS=rest_on_space
+
+# Controls the amount of screen updating for the map window when engaged
+# in multi-turn movement. Possible values are 'teleport', 'run', 'walk',
+# or 'crawl'.  Default is 'run'.
+#OPTIONS=runmode:run
+
+# Ask if you really want to hit your pet
+#OPTIONS=safe_pet
+
+# Perform extra data checking.  Wizard-mode only.
+#OPTIONS=sanity_check
+
+# 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.
+#OPTIONS=selectsaved
+
+# Which parts of the score file to show at end of game
+#OPTIONS=scores:10 top/2 around/own
+
+# Do not show experience points in the status line
+#OPTIONS=!showexp
+
+# Show your own symbol with the symbol of your race
+# eg. 'G' if you're a gnome, 'h' if dwarf, etc.
+#OPTIONS=showrace
+
+# Show score on the status line
+#OPTIONS=showscore
+
+# Suppress terminal beeps.  Default on.
+#OPTIONS=silent
+
+# Controls the sorting behavior of the pickup lists for inventory.
+# Possible values are 'full', 'loot', and 'none'.
+#OPTIONS=sortloot:full
+
+# Sort the pack contents by type when displaying inventory (default on).
+#OPTIONS=sortpack
+
+# Disable sparkly magic resistance animation effect
+#OPTIONS=!sparkle
+
+# Boldface monsters and --More-- (default off).
+#OPTIONS=standout
+
+# NetHack version level to suppress alert notification messages
+# about feature changes for that and prior versions.
+#OPTIONS=suppress_alert:3.6.0
+
+# Show current turn in the status line
+#OPTIONS=time
+
+# When pausing momentarily for display effect, such as with explosions and
+# moving objects, use a timer rather than sending extra characters to the
+# screen.  TTY only.
+#OPTIONS=timed_delay
+
+# Draw a tombstone graphic upon your death (default on).
+#OPTIONS=tombstone
+
+# Do not show top ten list in a separate window. Windows GUI only.
+#OPTIONS=!toptenwin
+
+# Enable travel (_) command.
+#OPTIONS=travel
+
+# Use the dark gray color
+#OPTIONS=use_darkgray
+
+# Use inverse text attribute in eg. menu titles
+#OPTIONS=use_inverse
+
+# Display this number of messages at a time in the message window.
+# WinCE, Windows GUI, and GEM only.
+#OPTIONS=vary_msgcount:3
+
+# Be less verbose with the messages
+#OPTIONS=!verbose
+
+# Set the color palette for PC systems using NO_TERMS (MS-DOS 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.
+#OPTIONS=videocolors:4-2-6-1-5-3-15-12-10-14-9-13-11
+
+# Gray shades to map to black-gray-white. possible values are 'dark',
+# 'normal', and 'light'.  MS-DOS only.
+#OPTIONS=videoshades:normal-normal-normal
+
+# When using '/' or ';' commands with autodescribe-option on, display
+# coordinates after the description. Possible values are 'compass',
+# 'map', 'screen', or 'none'
+#OPTIONS=whatis_coord:map
+
+# Windowing system to use, such as 'tty' or 'x11'.
+#OPTIONS=windowtype:tty
+
+# NetHack port should wrap long lines of text if they don't fit in
+# the visible area of the window.
+# WinCE only.
+#OPTIONS=wraptext
+
+
+
+# How the map window is shown?  Windows GUI only.
+# possible map_mode options include: tiles, ascii4x6,
+# ascii6x8, ascii8x8, ascii16x8, ascii7x12, ascii8x12, ascii16x12,
+# ascii12x16, ascii10x18, fit_to_screen
+#OPTIONS=map_mode:tiles
+
+# Define alternative file for the files, and the tile size
+#OPTIONS=tile_file:C:\absurd64.bmp
+#OPTIONS=tile_width:64,tile_height:64
+
+# When does the map window scroll? Windows GUI only.
+#OPTIONS=scroll_margin:5
+
+# Message window settings. Windows GUI only.
+#OPTIONS=font_message:Arial,font_size_message:9,align_message:top
+
+# Menu settings. Windows GUI only.
+#OPTIONS=font_menu:Arial,font_size_menu:9
+
+# Text settings. Windows GUI only.
+#OPTIONS=font_text:Courier New,font_size_text:9
+
+# Status window settings. Windows GUI only.
+#OPTIONS=font_status:Courier New,font_size_status:9
+
+# No startup splash screen. Windows GUI only.
+#OPTIONS=!splash_screen
+
+# How does NetHack prompt for character creation. Windows GUI only.
+#OPTIONS=player_selection:prompts
+
+# NetHack should pop up dialog boxes for input.
+# Windows GUI only.
+#OPTIONS=popup_dialog
+
+# Status/message window colors. Windows GUI only.
+# Possible color options include:
+# six digit hexadecimal RGB color value ("#8F8F8F"), black, red, green, brown,
+# blue, magenta, cyan, gray (or grey), orange, brightgreen, yellow, brightblue,
+# brightmagenta, brightcyan, white, trueblack, purple, silver, maroon, fuchsia,
+# lime, olive, navy, teal, aqua, activeborder, activecaption, appworkspace,
+# background, btnface, btnshadow, btntext, captiontext, graytext, highlight,
+# highlighttext, inactiveborder, inactivecaption, menu, menutext, scrollbar,
+# window, windowframe, windowtext.
+# windowcolors:<window> <text_color>/<background_color>
+#OPTIONS=windowcolors:status windowtext/window message windowtext/window
+
+# HACKDIR is the default location for everything.
+# Note: On Windows HACKDIR defaults to the location of the NetHack.exe or
+# NetHackw.exe file so setting HACKDIR below to override that is not usually
+# necessary or recommended.
+#HACKDIR=c:\games\nethack
+
+# The location that level files in progress are stored
+# (default=HACKDIR, writeable)
+#LEVELDIR=c:\nethack\levels
+
+# The location where saved games are kept (default=HACKDIR, writeable)
+#SAVEDIR=c:\nethack\save
+
+# The location that bones files are kept (default=HACKDIR, writeable)
+#BONESDIR=c:\nethack\save
+
+# The location that file synchronization locks are stored
+# (default=HACKDIR, writeable)
+#LOCKDIR=c:\nethack\levels
+
+# The location that a record of game aborts and self-diagnosed game problems
+# is kept (default=HACKDIR, writeable)
+#TROUBLEDIR=c:\nethack\trouble
+
+# Finnish keyboards might need these modifications uncommented. Windows GUI.
+# For  \, @, $, [, |
+#OPTIONS=subkeyvalue:171/92
+#OPTIONS=subkeyvalue:178/64
+#OPTIONS=subkeyvalue:180/36
+#OPTIONS=subkeyvalue:184/91
+#OPTIONS=subkeyvalue:188/124
+
+# Some versions of Windows allow you to adjust the win32 console port
+# colors using R-G-B settings.
+#OPTIONS=palette:black-0-0-0
+#OPTIONS=palette:red-210-0-0
+#OPTIONS=palette:green-80-200-0
+#OPTIONS=palette:brown-180-100-0
+#OPTIONS=palette:blue-0-0-200
+#OPTIONS=palette:magenta-128-0-128
+#OPTIONS=palette:cyan-50-180-180
+#OPTIONS=palette:gray-192-192-192
+#OPTIONS=palette:dark gray-100-100-100
+#OPTIONS=palette:orange-255-128-0
+#OPTIONS=palette:bright green-0-255-0
+#OPTIONS=palette:yellow-255-255-0
+#OPTIONS=palette:bright blue-100-100-240
+#OPTIONS=palette:bright magenta-255-0-255
+#OPTIONS=palette:bright cyan-0-255-255
+#OPTIONS=palette:white-255-255-255
+
+
+
+# Set exceptions to the pickup_types option. You can use multiple exceptions.
+# First character must be '<' (autopick) or '>' (don't autopick), followed
+# by a regular expression.
+#  Always autopickup any type of arrow
+#AUTOPICKUP_EXCEPTION="<arrow"
+#  Never autopickup any corpse
+#AUTOPICKUP_EXCEPTION=">corpse"
+#  Never autopickup any known cursed items
+#AUTOPICKUP_EXCEPTION="> cursed"
+
+
+# Change the way messages are shown in the top status line.
+# You can use multiple MSGTYPE lines.
+# Format is MSGTYPE=type "regular expression"
+# Where type is one of 'show', 'hide', 'stop', or 'norep'
+#  Always prompt for more after becoming hungry.
+#MSGTYPE=stop "You feel hungry."
+#  Never show any displacing your pet messages.
+#MSGTYPE=hide "You displaced .*"
+#  Don't repeat message when seeing same items on the floor
+#MSGTYPE=norep  "You see here a *"
+#MSGTYPE=norep  "You see here an *"
+
+
+# Highlight menu lines with different colors. You need to define the colors
+# with MENUCOLOR lines. Only for TTY and Windows GUI.
+#  Toggle menucolor use on or off
+#OPTIONS=menucolors
+# Define color used for a certain menu line. Format is
+# MENUCOLOR="regular expression"=color
+# or
+# MENUCOLOR="regular expression"=color&attribute
+#  Show all blessed items in green
+#MENUCOLOR=" blessed " = green
+#  Show all holy water in green
+#MENUCOLOR=" holy " = green
+#  Show all cursed items in red
+#MENUCOLOR=" cursed " = red
+#  Show all unholy water in red
+#MENUCOLOR=" unholy " = red
+#  Show all cursed worn items in orange and underlined
+#MENUCOLOR=" cursed .* (being worn)" = orange&underline
+
+
+# Use the IBM character set rather than just plain ascii characters
+# for tty window-port.
+#OPTIONS=symset:IBMGraphics_2
+# Use RogueEpyx character set for the rogue level
+#OPTIONS=roguesymset:RogueEpyx
+
+# Override one or more symbols in the symbols files.
+# See the Guidebook for the symbol names.
+#  Set boulder symbol to '0'
+#SYMBOLS=S_boulder:0
+# or
+#OPTIONS=S_boulder:0
+
+# Load DEC text characters display symbols. Deprecated.
+#OPTIONS=DECgraphics
+# Load IBM text characters display symbols. Deprecated.
+#OPTIONS=IBMgraphics
+# Set the character symbol used for boulders. Deprecated.
+#OPTION=boulder:0
+
+
+# Wizard-mode extra items, in a text file containing item names,
+# one per line, up to a maximum of 128 lines. Each line is processed
+# by the function that handles wishing.
+#WIZKIT=~/wizkit.txt
+
+
+# User sounds
+# Define the directory that contains the sound files
+#SOUNDDIR=C:\nethack\sounds\
+# Define a sound mapping
+# SOUND=MESG "pattern" file volume
+#SOUND=MESG "KAABLAMM" explosion.wav 100
+
+
+# Turn on all status hilites.
+#OPTIONS=statushilites
+# Use highlighting in the status lines when it changes?
+#OPTIONS=hilite_status:hitpoints/30%/bright-magenta/normal
+
index f9ab66f..7b31183 100644 (file)
@@ -1,6 +1,18 @@
-.TH DGN_COMP 6 "12 Dec 1995"
-.\" NetHack 3.6  dgn_comp.6    $NHDT-Date: 1432512786 2015/05/25 00:13:06 $  $NHDT-Branch: master $:$NHDT-Revision: 1.5 $
-.UC 4
+.TH DGN_COMP 6 "25 May 2015" NETHACK
+.de ND
+.ds Nd \\$3
+..
+.de NB
+.ds Nb \\$2
+..
+.de NR
+.ds Nr \\$2
+..
+.ND $NHDT-Date: 1524689548 2018/04/25 20:52:28 $
+.NB $NHDT-Branch: NetHack-3.6.0 $
+.NR $NHDT-Revision: 1.6 $
+.ds Na Kenneth Lorber
+
 .SH NAME
 dgn_comp \- NetHack dungeon compiler
 .SH SYNOPSIS
@@ -401,3 +413,7 @@ lev_comp(6), nethack(6)
 .SH BUGS
 .PP
 Probably infinite.
+.SH COPYRIGHT
+This file is Copyright (C) \*(Na and was last modified \*(Nd (version
+\*(Nb:\*(Nr).
+NetHack may be freely redistributed.  See license for details.
index e014d73..23e98c2 100644 (file)
--- a/doc/dlb.6
+++ b/doc/dlb.6
@@ -1,6 +1,17 @@
-.TH DLB 6 "28 Oct 1993"
-.\" NetHack 3.6  dlb.6 $NHDT-Date: 1432512786 2015/05/25 00:13:06 $  $NHDT-Branch: master $:$NHDT-Revision: 1.6 $
-.UC 4
+.TH DLB 6 "25 May 2015" NETHACK
+.de ND
+.ds Nd \\$3
+..
+.de NB
+.ds Nb \\$2
+..
+.de NR
+.ds Nr \\$2
+..
+.ND $NHDT-Date: 1524689548 2018/04/25 20:52:28 $
+.NB $NHDT-Branch: NetHack-3.6.0 $
+.NR $NHDT-Revision: 1.7 $
+.ds Na Kenneth Lorber
 .SH NAME
 dlb \- NetHack data librarian
 .SH SYNOPSIS
@@ -92,3 +103,7 @@ Not a good tar emulation; - does not mean stdin or stdout.
 Should include an optional compression facility.
 Not all read-only files for NetHack can be read out of an archive;
 examining the source is the only way to know which files can be. 
+.SH COPYRIGHT
+This file is Copyright (C) \*(Na and was last modified \*(Nd (version
+\*(Nb:\*(Nr).
+NetHack may be freely redistributed.  See license for details.
index a017178..5b5c783 100644 (file)
@@ -1,4 +1,4 @@
-$NHDT-Branch$:$NHDT-Revision$ $NHDT-Date$
+$NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.5 $ $NHDT-Date: 1524689548 2018/04/25 20:52:28 $
 
 [This is a partial list supplied by Ken Arromdee long after the fact]
 
index 72ad612..91b8507 100644 (file)
@@ -1,4 +1,4 @@
-$NHDT-Branch$:$NHDT-Revision$ $NHDT-Date$
+$NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.334 $ $NHDT-Date: 1524689548 2018/04/25 20:52:28 $
 
 General Fixes and Modified Features
 -----------------------------------
index a618d4b..8c6fb9c 100644 (file)
@@ -1,4 +1,4 @@
-$NHDT-Branch$:$NHDT-Revision$ $NHDT-Date$
+$NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.135 $ $NHDT-Date: 1524689548 2018/04/25 20:52:28 $
 
 General Fixes and Modified Features
 -----------------------------------
index 1c9edf8..61b9a9a 100644 (file)
@@ -1,4 +1,4 @@
-$NHDT-Branch$:$NHDT-Revision$ $NHDT-Date$
+$NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.106 $ $NHDT-Date: 1524689549 2018/04/25 20:52:29 $
 
 General Fixes and Modified Features
 -----------------------------------
index 30119b1..c429b9a 100644 (file)
@@ -1,3 +1,3 @@
-$NHDT-Branch$:$NHDT-Revision$ $NHDT-Date$
+$NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.543 $ $NHDT-Date: 1524689549 2018/04/25 20:52:29 $
 
 There was no NetHack 3.5.x release
index cc4947c..7321c54 100644 (file)
@@ -1,4 +1,4 @@
-$NHDT-Branch$:$NHDT-Revision$ $NHDT-Date$
+$NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.562 $ $NHDT-Date: 1524689549 2018/04/25 20:52:29 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -1172,6 +1172,11 @@ debug-mode viewing of object weight
 prizes on various levels now protected by ?oSM scrolls as well as Elbereth
 regexes now use system libraries consistently for all pattern-matching systems
 wet towels deal more damage
+'P' and 'W' commands work on both accessories and armor but treat different
+       types of items to be likely candidates when prompting for an item
+'R' and 'T' commands also work on both accessories and armor; setting the
+       Remove/Takeoff category for the paranoid_confirm option will be needed
+       if user wants to stick with just one command for all worn items
 
 
 Platform- and/or Interface-Specific New Features
diff --git a/doc/fixes36.1 b/doc/fixes36.1
new file mode 100644 (file)
index 0000000..0d8bf47
--- /dev/null
@@ -0,0 +1,891 @@
+$NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.448 $ $NHDT-Date: 1524780380 2018/04/26 22:06:20 $
+
+General Fixes and Modified Features
+-----------------------------------
+doc/*.6 man pages and corresponding doc/*.txt text copies were out of date
+data.base entry for "lava" had wrong first name for Don Woods' attribution
+cursed genocide of "none" sent in monsters, but "that's enough tries" didn't
+update MAXPLAYERS documentation in sysconf file and accept 0 for 'no limit'
+wizard mode: don't include feedback about named fruit for ^X and enlightenment
+looking at distant objects while wearing the Eyes of the Overworld made their
+       up-close descriptions known when not intended
+message when cursed wand zapped by a monster happens to explode was suppressed
+       if hero was deaf, even though that message has no audible component
+support explicit 'symset:default' and 'symset:Default symbols' in options
+crash during startup if player name set as 'player' in defaults
+crash during startup if defaults file has a long line
+any existing vampire shape-shifted into critter (fog cloud, bat, wolf) became
+       an unkillable critter if vampires were genocided
+unlike in previous versions, an uncursed scroll of enchant armor failed to
+       uncurse the piece of armor being enchanted (change was unintentional)
+slice of {pizza,cake,&} pluralized as "slouse of ..." due to false match
+       with "lice" (discovered pre-3.6.0-release)
+change dipping prompt to not ignore 'called' and 'named' attributes of item
+       to be dipped
+avoid 'the unlabeled {scroll,spellbook} fades' when blank item is hit by water
+wrong message given when high priest on astral plane rejects being assigned a
+       name (got the one for unique monsters instead of the one for priests)
+negative intrinsic protection shouldn't confer MC=1, "you are warded" (not
+       possible from divine protection but is possible from eating rings)
+make a slight adjustment to the quickmimic() sense wording
+fix typo in passage 1 of The Colour of Magic
+fix typos in passages 2 and 6 of Thud!
+falling asleep when reading dull spellbook ignored sleep resistance
+getpos() complaint about invalid movement keystroke didn't describe meta-chars
+       accurately
+'realtime' value in xlogfile was incorrect if 'checkpoint' option was active
+make a previously-discovered scroll written with marker while blind have its
+       label known so it can be read while blind
+#name or C for discoveries list that spanned multiple pages would exit on
+       space instead of advancing to next page (workaround: use '>' instead)
+don't show the old level when you die going down the stairs because of an
+       iron ball
+new high score with ", while helpless" attribute appended would erroneously
+       result in ", while helpless" being appended to all following entries
+allow bright aliases for colors in menucolors
+avoid hearing yelps when you are deaf
+make corpse visible if stethoscope told you about it being there
+sceptre of might database entry word change
+avoid "spellbook of novel" on discoveries list after object ID of novel
+add novel to discoveries list after reading one
+putting gold into hero-owned container on shop floor gave free credit
+stack splitting for dipping large quantities of potions was done poorly
+dipping fruit juice into enlightenment gave different result than the inverse
+make travel walk up to a trap and stop when the trap blocks the only
+       way forward, instead of trying to go straight line
+travel will displace pets rather than stop
+discard travel cache when moving to a different dungeon level
+do not autopickup unpaid items in shops
+death due an unseen gas spore's explosion resulted in "killed by a died"
+allow optional parameter "true", "yes", "false", or "no" for boolean options
+actually make the castle chest not trapped
+level-drain resistance wasn't shown during enlightenment if it was conferred
+       by worn/wielded equipment or by lycanthropy
+wizard mode enlightenment now shows more reasons for various intrinsics
+rehumanizing after being poly'd into vampire left hero with ability to sense
+       humans and elves
+Warn_of_mon wouldn't have been able to sense giant ants if any creature were
+       to have that ability, caused by using 0 instead of NON_PM for 'none'
+tone down energy vortex's drain energy attack
+fix message typo if tame mind flayer dies trying to eat Medusa's brains
+use alternate rejection message if attempting to name an unnameable monster
+       with the name it already has
+cockatrice corpse no longer leaves multiple statues for shape-shifted vampire
+alter name of monster causing hero's death if name contains characters that
+       could cause confusion when using record, logfile, or xlogfile later
+teleporting or polymorphing a sink via ring drop shouldn't depend upon being
+       able to see it happen
+change "unlockable chest" to "broken chest" so that it won't be misunderstood
+       ("capable of being unlocked" vs intended "not capable of being locked")
+use doname instead of xname when using '/' or ';' to look at objects on map
+when a pet moves reluctantly, name the top item of the pile it is reluctant
+       to step on if the hero sees or remembers any object(s) at that spot
+ensure sufficient messages are given to clarify the transition from detected
+       vampire bats to fog clouds in Vlad's tower
+fix "killing by kicking something weird" when kicking an object causes death
+avoid accessing mextra fields which haven't been allocated
+compile-time option for an alternate paniclog format for public server use
+make monsters forget where they stepped when fleeing or teleporting
+requiver pickup_thrown objects if quiver is empty
+make mimics mimicing walls or trees also block light
+stepping onto lava destroyed non-fireproof water walking boots but left other
+       vulnerable boot types intact
+damage and death reasons when eating globs referred to them as corpses
+fix death reason when petrified (avoid redundant 'while getting stoned')
+use appropriate place name for drum of earthquake shakes
+fix unmapped branch stairs on sokoban level
+redraw map when hilite_pile is toggled to display the highlighting
+make commands that accept a count prefix for item selection
+       show "Count:" like command repeating does
+make vault guard accept names starting with number
+fix weight of containers in special levels
+make the raven medusa level shortsighted
+fix possible segfault in lev_comp when map was too tall
+fix "the ice is bridged with ice" when freezing castle's moat or Medusa's sea
+make monsters and pets avoid poison gas clouds if it would damage them
+covetous monsters may choose to teleport to downstairs or ladders
+doppelganger posing as Rider would never change shape
+since doppelganger posing as Rider could never revert to innate form,
+       protection from shape changers turned it into genuine Rider
+don't create globs of ooze/slime/pudding with bknown flag set so pre-known to
+       be "uncursed"
+do allow globs with same curse/bless state to merge even when that state is
+       known for one and unknown for the other; result will have bknown clear
+make glob merging on floor behave the same as glob merging in inventory
+track age of merged globs
+support globs for edibility temporary intrinsic
+restore ability to gain intrinsics from black puddings (pass globs to cpostfx)
+eating tainted black pudding (glob in 3.6.0, corpse in 3.4.x and 3.3.x)
+       referred to it as "meat" (because it's not vegetarian food)
+fix pile mark after killing a monster carrying a potion which is destroyed
+don't list suit as likely candidate for Take-off if cloak blocks it
+only list known blank scrolls and known blank spellbooks as likely candidates
+       when choosing an item to write on for applied magic marker
+make status hilites use same color names as menucolors
+limit monster spell aggravate monsters to either outside or inside of the
+       Wizard's tower
+prevent revived unique from inheriting a user-defined name
+make hurtling out of air bubble on the Plane of Water handle entering water
+fix floor descriptions on the Planes when levitating
+fix warning glyph description when monster symbol coincided the warning symbol
+override MSGTYPE=norep while executing the ':' command
+if a chameleon took vampire form, it would stop periodically changing shape
+corpses obtained from tipping an ice box wouldn't rot away
+suppress "you climb up the stairs" message if verbose option is off
+physical damage from mind flayer attack was being inflicted twice
+adjust pending movement points when polymorphing into a slower creature
+damage inflicted by burning glob of green slime gave wrong messages
+monsters fleeing up the upstairs on level 1 were supposed to escape the
+       dungeon but ended up arriving on Plane of Earth
+monster hitting fire-dealing monster with weapon triggered passive damage to
+       weapon every time, when hero doing so only had 1/6 chance per hit
+hitting steam vortex with flammable weapon would damage the weapon with fire
+if a non-cursed spellbook being read becomes cursed and hero recognizes that
+       (bknown is set), interrupt reading
+if a non-cursed spellbook being read becomes cursed and hero doesn't notice,
+       don't leave it flagged as in-use (hence to be deleted during the
+       next save/restore cycle) if contact-poison cursed book effect occurs
+stolen_value, used when breaking shop items from outside the shop among other
+       times, could describe the shopkeeper as "it" when not seen
+when two or more shopkeepers were visible at once, 'p' command could be used
+       to probe map for locations of other shopkeepers and arbitrary monsters
+vortexes and other unsolid monsters need not avoid webs
+barbarian and samurai can achieve basic in their special spell's skill
+scalpel and tsurugi can now split puddings; bashing with darts or arrows can't
+jumping while punished could leave ball and chain in the wrong place
+improve Deaf message handling for the minetown watch and shops
+issues with Warning when you're adjacent to an undetected hider; clearly you
+       are aware a monster is present so this causes you to search it out
+allow lookup of names like Hachi when selecting monsters from the map
+lookup "More Info?" prompt will now tell you what it will look for on 'y'
+using 'R' on armor would bypass some restrictions imposed by 'T' (inner layer
+       could be taken off from under outer layer, embedded scales could be
+       attempted but triggered "select_off" impossible)
+when examining hidden monsters (probing, persistent monster detection), tell
+       how they're hidden (under an object, on the ceiling, etc)
+some quest text corrections
+use a much tighter upper bound when summoning nasties; old method could
+       theoretically create 200 critters at a time
+if a long worm inherited inventory from a previous shape, and if an egg or
+       figurine in that inventory hatched or auto-activated, messages were
+       given when hero could see any tail segment even if head was unseen,
+       making it seem as if worm's inventory was kept in the visible segment
+Wizard will now steal any quest artifact from hero, not just own role's
+prevent a hostile renegade Angel of <lawful god> from delivering taunt
+       messages which mention threats of retribution from that god
+a few types of monster (barrow wight, Nazgul, erinys) have weapon attacks that
+       don't deal physical damage, so special damage like stoning via wielded
+       cockatrice corpse wouldn't be inflicted
+non-item-using monsters who happened to be carrying scroll or wand of fire or
+       a fire horn could use it to cure themselves of being turned into slime
+when looting multiple containers, add 'n' for "loot next container", change
+       'q' and ESC from "done with this container" to "done looting"
+change looting to choose ":iobrs nq" action from a menu for menustyle:Partial
+wand/spell/breath zaps that reached the edge of the level on the Plane of Air
+       and "vanished into the aether" left temporary display effects on screen
+stop amulets and other items which aren't affected by erosion damage from
+       being subjected to erosion damage
+grammar bit: polyself w/ gender change yielded "you turn into a Elvenking"
+grammar bit when hallucinating: "you kill poor goblin" ('the' missing for pet)
+some blindness cures ignored u.ucreamed
+some instances of stun or confusion timers were being overridden rather than
+       incremented when new stun or confusion damage was suffered
+female gnome who gains level can grow up into male-only gnome lord; give
+       an alternate message instead of prohibiting the promotion
+kicked weapon which successfully hits monster vanishes from play
+unseen landmine explosion could result in "The <monst-type> statue crumbles."
+when using the 'O' command for regexp options (autopickup exceptions,
+       menucolors, message types), provide opportunity to add more than one
+       at a time [after 'add', return to add/list/remove menu]
+commands invoked by uppercase meta characters: M-A, M-C, M-N, M-O, M-R, M-T
+       were missing from '? c' list of game commands (dat/hh)
+tweak Baalzebub's lair and clean up the map display for it
+symbol set definitions didn't recognize S_darkroom and S_vibrating_square
+wizard mode enlightenment was reporting "very fast innately" (which is not
+       possible) for very fast hero who was innately fast
+when attacking a monster with a rust or corrosion or acid passive
+       counter-attack, grease wasn't protecting the attacker's weapon
+the Bell of Opening now correctly reports when it opens a trapdoor/hole
+knocking can no longer send a monster through a trapdoor/hole and desaddle it
+game no longer gets confused when you break an unpaid shop item while inside
+       a different shop
+shopkeepers now correctly handle nested containers and gold in containers
+for menustyle traditional, 'D' followed by (B|U|C|X)&m presented a menu of
+       everything, not just invent subset matching specified BUCX categories
+for menustyles traditional or combination, 'A' (or object ID) followed by i
+       displayed an inventory of everything rather than just worn items (or
+       not fully identified items)
+exploding chest trap would destroy uchain while still worn if uball carried
+if monster shapechange message "<foo> turns into <bar>!" was given, <bar>
+       could be "it" (if <foo> sensed telepathically and <bar> is mindless)
+automatic annotation for Ft.Ludios level got applied when a drawbridge became
+       mapped, but entry there is a secret door rather than a drawbridge
+sortloot changed to group holy water and unholy water with water instead of
+       placing them among the h- and u-named items
+sortloot changed to place diluted potion of foo after potion of foo instead
+       of listing all diluted potions followed by all non-diluted ones
+digging down on a grave converted the terrain to floor but did not create a
+       pit and uncover the grave's contents; digging again--on floor--did
+when feel_location removed a remembered-unseen-monster glyph from a known
+       water location while hero was levitating, the map was redrawn showing
+       floor instead of water at that spot
+Vlad's tower2 and tower3 didn't show up in wizard-mode ^O output or ^V? menu
+remove extra space from "All of your  <stack-of-potions> boil and explode."
+       (also applies to potions freezing and to scrolls burning)
+effects of cursed potion of levitation were skipped if already levitating
+when engulfed, having swallower be killed by angry deity trying to zap hero
+       no longer violates pacifist conduct (other penalties--reduced luck or
+       alignment--still apply if target is something you shouldn't kill)
+likewise when a monster kills inself trying to prevent turning to stone or
+       into slime that's been caused by the player, pacifism is not affected
+metabolism adjustments: hero poly'd into metallivore form still needs to eat;
+       being fainted or unconscious from other than sleep now consumes
+       nutrition at lower rate, like being asleep already did;
+       starvation threshold shortened due to slower food use while fainting
+after using detection magic or #terrain while underwater, then leaving water
+       and saving while on land, save would flag you as underwater again and
+       then restore would limit the map display accordingly; next move would
+       notice, retify things, and report "you are on solid land again"
+change #terrain used while underwater to view the regular map rather than the
+       crippled underwater one
+can see or feel adjacent lava or ice when underwater
+farlook when underwater now reports "land" for adjacent non-{water,lava,ice}
+       and "unreconnoitered" for non-adjacent anything, instead of "dark part
+       of a room" for the former and either dark-room or "unexplored" for the
+       latter depending upon whether the spot had previously been scouted
+monster who accidentally killed itself by zapping wand of fire or fire horn
+       at self to prevent turning into slime was not properly killed off;
+       it wouldn't benefit from an amulet of life saving and would trigger
+       impossible "dmonsfree: N removed doesn't match M pending"
+resurrecting a shopkeeper corpse caused crash (replmon -> replshk -> inhishop
+       -> no eshk data for temporary monster being replaced with revived shk)
+new character with OPTIONS=role:Valk,race:!human,align:!lawful yielded
+       "Shall I pick your Dwarven Valkyrie's for you?" where !human forces
+       dwarf and dwarf forces lawful, contradicting align:!lawful
+new character with OPTIONS=role:Valk,race:random yielded
+       "Shall I pick your Valkyrie's race and alignment for you?" instead
+       of honoring race:random without asking
+while in shop, undead turning at self causing carried, hero owned corpse to
+       resurrect claimed it belonged to shopkeeper
+while in shop, stone-to-flesh at self causing carried, hero owned figurine
+       or statue to animate claimed it belonged to shopkeeper
+reviving one of a stack of N corpses in a shop charged a usage fee for all N;
+       remaining N-1 were owned by hero if carried but by shop if on floor
+gremlin wailing in agony should wake up nearby monsters
+add more lighting variance to the second bigroom variant
+when getpos was picking a location, typing '^' to move to the next known trap
+       skipped some detected traps if their location was unseen
+describe detected door traps and chest traps as trapped door and trapped chest
+       instead of bear trap; bear trap tile is still used on map though
+thrown potion that killed peaceful monster would cause "the <mon> gets angry"
+       after the message about it being killed
+when poly'd into a hider and engulfed, attempt to hide via #monster was blocked
+       but feedback said "can't hide while held" rather than "while engulfed"
+various monster/object/food/gold/trap detections were inconsistent in how they
+       behaved if performed while engulfed or underwater
+show in inventory which monster a leash is attached to
+using /? to look up something by name, supplying multiple spaces (with no
+       other characters) as the name triggered impossible "singular of null?"
+add support for the 'altmeta' option to the 'what-does' command ('&' or '?f')
+when wielded weapon becomes untouchable (after alignment change or polymorph)
+       hero could be 'blasted by its power' twice in succession
+at startup, if sysconf had been read but user's own config file couldn't be
+       read, sysconf got processed again as if it contained user's options
+don't give "you cannot pass through the bars" when travel is testing possible
+       paths in the vicinity of iron bars
+if blind and no gloves, using 'm<dir>' to move and then 'e' could be used to
+       locate cockatrice corpse without fatal touching (by declining to eat)
+it's cannibalism for a were<foo> to eat a <foo> corpse
+conduct: wishing for an artifact and not getting it because it already exists
+       counts as wishing for an artifact, just like when not getting it
+       because of quest restrictions or too many artifacts in play does
+avoid ring of poison resistance as starting equipment for orcish wizard
+gelatinous cube shouldn't be able to eat a scroll of scare monster
+make fireballs or cones of cold cast at skilled or higher not go through walls
+prevent flying monsters from hovering over unreachable underwater objects
+lembas wafer gives increased nutrition to elves, reduced nutrition to orcs;
+       cram ration gives increased nutrition to dwarves
+when #tip's terse object drop format got interrupted by a regular message,
+       it continued using "obj2, obj3, ..." for subsequent objects, where
+       the sentence grammar no longer made sense (the interrupting message
+       still follows the comma of a partial sentence--attempting to fix that
+       seems hopeless; leaving it is better than always using verbose format)
+for #tip inside shop, credit was incorrectly given for spilled gold if that
+       gold's stale location coordinates didn't happen to be inside the shop
+when confused scroll of light summoned lights, player would be asked what to
+       call the scroll even if scroll of light was already identified
+if a visible monster becomes invisible, mark its spot with the 'remembered,
+       unseen monster' glyph ('I' character or '?' tile)
+monsters can throw cockatrice eggs at hero, but there was no handling for eggs
+       when the missile hit an intervening monster
+clarify that shape-shifted vampires revert to vampire form when petrified or
+       digested; when back in 'V' form, they're vulnerable to such damage
+when poly'd into an engulfer which does digestion damage, a kill resulting in
+       a level gain gave "welcome to level N+1" before "you digest <victim>"
+any corpse eaten by omnivorous hero always tasted "terrible"
+eating the corpse of a unique non-named monster (Wizard of Yendor, Oracle,
+       Chromatic Dragon, others) gave "The the <monster corpse> tastes ..."
+when escaping the dungeon, change "you were here" annotation in dungeon
+       overview to "you left from here"
+option parsing will crash if 'playmode' option is present without a value
+any item drained of enchantment was blamed on the player as far as shop
+       billing was concerned, even if caused by disenchanter attack
+if user supplied a specific monster name when asked to choose a monster class,
+       first prefix match was picked rather than best match ("titan" yielded
+       S_quadruped due to being preceded by "titanothere" in mons[])
+change ing_suffix() to not double final 'w' when adding 'ing' ('t=' yielded
+       "You mime throwwing something.")
+using 'D' to drop when not carrying anything finished (after doing nothing)
+       without giving any feedback for menustyles "full" and "partial"
+"you hear a distant <musical note> squeak" might actually be nearby
+differentiate symset and roguesymset option menu prompts
+don't show monster vs. monster attack message, if the message refers to
+       a monster that cannot be sensed by the hero
+umber hulk gazing at hidden mimic forces mimic to unhide
+show some timed hero properties in wizard-mode #timeout
+give quest guardians some equipment
+hero polyed into ghoul can only eat non-veggy corpses or eggs
+kicking activates statue traps
+pets start with apport equal to your charisma
+sometimes generate the random mazes with wide corridors, thick walls,
+       or with dead ends changed to loops
+put throne room gold in the chest
+novels are made of paper, not gold
+movement speeds are made less predictable by using random rounding, rather
+       than via adding a random offset
+some death by the-poison-was-deadly situations left stale non-zero HP shown
+       on the status line during final disclosure
+when sitting at a trap spot: You sit down. You step on a level teleporter.
+       (likewise for polymorph trap, and similar issue for web)
+show all statusline information in #attributes
+add option status_updates to prevent bottom of screen status line updates
+fix achievement recording bug with mines and sokoban prizes
+g.cubes would eat globs of green slime without harm; engulf those instead
+fix up true rumor about rock moles vs boots
+Bell of Opening could trigger segfault attempting to open some types of traps
+       if hero was mounted
+automatic #overview annotation for quest summons wasn't shown if the quest
+       entry portal was on same level as bigroom or rogue level
+gaining or losing strength while wearing gauntlets of power could give
+       misleading message about already being as strong or weak as possible
+levitation vs encumbrance message sequencing issues:  putting on boots of
+       levitation reported reduction of encumbrance before finish-wearing
+       and float-up messages, taking off such boots didn't report increase
+       of encumbrance until player took another action
+removing a blindfold with 'A' took two turns, with 'R' (and 'T') only one,
+       and could result in a crash if the blindfold was stolen during removal
+removing a blindfold and wielded weapon with 'A' could result in crash if the
+       weapon was destroyed by various methods
+cmdassist help for movement prefix followed by invalid direction was strange
+       when the direction was up, down, or self disallowed for that prefix
+poor message when shape-shifted vampire reverts to vampire if it has a name:
+       The Dracula suddenly transforms and rises as Dracula.
+poor message when shape-shifted vampire reverts if cause of 'death' was
+       disintegration or digestion and shifted form wasn't amorphous:
+       The vampire bat is disintegrated.  The vampire bat suddenly transforms
+       and rises as a vampire.  (fix: switch to existing alternate phrasing
+       used for amorphous form, "reconstitute" rather than "transform")
+poor message when named vampire shifts shape within view:
+       You observe a Dracula where a Dracula was.
+vampire shifting into fog cloud to pass under door "oozed" rather than "flowed"
+vampires in fog cloud shape would tend to stay that way unless killed; give
+       them a chance to change to bat or wolf shape if not seen or far away
+adult green dragons and the Chromatic Dragon were blinded by gas clouds
+named floating eye (when hit by another monster with reflection) or named
+       silver weapon (when hero hits silver-hating monster) could disrupt
+       message formatting and conceivably trigger crash if name had '%' in it
+fix "you feel like a new man" if female human hero's polymorph attempt failed
+       while in human form (when already poly'd, "new woman" correctly shown)
+fix the 'A' command to have the 'D' command's fix for C331-1 (quirk for
+       menustyle:Combination; if user included 'a' in "which object classes?"
+       response, to operate on applicable all items, there would still be a
+       followup menu asking to choose specific items)
+eating 1 tin from stack of N (for N >= 2) on shop's floor forced hero to buy 2
+using a cursed whistle in a vault will summon the guard immediately
+throne room's throne is occupied by a king
+using a grappling hook and getting pulled toward the target into water would
+       drown hero without any chance to crawl out
+blinded monster who eats a carrot will have blindness cured (hero already did)
+the "bonesid" written into bones files when they're created so that they can
+       be validated when loaded was incorrect for bones in the quest branch
+       ("QBar.2" ended up being "ar.2", "QKni.4" ended up as "ni.4", and so
+       forth) but worked anyway, because validation used same incorrect value
+surviving a gas spore's explosion would leave that explosion as a stale reason
+       for death which might show up strangely ("crushed to death by a gas
+       spore's explosion" when killed by an opening drawbridge)
+add database entry for "martial arts"
+add catch-all database entry for the polearms
+starting inventory for rogues specified +9 lock pick, where +/-N is meaningless
+fix pile mark when picking up all-but-one items while invisible
+improve config file error reporting
+when polymorphed into something with a passive counterattack, being 'killed'
+       and returning to normal form allows a subset of counterattacks to
+       continue after telling the player than the hero has reverted; change
+       "Mon is splashed by your acid" to "Mon is splashed by acid" in that
+       situation so that the message sequence doesn't look quite so strange
+when returning to quest nemesis' level, the message for some roles (A,S,T,W)
+       referred to sensing presence of the quest artifact even if had been
+       removed from that level; give an alternate message in that situation
+when the Amulet increased spell casting cost, nothing actually happened (aside
+       from the message about feeling the Amulet drain the hero's power) if
+       hero lacked sufficient energy to cast the spell
+if was possible to leash an adjacent pet while engulfed
+if leash or unleash attempt was directed at "remembered, unseen monster" glyph
+       and yielded "there's no creature there", the glyph wasn't removed
+wizmode level teleport menu indicates on what level you currently are
+fix invisible gold symbol in status line when S_coin was set to space
+fix buffer overflow in wizard mode for '#' command when 'extmenu' option is on
+"you suddenly vomit" was given two turns before actually vomiting, so you
+       could get that message, move a bit, then get "you can move again"
+       after the 2 turn freeze applied along with the actual vomit
+give an alternate message if you vomit when stomach is empty (ie, fainting)
+corpses and other flammable items not subject to direct burning or fire-based
+       erosion which were thrown or dropped into lava remained intact
+if a potion on the floor survived a land mine explosion and got propelled at
+       the hero, it didn't behave like a potion if it hit
+adjust candelabrum's weight when candles are attached
+when lit candelabrum burned out, persistent inventory window showed that it
+       was no longer lit but still showed phantom candles attached
+improve hilite_status, allowing multiple stops per field, and temporarily or
+       permanently hilited fields
+give feedback when released from a bear trap
+#version output sometimes had ", and basic NetHack features." on its own line
+       depending upon how the dynamically inserted pattern-match phrase fit
+#version output left out "pattern matching via <method>" if the basic NetHack
+       features entry was split across two lines
+recovery of strength lost due to weakness from hunger was vulnerable to abuse
+monsters hit by scroll of earth boulder did not get angry
+hero could "pronounce the words on the scroll" when blind (if its label is
+       known) even while being strangled at the time
+hero could cast spells while poly'd into a form which can't speak (or grunt,&c)
+       or while being strangled
+when poly'd into a giant and moving onto a boulder's spot, you could get "you
+       try to move the boulder, but in vain", "however, you can easily pick
+       it up", "you are carrying too much stuff to pick up another boulder"
+improve #adjust command's handling of the '$' and '#' inventory slots
+prevent #adjust from allowing anything to be moved into the special '-' slot
+sometimes rings dropped into sinks can be found in the pipes
+doors in special levels were always generated in vertical orientation
+assigning a type name to a potion on the floor which is actually a mimic could
+       prompt "Call a stream of <potion-type> fluid:" (bogus 'fromsink')
+with perm_invent option enabled and no inventory, 'i' put up an empty menu
+charisma affects the leeway in demon lord bribes
+make Vlad slightly tougher
+reduce the amount of gold laying on the floor
+locked chests and large boxes contain more stuff
+make shopkeepers bill hero for burying merchandise
+monster holding hero takes double damage from an explosion for reaching into
+       adjacent spot, but it was being inflicted even when hero was swallowed
+       or beyond the explosion radius
+poly'd hero holding monster now takes double damage (if monster is within
+       explosion radious) instead of inflicting that upon the monster
+when trying to swap places with a pet and failing due to pet being unable
+       to move diagonally to hero's spot (grid bug or too tight squeeze), if
+       pet became untame the map would briefly show hero at pet's location
+when trying to swap places with a pet and failing due to pet being trapped
+       or disallowed diagonal move, the arrive-on-new-spot code (autopickup,
+       trap triggering) executed even though hero didn't ultimately move
+being "dead inside" (self-genocide while polymorphed) conferred partial
+       invulnerability--normal monster behavior stopped attacking hero
+if a fiery monster, wand of fire, or fiery explosion burned up a paper golem,
+       it could still leave blank scrolls
+hero poly'd into paper or straw golem reverts to human if burned up even when
+       Unchanging without any explanation given
+hero polymorphed into form which can't wear armor via 'W' (eliciting "don't
+       even bother") could wear it via 'P'
+make multi-shot missiles fired by monsters be less verbose when they miss
+can no longer play controlled notes on musical instrument if impaired
+if a special level specified the appearance of a mimic and mimics had been
+       genocided prior to creating the level, whatever random monster took
+       the mimic's place got its intended appearance
+redundant "hit by gush of water" message if poly'd into iron golem or gremlin
+a shop object stolen from outside the shop (via grappling hook) would be left
+       marked as 'unpaid' after the shop robbery took place, resulting in
+       "unpaid_cost: object wasn't on any bill" when looking at inventory
+a shop object stolen from outside the shop could trigger a crash if that shop
+       had never been entered by the hero
+shopkeepers in their own shop and priests in their own temple are no longer
+       frightened by hero standing on scroll of scare monster
+the Wizard, Angels and lawful minions, the Riders, shopkeep/priest in own room
+       are never frightened by tooled horns
+'Iu' would reveal unknown container contents if carrying one unpaid item inside
+       a hero-owned container whose contents weren't known
+docall for type of object could overflow its prompt buffer if there was a very
+       long type name previously assigned
+whatis lookup for 'more info?' would behave strangely for plural names, either
+       entered by player or from "N foo" stacks on the map
+you should not hear a whistle if you are deaf
+change the deity's "congratulations" message upon ascension to something which
+       sounds a bit more archaic to fit better with the other messages
+prayer boon of 'fix all troubles' could get stuck in an infinite loop for
+       TROUBLE_STUCK_IN_WALL if there was no spot to teleport into available
+It shouldn't be considered hypocrisy if you speed up your pet while standing
+       on Elbereth
+fix 'object lost' panic if hero with lycanthropy but in human form is wielding
+       a potion of unholy water which gets boiled/exploded by fire, causing
+       were-transformation and drop of wielded weapon
+prevent segfault if pline() is called recursively (which could happen if the
+       interface code issues a debugpline() while processing putstr())
+open at yourself is the same as #loot
+when #force reports that a chest's lock is already broken or already unlocked,
+       force it to be described as "a chest", even when its lock state is
+       already known, rather than as "a broken chest" or "an unlocked chest"
+honor wish for "locked", "unlocked", or "broken" chest or box
+honor wish for "empty" container including statue, bag-o-tricks, horn-o-plenty
+gas spore explosion killing a gas spore which triggers a recursive explosion
+       would have killer reason for outer call clobbered by inner one; when
+       they were both "gas spore's explosion" it wouldn't be noticeable (see
+       corresponding post-3.6.0 entry for more...)
+wizard mode 'sanity_check' gave spurious "mon not on map" warnings when mounted
+at the prompt for entering a level annotation, responding with <return>
+       erroneously removed old annotation; use <space><return> to do that
+reorder the #droptype menu and add some separator lines
+moving from a pit to an adjacent pit with uncleared debris shouldn't be a fall
+open drawbridge spanning ice would vanish if the ice melted
+if a warned-of mon moved onto a spot containing a 'remembered, unseen mon'
+       then moved off, the unseen marker was redisplayed even though the
+       hero should now know that the remembered monster isn't there anymore
+
+
+Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
+------------------------------------------------------------------
+fix "object lost" panic during pickup caused by sortloot revamp
+more sortloot revisions
+fix inventory menu for response of '?' to getobj (more sortloot revamp fallout)
+rings covered by non-cursed gloves not listed as 'R' candidates
+in baalz_fixup, move any monster away from the two fake pool spots
+switching farlook from xname to doname was giving away information for items
+       located via object detection (quantity of detected gold)
+changing doname to use "some" instead of precise quantity when an item's
+       dknown flag is not set could result in blind hero getting
+       "There is a some jackal corpses here.  Eat one?" and
+       "You can only lift some of the some jackal corpses.  Continue?"
+catch up win/Qt/qt_win.cpp on 18-Dec-2015 change to formatkiller()
+fix for long lines in config file (28-Jan-2016) made 'O' command's 'list' and
+       'remove' menu choices in interactive handling for menu colorings,
+       message types, and autopickup exceptions subject to buffer overflow
+when picking a destination for #jump, '$' to show valid dest. is more accurate
+enchant armor gave "your pair of boots/gloves glow", should have been "glows"
+when autopickup is overridden in a shop, always-pick-up exceptions and
+       pickup_thrown still picked unpaid items up
+the fix for giving an alternate grow up message when a monster becomes a new
+       form with the opposite sex (female gnome into male gnome lord, for
+       example) had the logic wrong
+DUMPLOG: genocided and extinct species was always a blank line;
+       vanquished creatures was just a blank line if nothing had been killed
+DUMPLOG: RIP tombstone was printed for characters who survived (ascended,
+       escaped dungeon, quit, trickery or panic)
+DUMPLOG: pets who accompany hero during ascension or dungeon escape were
+       already gone by the time known portion of the level map was dumped
+artifact creation violated illiterate conduct when artifact name was assigned,
+       behavior intended only for creating Sting or Orcrist via naming
+tty: revert to pline() for issuing prompts (override MSGTYPE=hide differently)
+previous tty-revert fix had the override test backwards, breaking MSGTYPE
+save 'autodescribe' option value prior to detection or #terrain display and
+       restore it after rather than leave it forced on
+humanoid pet could become hostile but still remain tame if it observed hero
+       attacking a peaceful creature
+minor ^X/enlightenment bugs: grammar when poly'd into '1 hit dice' critter,
+       missing punctuation for "You entered the dungeon N turns ago"
+when configured with DUMPLOG enabled, artifacts were counted twice towards
+       final score
+once Moloch's Sanctum (or Astral Plane via wizard mode level teleport direct
+       to end-game) was entered, end of game disclosure would reveal that
+       high priests had been incorrectly flagged as extinct
+attempting to name an item as an artifact and failing via hand slip violates
+       illiterate conduct
+crashes for 'A' above were downgraded to impossible "cursed without otmp"
+wizhelp: ^O is #overview in wizard mode too; #wizwhere shows dungeon layout
+wishing for tins sometimes yielded a tin wand
+replace the fix for preventing putting on a helm of opposite alignment from
+       causing wielded Excalibur from blasting hero twice
+hero poly'd into vampire could drain monster down to 0 HP without killing it,
+       triggering impossible "dmonsfree: 1 removed doesn't match 0 pending"
+"you observe a fog cloud where a vampire/bat was" if an unseen vampire on the
+       far side of a closed door shifted shape to pass under that door
+fix mention_walls reporting secret doors as solid stone
+jumping over water unintentionally moved hero through that water, causing
+       drowning if not able to water walk or fly
+try again to fix achievement recording bug with mines and sokoban prizes
+the fix for secret doors on special levels always having vertical orientation
+       resulted in some--but not all--secret doors within vertical walls
+       being displayed as horizontal walls while still hidden
+and the previous fix for the for secret doors didn't work if the level hadn't
+       been wallified yet (Cav quest) so horizontal wall with secret door
+       mis-displayed as a vertical wall segment could occur
+and both the previous fixes only worked if the level description contained
+       an explicit DOOR directive rather than just '+' or 'S' on the map
+       (as with lower right area of Cav 'locate' level)
+the fix intended for "a shop object stolen from outside the shop (via
+       grappling hook) would be left marked as 'unpaid'" broke normal pickup,
+       preventing any picked up item from merging with compatible stack
+unix: freeing mailbox data at game end crashed if MAIL came from environment
+unix: fix for freeing MAIL introduced a one-byte buffer overrun which could
+       interfere with malloc/free operation
+unix: fix for freeing MAIL also introduced a memory leak whenever new mail
+       is detected and MAIL comes from the environment
+when clairvoyance lets you move the cursor to examine the map (if it occurs
+       when engulfed or underwater or when blessed clairvoyance finds a
+       monster), the "for instructions type '?'" prompt could be confusing
+prevent Mjollnir from being auto-quivered if it's been thrown without return
+       and then picked back up while quiver slot is empty
+plural of "fox" is not "foxen"
+gas spore explosion killing a gas spore which triggers a recursive explosion
+       would have killer reason for outer call clobbered by inner one;
+       "You are hit by the gas spore's explosion!" (inner call, followed by)
+       "You are hit by the !" (outer call, possibly repeated for multiple
+       explosions causing multiple levels of recursion)
+if multiple bands of blank lines were squeezed out of DUMPLOG's map, spurious
+       blank lines appeared in the final map output
+cursor positioning autodescribe of a statue while hallucinating was blank
+tty+EDIT_GETLIN: if prompt plus existing output buffer contents (result of
+       a prior getlin() used as default input) was long enough to wrap to
+       second line, the wrap point could be different from when the previous
+       input was typed, resulting it strange erase-char/kill-chars behavior
+
+
+Platform- and/or Interface-Specific Fixes
+-----------------------------------------
+tiles: wrinkled spellbook had a spurious brown pixel on far right edge of tile
+tiles: when statues are displayed as corresponding monsters, total_tiles_used
+       in generated src/tile.c had incorrect value
+tty: M-N gave "Unknown command 'M-" with "'." finishing the sentence on the
+       line below it, leaving bogus '.' displayed on the top row of the map
+tty: specifying all four of role, race, gender, and alignment still prompted
+       for confirmation with "Is this ok?" before starting play
+tty: responding with <return> or <enter> during role, race, &c selection
+       behaved same as <escape> to quit; now it will pick [random] instead
+tty: rename struct variable 'filter' (role.c) and function 'winch()' (wintty.c)
+       to avoid conflicts with <curses.h>
+tty: skip selector letter and selection indicator (-,+,#) during menu coloring
+tty: '>' no longer closes a menu window
+tty: if color is disabled and use_inverse is enabled, display lava in inverse
+       video so that it is visually distinguishable from water
+tty: if "--More--" was written to leftmost column (beginning of second line)
+       while hero was swallowed, cursor would end up in wrong place (at end
+       of status line instead back on map) after message line was cleared
+tty: long message lines which wrap when shown on the top line might be
+       re-displayed incorrectly by ^P for msg_window={full,combo,reverse}
+tty: MSGTYPE=hide could interfere with display of prompts
+tty: treat carriage return as a newline for input text and --More-- prompts
+unix/X11: in top level Makefile, some commented out definitions of VARDATND
+       misspelled pilemark.xbm (as pilemark.xpm)
+unix: options file with CR+LF line ends and an invalid option line resulted in
+       "ad option line: "whatever-the-line-was
+       because embedded carriage return character changed cursor's position
+unix: race condition with parallel make: src/Makefile might start building
+       makedefs before finishing monst.o and objects.o; if so, util/Makefile
+       can build them too, and they might be clobbered by simultaneous write
+unix: Makefile.{src,utl} ignored CPPFLAGS which is expanded by the default .c
+       rule by GNU make so if user had a value for that in the environment,
+       it would apply to some files but not others; explicitly override it
+unix: enable code guarded by USE_WIN_IOCTL by default unless prevented by
+       uncommenting #define AVOID_WIN_IOCTL in include/unixconf.h
+win32gui: getversionstring() was overflowing the provided Help About buffer
+win32gui: guard against buffer overflow in in mswin_getlin()
+win32gui: handle menu_color attribute
+win32gui: name-from-discoveries list menu selector characters were punctuation
+       instead of letters, repeated for each class; caused by the core bug
+       of erroneously specifying space as a selector for class header lines
+win32gui: allow toggling mouse_support off
+MacOSX: initial binary release was built from out of date source code that
+       had 'BETA' and 'DEBUG' inappropriately enabled
+MacOSX: force TIMED_DELAY build option on so that 'runmode' run-time option
+       is functional
+Qt: could issue impossible "Destroy called before we know if Menu or Text"
+       followed by crash caused by deferencing a Null pointer if player quit
+       immediately after creating character and declined to disclose anything
+X11: core bug for '`' (backtick) and #terrain commands was only noticed by
+       X11 interface: impossible "add_menu: called before start_menu"
+X11: enable a scroll bar in menu windows
+X11: support pre-selected entries in menu windows
+X11: make the extended command menu be easier to use and look a little nicer
+X11: make the getline text entry widget display a bigger text entry area
+X11: color didn't work when the map was displayed as text rather than tiles
+X11: use grayscale monster tiles for statues
+X11/USE_XPM: [post-3.6.0 issue] the 'tiles' bug of incorrect total_tiles_used
+       for STATUES_LOOK_LIKE_MONSTERS broke XPM manipulation of tiles data
+PANICTRACE: PANICTRACE_GDB used wrong value for ARGV0 when launching gdb if
+       'nethack -dpath' was used to specify non-default playground directory
+win32gui: gather raw_print error messages into a single dialog window
+win32tty: fix display errors when using a font with double wide or ambiguous
+       width characters
+Amiga (untested): 'makedefs -z' didn't handle FILE_PREFIX correctly when
+       building vis_tab.h and vis_tab.c
+
+
+General New Features
+--------------------
+naming Sting or Orcrist now breaks illiterate conduct
+different feedback for reading a scroll of mail created by writing with marker
+reading non-cursed scroll of enchant weapon uncurses welded tin opener
+if hero has no jumping ability but knows the jumping spell, the #jump command
+       will attempt to cast the spell
+allow moving cursor to monsters with 'm' (nearest first) and 'M' (furthest
+       first) when asked for map location, or to objects with 'o' and 'O'
+allow picking a used inventory letter from menu when #adjusting
+zapping wand of opening at yourself, unlock carried boxes
+dissolve iron bars by force-fighting with wielded potion of acid
+poison breath leaves a trail of poison gas
+allow knife and stiletto as possible tin opening tools
+wizard mode #wizintrinsic command
+additional tribute passages for The Colour of Magic, The Light Fantastic,
+       Equal Rites, Mort, Sourcery, Wyrd Sisters, Pyramids, Guards! Guards!,
+       Eric, Moving Pictures, Reaper Man, Witches Abroad, Snuff,
+       Raising Steam, and The Shepherd's Crown
+compile-time options SIMPLE_MAIL and SERVER_ADMIN_MSG for public server use
+database entries for Cleaver, Sunsword, Frost and Fire brands, and
+       polymorph trap
+allow showing coordinates when picking a position on the map and
+       autodescribe option is on
+new status line conditions Stone Strngl Deaf Lev Fly Ride
+allow some extra color name aliases for menucolors and status hilites
+add extended command #kick
+when choosing an inventory item and '-' for bare-hands/fingers/no-ammo is a
+       choice, include that in the inventory menu if player types '?' or '*'
+feedback from probing of long worm now includes number of segments it has
+monk starts with 'shuriken' pre-discovered (despite language issue...)
+item-using monster on or next to a fire trap can use it to be cured of
+       turning into slime
+wizard mode ^G can now specify "sleeping", "male" or "female" when
+       creating a monster
+REPRODUCIBLE_BUILD is new config.h setting to fetch build date+time from
+       environment instead of using current date+time, so that later rebuild
+       could duplicate the original (disabled by default; tested for Unix)
+default value for vibrating square symbol changed from yellow '^' to purple '~'
+allow symbol set values to be specified via char within single quotes
+add symbols set "plain", same as default except it uses '+' for corner walls
+extend wizard-mode '#stats' command
+'Q' to ready an item for quick-throwing ('f') now allows the wielded weapon to
+       be moved to quiver; if quantity is more than 1, it offers to split the
+       stack and leave 1 wielded, otherwise it requires confirmation
+'Q' will accept an item count to manually split a stack as part of it being
+       quivered, provided the stack isn't already in the quiver slot
+during end of game disclosure, the vanquished monsters list can be sorted in
+       one of several ways by answering 'a' to "disclose vanquished monsters?"
+when #terrain is displaying a censored version of the map (no monsters, &c),
+       moving the cursor will display farlook's brief autodescribe feedback
+when monster/object/trap detection temporarily clears the map to highlight the
+       results of such detection, farlook autodescibe can be used to view it
+interrupt a multi turn action if hp or pw is restored to maximum
+pressing d or D when cursor positioning targets doors and doorways
+pressing x or X when cursor positioning targets possibly unexplored location
+       (potentially useful when using '_' [not mouse] to invoke travel)
+swallowers can't re-engulf hero immediately after spitting him/her out
+werejackals can summon foxes and coyotes; werewolves can summon wargs
+allow taming monkeys and apes with bananas
+GENERICUSERS is now a sysconf statement instead of compile-time option
+fountains are bright blue, graves are white
+ray bounceback chance depends on the wall type
+undead #turning takes less time at higher experience level
+peacefuls may react when you attack other peacefuls
+prevent diagonal jumping through open doorways
+different liquids when hallucinating
+when moving a cursor for travel target, show if there is no known travel
+       path to that location, if "autodescribe" is on
+show the reason why travel was interrupted if mention_walls is on
+random horses have a tiny chance of being generated saddled
+give feedback just before timed levitation runs out
+travel accepts 'm' (request menu) prefix
+pressing a or A when cursor positioning shows menu of "interesting" features
+pressing z or Z when cursor positioning cycles through valid locations for
+       jumping, hitting with polearm, or casting a stinking cloud
+when moving a cursor for a jump, polearm, or stinking cloud targeting, show
+       if the location is illegal, if "autodescribe" is on
+wizard-mode command #wizmakemap to recreate the current level
+'goldX' boolean option to treat gold pieces as X (vs U) during BUCX filtering
+       (should be persistent but is reset each save/restore cycle in order
+       to avoid breaking 3.6.0 save files)
+for menustyle:Traditional and Combination, support BUCX filtering for item
+       pick-up and container put-in and take-out; also for object IDing
+for menustyle:Full and Traditional and Combination, support BUCX filtering
+       for the 'A' command
+option whatis_filter to set filtering for eligible map locations when cursor
+       positioning
+blinded hero or monster who eats a nurse corpse will have blindness cured
+blinded hero or monster who breathes vapor from broken potion of healing,
+       extra healing, or full healing might have blindness cured (depends on
+       potion: full == always; extra == if not-cursed; plain == if blessed)
+sysconf definition BONES_POOLS to allow more bones files per level
+blessed scroll of fire lets you choose explosion location like stinking cloud
+optional sections in the config file, selected with CHOOSE
+new paranoid_confirm settings: wand-break to require "yes" rather than 'y'
+       to break a wand via (a)pply, and Were-change to require "yes" rather
+       than 'y' when hero inflicted with lycanthropy has polymorph control
+option force_invmenu to make commands asking for inventory items always
+       use a menu instead of a text line query
+option hitpointbar to show a bar graph of hit points behind title field
+wielding Trollsbane prevents troll corpses from reviving
+wielding Demonbane prevents demons summoning friends
+wielding Dragonbane confers reflection
+wielding Ogresmasher grants 25 constitution
+Cleaver can hit three adjacent monsters with one swing
+Master Key of Thievery warns about undetected traps if wielded without gloves
+Master Key of Thievery always finds door and chest traps if used to lock or
+       unlock a trapped door or chest while non-cursed (for rogues) or
+       blessed (for non-rogues); player is offered the opportunity to disarm
+"Elbereth" must now be the only engraved text on a square to function
+"Elbereth" now erodes based on attacks by the player, not monsters scared
+add option herecmd_menu to make a mouse click on your character pop up
+       a context menu, and extended command #herecmdmenu to do the same
+change #adjust's behavior when collecting compatible stacks; that used to
+       occur for any #adjust which lacked a split count, now it only happens
+       when 'adjusting' into a stack's own inventory slot
+a prayer result which results in uncursing some or all of the hero's items
+       won't uncurse a worn helm of opposite alignment since that would
+       facilitate the hero switching to another god by taking it off
+wielded aklys behaves like Mjollnir when thrown--it usually returns; unlike
+       Mjollnir, it isn't limited to Valkyries or need gauntlets of power
+       (so far, hero-only; an aklys won't return if thrown by a monster)
+allow 'm' prefix for wizard mode level teleport command (^V) to bypass prompt
+       for destination and use menu of special level locations
+
+
+Platform- and/or Interface-Specific New Features
+------------------------------------------------
+tty: menu_overlay -option to clear screen and align menus to left
+tty: compile-time option to output escape codes for tile data hints
+unix: compile-time option MSGHANDLER to pass messages to external program
+unix: add CHECK_PLNAME-option to sysconf to make WIZARDS, EXPLORERS, and
+       SHELLERS check player's character name instead of login name
+X11: new NetHack*highlight_prompt resource to control whether the persistent
+       prompt line between the map and message windows for the NetHack*slow
+       configuration will be highlighted when it's expecting input
+X11: NetHack*extcmd_height_delta resource can be used to adjust initial size
+       of the extended commands menu
+X11: status display split into three columns to accomodate Stone/Deaf/Lev/&c;
+       NetHack*status_condition.foreground, .background, and .showGrip
+       resources replaced by status_condition[1-3].*
+X11: more terminal-like default resources
+win32gui: save and load map colors from registry
+X11: add new character selection dialog, and obey player_selection:dialog
+unix: reduce makefile verbosity by default
+win32gui: new player selection dialog
+tty, X11, qt4, win32gui: compile-time option to allow some prompts remember
+       the input
+
+
+NetHack Community Patches (or Variation) Included
+-------------------------------------------------
+Malcolm Ryan's improved tin opener
+Ray Chason's keyboard may stop responding after locking or unlocking a door
+       when using altkeyhandler=nhraykey.dll
+Ray Chason's fix: window interfaces that support transparency may give away
+       unseen parts of the map
+Ray Chason's xprname should honor iflags.menu_tab_sep
+Ray Chason's punctuation for "That foo is really a mimic."
+Ray Chason's proper background tiles for lava and water
+Ray Chason's MS-DOS port restored to functionality with credit to Reddit user
+       b_helyer for the fix to sys/share/pcmain.c
+Ray Chason's MSDOS port support for some VESA modes
+Ray Chason's Qt4 windowport
+Darshan Shaligram's pet ranged attack
+Jason Dorje Short's key rebinding
+Maxime Bacoux's new DUMPLOG: compile-time option to enable logging of
+        end-of-game information into a text file
+
+
+Code Cleanup and Reorganization
+-------------------------------
+removed some unused variables and dead code
+the level generator no longer uses the native pRNG
index 757cbe5..fdb1945 100644 (file)
@@ -1,6 +1,17 @@
-.TH LEV_COMP 6 "16 May 1996"
-.\" NetHack 3.6  lev_comp.6    $NHDT-Date: 1432512786 2015/05/25 00:13:06 $  $NHDT-Branch: master $:$NHDT-Revision: 1.5 $
-.UC 4
+.TH LEV_COMP 6 "25 May 2015" NETHACK
+.de ND
+.ds Nd \\$3
+..
+.de NB
+.ds Nb \\$2
+..
+.de NR
+.ds Nr \\$2
+..
+.ND $NHDT-Date: 1524689549 2018/04/25 20:52:29 $
+.NB $NHDT-Branch: NetHack-3.6.0 $
+.NR $NHDT-Revision: 1.7 $
+.ds Na Kenneth Lorber
 .SH NAME
 lev_comp \- NetHack special levels compiler
 .SH SYNOPSIS
@@ -571,3 +582,7 @@ dgn_comp(6), nethack(6)
 .PP
 Probably infinite.
 Most importantly, still needs additional bounds checking.
+.SH COPYRIGHT
+This file is Copyright (C) \*(Na and was last modified \*(Nd (version
+\*(Nb:\*(Nr).
+NetHack may be freely redistributed.  See license for details.
index 7b55de3..7917996 100644 (file)
@@ -1,6 +1,17 @@
-.TH MAKEDEFS 6 "29 Apr 2010"
-.\" NetHack 3.6  makedefs.6    $NHDT-Date: 1432512786 2015/05/25 00:13:06 $  $NHDT-Branch: master $:$NHDT-Revision: 1.7 $
-.UC 4
+.TH MAKEDEFS 6 "25 May 2015" NETHACK
+.de ND
+.ds Nd \\$3
+..
+.de NB
+.ds Nb \\$2
+..
+.de NR
+.ds Nr \\$2
+..
+.ND $NHDT-Date: 1524689549 2018/04/25 20:52:29 $
+.NB $NHDT-Branch: NetHack-3.6.0 $
+.NR $NHDT-Revision: 1.10 $
+.ds Na Kenneth Lorber
 .SH NAME
 makedefs \- NetHack miscellaneous build-time functions
 .SH SYNOPSIS
@@ -85,6 +96,14 @@ Generate
 .I date.h
 and
 .I options
+file. It will read 
+.IR dat/gitinfo.txt ,
+only if it is present, to obtain 
+.B githash=
+and 
+.B gitbranch=
+ info and include related preprocessor #defines in
+.I date.h
 file.
 .br
 .TP
@@ -126,7 +145,7 @@ and
 .IR vis_tab.h .
 .SH LONG COMMANDS
 .TP
-.BI --debug
+.B --debug
 Show debugging output.
 .br
 .TP
@@ -250,3 +269,7 @@ The NetHack Development Team
 .SH "SEE ALSO"
 .PP
 .BR dgn_comp (6)
+.SH COPYRIGHT
+This file is Copyright (C) \*(Na and was last modified \*(Nd (version
+\*(Nb:\*(Nr).
+NetHack may be freely redistributed.  See license for details.
index f927030..1bf53a6 100644 (file)
@@ -1,5 +1,17 @@
-.TH NETHACK 6 "6 March 2004"
-.\" NetHack 3.6  nethack.6     $NHDT-Date: 1432512786 2015/05/25 00:13:06 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $
+.TH NETHACK 6 "2 February 2018" NETHACK
+.de ND
+.ds Nd \\$3
+..
+.de NB
+.ds Nb \\$2
+..
+.de NR
+.ds Nr \\$2
+..
+.ND $NHDT-Date: 1524689549 2018/04/25 20:52:29 $
+.NB $NHDT-Branch: NetHack-3.6.0 $
+.NR $NHDT-Revision: 1.14 $
+.ds Na Robert Patrick Rankin
 .SH NAME
 nethack \- Exploring The Mazes of Menace
 .SH SYNOPSIS
@@ -34,6 +46,9 @@ nethack \- Exploring The Mazes of Menace
 [
 .B \-ibm
 ]
+[
+.BR \-\-version [ :paste ]
+]
 .PP
 .B nethack
 [
@@ -207,6 +222,17 @@ The playground must contain several auxiliary files such as help files,
 the list of top scorers, and a subdirectory
 .I save
 where games are saved.
+.PP
+.B \-\-version
+can be used to cause NetHack to show the version information it
+was compiled with, then exit. That will include the
+.I git
+commit hash if the information was available when the game was compiled.
+On some platforms, such as windows and macosx, a variation 
+.B \-\-version:paste
+can be used to cause NetHack to show the version information, then exit,
+while also leaving a copy of the version information in the paste buffer 
+or clipboard for potential insertion into things like bug reports.
 .SH AUTHORS
 .PP
 Jay Fenlason (+ Kenny Woodland, Mike Thome and Jon Payne) wrote the
@@ -226,10 +252,17 @@ development by the Usenet.  Andries Brouwer has made this request for the
 distinction, as he may eventually release a new version of his own.
 .SH FILES
 .PP
-All files are in the playground, normally /usr/games/lib/nethackdir.
+Run-time configuration options were discussed above and use a platform
+specific name for a file in a platform specific location.  For Unix, the
+name is '.nethackrc' in the user's home directory.
+
+.br
+All other files are in the playground directory,
+normally /usr/games/lib/nethackdir.
 If DLB was defined during the compile, the data files and special levels
 will be inside a larger file, normally nhdat, instead of being separate
 files.
+
 .br
 .DT
 .ta \w'cmdhelp, opthelp, wizhelp\ \ \ 'u
@@ -237,7 +270,18 @@ nethack            The program itself.
 .br
 data, oracles, rumors  Data files used by NetHack.
 .br
-options, quest.dat     More data files.
+quest.dat, bogusmon    More data files.
+.br
+engrave, epitaph, tribute      Still more data files.
+.br
+symbols        Data file holding sets of specifications
+.br
+       for how to display monsters, objects, and
+.br
+       map features.
+.br
+options        Data file containing a description of the
+       build-time option settings.
 .br
 help, hh       Help data files.
 .br
@@ -253,26 +297,63 @@ license   Rules governing redistribution.
 .br
 record The list of top scorers.
 .br
-logfile        An extended list of games
+logfile        An extended list of games played
+.br
+       (optional).
+.br
+xlogfile       A more detailed version of 'logfile'
+.br
+       (also optional).
+.br
+paniclog       Record of exceptional conditions
+.br
+       discovered during program execution.
+.br
+xlock.nn       Description of dungeon level 'nn' of
 .br
-       played.
+       active game 'x' if there's a limit on the
 .br
-xlock.nnn      Description of a dungeon level.
+       number of simultaneously active games.
 .br
-perm   Lock file for xlock.dd.
+UUcccccc.nn    Alternate form for dungeon level 'nn'
 .br
-bonesDD.nn     Descriptions of the ghost and
+       of active game by user 'UU' playing
 .br
-       belongings of a deceased
+       character named 'cccccc' when there's no
 .br
-       adventurer.
+       limit on number of active games.
 .br
-save   A subdirectory containing the
+perm   Lock file for xlock.0 or UUcccccc.0.
 .br
-       saved games.
+bonesDD.nn     Descriptions of the ghost and belongings
+.br
+       of a deceased adventurer who met his
+.br
+       or her demise on level 'nn'.
+.br
+.\"following line should contain <space><tab>
+       
+.br
+save/  A subdirectory containing saved games.
+.br
+.\"following line should contain <space><tab>
+       
+.br
+sysconf        System-wide options.  Required if
+.br
+       program is built with 'SYSCF' option
+.br
+       enabled, ignored if not.
+.br
+
+The location of 'sysconf' is specified at build time and can't be changed
+except by updating source file "config.h" and rebuilding the program.
+.br
+
+In a perfect world, 'paniclog' would remain empty.
 .SH ENVIRONMENT
 .DT
-.ta \w'HACKPAGER or PAGER\ \ \ 'u
+.ta \w'NETHACKDIR or HACKDIR\ \ \ 'u
 USER or LOGNAME        Your login name.
 .br
 HOME           Your home directory.
@@ -289,21 +370,29 @@ MAILREADER        Replacement for default reader
 .br
        (probably /bin/mail or /usr/ucb/mail).
 .br
-NETHACKDIR     Playground.
+NETHACKDIR or HACKDIR  Playground.
 .br
 NETHACKOPTIONS String predefining several NetHack
 .br
        options.
 .br
 
-In addition, SHOPTYPE is used in debugging (wizard) mode.
+If the same option is specified in both NETHACKOPTIONS and .nethackrc,
+the value assigned in NETHACKOPTIONS takes precedence.
+.br
+
+SHOPTYPE and SPLEVTYPE can be used in debugging (wizard) mode.
+.br
+DEBUGFILES can be used if the program was built with 'DEBUG' enabled.
 .SH "SEE ALSO"
 .PP
 dgn_comp(6), lev_comp(6), recover(6)
 .SH BUGS
 .PP
 Probably infinite.
-
-
+.SH COPYRIGHT
+This file is Copyright (C) \*(Na and was last modified \*(Nd (version
+\*(Nb:\*(Nr).
+NetHack may be freely redistributed.  See license for details.
 .PP
 Dungeons & Dragons is a Trademark of Wizards of the Coast, Inc.
index e75cc93..4c99863 100644 (file)
@@ -1,4 +1,4 @@
-NETHACK(6)                                                    NETHACK(6)
+NETHACK(6)                                                          NETHACK(6)
 
 
 
@@ -6,143 +6,150 @@ NAME
        nethack - Exploring The Mazes of Menace
 
 SYNOPSIS
-       nethack [ -d directory ] [ -n ] [ -p profession ] [ -r race ] [
-       -[DX] ] [ -u playername ] [ -dec ] [ -ibm ]
+       nethack [ -d directory ] [ -n ] [ -p profession ] [ -r race ] [ -[DX] ]
+       [ -u playername ] [ -dec ] [ -ibm ] [ --version[:paste] ]
 
-       nethack [ -d directory ] -s [ -v ] [ -p profession ] [ -r race ]
-       playernames ]
+       nethack [ -d directory ] -s [ -v ] [ -p profession ] [ -r race ] [
+       playernames ]
 
 DESCRIPTION
-       NetHack is a display oriented Dungeons & Dragons(tm) - like game.
-       The standard tty display and command structure resemble rogue.
-
-       Other, more graphical display options  exist  if  you  are  using
-       either a PC, or an X11 interface.
-
-       To  get  started  you really only need to know two commands.  The
-       command ?  will give you a list of  the  available  commands  (as
-       well  as  other  information) and the command / will identify the
-       things you see on the screen.
-
-       To win the game (as opposed to merely playing to beat other  peo-
-       ple's  high scores) you must locate the Amulet of Yendor which is
-       somewhere below the 20th level of the dungeon  and  get  it  out.
-       Nobody  has  achieved this yet; anybody who does will probably go
-       down in history as a hero among heroes.
-
-       When the game ends, whether by your dying, quitting, or  escaping
-       from the caves, NetHack will give you (a fragment of) the list of
-       top scorers.  The scoring is based on many aspects of your behav-
-       ior,  but  a  rough  estimate is obtained by taking the amount of
-       gold you've found in the cave plus four times your (real) experi-
-       ence.  Precious stones may be worth a lot of gold when brought to
-       the exit.  There is a 10% penalty for getting yourself killed.
-
-       The environment variable NETHACKOPTIONS can be used to initialize
-       many  run-time  options.  The ? command provides a description of
-       these options and  syntax.   (The  -dec  and  -ibm  command  line
-       options  are  equivalent  to the decgraphics and ibmgraphics run-
-       time options described there, and are provided purely for  conve-
-       nience on systems supporting multiple types of terminals.)
-
-       Because the option list can be very long (particularly when spec-
-       ifying graphics characters), options may also be  included  in  a
-       configuration  file.   The default is located in your home direc-
-       tory and named .nethackrc on Unix systems.  On other systems, the
-       default  may  be  different, usually NetHack.cnf.  On DOS or Win-
-       dows, the name is defaults.nh, while on the Macintosh or BeOS, it
-       is  NetHack  Defaults.   The configuration file's location may be
-       specified by setting NETHACKOPTIONS to a string consisting of  an
-       @ character followed by the filename.
-
-       The -u playername option supplies the answer to the question "Who
-       are you?".  It overrides any name from the options or  configura-
-       tion  file, USER, LOGNAME, or getlogin(), which will otherwise be
-       tried in order.  If none of these provides  a  useful  name,  the
-       player  will be asked for one.  Player names (in conjunction with
-       uids) are used to identify save files, so you  can  have  several
-       saved  games under different names.  Conversely, you must use the
-       appropriate player name to restore a saved game.
-
-       A playername suffix can be used to specify the profession,  race,
-       alignment and/or gender of the character.  The full syntax of the
-       playername that  includes  a  suffix  is  "name-ppp-rrr-aaa-ggg".
-       "ppp"  are  at  least  the  first three letters of the profession
-       (this can also  be  specified  using  a  separate  -p  profession
-       option).  "rrr" are at least the first three letters of the char-
-       acter's race (this can also be specified using a separate -r race
-       option).   "aaa" are at last the first three letters of the char-
-       acter's alignment, and "ggg" are at least the first three letters
-       of the character's gender.  Any of the parts of the suffix may be
-       left out.
-
-       -p profession can be used to determine the character  profession,
-       also known as the role. You can specify either the male or female
-       name for the character role, or the first three characters of the
-       role  as  an  abbreviation.  -p @ has been retained to explicitly
-       request that a random role be chosen.  It may need to  be  quoted
-       with  a  backslash (\@) if @ is the "kill" character (see "stty")
-       for the terminal, in order to prevent the current input line from
-       being cleared.
-
-       Likewise,  -r  race can be used to explicitly request that a race
-       be chosen.
-
-       Leaving out any of these characteristics will result in you being
+       NetHack  is a display oriented Dungeons & Dragons(tm) - like game.  The
+       standard tty display and command structure resemble rogue.
+
+       Other, more graphical display options exist for most platforms.
+
+       To get started you really only need to know two commands.  The  command
+       ?   will  give  you  a list of the available commands (as well as other
+       information) and the command / will identify the things you see on  the
+       screen.
+
+       To  win  the  game (as opposed to merely playing to beat other people's
+       high scores) you must locate the Amulet of Yendor  which  is  somewhere
+       below the 20th level of the dungeon and get it out.  Few people achieve
+       this; most never do.  Those who have go down in history as heros  among
+       heroes  -  and then they find ways of making the game even harder.  See
+       the Guidebook section on Conduct if this game has gotten too  easy  for
+       you.
+
+       When  the  game ends, whether by your dying, quitting, or escaping from
+       the caves, NetHack will give you (a fragment of) the list of top  scor-
+       ers.   The  scoring  is  based  on many aspects of your behavior, but a
+       rough estimate is obtained by taking the amount of gold you've found in
+       the  cave  plus four times your (real) experience.  Precious stones may
+       be worth a lot of gold when brought  to  the  exit.   There  is  a  10%
+       penalty for getting yourself killed.
+
+       The  environment variable NETHACKOPTIONS can be used to initialize many
+       run-time options.  The  ?  command  provides  a  description  of  these
+       options and syntax.  (The -dec and -ibm command line options are equiv-
+       alent to the decgraphics and  ibmgraphics  run-time  options  described
+       there,  and  are  provided purely for convenience on systems supporting
+       multiple types of terminals.)
+
+       Because the option list can be very long (particularly when  specifying
+       graphics  characters),  options may also be included in a configuration
+       file.  The  default  is  located  in  your  home  directory  and  named
+       .nethackrc  on Unix systems.  On other systems, the default may be dif-
+       ferent,  usually  NetHack.cnf.   On  DOS  or  Windows,  the   name   is
+       defaults.nh,  while  on  the Macintosh or BeOS, it is NetHack Defaults.
+       The configuration file's location may be specified by setting  NETHACK-
+       OPTIONS  to a string consisting of an @ character followed by the file-
+       name.
+
+       The -u playername option supplies the answer to the question  "Who  are
+       you?".   It  overrides any name from the options or configuration file,
+       USER, LOGNAME, or getlogin(), which will otherwise be tried  in  order.
+       If  none  of these provides a useful name, the player will be asked for
+       one.  Player names (in conjunction with uids) are used to identify save
+       files, so you can have several saved games under different names.  Con-
+       versely, you must use the appropriate player name to  restore  a  saved
+       game.
+
+       A playername suffix can be used to specify the profession, race, align-
+       ment and/or gender of the character.  The full syntax of the playername
+       that  includes  a suffix is "name-ppp-rrr-aaa-ggg".  "ppp" are at least
+       the first three letters of the profession (this can also  be  specified
+       using  a  separate -p profession option).  "rrr" are at least the first
+       three letters of the character's race (this can also be specified using
+       a  separate -r race option).  "aaa" are at last the first three letters
+       of the character's alignment, and "ggg" are at least  the  first  three
+       letters  of the character's gender.  Any of the parts of the suffix may
+       be left out.
+
+       -p profession can be used to determine the character  profession,  also
+       known  as the role.  You can specify either the male or female name for
+       the character role, or the first three characters of  the  role  as  an
+       abbreviation.  -p @ has been retained to explicitly request that a ran-
+       dom role be chosen.  It may need to be quoted with a backslash (\@)  if
+       @  is  the  "kill" character (see "stty") for the terminal, in order to
+       prevent the current input line from being cleared.
+
+       Likewise, -r race can be used to explicitly request that a race be cho-
+       sen.
+
+       Leaving  out  any  of  these  characteristics  will result in you being
        prompted during the game startup for the information.
 
 
-       The -s option alone will print out the list of your scores on the
-       current version.  An immediately following -v reports on all ver-
-       sions  present in the score file.  The -s may also be followed by
-       arguments -p and -r to print the scores of particular  roles  and
-       races  only.  It may also be followed by one or more player names
-       to print the scores of the players mentioned, by 'all'  to  print
-       out all scores, or by a number to print that many top scores.
+       The -s option alone will print out the list of your scores on the  cur-
+       rent  version.   An  immediately  following  -v reports on all versions
+       present in the score file.  The -s may also be followed by arguments -p
+       and  -r to print the scores of particular roles and races only.  It may
+       also be followed by one or more player names to print the scores of the
+       players  mentioned, by 'all' to print out all scores, or by a number to
+       print that many top scores.
 
-       The  -n  option  suppresses  printing  of  any news from the game
-       administrator.
+       The -n option suppresses printing of any news from the game administra-
+       tor.
 
-       The -D or -X option will start the game in a special  non-scoring
-       discovery  mode.   -D will, if the player is the game administra-
-       tor, start in debugging (wizard) mode instead.
+       The  -D  or -X option will start the game in a special non-scoring dis-
+       covery mode.  -D will, if the player is the game  administrator,  start
+       in debugging (wizard) mode instead.
 
-       The -d option, which must be the first argument  if  it  appears,
-       supplies  a  directory  which  is to serve as the playground.  It
-       overrides the value from NETHACKDIR, HACKDIR,  or  the  directory
-       specified  by  the game administrator during compilation (usually
-       /usr/games/lib/nethackdir).  This option is usually  only  useful
-       to  the  game administrator.  The playground must contain several
-       auxiliary files such as help files, the list of top scorers,  and
-       a subdirectory save where games are saved.
+       The -d option, which must be the first argument if it appears, supplies
+       a directory which is to serve as  the  playground.   It  overrides  the
+       value  from NETHACKDIR, HACKDIR, or the directory specified by the game
+       administrator during compilation  (usually  /usr/games/lib/nethackdir).
+       This  option  is  usually  only  useful to the game administrator.  The
+       playground must contain several auxiliary files such as help files, the
+       list of top scorers, and a subdirectory save where games are saved.
 
 AUTHORS
-       Jay  Fenlason  (+ Kenny Woodland, Mike Thome and Jon Payne) wrote
-       the original hack, very much like rogue (but full of bugs).
+       Jay  Fenlason  (+  Kenny  Woodland, Mike Thome and Jon Payne) wrote the
+       original hack, very much like rogue (but full of bugs).
 
-       Andries Brouwer  continuously  deformed  their  sources  into  an
-       entirely different game.
+       Andries Brouwer continuously deformed their sources  into  an  entirely
+       different game.
 
-       Mike  Stephenson  has continued the perversion of sources, adding
-       various warped character classes and sadistic traps with the help
-       of  many  strange  people  who  reside  in that place between the
-       worlds, the Usenet Zone.  A number of these miscreants are immor-
-       talized  in  the  historical  roll  of dishonor and various other
-       places.
+       Mike Stephenson has continued the perversion of sources, adding various
+       warped character classes and sadistic  traps  with  the  help  of  many
+       strange  people who reside in that place between the worlds, the Usenet
+       Zone.  A number of these miscreants are immortalized in the  historical
+       roll of dishonor and various other places.
 
-       The resulting mess is now called NetHack, to denote its  develop-
-       ment  by  the  Usenet.  Andries Brouwer has made this request for
-       the distinction, as he may eventually release a  new  version  of
-       his own.
+       The  resulting mess is now called NetHack, to denote its development by
+       the Usenet.  Andries Brouwer has made this request for the distinction,
+       as he may eventually release a new version of his own.
 
 FILES
-       All     files     are     in     the     playground,     normally
-       /usr/games/lib/nethackdir.  If DLB was defined  during  the  com-
-       pile,  the  data files and special levels will be inside a larger
-       file, normally nhdat, instead of being separate files.
+       Run-time  configuration options were discussed above and use a platform
+       specific name for a file in a platform specific  location.   For  Unix,
+       the name is '.nethackrc' in the user's home directory.
+
+       All   other   files   are   in   the   playground  directory,  normally
+       /usr/games/lib/nethackdir.  If DLB was defined during the compile,  the
+       data  files  and  special levels will be inside a larger file, normally
+       nhdat, instead of being separate files.
+
        nethack                     The program itself.
        data, oracles, rumors       Data files used by NetHack.
-       options, quest.dat          More data files.
+       quest.dat, bogusmon         More data files.
+       engrave, epitaph, tribute   Still more data files.
+       symbols                     Data file holding sets of specifications
+                                   for how to display monsters, objects, and
+                                   map features.
+       options                     Data file containing a description  of  the
+                                   build-time option settings.
        help, hh                    Help data files.
        cmdhelp, opthelp, wizhelp   More help data files.
        *.lev                       Predefined special levels.
@@ -150,30 +157,54 @@ FILES
        history                     A short history of NetHack.
        license                     Rules governing redistribution.
        record                      The list of top scorers.
-       logfile                     An extended list of games
-                                   played.
-       xlock.nnn                   Description of a dungeon level.
-       perm                        Lock file for xlock.dd.
-       bonesDD.nn                  Descriptions of the ghost and
-                                   belongings of a deceased
-                                   adventurer.
-       save                        A subdirectory containing the
-                                   saved games.
+       logfile                     An extended list of games played
+                                   (optional).
+       xlogfile                    A more detailed version of 'logfile'
+                                   (also optional).
+       paniclog                    Record of exceptional conditions
+                                   discovered during program execution.
+       xlock.nn                    Description of dungeon level 'nn' of
+                                   active game 'x' if there's a limit on the
+                                   number of simultaneously active games.
+       UUcccccc.nn                 Alternate form for dungeon level 'nn'
+                                   of active game by user 'UU' playing
+                                   character named 'cccccc' when there's no
+                                   limit on number of active games.
+       perm                        Lock file for xlock.0 or UUcccccc.0.
+       bonesDD.nn                  Descriptions of the ghost and belongings
+                                   of a deceased adventurer who met his
+                                   or her demise on level 'nn'.
+
+       save/                       A subdirectory containing saved games.
+
+       sysconf                     System-wide options.  Required if
+                                   program is built with 'SYSCF' option
+                                   enabled, ignored if not.
+
+       The  location  of  'sysconf'  is  specified  at build time and can't be
+       changed except by updating source file "config.h"  and  rebuilding  the
+       program.
+
+       In a perfect world, 'paniclog' would remain empty.
 
 ENVIRONMENT
-       USER or LOGNAME      Your login name.
-       HOME                 Your home directory.
-       SHELL                Your shell.
-       TERM                 The type of your terminal.
-       HACKPAGER or PAGER   Replacement for default pager.
-       MAIL                 Mailbox file.
-       MAILREADER           Replacement for default reader
-                            (probably /bin/mail or /usr/ucb/mail).
-       NETHACKDIR           Playground.
-       NETHACKOPTIONS       String predefining several NetHack
-                            options.
-
-       In addition, SHOPTYPE is used in debugging (wizard) mode.
+       USER or LOGNAME         Your login name.
+       HOME                    Your home directory.
+       SHELL                   Your shell.
+       TERM                    The type of your terminal.
+       HACKPAGER or PAGER      Replacement for default pager.
+       MAIL                    Mailbox file.
+       MAILREADER              Replacement for default reader
+                               (probably /bin/mail or /usr/ucb/mail).
+       NETHACKDIR or HACKDIR   Playground.
+       NETHACKOPTIONS          String predefining several NetHack
+                               options.
+
+       If  the same option is specified in both NETHACKOPTIONS and .nethackrc,
+       the value assigned in NETHACKOPTIONS takes precedence.
+
+       SHOPTYPE and SPLEVTYPE can be used in debugging (wizard) mode.
+       DEBUGFILES can be used if the program was built with 'DEBUG' enabled.
 
 SEE ALSO
        dgn_comp(6), lev_comp(6), recover(6)
@@ -187,4 +218,4 @@ BUGS
 
 
 
-                              6 March 2004                    NETHACK(6)
+                                7 December 2015                     NETHACK(6)
index 4c9f509..1209d31 100644 (file)
@@ -1,6 +1,17 @@
-.TH RECOVER 6 "9 January 1993"
-.\" NetHack 3.6  recover.6     $NHDT-Date: 1432512786 2015/05/25 00:13:06 $  $NHDT-Branch: master $:$NHDT-Revision: 1.6 $
-.UC 4
+.TH RECOVER 6 "14 December 2015" NETHACK
+.de ND
+.ds Nd \\$3
+..
+.de NB
+.ds Nb \\$2
+..
+.de NR
+.ds Nr \\$2
+..
+.ND $NHDT-Date: 1524689550 2018/04/25 20:52:30 $
+.NB $NHDT-Branch: NetHack-3.6.0 $
+.NR $NHDT-Revision: 1.9 $
+.ds Na Kenneth Lorber
 .SH NAME
 recover \- recover a NetHack game interrupted by disaster
 .SH SYNOPSIS
@@ -130,3 +141,7 @@ determine.
 .I recover
 should be taught to use the nethack playground locking mechanism to
 avoid conflicts.
+.SH COPYRIGHT
+This file is Copyright (C) \*(Na and was last modified \*(Nd (version
+\*(Nb:\*(Nr).
+NetHack may be freely redistributed.  See license for details.
index 2ebf9f8..e648b23 100644 (file)
@@ -401,7 +401,7 @@ status_enablefield(int fldindex, char fldname, char fieldfmt, boolean enable)
                   BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, 
                   BL_LEVELDESC, BL_EXP, BL_CONDITION
                -- There are MAXBLSTATS status fields (from botl.h)
-status_update(int fldindex, genericptr_t ptr, int chg, int percentage)
+status_update(int fldindex, genericptr_t ptr, int chg, int percentage, int color, long *colormasks)
                -- update the value of a status field.
                -- the fldindex identifies which field is changing and
                   is an integer index value from botl.h
@@ -417,58 +417,124 @@ status_update(int fldindex, genericptr_t ptr, int chg, int percentage)
                -- ptr is usually a "char *", unless fldindex is BL_CONDITION.
                   If fldindex is BL_CONDITION, then ptr is a long value with
                   any or none of the following bits set (from botl.h):
-                       BL_MASK_BLIND           0x00000001L
-                       BL_MASK_CONF            0x00000002L
-                       BL_MASK_FOODPOIS        0x00000004L
-                       BL_MASK_ILL             0x00000008L
-                       BL_MASK_HALLU           0x00000010L
-                       BL_MASK_STUNNED         0x00000020L
-                       BL_MASK_SLIMED          0x00000040L
+                        BL_MASK_STONE           0x00000001L
+                        BL_MASK_SLIME           0x00000002L
+                        BL_MASK_STRNGL          0x00000004L
+                        BL_MASK_FOODPOIS        0x00000008L
+                        BL_MASK_TERMILL         0x00000010L
+                        BL_MASK_BLIND           0x00000020L
+                        BL_MASK_DEAF            0x00000040L
+                        BL_MASK_STUN            0x00000080L
+                        BL_MASK_CONF            0x00000100L
+                        BL_MASK_HALLU           0x00000200L
+                        BL_MASK_LEV             0x00000400L
+                        BL_MASK_FLY             0x00000800L
+                        BL_MASK_RIDE            0x00001000L
                -- The value passed for BL_GOLD includes a leading
                   symbol for GOLD "$:nnn". If the window port needs to use 
                   the textual gold amount without the leading "$:" the port 
                   will have to add 2 to the passed "ptr" for the BL_GOLD case.
+                -- color is an unsigned int.
+                   int & 0x00FF = color CLR_*
+                   int >> 8 = attribute (if any)
+
+                   This contains the color and attribute that the field should
+                   be displayed in.
+
+                   This is relevant for everything except BL_CONDITION fldindex.
+                   If fldindex is BL_CONDITION, this parameter should be ignored,
+                   as condition hilighting is done via the next colormasks
+                   parameter instead.
+
+                -- colormasks - pointer to cond_hilites[] array of colormasks.
+
+                   Only relevant for BL_CONDITION fldindex. The window port
+                   should ignore this parameter for other fldindex values.
+
+                   Each condition bit must only ever appear in one of the
+                   CLR_ array members, but can appear in multiple HL_ATTCLR_
+                   offsets (because more than one attribute can co-exist).
+
+                   For the user's chosen set of BL_MASK_ condition bits,
+                   They are stored internally in the cond_hilites[] array,
+                   at the array offset aligned to the color those condtion
+                   bits should display in.
+
+                   For example, if the user has chosen to display strngl
+                   and stone and termill in red and inverse,
+
+                        BL_MASK_SLIME           0x00000002
+                        BL_MASK_STRNGL          0x00000004
+                        BL_MASK_TERMILL         0x00000010
+
+                   The bitmask corresponding to those conditions is
+                   0x00000016 (or 00010110 in binary) and the color
+                   is at offset 1 (CLR_RED).
+
+                   Here is how that is stored in the cond_hilites[] array:
+
+                   +------+----------------------+--------------------+
+                   |array |                      |                    |
+                   |offset| macro for indexing   |   bitmask          |
+                   |------+----------------------+--------------------+
+                   |   0  |   CLR_BLACK          |                    |
+                   +------+----------------------+--------------------+
+                   |   1  |   CLR_RED            |   00010110         |
+                   +------+----------------------+--------------------+
+                   |   2  |   CLR_GREEN          |                    |
+                   +------+----------------------+--------------------+
+                   |   3  |   CLR_BROWN          |                    |
+                   +------+----------------------+--------------------+
+                   |   4  |   CLR_BLUE           |                    |
+                   +------+----------------------+--------------------+
+                   |   5  |   CLR_MAGENTA        |                    |
+                   +------+----------------------+--------------------+
+                   |   6  |   CLR_CYAN           |                    |
+                   +------+----------------------+--------------------+
+                   |   7  |   CLR_GRAY           |                    |
+                   +------+----------------------+--------------------+
+                   |   8  |   NO_COLOR           |                    |
+                   +------+----------------------+--------------------+
+                   |   9  |   CLR_ORANGE         |                    |
+                   +------+----------------------+--------------------+
+                   |  10  |   CLR_BRIGHT_GREEN   |                    |
+                   +------+----------------------+--------------------+
+                   |  11  |   CLR_BRIGHT_YELLOW  |                    |
+                   +------+----------------------+--------------------+
+                   |  12  |   CLR_BRIGHT_BLUE    |                    |
+                   +------+----------------------+--------------------+
+                   |  13  |   CLR_BRIGHT_MAGENTA |                    |
+                   +------+----------------------+--------------------+
+                   |  14  |   CLR_BRIGHT_CYAN    |                    |
+                   +------+----------------------+--------------------+
+                   |  15  |   CLR_WHITE          |                    |
+                   +------+----------------------+--------------------+
+                   |  16  |   HL_ATTCLR_DIM      |                    | CLR_MAX
+                   +------+----------------------+--------------------+
+                   |  17  |   HL_ATTCLR_BLINK    |                    |
+                   +------+----------------------+--------------------+
+                   |  18  |   HL_ATTCLR_ULINE    |                    |
+                   +------+----------------------+--------------------+
+                   |  19  |   HL_ATTCLR_INVERSE  |   00010110         |
+                   +------+----------------------+--------------------+
+                   |  20  |   HL_ATTCLR_BOLD     |                    |
+                   +------+----------------------+--------------------+
+                   |  21  |  beyond array boundary                    | BL_ATTCLR_MAX
+
+                   The window port can AND (&) the bits passed in the
+                   ptr argument to status_update() with any non-zero
+                   entries in the cond_hilites[] array to determine
+                   the color and attributes for displaying the
+                   condition on the screen for the user.
+
+                   If the bit for a particular condition does not
+                   appear in any of the cond_hilites[] array offsets,
+                   that condition should be displayed in the default
+                   color and attributes.
 
 status_finish() -- called when it is time for the window port to tear down
                   the status display and free allocated memory, etc.
 
-status_threshold(int fldidx, int threshholdtype, anything threshold, 
-                                       int behavior, int under, int over)
-               -- called when a hiliting preference is added, changed, or
-                  removed.
-               -- the fldindex identifies which field is having its hiliting
-                  preference set. It is an integer index value from botl.h
-               -- fldindex could be any one of the following from botl.h:
-                  BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, 
-                  BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX, 
-                  BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, 
-                  BL_LEVELDESC, BL_EXP, BL_CONDITION
-               -- datatype is P_INT, P_UINT, P_LONG, or P_MASK.
-               -- threshold is an "anything" union which can contain the 
-                  datatype value.
-               -- behavior is used to define how threshold is used and can
-                  be BL_TH_NONE, BL_TH_VAL_PERCENTAGE, BL_TH_VAL_ABSOLUTE,
-                  or BL_TH_UPDOWN. BL_TH_NONE means don't do anything above
-                  or below the threshold.  BL_TH_VAL_PERCENTAGE treats the
-                  threshold value as a precentage of the maximum possible
-                  value. BL_TH_VAL_ABSOLUTE means that the threshold is an
-                  actual value. BL_TH_UPDOWN means that threshold is not
-                  used, and the two below/above hilite values indicate how
-                  to display something going down (under) or rising (over).                
-               -- under is the hilite attribute used if value is below the 
-                  threshold. The attribute can be BL_HILITE_NONE, 
-                  BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one 
-                  of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN, 
-                  CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY, 
-                  CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE, 
-                  CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
-               -- over is the hilite attribute used if value is at or above 
-                  the threshold. The attribute can be BL_HILITE_NONE, 
-                  BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one 
-                  of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN, 
-                  CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY, 
-                  CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE, 
-                  CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
 
 E.  Misc. Routines
 
@@ -703,6 +769,7 @@ to support:
   |  softkeyboard      | WC2_SOFTKEYBOARD   | wc2_softkeyboard   |boolean |
   |  wraptext          | WC2_WRAPTEXT       | wc2_wraptext       |boolean |
   |  selectsaved       | WC2_SELECTSAVED    | wc2_selectsaved    |boolean |
+  |  hitpointbar       | WC2_HITPOINTBAR    | wc2_hitpointbar    |boolean |
   +--------------------+--------------------+--------------------+--------+
 
 align_message  -- where to place message window (top, bottom, left, right)
@@ -723,6 +790,7 @@ font_status -- port should use a font by this name for status display.
 font_text      -- port should use a font by this name for text windows.
 fullscreen      -- port should try to use the whole screen.
 hilite_pet     -- port should mark pets in some special way on the map.
+hitpointbar    -- port should show a graphical bar representing hit points
 map_mode       -- port should display the map in the manner specified.
 player_selection
                -- dialog or prompts for choosing character.
index 4b7f55d..4e5193f 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 artifact.h      $NHDT-Date: 1433050871 2015/05/31 05:41:11 $  $NHDT-Branch: master $:$NHDT-Revision: 1.11 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef ARTIFACT_H
@@ -56,14 +57,16 @@ struct artifact {
 };
 
 /* invoked properties with special powers */
-#define TAMING (LAST_PROP + 1)
-#define HEALING (LAST_PROP + 2)
-#define ENERGY_BOOST (LAST_PROP + 3)
-#define UNTRAP (LAST_PROP + 4)
-#define CHARGE_OBJ (LAST_PROP + 5)
-#define LEV_TELE (LAST_PROP + 6)
-#define CREATE_PORTAL (LAST_PROP + 7)
-#define ENLIGHTENING (LAST_PROP + 8)
-#define CREATE_AMMO (LAST_PROP + 9)
+enum invoke_prop_types {
+    TAMING = (LAST_PROP + 1),
+    HEALING,
+    ENERGY_BOOST,
+    UNTRAP,
+    CHARGE_OBJ,
+    LEV_TELE,
+    CREATE_PORTAL,
+    ENLIGHTENING,
+    CREATE_AMMO
+};
 
 #endif /* ARTIFACT_H */
index b351038..8948e52 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6  artilist.h      $NHDT-Date: 1433050874 2015/05/31 05:41:14 $  $NHDT-Branch: master $:$NHDT-Revision: 1.16 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2017. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifdef MAKEDEFS_C
@@ -103,7 +104,8 @@ STATIC_OVL NEARDATA struct artifact artilist[] = {
       FIRE(5, 0), FIRE(0, 0), NO_CARY, 0, A_NONE, NON_PM, NON_PM, 3000L,
       NO_COLOR),
 
-    A("Dragonbane", BROADSWORD, (SPFX_RESTR | SPFX_DCLAS), 0, S_DRAGON,
+    A("Dragonbane", BROADSWORD,
+      (SPFX_RESTR | SPFX_DCLAS | SPFX_REFLECT), 0, S_DRAGON,
       PHYS(5, 0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 500L,
       NO_COLOR),
 
@@ -207,6 +209,9 @@ A("The Palantir of Westernesse",        CRYSTAL_BALL,
       PHYS(5, 0), NO_DFNS, NO_CARY, CREATE_AMMO, A_CHAOTIC, PM_RANGER, NON_PM,
       4000L, NO_COLOR),
 
+    /* MKoT has an additional carry property if the Key is not cursed (for
+       rogues) or blessed (for non-rogues):  #untrap of doors and chests
+       will always find any traps and disarming those will always succeed */
     A("The Master Key of Thievery", SKELETON_KEY,
       (SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL | SPFX_SPEAK),
       (SPFX_WARN | SPFX_TCTRL | SPFX_HPHDAM), 0, NO_ATTK, NO_DFNS, NO_CARY,
index ed2c5d8..fe97a9f 100644 (file)
@@ -7,14 +7,16 @@
 #ifndef ATTRIB_H
 #define ATTRIB_H
 
-#define A_STR 0
-#define A_INT 1
-#define A_WIS 2
-#define A_DEX 3
-#define A_CON 4
-#define A_CHA 5
-
-#define A_MAX 6 /* used in rn2() selection of attrib */
+enum attrib_types {
+    A_STR = 0,
+    A_INT,
+    A_WIS,
+    A_DEX,
+    A_CON,
+    A_CHA,
+
+    A_MAX /* used in rn2() selection of attrib */
+};
 
 #define ABASE(x) (u.acurr.a[x])
 #define ABON(x) (u.abon.a[x])
index 8945fa2..ce2a944 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6  botl.h  $NHDT-Date: 1433105378 2015/05/31 20:49:38 $  $NHDT-Branch: status_hilite $:$NHDT-Revision: 1.14 $ */
+/* NetHack 3.6  botl.h  $NHDT-Date: 1452660165 2016/01/13 04:42:45 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $ */
 /* Copyright (c) Michael Allison, 2003                            */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -9,71 +9,61 @@
  * than COLNO
  *
  * longest practical second status line at the moment is
- *     Astral Plane $:12345 HP:700(700) Pw:111(111) AC:-127 Xp:30/123456789
- *     T:123456 Satiated Conf FoodPois Ill Blind Stun Hallu Overloaded
- * -- or somewhat over 130 characters
+Astral Plane \GXXXXNNNN:123456 HP:1234(1234) Pw:1234(1234) AC:-127
+ Xp:30/123456789 T:123456  Stone Slime Strngl FoodPois TermIll
+ Satiated Overloaded Blind Deaf Stun Conf Hallu Lev Ride
+ * -- or about 185 characters.  '$' gets encoded even when it
+ * could be used as-is.  The first five status conditions are fatal
+ * so it's rare to have more than one at a time.
+ *
+ * When the full line is wider than the map, the basic status line
+ * formatting will move less important fields to the end, so if/when
+ * truncation is necessary, it will chop off the least significant
+ * information.
  */
-#if COLNO <= 140
-#define MAXCO 160
+#if COLNO <= 160
+#define MAXCO 200
 #else
-#define MAXCO (COLNO + 20)
+#define MAXCO (COLNO + 40)
 #endif
 
-#ifdef STATUS_VIA_WINDOWPORT
-#if 0
-/* clang-format off */
-#define BL_FLUSH        -1
-#define BL_TITLE        0
-#define BL_STR          1
-#define BL_DX           2
-#define BL_CO           3
-#define BL_IN           4
-#define BL_WI           5
-#define BL_CH           6
-#define BL_ALIGN        7
-#define BL_SCORE        8
-#define BL_CAP          9
-#define BL_GOLD         10
-#define BL_ENE          11
-#define BL_ENEMAX       12
-#define BL_XP           13
-#define BL_AC           14
-#define BL_HD           15
-#define BL_TIME         16
-#define BL_HUNGER       17
-#define BL_HP           18
-#define BL_HPMAX        19
-#define BL_LEVELDESC    20
-#define BL_EXP          21
-#define BL_CONDITION    22
-/* clang-format on */
+enum statusfields {
+    BL_CHARACTERISTICS = -2, /* alias for BL_STR..BL_CH */
+    BL_FLUSH = -1, BL_TITLE = 0,
+    BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,  /* 1..6 */
+    BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX, /* 7..12 */
+    BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, BL_LEVELDESC, /* 13..20 */
+    BL_EXP, BL_CONDITION
+};
 
-#else
-enum statusfields { BL_FLUSH = -1, BL_TITLE = 0, BL_STR, BL_DX, BL_CO, BL_IN,
-BL_WI, BL_CH, BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
-BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, BL_LEVELDESC,
-BL_EXP, BL_CONDITION };
-#define MAXBLSTATS      BL_CONDITION+1
+enum relationships { LT_VALUE = -1, EQ_VALUE, GT_VALUE, TXT_VALUE };
+
+#define MAXBLSTATS      (BL_CONDITION + 1)
 
 #define BEFORE  0
 #define NOW     1
-#endif
 
 /* Boolean condition bits for the condition mask */
 
 /* clang-format off */
-#define BL_MASK_BLIND           0x00000001L
-#define BL_MASK_CONF            0x00000002L
-#define BL_MASK_FOODPOIS        0x00000004L
-#define BL_MASK_ILL             0x00000008L
-#define BL_MASK_HALLU           0x00000010L
-#define BL_MASK_STUNNED         0x00000020L
-#define BL_MASK_SLIMED          0x00000040L
+#define BL_MASK_STONE           0x00000001L
+#define BL_MASK_SLIME           0x00000002L
+#define BL_MASK_STRNGL          0x00000004L
+#define BL_MASK_FOODPOIS        0x00000008L
+#define BL_MASK_TERMILL         0x00000010L
+#define BL_MASK_BLIND           0x00000020L
+#define BL_MASK_DEAF            0x00000040L
+#define BL_MASK_STUN            0x00000080L
+#define BL_MASK_CONF            0x00000100L
+#define BL_MASK_HALLU           0x00000200L
+#define BL_MASK_LEV             0x00000400L
+#define BL_MASK_FLY             0x00000800L
+#define BL_MASK_RIDE            0x00001000L
 /* clang-format on */
 
 #define REASSESS_ONLY TRUE
 
-#ifdef STATUS_HILITES
+/* #ifdef STATUS_HILITES */
 /* hilite status field behavior - coloridx values */
 #define BL_HILITE_NONE -1    /* no hilite of this field */
 #define BL_HILITE_INVERSE -2 /* inverse hilite */
@@ -84,9 +74,26 @@ BL_EXP, BL_CONDITION };
 #define BL_TH_VAL_ABSOLUTE 101   /* threshold is particular value */
 #define BL_TH_UPDOWN 102         /* threshold is up or down change */
 #define BL_TH_CONDITION 103      /* threshold is bitmask of conditions */
-#endif
+#define BL_TH_TEXTMATCH 104      /* threshold text value to match against */
+#define BL_TH_ALWAYS_HILITE 105  /* highlight regardless of value */
+
+
+#define HL_ATTCLR_DIM     CLR_MAX + 0
+#define HL_ATTCLR_BLINK   CLR_MAX + 1
+#define HL_ATTCLR_ULINE   CLR_MAX + 2
+#define HL_ATTCLR_INVERSE CLR_MAX + 3
+#define HL_ATTCLR_BOLD    CLR_MAX + 4
+#define BL_ATTCLR_MAX     CLR_MAX + 5
+
+enum hlattribs { HL_UNDEF   = 0x00,
+                 HL_NONE    = 0x01,
+                 HL_BOLD    = 0x02,
+                 HL_INVERSE = 0x04,
+                 HL_ULINE   = 0x08,
+                 HL_BLINK   = 0x10,
+                 HL_DIM     = 0x20 };
+/* #endif STATUS_HILITES */
 
 extern const char *status_fieldnames[]; /* in botl.c */
-#endif
 
 #endif /* BOTL_H */
index 141a684..828131e 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 config.h        $NHDT-Date: 1447728911 2015/11/17 02:55:11 $  $NHDT-Branch: master $:$NHDT-Revision: 1.91 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2016. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef CONFIG_H /* make sure the compiler does not see the typedefs twice */
@@ -11,6 +12,7 @@
  *              For "UNIX" select BSD, ULTRIX, SYSV, or HPUX in unixconf.h.
  *              A "VMS" option is not needed since the VMS C-compilers
  *              provide it (no need to change sec#1, vmsconf.h handles it).
+ *              MacOSX uses the UNIX configuration, not the old MAC one.
  */
 
 #define UNIX /* delete if no fork(), exec() available */
 #define NEWS     "news"     /* the file containing the latest hack news */
 #define PANICLOG "paniclog" /* log of panic and impossible events */
 
+/* alternative paniclog format, better suited for public servers with
+   many players, as it saves the player name and the game start time */
+/* #define PANICLOG_FMT2 */
+
 /*
  *      PERSMAX, POINTSMIN, ENTRYMAX, PERS_IS_UID:
  *      These control the contents of 'record', the high-scores file.
 /* #define DLB */ /* not supported on all platforms */
 
 /*
+ *      Defining REPRODUCIBLE_BUILD causes 'util/makedefs -v' to construct
+ *      date+time in include/date.h (to be shown by nethack's 'v' command)
+ *      from SOURCE_DATE_EPOCH in the build environment rather than use
+ *      current date+time when makedefs is run.
+ *
+ *      [The version string will show "last revision <date><time>" instead
+ *      of "last build <date><time>" if SOURCE_DATE_EPOCH has a value
+ *      which seems valid at the time date.h is generated.  The person
+ *      building the program is responsible for setting it correctly,
+ *      and the value should be in UTC rather than local time.  NetHack
+ *      normally uses local time and doesn't display timezone so toggling
+ *      REPRODUCIBLE_BUILD on or off might yield a date+time that appears
+ *      to be incorrect relative to what the other setting produced.]
+ *
+ *      Intent is to be able to rebuild the program with the same value
+ *      and obtain an identical copy as was produced by a previous build.
+ *      Not necessary for normal game play....
+ */
+/* #define REPRODUCIBLE_BUILD */ /* use getenv("SOURCE_DATE_EPOCH") instead
+                                    of current time when creating date.h */
+
+/*
  *      Defining INSURANCE slows down level changes, but allows games that
  *      died due to program or system crashes to be resumed from the point
  *      of the last level change, after running a utility program.
  */
 #endif /* CHDIR */
 
-/* If GENERIC_USERNAMES is defined, and the player's username is found
- * in the list, prompt for character name instead of using username.
- * A public server should probably disable this. */
-#define GENERIC_USERNAMES "play player game games nethack nethacker"
-
 /*
  * Section 3:   Definitions that may vary with system type.
  *              For example, both schar and uchar should be short ints on
@@ -427,6 +450,14 @@ typedef unsigned char uchar;
 
 #define DOAGAIN '\001' /* ^A, the "redo" key used in cmd.c and getline.c */
 
+/* CONFIG_ERROR_SECURE: If user makes NETHACKOPTIONS point to a file ...
+ *  TRUE: Show the first error, nothing else.
+ *  FALSE: Show all errors as normal, with line numbers and context.
+ */
+#ifndef CONFIG_ERROR_SECURE
+# define CONFIG_ERROR_SECURE TRUE
+#endif
+
 /*
  * Section 4:  EXPERIMENTAL STUFF
  *
@@ -435,9 +466,40 @@ typedef unsigned char uchar;
  * bugs left here.
  */
 
-/* #define STATUS_VIA_WINDOWPORT */ /* re-work of the status line
-                                       updating process */
-/* #define STATUS_HILITES */        /* support hilites of status fields */
+/* TTY_TILES_ESCCODES: Enable output of special console escape codes
+ * which act as hints for external programs such as EbonHack.
+ *
+ * Only for TTY_GRAPHICS.
+ *
+ * All of the escape codes are in the format ESC [ N z, where N can be
+ * one or more positive integer values, separated by semicolons.
+ * For example ESC [ 1 ; 0 ; 120 z
+ *
+ * Possible codes are:
+ *  ESC [ 1 ; 0 ; n ; m z   Start a glyph (aka a tile) number n, with flags m
+ *  ESC [ 1 ; 1 z           End a glyph.
+ *  ESC [ 1 ; 2 ; n z       Select a window n to output to.
+ *  ESC [ 1 ; 3 z           End of data. NetHack has finished sending data,
+ *                          and is waiting for input.
+ *
+ * Whenever NetHack outputs anything, it will first output the "select window"
+ * code. Whenever NetHack outputs a tile, it will first output the "start
+ * glyph" code, then the escape codes for color and the glyph character
+ * itself, and then the "end glyph" code.
+ *
+ * To compile NetHack with this, add tile.c to WINSRC and tile.o to WINOBJ
+ * in the hints file or Makefile.
+ * Set boolean option vt_tiledata in your config file to turn this on.
+ * Note that gnome-terminal at least doesn't work with this. */
+/* #define TTY_TILES_ESCCODES */
+
+/* NetHack will execute an external program whenever a new message-window
+ * message is shown.  The program to execute is given in environment variable
+ * NETHACK_MSGHANDLER.  It will get the message as the only parameter.
+ * Only available with POSIX_TYPES or GNU C */
+/* #define MSGHANDLER */
+
+#define STATUS_HILITES         /* support hilites of status fields */
 
 /* #define WINCHAIN */              /* stacked window systems */
 
@@ -453,8 +515,45 @@ typedef unsigned char uchar;
    but it isn't necessary for successful operation of the program */
 #define FREE_ALL_MEMORY             /* free all memory at exit */
 
+/* EDIT_GETLIN makes the string input in TTY, Qt4, and X11
+   so some prompts will remember the previously input text
+   (within the same session) */
+/* #define EDIT_GETLIN */
+
+/* #define DUMPLOG */  /* End-of-game dump logs */
+#ifdef DUMPLOG
+
+#ifndef DUMPLOG_MSG_COUNT
+#define DUMPLOG_MSG_COUNT   50
+#endif
+
+#ifndef DUMPLOG_FILE
+#define DUMPLOG_FILE        "/tmp/nethack.%n.%d.log"
+/* DUMPLOG_FILE allows following placeholders:
+   %% literal '%'
+   %v version (eg. "3.6.1-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
+   DUMPLOG_FILE is not used if SYSCF is defined
+*/
+#endif
+
+#endif
+
+
 /* End of Section 4 */
 
+#ifdef TTY_TILES_ESCCODES
+# ifndef USE_TILES
+#  define USE_TILES
+# endif
+#endif
+
 #include "global.h" /* Define everything else according to choices above */
 
 #endif /* CONFIG_H */
index e533973..738fd96 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 config1.h       $NHDT-Date: 1432512781 2015/05/25 00:13:01 $  $NHDT-Branch: master $:$NHDT-Revision: 1.17 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef CONFIG1_H
index bddc8e9..c24da8d 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 context.h       $NHDT-Date: 1447653421 2015/11/16 05:57:01 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */
+/* NetHack 3.6 context.h       $NHDT-Date: 1455907260 2016/02/19 18:41:00 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.30 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* If you change the context structure make sure you increment EDITLEVEL in */
@@ -93,7 +94,15 @@ struct tribute_info {
 struct novel_tracking { /* for choosing random passage when reading novel */
     unsigned id;        /* novel oid from previous passage selection */
     int count;          /* number of passage indices available in pasg[] */
-    xchar pasg[30];     /* pasg[0..count] are passage indices */
+    xchar pasg[30];     /* pasg[0..count-1] are passage indices */
+    /* tribute file is allowed to have more than 30 passages for a novel;
+       if it does, reading will first choose a random subset of 30 of them;
+       reading all 30 or switching to a different novel and then back again
+       will pick a new subset, independent of previous ones so might not
+       contain all--or even any--of the ones left out of the prior subset;
+       chatting with Death works the same as reading a novel except that
+       sometimes he delivers one of a few hardcoded messages rather than a
+       passage from the Death Quotes section of dat/tribute */
 };
 
 struct context_info {
index a31a0bf..e800fb8 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 coord.h $NHDT-Date: 1432512778 2015/05/25 00:12:58 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef COORD_H
index 27fccf9..1717c75 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6  decl.h  $NHDT-Date: 1432512782 2015/05/25 00:13:02 $  $NHDT-Branch: master $:$NHDT-Revision: 1.76 $ */
+/* NetHack 3.6  decl.h  $NHDT-Date: 1496531104 2017/06/03 23:05:04 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.82 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2007. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef DECL_H
@@ -188,8 +189,6 @@ E NEARDATA struct kinfo {
 } killer;
 
 E long done_money;
-E const char *configfile;
-E char lastconfigfile[BUFSZ]; /* used for messaging */
 E NEARDATA char plname[PL_NSIZ];
 E NEARDATA char dogname[];
 E NEARDATA char catname[];
@@ -246,7 +245,8 @@ E NEARDATA struct obj *migrating_objs;
 E NEARDATA struct obj *billobjs;
 E NEARDATA struct obj *current_wand, *thrownobj, *kickedobj;
 
-E NEARDATA struct obj zeroobj; /* init'd and defined in decl.c */
+E NEARDATA struct obj zeroobj; /* for init; &zeroobj used as special value */
+
 E NEARDATA anything zeroany;   /* init'd and defined in decl.c */
 
 #include "you.h"
@@ -259,7 +259,8 @@ E NEARDATA struct u_realtime urealtime;
 #include "pm.h"
 #endif
 
-E NEARDATA struct monst youmonst; /* init'd and defined in decl.c */
+E NEARDATA struct monst zeromonst; /* for init of new or temp monsters */
+E NEARDATA struct monst youmonst; /* monster details when hero is poly'd */
 E NEARDATA struct monst *mydogs, *migrating_mons;
 
 E NEARDATA struct mvitals {
@@ -320,6 +321,7 @@ E const char *materialnm[];
 #define SUPPRESS_HALLUCINATION 0x04
 #define SUPPRESS_SADDLE 0x08
 #define EXACT_NAME 0x0F
+#define SUPPRESS_NAME 0x10
 
 /* Vision */
 E NEARDATA boolean vision_full_recalc; /* TRUE if need vision recalc */
@@ -327,9 +329,7 @@ E NEARDATA char **viz_array;           /* could see/in sight row pointers */
 
 /* Window system stuff */
 E NEARDATA winid WIN_MESSAGE;
-#ifndef STATUS_VIA_WINDOWPORT
 E NEARDATA winid WIN_STATUS;
-#endif
 E NEARDATA winid WIN_MAP, WIN_INVEN;
 
 /* pline (et al) for a single string argument (suppress compiler warning) */
@@ -391,6 +391,14 @@ E char *fqn_prefix_names[PREFIX_COUNT];
 
 E NEARDATA struct savefile_info sfcap, sfrestinfo, sfsaveinfo;
 
+struct opvar {
+    xchar spovartyp; /* one of SPOVAR_foo */
+    union {
+        char *str;
+        long l;
+    } vardata;
+};
+
 struct autopickup_exception {
     struct nhregex *regex;
     char *pattern;
@@ -409,13 +417,24 @@ struct plinemsg_type {
 #define MSGTYP_NOREP    1
 #define MSGTYP_NOSHOW   2
 #define MSGTYP_STOP     3
+/* bitmask for callers of hide_unhide_msgtypes() */
+#define MSGTYP_MASK_REP_SHOW ((1 << MSGTYP_NOREP) | (1 << MSGTYP_NOSHOW))
 
 E struct plinemsg_type *plinemsg_types;
 
 #ifdef PANICTRACE
-E char *ARGV0;
+E const char *ARGV0;
 #endif
 
+enum earlyarg {ARG_DEBUG, ARG_VERSION};
+
+struct early_opt {
+    enum earlyarg e;
+    const char *name;
+    int minlength;
+    boolean valallowed;
+};
+
 #if 1 /*JP*/
 struct trans_verb {
     const char *en;
index 23965e6..f7b16cf 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 dungeon.h       $NHDT-Date: 1447755969 2015/11/17 10:26:09 $  $NHDT-Branch: master $:$NHDT-Revision: 1.24 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef DUNGEON_H
@@ -35,13 +36,15 @@ typedef struct stairway { /* basic stairway identifier */
 } stairway;
 
 /* level region types */
-#define LR_DOWNSTAIR 0
-#define LR_UPSTAIR 1
-#define LR_PORTAL 2
-#define LR_BRANCH 3
-#define LR_TELE 4
-#define LR_UPTELE 5
-#define LR_DOWNTELE 6
+enum level_region_types {
+    LR_DOWNSTAIR = 0,
+    LR_UPSTAIR,
+    LR_PORTAL,
+    LR_BRANCH,
+    LR_TELE,
+    LR_UPTELE,
+    LR_DOWNTELE
+};
 
 typedef struct dest_area { /* non-stairway level change identifier */
     xchar lx, ly;          /* "lower" left corner (near [0,0]) */
index fa4f152..86f6fcd 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 engrave.h       $NHDT-Date: 1432512777 2015/05/25 00:12:57 $  $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef ENGRAVE_H
index 1c3d240..bc490b2 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 extern.h        $NHDT-Date: 1449051498 2015/12/02 10:18:18 $  $NHDT-Branch: master $:$NHDT-Revision: 1.520 $ */
+/* NetHack 3.6 extern.h        $NHDT-Date: 1518053385 2018/02/08 01:29:45 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.625 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -26,6 +26,7 @@ E void NDECL(display_gamewindows);
 E void NDECL(newgame);
 E void FDECL(welcome, (BOOLEAN_P));
 E time_t NDECL(get_realtime);
+E boolean FDECL(argcheck, (int, char **, enum earlyarg));
 
 /* ### apply.c ### */
 
@@ -78,8 +79,8 @@ E int FDECL(spec_dbon, (struct obj *, struct monst *, int));
 E void FDECL(discover_artifact, (XCHAR_P));
 E boolean FDECL(undiscovered_artifact, (XCHAR_P));
 E int FDECL(disp_artifact_discoveries, (winid));
-E boolean FDECL(artifact_hit,
-                (struct monst *, struct monst *, struct obj *, int *, int));
+E boolean FDECL(artifact_hit, (struct monst *, struct monst *, struct obj *,
+                               int *, int));
 E int NDECL(doinvoke);
 E boolean FDECL(finesse_ahriman, (struct obj *));
 E void FDECL(arti_speak, (struct obj *));
@@ -92,6 +93,9 @@ E const char *FDECL(glow_color, (int));
 E void FDECL(Sting_effects, (int));
 E int FDECL(retouch_object, (struct obj **, BOOLEAN_P));
 E void FDECL(retouch_equipment, (int));
+E void NDECL(mkot_trap_warn);
+E boolean FDECL(is_magic_key, (struct monst *, struct obj *));
+E struct obj *FDECL(has_magic_key, (struct monst *));
 
 /* ### attrib.c ### */
 
@@ -141,6 +145,9 @@ E int NDECL(getbones);
 
 /* ### botl.c ### */
 
+E char *NDECL(do_statusline1);
+E void NDECL(check_gold_symbol);
+E char *NDECL(do_statusline2);
 E int FDECL(xlev_to_rank, (int));
 E int FDECL(title_to_mon, (const char *, int *, int *));
 E void NDECL(max_rank_sz);
@@ -150,20 +157,23 @@ E long NDECL(botl_score);
 E int FDECL(describe_level, (char *));
 E const char *FDECL(rank_of, (int, SHORT_P, BOOLEAN_P));
 E void NDECL(bot);
-#ifdef STATUS_VIA_WINDOWPORT
 E void FDECL(status_initialize, (BOOLEAN_P));
 E void NDECL(status_finish);
 E void FDECL(status_notify_windowport, (BOOLEAN_P));
+E void NDECL(status_eval_next_unhilite);
 #ifdef STATUS_HILITES
-E boolean FDECL(set_status_hilites, (char *op, BOOLEAN_P));
-E void FDECL(clear_status_hilites, (BOOLEAN_P));
-E char *FDECL(get_status_hilites, (char *, int));
+E boolean FDECL(parse_status_hl1, (char *op, BOOLEAN_P));
+E void NDECL(clear_status_hilites);
+E void NDECL(reset_status_hilites);
+E int NDECL(count_status_hilites);
 E boolean NDECL(status_hilite_menu);
 #endif
-#endif
 
 /* ### cmd.c ### */
 
+E int NDECL(doconduct);
+E int NDECL(domonability);
+E char FDECL(cmd_from_func, (int NDECL((*))));
 E boolean FDECL(redraw_cmd, (CHAR_P));
 #ifdef USE_TRAMPOLI
 E int NDECL(doextcmd);
@@ -184,7 +194,10 @@ E void FDECL(set_occupation, (int (*)(void), const char *, int));
 E char NDECL(pgetchar);
 E void FDECL(pushch, (CHAR_P));
 E void FDECL(savech, (CHAR_P));
-E void NDECL(add_debug_extended_commands);
+E const char *FDECL(key2extcmddesc, (UCHAR_P));
+E boolean FDECL(bind_specialkey, (UCHAR_P, const char *));
+E char FDECL(txt2key, (char *));
+E void FDECL(parseautocomplete, (char *, BOOLEAN_P));
 E void FDECL(reset_commands, (BOOLEAN_P));
 E void FDECL(rhack, (char *));
 E int NDECL(doextlist);
@@ -193,6 +206,8 @@ E int NDECL(enter_explore_mode);
 E void FDECL(enlightenment, (int, int));
 E void FDECL(youhiding, (BOOLEAN_P, int));
 E void FDECL(show_conduct, (int));
+E boolean FDECL(bind_key, (UCHAR_P, const char *));
+E void NDECL(dokeylist);
 E int FDECL(xytod, (SCHAR_P, SCHAR_P));
 E void FDECL(dtoxy, (coord *, int));
 E int FDECL(movecmd, (CHAR_P));
@@ -204,12 +219,14 @@ E int FDECL(isok, (int, int));
 E int FDECL(get_adjacent_loc,
             (const char *, const char *, XCHAR_P, XCHAR_P, coord *));
 E const char *FDECL(click_to_cmd, (int, int, int));
+E char FDECL(get_count, (char *, CHAR_P, long, long *, BOOLEAN_P));
 #ifdef HANGUPHANDLING
 E void FDECL(hangup, (int));
 E void NDECL(end_of_input);
 #endif
 E char NDECL(readchar);
 E void NDECL(sanity_check);
+E char* FDECL(key2txt, (UCHAR_P, char *));
 E char FDECL(yn_function, (const char *, const char *, CHAR_P));
 E boolean FDECL(paranoid_query, (BOOLEAN_P, const char *));
 
@@ -235,6 +252,8 @@ E void NDECL(decl_init);
 
 /* ### detect.c ### */
 
+E boolean FDECL(trapped_chest_at, (int, int, int));
+E boolean FDECL(trapped_door_at, (int, int, int));
 E struct obj *FDECL(o_in, (struct obj *, CHAR_P));
 E struct obj *FDECL(o_material, (struct obj *, unsigned));
 E int FDECL(gold_detect, (struct obj *));
@@ -245,7 +264,7 @@ E int FDECL(trap_detect, (struct obj *));
 E const char *FDECL(level_distance, (d_level *));
 E void FDECL(use_crystal_ball, (struct obj **));
 E void NDECL(do_mapping);
-E void NDECL(do_vicinity_map);
+E void FDECL(do_vicinity_map, (struct obj *));
 E void FDECL(cvt_sdoor_to_door, (struct rm *));
 #ifdef USE_TRAMPOLI
 E void FDECL(findone, (int, int, genericptr_t));
@@ -255,9 +274,13 @@ E int NDECL(findit);
 E int NDECL(openit);
 E boolean FDECL(detecting, (void (*)(int, int, genericptr)));
 E void FDECL(find_trap, (struct trap *));
+E void NDECL(warnreveal);
 E int FDECL(dosearch0, (int));
 E int NDECL(dosearch);
 E void NDECL(sokoban_detect);
+#ifdef DUMPLOG
+E void NDECL(dump_map);
+#endif
 E void FDECL(reveal_terrain, (int, int));
 
 /* ### dig.c ### */
@@ -304,11 +327,13 @@ E void FDECL(map_background, (XCHAR_P, XCHAR_P, int));
 E void FDECL(map_trap, (struct trap *, int));
 E void FDECL(map_object, (struct obj *, int));
 E void FDECL(map_invisible, (XCHAR_P, XCHAR_P));
+E boolean FDECL(unmap_invisible, (int, int));
 E void FDECL(unmap_object, (int, int));
 E void FDECL(map_location, (int, int, int));
 E void FDECL(feel_newsym, (XCHAR_P, XCHAR_P));
 E void FDECL(feel_location, (XCHAR_P, XCHAR_P));
 E void FDECL(newsym, (int, int));
+E void FDECL(newsym_force, (int, int));
 E void FDECL(shieldeff, (XCHAR_P, XCHAR_P));
 E void FDECL(tmp_at, (int, int));
 E void FDECL(swallowed, (int));
@@ -331,6 +356,7 @@ E int FDECL(zapdir_to_glyph, (int, int, int));
 E int FDECL(glyph_at, (XCHAR_P, XCHAR_P));
 E void NDECL(set_wall_state);
 E void FDECL(unset_seenv, (struct rm *, int, int, int, int));
+E int FDECL(warning_of, (struct monst *));
 
 /* ### do.c ### */
 
@@ -366,8 +392,10 @@ E void NDECL(heal_legs);
 
 /* ### do_name.c ### */
 
+E char *FDECL(coord_desc, (int, int, char *, CHAR_P));
+E boolean FDECL(getpos_menu, (coord *, int));
 E int FDECL(getpos, (coord *, BOOLEAN_P, const char *));
-E void FDECL(getpos_sethilite, (void (*f)(int)));
+E void FDECL(getpos_sethilite, (void (*f)(int), boolean (*d)(int,int)));
 E void FDECL(new_mname, (struct monst *, int));
 E void FDECL(free_mname, (struct monst *));
 E void FDECL(new_oname, (struct obj *, int));
@@ -385,6 +413,7 @@ E char *FDECL(mon_nam, (struct monst *));
 E char *FDECL(noit_mon_nam, (struct monst *));
 E char *FDECL(Monnam, (struct monst *));
 E char *FDECL(noit_Monnam, (struct monst *));
+E char *FDECL(noname_monnam, (struct monst *, int));
 E char *FDECL(m_monnam, (struct monst *));
 E char *FDECL(y_monnam, (struct monst *));
 E char *FDECL(Adjmonnam, (struct monst *, const char *));
@@ -394,6 +423,7 @@ E char *FDECL(distant_monnam, (struct monst *, int, char *));
 E char *FDECL(rndmonnam, (char *));
 E const char *FDECL(hcolor, (const char *));
 E const char *NDECL(rndcolor);
+E const char *FDECL(hliquid, (const char *));
 E const char *NDECL(roguename);
 E struct obj *FDECL(realloc_obj,
                     (struct obj *, int, genericptr_t, int, const char *));
@@ -415,12 +445,14 @@ E void FDECL(off_msg, (struct obj *));
 E void FDECL(set_wear, (struct obj *));
 E boolean FDECL(donning, (struct obj *));
 E boolean FDECL(doffing, (struct obj *));
+E void FDECL(cancel_doff, (struct obj *, long));
 E void NDECL(cancel_don);
 E int FDECL(stop_donning, (struct obj *));
 E int NDECL(Armor_off);
 E int NDECL(Armor_gone);
 E int NDECL(Helmet_off);
 E int NDECL(Gloves_off);
+E int NDECL(Boots_on);
 E int NDECL(Boots_off);
 E int NDECL(Cloak_off);
 E int NDECL(Shield_off);
@@ -498,17 +530,18 @@ E void FDECL(endmultishot, (BOOLEAN_P));
 E void FDECL(hitfloor, (struct obj *));
 E void FDECL(hurtle, (int, int, int, BOOLEAN_P));
 E void FDECL(mhurtle, (struct monst *, int, int, int));
+E boolean FDECL(throwing_weapon, (struct obj *));
 E void FDECL(throwit, (struct obj *, long, BOOLEAN_P));
 E int FDECL(omon_adj, (struct monst *, struct obj *, BOOLEAN_P));
 E int FDECL(thitmonst, (struct monst *, struct obj *));
 E int FDECL(hero_breaks, (struct obj *, XCHAR_P, XCHAR_P, BOOLEAN_P));
 E int FDECL(breaks, (struct obj *, XCHAR_P, XCHAR_P));
 E void FDECL(release_camera_demon, (struct obj *, XCHAR_P, XCHAR_P));
-E void FDECL(breakobj,
-             (struct obj *, XCHAR_P, XCHAR_P, BOOLEAN_P, BOOLEAN_P));
+E void FDECL(breakobj, (struct obj *, XCHAR_P, XCHAR_P, BOOLEAN_P, BOOLEAN_P));
 E boolean FDECL(breaktest, (struct obj *));
 E boolean FDECL(walk_path, (coord *, coord *,
                             boolean (*)(genericptr, int, int), genericptr_t));
+E boolean FDECL(hurtle_jump, (genericptr_t, int, int));
 E boolean FDECL(hurtle_step, (genericptr_t, int, int));
 
 /* ### drawing.c ### */
@@ -583,11 +616,13 @@ E int NDECL(donamelevel);
 E int NDECL(dooverview);
 E void FDECL(show_overview, (int, int));
 E void FDECL(forget_mapseen, (int));
+E void FDECL(rm_mapseen, (int));
 E void FDECL(init_mapseen, (d_level *));
 E void NDECL(recalc_mapseen);
 E void FDECL(mapseen_temple, (struct monst *));
 E void FDECL(room_discovered, (int));
 E void FDECL(recbranch_mapseen, (d_level *, d_level *));
+E void FDECL(overview_stats, (winid, const char *, long *, long *));
 E void FDECL(remdun_mapseen, (int));
 
 /* ### eat.c ### */
@@ -604,6 +639,7 @@ E void NDECL(init_uhunger);
 E int NDECL(Hear_again);
 E void NDECL(reset_eat);
 E int NDECL(doeat);
+E int FDECL(use_tin_opener, (struct obj *));
 E void NDECL(gethungry);
 E void FDECL(morehungry, (int));
 E void FDECL(lesshungry, (int));
@@ -640,7 +676,7 @@ E void VDECL(panic, (const char *, ...)) PRINTF_F(1, 2) NORETURN;
 E void FDECL(done, (int));
 E void FDECL(container_contents, (struct obj *, BOOLEAN_P,
                                   BOOLEAN_P, BOOLEAN_P));
-E void FDECL(terminate, (int)) NORETURN;
+E void FDECL(nh_terminate, (int)) NORETURN;
 E int NDECL(dovanquished);
 E int NDECL(num_genocides);
 E void FDECL(delayed_killer, (int, int, const char *));
@@ -673,6 +709,7 @@ E int NDECL(doengrave);
 E void NDECL(sanitize_engravings);
 E void FDECL(save_engravings, (int, int));
 E void FDECL(rest_engravings, (int));
+E void FDECL(engr_stats, (const char *, char *, long *, long *));
 E void FDECL(del_engr, (struct engr *));
 E void FDECL(rloc_engr, (struct engr *));
 E void FDECL(make_grave, (int, int, const char *));
@@ -740,6 +777,9 @@ E void FDECL(unlock_file, (const char *));
 #ifdef USER_SOUNDS
 E boolean FDECL(can_read_file, (const char *));
 #endif
+E void FDECL(config_error_init, (BOOLEAN_P, const char *, BOOLEAN_P));
+E void FDECL(config_error_add, (const char *, ...)) PRINTF_F(1, 2);
+E int NDECL(config_error_done);
 E boolean FDECL(read_config_file, (const char *, int));
 E void FDECL(check_recordfile, (const char *));
 E void NDECL(read_wizkit);
@@ -784,6 +824,7 @@ E void NDECL(drinksink);
 
 /* ### hack.c ### */
 
+E boolean FDECL(is_valid_travelpt, (int,int));
 E anything *FDECL(uint_to_any, (unsigned));
 E anything *FDECL(long_to_any, (long));
 E anything *FDECL(monst_to_any, (struct monst *));
@@ -834,6 +875,9 @@ E char *FDECL(lcase, (char *));
 E char *FDECL(ucase, (char *));
 E char *FDECL(upstart, (char *));
 E char *FDECL(mungspaces, (char *));
+E char *FDECL(trimspaces, (char *));
+E char *FDECL(strip_newline, (char *));
+E char *FDECL(stripchars, (char *, const char *, const char *));
 E char *FDECL(eos, (char *));
 E boolean FDECL(str_end_is, (const char *, const char *));
 E char *FDECL(strkitten, (char *, CHAR_P));
@@ -847,6 +891,7 @@ E boolean FDECL(onlyspace, (const char *));
 E char *FDECL(tabexpand, (char *));
 E char *FDECL(visctrl, (CHAR_P));
 E char *FDECL(strsubst, (char *, const char *, const char *));
+E int FDECL(strNsubst, (char *, const char *, const char *, int));
 E const char *FDECL(ordin, (int));
 E char *FDECL(sitoa, (int));
 E int FDECL(sgn, (int));
@@ -880,11 +925,15 @@ E int NDECL(phase_of_the_moon);
 E boolean NDECL(friday_13th);
 E int NDECL(night);
 E int NDECL(midnight);
+E void FDECL(strbuf_init, (strbuf_t *));
+E void FDECL(strbuf_append, (strbuf_t *, const char *));
+E void FDECL(strbuf_reserve, (strbuf_t *, int));
+E void FDECL(strbuf_empty, (strbuf_t *));
+E void FDECL(strbuf_nl_to_crlf, (strbuf_t *));
 
 /* ### invent.c ### */
 
-E struct obj **FDECL(objarr_init, (int));
-E void FDECL(objarr_set, (struct obj *, int, struct obj **, BOOLEAN_P));
+E void FDECL(sortloot, (struct obj **, unsigned, BOOLEAN_P));
 E void FDECL(assigninvlet, (struct obj *));
 E struct obj *FDECL(merge_choice, (struct obj *, struct obj *));
 E int FDECL(merged, (struct obj **, struct obj **));
@@ -913,6 +962,7 @@ E boolean FDECL(obj_here, (struct obj *, int, int));
 E boolean NDECL(wearing_armor);
 E boolean FDECL(is_worn, (struct obj *));
 E struct obj *FDECL(g_at, (int, int));
+E boolean FDECL(splittable, (struct obj *));
 E struct obj *FDECL(getobj, (const char *, const char *));
 E int FDECL(ggetobj, (const char *, int (*)(OBJ_P), int,
                       BOOLEAN_P, unsigned *));
@@ -937,6 +987,7 @@ E int NDECL(dolook);
 E boolean FDECL(will_feel_cockatrice, (struct obj *, BOOLEAN_P));
 E void FDECL(feel_cockatrice, (struct obj *, BOOLEAN_P));
 E void FDECL(stackobj, (struct obj *));
+E boolean FDECL(mergable, (struct obj *, struct obj *));
 E int NDECL(doprgold);
 E int NDECL(doprwep);
 E int NDECL(doprarm);
@@ -951,7 +1002,9 @@ E void NDECL(reassign);
 E int NDECL(doorganize);
 E void NDECL(free_pickinv_cache);
 E int FDECL(count_unpaid, (struct obj *));
-E int FDECL(count_buc, (struct obj *, int));
+E int FDECL(count_buc, (struct obj *, int, boolean (*)(OBJ_P)));
+E void FDECL(tally_BUCX, (struct obj *, BOOLEAN_P,
+                          int *, int *, int *, int *, int *));
 E long FDECL(count_contents, (struct obj *, BOOLEAN_P, BOOLEAN_P, BOOLEAN_P));
 E void FDECL(carry_obj_effects, (struct obj *));
 E const char *FDECL(currency, (long));
@@ -976,6 +1029,7 @@ E void FDECL(do_light_sources, (char **));
 E struct monst *FDECL(find_mid, (unsigned, unsigned));
 E void FDECL(save_light_sources, (int, int, int));
 E void FDECL(restore_light_sources, (int));
+E void FDECL(light_stats, (const char *, char *, long *, long *));
 E void FDECL(relink_light_sources, (BOOLEAN_P));
 E void NDECL(light_sources_sanity_check);
 E void FDECL(obj_move_light_source, (struct obj *, struct obj *));
@@ -1001,6 +1055,7 @@ E boolean FDECL(picking_lock, (int *, int *));
 E boolean FDECL(picking_at, (int, int));
 E void FDECL(breakchestlock, (struct obj *, BOOLEAN_P));
 E void NDECL(reset_pick);
+E void NDECL(maybe_reset_pick);
 E int FDECL(pick_lock, (struct obj *));
 E int NDECL(doforce);
 E boolean FDECL(boxlock, (struct obj *, struct obj *));
@@ -1058,7 +1113,9 @@ E void FDECL(nocmov, (int x, int y));
 
 #ifdef MAIL
 #ifdef UNIX
+E void NDECL(free_maildata);
 E void NDECL(getmailstatus);
+E void NDECL(ck_server_admin_msg);
 #endif
 E void NDECL(ckmailstatus);
 E void FDECL(readmail, (struct obj *));
@@ -1126,8 +1183,8 @@ E const char *FDECL(mpoisons_subj, (struct monst *, struct attack *));
 E void NDECL(u_slow_down);
 E struct monst *NDECL(cloneu);
 E void FDECL(expels, (struct monst *, struct permonst *, BOOLEAN_P));
-E struct attack *FDECL(getmattk,
-                       (struct permonst *, int, int *, struct attack *));
+E struct attack *FDECL(getmattk, (struct monst *, struct monst *,
+                                  int, int *, struct attack *));
 E int FDECL(mattacku, (struct monst *));
 E int FDECL(magic_negation, (struct monst *));
 E boolean NDECL(gulp_blnd_check);
@@ -1188,6 +1245,7 @@ E void FDECL(remove_rooms, (int, int, int, int));
 /* ### mkmaze.c ### */
 
 E void FDECL(wallification, (int, int, int, int));
+E void FDECL(fix_wall_spines, (int, int, int, int));
 E void FDECL(walkfrom, (int, int, SCHAR_P));
 E void FDECL(makemaz, (const char *));
 E void FDECL(mazexy, (coord *));
@@ -1197,6 +1255,7 @@ E boolean FDECL(bad_location, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P,
                                XCHAR_P, XCHAR_P));
 E void FDECL(place_lregion, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P,
                              XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P, d_level *));
+E void NDECL(fixup_special);
 E void NDECL(fumaroles);
 E void NDECL(movebubbles);
 E void NDECL(water_friction);
@@ -1226,6 +1285,7 @@ E struct obj *FDECL(splitobj, (struct obj *, long));
 E struct obj *FDECL(unsplitobj, (struct obj *));
 E void NDECL(clear_splitobjs);
 E void FDECL(replace_object, (struct obj *, struct obj *));
+E struct obj *FDECL(unknwn_contnr_contents, (struct obj *));
 E void FDECL(bill_dummy_object, (struct obj *));
 E void FDECL(costly_alteration, (struct obj *, int));
 E struct obj *FDECL(mksobj, (int, BOOLEAN_P, BOOLEAN_P));
@@ -1266,9 +1326,10 @@ E long FDECL(peek_at_iced_corpse_age, (struct obj *));
 E int FDECL(hornoplenty, (struct obj *, BOOLEAN_P));
 E void NDECL(obj_sanity_check);
 E struct obj *FDECL(obj_nexto, (struct obj *));
-E struct obj *FDECL(obj_nexto_xy, (int, int, int, unsigned));
+E struct obj *FDECL(obj_nexto_xy, (struct obj *, int, int, BOOLEAN_P));
 E struct obj *FDECL(obj_absorb, (struct obj **, struct obj **));
 E struct obj *FDECL(obj_meld, (struct obj **, struct obj **));
+E void FDECL(pudding_merge_message, (struct obj *, struct obj *));
 
 /* ### mkroom.c ### */
 
@@ -1322,12 +1383,13 @@ E void FDECL(unstuck, (struct monst *));
 E void FDECL(killed, (struct monst *));
 E void FDECL(xkilled, (struct monst *, int));
 E void FDECL(mon_to_stone, (struct monst *));
+E void FDECL(m_into_limbo, (struct monst *));
 E void FDECL(mnexto, (struct monst *));
 E void FDECL(maybe_mnexto, (struct monst *));
 E boolean FDECL(mnearto, (struct monst *, XCHAR_P, XCHAR_P, BOOLEAN_P));
 E void FDECL(m_respond, (struct monst *));
-E void FDECL(setmangry, (struct monst *));
-E void FDECL(wakeup, (struct monst *));
+E void FDECL(setmangry, (struct monst *, BOOLEAN_P));
+E void FDECL(wakeup, (struct monst *, BOOLEAN_P));
 E void NDECL(wake_nearby);
 E void FDECL(wake_nearto, (int, int, int));
 E void FDECL(seemimic, (struct monst *));
@@ -1337,6 +1399,7 @@ E void FDECL(restore_cham, (struct monst *));
 E boolean FDECL(hideunder, (struct monst *));
 E void FDECL(hide_monst, (struct monst *));
 E void FDECL(mon_animal_list, (BOOLEAN_P));
+E boolean FDECL(validvamp, (struct monst *, int *, int));
 E int FDECL(select_newcham_form, (struct monst *));
 E void FDECL(mgender_from_permonst, (struct monst *, struct permonst *));
 E int FDECL(newcham,
@@ -1349,6 +1412,7 @@ E void FDECL(golemeffects, (struct monst *, int, int));
 E boolean FDECL(angry_guards, (BOOLEAN_P));
 E void NDECL(pacify_guards);
 E void FDECL(decide_to_shapeshift, (struct monst *, int));
+E boolean FDECL(vamp_stone, (struct monst *));
 
 /* ### mondata.c ### */
 
@@ -1367,6 +1431,7 @@ E boolean FDECL(hates_silver, (struct permonst *));
 E boolean FDECL(mon_hates_silver, (struct monst *));
 E boolean FDECL(passes_bars, (struct permonst *));
 E boolean FDECL(can_blow, (struct monst *));
+E boolean FDECL(can_chant, (struct monst *));
 E boolean FDECL(can_be_strangled, (struct monst *));
 E boolean FDECL(can_track, (struct permonst *));
 E boolean FDECL(breakarm, (struct permonst *));
@@ -1387,6 +1452,7 @@ E int FDECL(pronoun_gender, (struct monst *));
 E boolean FDECL(levl_follower, (struct monst *));
 E int FDECL(little_to_big, (int));
 E int FDECL(big_to_little, (int));
+E boolean FDECL(big_little_match, (int, int));
 E const char *FDECL(locomotion, (const struct permonst *, const char *));
 E const char *FDECL(stagger, (const struct permonst *, const char *));
 E const char *FDECL(on_fire, (struct permonst *, struct attack *));
@@ -1407,6 +1473,7 @@ E boolean FDECL(onscary, (int, int, struct monst *));
 E void FDECL(monflee, (struct monst *, int, BOOLEAN_P, BOOLEAN_P));
 E void FDECL(mon_yells, (struct monst *, const char *));
 E int FDECL(dochug, (struct monst *));
+E boolean FDECL(m_digweapon_check, (struct monst *, XCHAR_P, XCHAR_P));
 E int FDECL(m_move, (struct monst *, int));
 E void FDECL(dissolve_bars, (int, int));
 E boolean FDECL(closed_door, (int, int));
@@ -1486,7 +1553,7 @@ E void FDECL(Delay, (int));
 
 /* ### mthrowu.c ### */
 
-E int FDECL(thitu, (int, int, struct obj *, const char *));
+E int FDECL(thitu, (int, int, struct obj **, const char *));
 E int FDECL(ohitmon, (struct monst *, struct obj *, int, BOOLEAN_P));
 E void FDECL(thrwmu, (struct monst *));
 E int FDECL(spitmu, (struct monst *, struct attack *));
@@ -1494,11 +1561,15 @@ E int FDECL(breamu, (struct monst *, struct attack *));
 E boolean FDECL(linedup, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P, int));
 E boolean FDECL(lined_up, (struct monst *));
 E struct obj *FDECL(m_carrying, (struct monst *, int));
+E int FDECL(thrwmm, (struct monst *, struct monst *));
+E int FDECL(spitmm, (struct monst *, struct attack *, struct monst *));
+E int FDECL(breamm, (struct monst *, struct attack *, struct monst *));
 E void FDECL(m_useupall, (struct monst *, struct obj *));
 E void FDECL(m_useup, (struct monst *, struct obj *));
-E void FDECL(m_throw,
-             (struct monst *, int, int, int, int, int, struct obj *));
-E boolean FDECL(hits_bars, (struct obj **, int, int, int, int));
+E void FDECL(m_throw, (struct monst *, int, int, int, int, int, struct obj *));
+E void FDECL(hit_bars, (struct obj **, int, int, int, int,
+                        BOOLEAN_P, BOOLEAN_P));
+E boolean FDECL(hits_bars, (struct obj **, int, int, int, int, int, int));
 
 /* ### muse.c ### */
 
@@ -1517,6 +1588,7 @@ E int FDECL(rnd_misc_item, (struct monst *));
 E boolean FDECL(searches_for_item, (struct monst *, struct obj *));
 E boolean FDECL(mon_reflects, (struct monst *, const char *));
 E boolean FDECL(ureflects, (const char *, const char *));
+E void FDECL(mcureblindness, (struct monst *, BOOLEAN_P));
 E boolean FDECL(munstone, (struct monst *, BOOLEAN_P));
 E boolean FDECL(munslime, (struct monst *, BOOLEAN_P));
 
@@ -1576,12 +1648,17 @@ E char *FDECL(simple_typename, (int));
 E boolean FDECL(obj_is_pname, (struct obj *));
 E char *FDECL(distant_name, (struct obj *, char *(*)(OBJ_P)));
 E char *FDECL(fruitname, (BOOLEAN_P));
+E struct fruit *FDECL(fruit_from_indx, (int));
+E struct fruit *FDECL(fruit_from_name, (const char *, BOOLEAN_P, int *));
+E void FDECL(reorder_fruit, (BOOLEAN_P));
 E char *FDECL(xname, (struct obj *));
 E char *FDECL(mshot_xname, (struct obj *));
 E boolean FDECL(the_unique_obj, (struct obj *));
 E boolean FDECL(the_unique_pm, (struct permonst *));
+E boolean FDECL(erosion_matters, (struct obj *));
 E char *FDECL(doname, (struct obj *));
 E char *FDECL(doname_with_price, (struct obj *));
+E char *FDECL(doname_vague_quan, (struct obj *));
 E boolean FDECL(not_fully_identified, (struct obj *));
 E char *FDECL(corpse_xname, (struct obj *, const char *, unsigned));
 E char *FDECL(cxname, (struct obj *));
@@ -1627,16 +1704,19 @@ E boolean FDECL(match_optname, (const char *, const char *, int, BOOLEAN_P));
 E void NDECL(initoptions);
 E void NDECL(initoptions_init);
 E void NDECL(initoptions_finish);
-E void FDECL(parseoptions, (char *, BOOLEAN_P, BOOLEAN_P));
+E boolean FDECL(parseoptions, (char *, BOOLEAN_P, BOOLEAN_P));
 E int NDECL(doset);
 E int NDECL(dotogglepickup);
 E void NDECL(option_help);
 E void FDECL(next_opt, (winid, const char *));
 E int FDECL(fruitadd, (char *, struct fruit *));
-E int FDECL(choose_classes_menu,
-            (const char *, int, BOOLEAN_P, char *, char *));
+E int FDECL(choose_classes_menu, (const char *, int, BOOLEAN_P,
+                                  char *, char *));
+E boolean FDECL(parsebindings, (char *));
 E void FDECL(add_menu_cmd_alias, (CHAR_P, CHAR_P));
+E char FDECL(get_menu_cmd_key, (CHAR_P));
 E char FDECL(map_menu_cmd, (CHAR_P));
+E void FDECL(show_menu_controls, (winid, BOOLEAN_P));
 E void FDECL(assign_warnings, (uchar *));
 E char *FDECL(nh_getenv, (const char *));
 E void FDECL(set_duplicate_opt_detection, (int));
@@ -1647,22 +1727,31 @@ E int FDECL(add_autopickup_exception, (const char *));
 E void NDECL(free_autopickup_exceptions);
 E int FDECL(load_symset, (const char *, int));
 E void NDECL(free_symsets);
-E void FDECL(parsesymbols, (char *));
+E boolean FDECL(parsesymbols, (char *));
 E struct symparse *FDECL(match_sym, (char *));
 E void NDECL(set_playmode);
-E int FDECL(sym_val, (char *));
+E int FDECL(sym_val, (const char *));
+E int FDECL(query_color, (const char *));
+E int FDECL(query_attr, (const char *));
 E const char *FDECL(clr2colorname, (int));
+E int FDECL(match_str2clr, (char *));
+E int FDECL(match_str2attr, (const char *, BOOLEAN_P));
 E boolean FDECL(add_menu_coloring, (char *));
-E boolean FDECL(get_menu_coloring, (char *, int *, int *));
+E boolean FDECL(get_menu_coloring, (const char *, int *, int *));
 E void NDECL(free_menu_coloring);
 E boolean FDECL(msgtype_parse_add, (char *));
-E int FDECL(msgtype_type, (const char *));
+E int FDECL(msgtype_type, (const char *, BOOLEAN_P));
+E void FDECL(hide_unhide_msgtypes, (BOOLEAN_P, int));
 E void NDECL(msgtype_free);
 
 /* ### pager.c ### */
 
 E char *FDECL(self_lookat, (char *));
+E void FDECL(mhidden_description, (struct monst *, BOOLEAN_P, char *));
 E boolean FDECL(object_from_map, (int,int,int,struct obj **));
+E int FDECL(do_screen_description, (coord, BOOLEAN_P, int, char *,
+                                    const char **));
+E int FDECL(do_look, (int, coord *));
 E int NDECL(dowhatis);
 E int NDECL(doquickwhatis);
 E int NDECL(doidtrap);
@@ -1670,9 +1759,6 @@ E int NDECL(dowhatdoes);
 E char *FDECL(dowhatdoes_core, (CHAR_P, char *));
 E int NDECL(dohelp);
 E int NDECL(dohistory);
-E int FDECL(do_screen_description,
-            (coord, BOOLEAN_P, int, char *, const char **));
-E int FDECL(do_look, (int, coord *));
 
 /* ### pcmain.c ### */
 
@@ -1729,6 +1815,7 @@ E void NDECL(getlock);
 E int FDECL(collect_obj_classes, (char *, struct obj *, BOOLEAN_P,
                                   boolean FDECL((*), (OBJ_P)), int *));
 E boolean FDECL(rider_corpse_revival, (struct obj *, BOOLEAN_P));
+E boolean FDECL(menu_class_present, (int));
 E void FDECL(add_valid_menu_class, (int));
 E boolean FDECL(allow_all, (struct obj *));
 E boolean FDECL(allow_category, (struct obj *));
@@ -1740,23 +1827,30 @@ E int FDECL(out_container, (struct obj *));
 #endif
 E int FDECL(pickup, (int));
 E int FDECL(pickup_object, (struct obj *, long, BOOLEAN_P));
-E int FDECL(query_category,
-            (const char *, struct obj *, int, menu_item **, int));
-E int FDECL(query_objlist, (const char *, struct obj *, int, menu_item **,
-                            int, boolean (*)(OBJ_P)));
+E int FDECL(query_category, (const char *, struct obj *, int,
+                             menu_item **, int));
+E int FDECL(query_objlist, (const char *, struct obj **, int,
+                            menu_item **, int, boolean (*)(OBJ_P)));
 E struct obj *FDECL(pick_obj, (struct obj *));
 E int NDECL(encumber_msg);
+E int FDECL(container_at, (int, int, BOOLEAN_P));
 E int NDECL(doloot);
 E boolean FDECL(container_gone, (int (*)(OBJ_P)));
 E boolean NDECL(u_handsy);
-E int FDECL(use_container, (struct obj **, int));
+E int FDECL(use_container, (struct obj **, int, BOOLEAN_P));
 E int FDECL(loot_mon, (struct monst *, int *, boolean *));
 E int NDECL(dotip);
 E boolean FDECL(is_autopickup_exception, (struct obj *, BOOLEAN_P));
+E boolean FDECL(autopick_testobj, (struct obj *, BOOLEAN_P));
 
 /* ### pline.c ### */
 
+#ifdef DUMPLOG
+E void FDECL(dumplogmsg, (const char *));
+E void NDECL(dumplogfreemessages);
+#endif
 E void VDECL(pline, (const char *, ...)) PRINTF_F(1, 2);
+E void VDECL(custompline, (unsigned, const char *, ...)) PRINTF_F(2, 3);
 E void VDECL(Norep, (const char *, ...)) PRINTF_F(1, 2);
 E void NDECL(free_youbuf);
 E void VDECL(You, (const char *, ...)) PRINTF_F(1, 2);
@@ -1770,11 +1864,6 @@ E void VDECL(There, (const char *, ...)) PRINTF_F(1, 2);
 E void VDECL(verbalize, (const char *, ...)) PRINTF_F(1, 2);
 E void VDECL(raw_printf, (const char *, ...)) PRINTF_F(1, 2);
 E void VDECL(impossible, (const char *, ...)) PRINTF_F(1, 2);
-E const char *FDECL(align_str, (ALIGNTYP_P));
-E void FDECL(mstatusline, (struct monst *));
-E void NDECL(ustatusline);
-E void NDECL(self_invis_message);
-E void FDECL(pudding_merge_message, (struct obj *, struct obj *));
 
 /* ### polyself.c ### */
 
@@ -1798,6 +1887,8 @@ E const char *FDECL(mbodypart, (struct monst *, int));
 E const char *FDECL(body_part, (int));
 E int NDECL(poly_gender);
 E void FDECL(ugolemeffects, (int, int));
+E boolean NDECL(ugenocided);
+E const char *NDECL(udeadinside);
 
 /* ### potion.c ### */
 
@@ -1812,12 +1903,13 @@ E void FDECL(make_stoned, (long, const char *, int, const char *));
 E void FDECL(make_vomiting, (long, BOOLEAN_P));
 E boolean FDECL(make_hallucinated, (long, BOOLEAN_P, long));
 E void FDECL(make_deaf, (long, BOOLEAN_P));
+E void NDECL(self_invis_message);
 E int NDECL(dodrink);
 E int FDECL(dopotion, (struct obj *));
 E int FDECL(peffects, (struct obj *));
 E void FDECL(healup, (int, int, BOOLEAN_P, BOOLEAN_P));
 E void FDECL(strange_feeling, (struct obj *, const char *));
-E void FDECL(potionhit, (struct monst *, struct obj *, BOOLEAN_P));
+E void FDECL(potionhit, (struct monst *, struct obj *, int));
 E void FDECL(potionbreathe, (struct obj *));
 E int NDECL(dodip);
 E void FDECL(mongrantswish, (struct monst **));
@@ -1828,6 +1920,7 @@ E const char *NDECL(bottlename);
 /* ### pray.c ### */
 
 E boolean FDECL(critically_low_hp, (BOOLEAN_P));
+E boolean NDECL(stuck_in_wall);
 #ifdef USE_TRAMPOLI
 E int NDECL(prayer_done);
 #endif
@@ -1868,6 +1961,10 @@ E void NDECL(clearpriests);
 E void FDECL(restpriest, (struct monst *, BOOLEAN_P));
 E void FDECL(newepri, (struct monst *));
 E void FDECL(free_epri, (struct monst *));
+E const char *FDECL(align_str, (ALIGNTYP_P));
+E char *FDECL(piousness, (BOOLEAN_P, const char *));
+E void FDECL(mstatusline, (struct monst *));
+E void NDECL(ustatusline);
 
 /* ### quest.c ### */
 
@@ -1889,6 +1986,7 @@ E void NDECL(unload_qtlist);
 E short FDECL(quest_info, (int));
 E const char *NDECL(ldrname);
 E boolean FDECL(is_quest_artifact, (struct obj *));
+E struct obj *FDECL(find_quest_artifact, (unsigned));
 E void FDECL(com_pager, (int));
 E void FDECL(qt_pager, (int));
 E struct permonst *NDECL(qt_montype);
@@ -1949,6 +2047,7 @@ E NhRegion *FDECL(visible_region_at, (XCHAR_P, XCHAR_P));
 E void FDECL(show_region, (NhRegion *, XCHAR_P, XCHAR_P));
 E void FDECL(save_regions, (int, int));
 E void FDECL(rest_regions, (int, BOOLEAN_P));
+E void FDECL(region_stats, (const char *, char *, long *, long *));
 E NhRegion *FDECL(create_gas_cloud, (XCHAR_P, XCHAR_P, int, int));
 E boolean NDECL(region_danger);
 E void NDECL(region_safety);
@@ -2015,7 +2114,7 @@ E char *FDECL(build_plselection_prompt, (char *, int, int, int, int, int));
 E char *FDECL(root_plselection_prompt, (char *, int, int, int, int, int));
 E void NDECL(plnamesuffix);
 E void FDECL(role_selection_prolog, (int, winid));
-E void FDECL(role_menu_extra, (int, winid));
+E void FDECL(role_menu_extra, (int, winid, BOOLEAN_P));
 E void NDECL(role_init);
 E const char *FDECL(Hello, (struct monst *));
 E const char *NDECL(Goodbye);
@@ -2065,6 +2164,7 @@ E void FDECL(store_savefileinfo, (int));
 
 /* ### shk.c ### */
 
+E void FDECL(setpaid, (struct monst *));
 E long FDECL(money2mon, (struct monst *, long));
 E void FDECL(money2u, (struct monst *, long));
 E void FDECL(shkgone, (struct monst *));
@@ -2136,7 +2236,8 @@ E void FDECL(free_eshk, (struct monst *));
 E void FDECL(stock_room, (int, struct mkroom *));
 E boolean FDECL(saleable, (struct monst *, struct obj *));
 E int FDECL(get_shop_item, (int));
-E const char *FDECL(shkname, (struct monst *));
+E char *FDECL(Shknam, (struct monst *));
+E char *FDECL(shkname, (struct monst *));
 E boolean FDECL(shkname_is_pname, (struct monst *));
 E boolean FDECL(is_izchak, (struct monst *, BOOLEAN_P));
 
@@ -2183,9 +2284,15 @@ E boolean
 FDECL(dig_corridor, (coord *, coord *, BOOLEAN_P, SCHAR_P, SCHAR_P));
 E void FDECL(fill_room, (struct mkroom *, BOOLEAN_P));
 E boolean FDECL(load_special, (const char *));
+E xchar FDECL(selection_getpoint, (int, int, struct opvar *));
+E struct opvar *FDECL(selection_opvar, (char *));
+E void FDECL(opvar_free_x, (struct opvar *));
+E void FDECL(set_selection_floodfillchk, (int FDECL((*), (int,int))));
+E void FDECL(selection_floodfill, (struct opvar *, int, int, BOOLEAN_P));
 
 /* ### spell.c ### */
 
+E void FDECL(book_cursed, (struct obj *));
 #ifdef USE_TRAMPOLI
 E int NDECL(learn);
 #endif
@@ -2222,6 +2329,7 @@ E struct obj *FDECL(findgold, (struct obj *));
 E void NDECL(rider_cant_reach);
 E boolean FDECL(can_saddle, (struct monst *));
 E int FDECL(use_saddle, (struct obj *));
+E void FDECL(put_saddle_on_mon, (struct obj *, struct monst *));
 E boolean FDECL(can_ride, (struct monst *));
 E int NDECL(doride);
 E boolean FDECL(mount_steed, (struct monst *, BOOLEAN_P));
@@ -2235,8 +2343,8 @@ E boolean FDECL(stucksteed, (BOOLEAN_P));
 
 E boolean FDECL(goodpos, (int, int, struct monst *, unsigned));
 E boolean FDECL(enexto, (coord *, XCHAR_P, XCHAR_P, struct permonst *));
-E boolean
-FDECL(enexto_core, (coord *, XCHAR_P, XCHAR_P, struct permonst *, unsigned));
+E boolean FDECL(enexto_core, (coord *, XCHAR_P, XCHAR_P,
+                              struct permonst *, unsigned));
 E void FDECL(teleds, (int, int, BOOLEAN_P));
 E boolean FDECL(safe_teleds, (BOOLEAN_P));
 E boolean FDECL(teleport_pet, (struct monst *, BOOLEAN_P));
@@ -2246,13 +2354,13 @@ E int NDECL(dotele);
 E void NDECL(level_tele);
 E void FDECL(domagicportal, (struct trap *));
 E void FDECL(tele_trap, (struct trap *));
-E void FDECL(level_tele_trap, (struct trap *));
+E void FDECL(level_tele_trap, (struct trap *, unsigned));
 E void FDECL(rloc_to, (struct monst *, int, int));
 E boolean FDECL(rloc, (struct monst *, BOOLEAN_P));
 E boolean FDECL(tele_restrict, (struct monst *));
 E void FDECL(mtele_trap, (struct monst *, struct trap *, int));
-E int FDECL(mlevel_tele_trap,
-            (struct monst *, struct trap *, BOOLEAN_P, int));
+E int FDECL(mlevel_tele_trap, (struct monst *, struct trap *,
+                               BOOLEAN_P, int));
 E boolean FDECL(rloco, (struct obj *));
 E int NDECL(random_teleport_level);
 E boolean FDECL(u_teleport_mon, (struct monst *, BOOLEAN_P));
@@ -2290,15 +2398,17 @@ E long FDECL(spot_time_left, (XCHAR_P, XCHAR_P, SHORT_P));
 E boolean FDECL(obj_is_local, (struct obj *));
 E void FDECL(save_timers, (int, int, int));
 E void FDECL(restore_timers, (int, int, BOOLEAN_P, long));
+E void FDECL(timer_stats, (const char *, char *, long *, long *));
 E void FDECL(relink_timers, (BOOLEAN_P));
 E int NDECL(wiz_timeout_queue);
 E void NDECL(timer_sanity_check);
 
 /* ### topten.c ### */
 
-E void FDECL(formatkiller, (char *, unsigned, int));
+E void FDECL(formatkiller, (char *, unsigned, int, BOOLEAN_P));
 E void FDECL(topten, (int, time_t));
 E void FDECL(prscore, (int, char **));
+E struct toptenentry *NDECL(get_rnd_toptenentry);
 E struct obj *FDECL(tt_oname, (struct obj *));
 
 /* ### track.c ### */
@@ -2333,6 +2443,7 @@ E void NDECL(climb_pit);
 E boolean FDECL(fire_damage, (struct obj *, BOOLEAN_P, XCHAR_P, XCHAR_P));
 E int FDECL(fire_damage_chain,
             (struct obj *, BOOLEAN_P, BOOLEAN_P, XCHAR_P, XCHAR_P));
+E boolean FDECL(lava_damage, (struct obj *, XCHAR_P, XCHAR_P));
 E void acid_damage(struct obj *);
 E int FDECL(water_damage, (struct obj *, const char *, BOOLEAN_P));
 E void FDECL(water_damage_chain, (struct obj *, BOOLEAN_P));
@@ -2368,13 +2479,14 @@ E void NDECL(u_init);
 E void FDECL(erode_armor, (struct monst *, int));
 E boolean FDECL(attack_checks, (struct monst *, struct obj *));
 E void FDECL(check_caitiff, (struct monst *));
-E int FDECL(find_roll_to_hit,
-            (struct monst *, UCHAR_P, struct obj *, int *, int *));
+E int FDECL(find_roll_to_hit, (struct monst *, UCHAR_P, struct obj *,
+                               int *, int *));
 E boolean FDECL(attack, (struct monst *));
-E boolean FDECL(hmon, (struct monst *, struct obj *, int));
+E boolean FDECL(hmon, (struct monst *, struct obj *, int, int));
 E int FDECL(damageum, (struct monst *, struct attack *));
 E void FDECL(missum, (struct monst *, struct attack *, BOOLEAN_P));
-E int FDECL(passive, (struct monst *, BOOLEAN_P, int, UCHAR_P, BOOLEAN_P));
+E int FDECL(passive, (struct monst *, struct obj *, BOOLEAN_P, int,
+                      UCHAR_P, BOOLEAN_P));
 E void FDECL(passive_obj, (struct monst *, struct obj *, struct attack *));
 E void FDECL(stumble_onto_mimic, (struct monst *));
 E int FDECL(flash_hits_mon, (struct monst *, struct obj *));
@@ -2389,6 +2501,7 @@ E void NDECL(port_help);
 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);
 #endif /* UNIX */
 
 /* ### unixtty.c ### */
@@ -2434,6 +2547,7 @@ E int FDECL(hide_privileges, (BOOLEAN_P));
 E void FDECL(newegd, (struct monst *));
 E void FDECL(free_egd, (struct monst *));
 E boolean FDECL(grddead, (struct monst *));
+E void NDECL(vault_summon_gd);
 E char FDECL(vault_occupied, (char *));
 E void NDECL(invault);
 E int FDECL(gd_move, (struct monst *));
@@ -2458,9 +2572,13 @@ E void FDECL(store_version, (int));
 E unsigned long FDECL(get_feature_notice_ver, (char *));
 E unsigned long NDECL(get_current_feature_ver);
 E const char *FDECL(copyright_banner_line, (int));
+E void FDECL(early_version_info, (BOOLEAN_P));
 
 #ifdef RUNTIME_PORT_ID
-E void FDECL(append_port_id, (char *));
+E char *FDECL(get_port_id, (char *));
+#endif
+#ifdef RUNTIME_PASTEBUF_SUPPORT
+E void FDECL(port_insert_pastebuf, (char *));
 #endif
 
 /* ### video.c ### */
@@ -2611,6 +2729,7 @@ E void FDECL(new_were, (struct monst *));
 E int FDECL(were_summon, (struct permonst *, BOOLEAN_P, int *, char *));
 E void NDECL(you_were);
 E void FDECL(you_unwere, (BOOLEAN_P));
+E void FDECL(set_ulycn, (int));
 
 /* ### wield.c ### */
 
@@ -2650,16 +2769,16 @@ E void FDECL(genl_putmsghistory, (const char *, BOOLEAN_P));
 #ifdef HANGUPHANDLING
 E void NDECL(nhwindows_hangup);
 #endif
-#ifdef STATUS_VIA_WINDOWPORT
 E void NDECL(genl_status_init);
 E void NDECL(genl_status_finish);
 E void FDECL(genl_status_enablefield,
              (int, const char *, const char *, BOOLEAN_P));
-E void FDECL(genl_status_update, (int, genericptr_t, int, int));
-#ifdef STATUS_HILITES
-E void FDECL(genl_status_threshold, (int, int, anything, int, int, int));
-#endif
-#endif
+E void FDECL(genl_status_update, (int, genericptr_t, int, int, int, unsigned long *));
+
+E void FDECL(dump_open_log, (time_t));
+E void NDECL(dump_close_log);
+E void FDECL(dump_redirect, (BOOLEAN_P));
+E void FDECL(dump_forward_putstr, (winid, int, const char*, int));
 
 /* ### wizard.c ### */
 
@@ -2667,6 +2786,7 @@ E void NDECL(amulet);
 E int FDECL(mon_has_amulet, (struct monst *));
 E int FDECL(mon_has_special, (struct monst *));
 E int FDECL(tactics, (struct monst *));
+E boolean FDECL(has_aggravatables, (struct monst *));
 E void NDECL(aggravate);
 E void NDECL(clonewiz);
 E int NDECL(pick_nasty);
@@ -2690,11 +2810,14 @@ E void FDECL(detect_wsegs, (struct monst *, BOOLEAN_P));
 E void FDECL(save_worm, (int, int));
 E void FDECL(rest_worm, (int));
 E void FDECL(place_wsegs, (struct monst *));
+E void FDECL(sanity_check_worm, (struct monst *));
 E void FDECL(remove_worm, (struct monst *));
 E void FDECL(place_worm_tail_randomly, (struct monst *, XCHAR_P, XCHAR_P));
+E int FDECL(size_wseg, (struct monst *));
 E int FDECL(count_wsegs, (struct monst *));
 E boolean FDECL(worm_known, (struct monst *));
 E boolean FDECL(worm_cross, (int, int, int, int));
+E int FDECL(wseg_at, (struct monst *, int, int));
 
 /* ### worn.c ### */
 
@@ -2732,7 +2855,7 @@ E struct monst *FDECL(montraits, (struct obj *, coord *));
 E struct monst *FDECL(revive, (struct obj *, BOOLEAN_P));
 E int FDECL(unturn_dead, (struct monst *));
 E void FDECL(cancel_item, (struct obj *));
-E boolean FDECL(drain_item, (struct obj *));
+E boolean FDECL(drain_item, (struct obj *, BOOLEAN_P));
 E struct obj *FDECL(poly_obj, (struct obj *, int));
 E boolean FDECL(obj_resists, (struct obj *, int, int));
 E boolean FDECL(obj_shudders, (struct obj *));
@@ -2762,6 +2885,7 @@ E struct monst *FDECL(boomhit, (struct obj *, int, int));
 E int FDECL(zhitm, (struct monst *, int, int, struct obj **));
 E int FDECL(burn_floor_objects, (int, int, BOOLEAN_P, BOOLEAN_P));
 E void FDECL(buzz, (int, int, XCHAR_P, XCHAR_P, int, int));
+E void FDECL(dobuzz, (int, int, XCHAR_P, XCHAR_P, int, int, BOOLEAN_P));
 E void FDECL(melt_ice, (XCHAR_P, XCHAR_P, const char *));
 E void FDECL(start_melt_ice_timeout, (XCHAR_P, XCHAR_P, long));
 E void FDECL(melt_ice_away, (ANY_P *, long));
index b39a1f0..5dd13b2 100644 (file)
@@ -1,10 +1,11 @@
-/* NetHack 3.6 flag.h  $NHDT-Date: 1435002669 2015/06/22 19:51:09 $  $NHDT-Branch: master $:$NHDT-Revision: 1.89 $ */
+/* NetHack 3.6 flag.h  $NHDT-Date: 1514071158 2017/12/23 23:19:18 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.132 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* If you change the flag structure make sure you increment EDITLEVEL in   */
-/* patchlevel.h if needed.  Changing the instance_flags structure does    */
-/* not require incrementing EDITLEVEL.                                    */
+/* patchlevel.h if needed.  Changing the instance_flags structure does     */
+/* not require incrementing EDITLEVEL.                                     */
 
 #ifndef FLAG_H
 #define FLAG_H
@@ -48,7 +49,42 @@ struct flag {
     boolean showexp;         /* show experience points */
     boolean showscore;       /* show score */
     boolean silent;          /* whether the bell rings or not */
-    boolean sortloot;        /* sort items alphabetically when looting */
+    /* The story so far:
+     * 'sortloot' originally took a True/False value but was changed
+     * to use a letter instead.  3.6.0 was released without changing its
+     * type from 'boolean' to 'char'.  A compiler was smart enough to
+     * complain that assigning any of the relevant letters was not 0 or 1
+     * so not appropriate for boolean (by a configuration which used
+     * SKIP_BOOLEAN to bypass nethack's 'boolean' and use a C++-compatible
+     * one).  So the type was changed to 'xchar', which is guaranteed to
+     * match the size of 'boolean' (this guarantee only applies for the
+     * !SKIP_BOOLEAN config, unfortunately).  Since xchar does not match
+     * actual use, the type was later changed to 'char'.  But that would
+     * break 3.6.0 savefile compatibility for configurations which typedef
+     * 'schar' to 'short int' instead of to 'char'.  (Needed by pre-ANSI
+     * systems that use unsigned characters without a way to force them
+     * to be signed.)  So, the type has been changed back to 'xchar' for
+     * 3.6.1.
+     *
+     * TODO:  change to 'char' (and move out of this block of booleans,
+     * and get rid of these comments...) once 3.6.0 savefile compatibility
+     * eventually ends.
+     */
+#ifndef SKIP_BOOLEAN
+    /* this is the normal configuration; assigning a character constant
+       for a normal letter to an 'xchar' variable should always work even
+       if 'char' is unsigned since character constants are actually 'int'
+       and letters are within the range where signedness shouldn't matter */
+    xchar   sortloot; /* 'n'=none, 'l'=loot (pickup), 'f'=full ('l'+invent) */
+#else
+    /* with SKIP_BOOLEAN, we have no idea what underlying type is being
+       used, other than it isn't 'xchar' (although its size might match
+       that) or a bitfield (because it must be directly addressable);
+       it's probably either 'char' for compactness or 'int' for access,
+       but we don't know which and it might be something else anyway;
+       flip a coin here and guess 'char' for compactness */
+    char    sortloot; /* 'n'=none, 'l'=loot (pickup), 'f'=full ('l'+invent) */
+#endif
     boolean sortpack;        /* sorted inventory */
     boolean sparkle;         /* show "resisting" special FX (Scott Bigham) */
     boolean standout;        /* use standout for --More-- */
@@ -60,15 +96,16 @@ struct flag {
     unsigned long suppress_alert;
 #define NEW_MOON 0
 #define FULL_MOON 4
-    int paranoia_bits; /* alternate confirmation prompting */
-#define PARANOID_CONFIRM 0x01
-#define PARANOID_QUIT 0x02
-#define PARANOID_DIE 0x04
-#define PARANOID_BONES 0x08
-#define PARANOID_HIT 0x10
-#define PARANOID_PRAY 0x20
-#define PARANOID_REMOVE 0x40
-#define PARANOID_BREAKWAND 0x80
+    unsigned paranoia_bits; /* alternate confirmation prompting */
+#define PARANOID_CONFIRM    0x0001
+#define PARANOID_QUIT       0x0002
+#define PARANOID_DIE        0x0004
+#define PARANOID_BONES      0x0008
+#define PARANOID_HIT        0x0010
+#define PARANOID_PRAY       0x0020
+#define PARANOID_REMOVE     0x0040
+#define PARANOID_BREAKWAND  0x0080
+#define PARANOID_WERECHANGE 0x0100
     int pickup_burden; /* maximum burden before prompt */
     int pile_limit;    /* controls feedback when walking over objects */
     char inv_order[MAXOCLASSES];
@@ -76,8 +113,10 @@ struct flag {
 #define NUM_DISCLOSURE_OPTIONS 6 /* i,a,v,g,c,o (decl.c) */
 #define DISCLOSE_PROMPT_DEFAULT_YES 'y'
 #define DISCLOSE_PROMPT_DEFAULT_NO 'n'
+#define DISCLOSE_PROMPT_DEFAULT_SPECIAL '?' /* v, default a */
 #define DISCLOSE_YES_WITHOUT_PROMPT '+'
 #define DISCLOSE_NO_WITHOUT_PROMPT '-'
+#define DISCLOSE_SPECIAL_WITHOUT_PROMPT '#' /* v, use a */
     char end_disclose[NUM_DISCLOSURE_OPTIONS + 1]; /* disclose various
                                                       info upon exit */
     char menu_style;    /* User interface style setting */
@@ -95,7 +134,7 @@ struct flag {
      * characters or letters, because that limits us to 26 roles.
      * They are not booleans, because someday someone may need a neuter
      * gender.  Negative values are used to indicate that the user
-     * hasn't yet specified that particular value.     If you determine
+     * hasn't yet specified that particular value.  If you determine
      * that the user wants a random choice, then you should set an
      * appropriate random value; if you just left the negative value,
      * the user would be asked again!
@@ -167,57 +206,104 @@ struct sysflag {
  *
  */
 
+/* values for iflags.getpos_coords */
+#define GPCOORDS_NONE    'n'
+#define GPCOORDS_MAP     'm'
+#define GPCOORDS_COMPASS 'c'
+#define GPCOORDS_COMFULL 'f'
+#define GPCOORDS_SCREEN  's'
+
+enum getloc_filters {
+    GFILTER_NONE = 0,
+    GFILTER_VIEW,
+    GFILTER_AREA,
+
+    NUM_GFILTER
+};
+
 struct instance_flags {
     /* stuff that really isn't option or platform related. They are
      * set and cleared during the game to control the internal
      * behaviour of various NetHack functions and probably warrant
      * a structure of their own elsewhere some day.
      */
+    boolean defer_plname;  /* X11 hack: askname() might not set plname */
+    boolean herecmd_menu;  /* use menu when mouseclick on yourself */
+    boolean invis_goldsym; /* gold symbol is ' '? */
+    int parse_config_file_src;  /* hack for parse_config_line() */
     int in_lava_effects;   /* hack for Boots_off() */
     int last_msg;          /* indicator of last message player saw */
     int purge_monsters;    /* # of dead monsters still on fmon list */
     int override_ID;       /* true to force full identification of objects */
     int suppress_price;    /* controls doname() for unpaid objects */
+    int terrainmode; /* for getpos()'s autodescribe when #terrain is active */
+#define TER_MAP    0x01
+#define TER_TRP    0x02
+#define TER_OBJ    0x04
+#define TER_MON    0x08
+#define TER_DETECT 0x10    /* detect_foo magic rather than #terrain */
+    boolean getloc_travelmode;
+    int getloc_filter;     /* GFILTER_foo */
+    boolean getloc_usemenu;
+    boolean getloc_moveskip;
     coord travelcc;        /* coordinates for travel_cache */
     boolean window_inited; /* true if init_nhwindows() completed */
     boolean vision_inited; /* true if vision is ready */
     boolean sanity_check;  /* run sanity checks */
     boolean mon_polycontrol; /* debug: control monster polymorphs */
-    /* stuff that is related to options and/or user or platform preferences */
+    boolean in_dumplog;    /* doing the dumplog right now? */
+    boolean in_parse;      /* is a command being parsed? */
+
+    /* stuff that is related to options and/or user or platform preferences
+     */
     unsigned msg_history; /* hint: # of top lines to save */
+    int getpos_coords;    /* show coordinates when getting cursor position */
     int menu_headings;    /* ATR for menu headings */
     int *opt_booldup;     /* for duplication of boolean opts in config file */
-    int *opt_compdup; /* for duplication of compound opts in config file */
+    int *opt_compdup;     /* for duplication of compound opts in conf file */
 #ifdef ALTMETA
-    boolean altmeta; /* Alt-c sends ESC c rather than M-c */
+    boolean altmeta;      /* Alt-c sends ESC c rather than M-c */
 #endif
+    boolean autodescribe;     /* autodescribe mode in getpos() */
     boolean cbreak;           /* in cbreak mode, rogue format */
     boolean deferred_X;       /* deferred entry into explore mode */
-    boolean num_pad;          /* use numbers for movement commands */
-    boolean news;             /* print news */
+    boolean echo;             /* 1 to echo characters */
+    boolean force_invmenu;    /* always menu when handling inventory */
+    /* FIXME: goldX belongs in flags, but putting it in iflags avoids
+       breaking 3.6.[01] save files */
+    boolean goldX;            /* for BUCX filtering, whether gold is X or U */
+    boolean hilite_pile;      /* mark piles of objects with a hilite */
     boolean implicit_uncursed; /* maybe omit "uncursed" status in inventory */
     boolean mention_walls;    /* give feedback when bumping walls */
-    boolean menu_tab_sep;     /* Use tabs to separate option menu fields */
     boolean menu_head_objsym; /* Show obj symbol in menu headings */
+    boolean menu_overlay;     /* Draw menus over the map */
     boolean menu_requested;   /* Flag for overloaded use of 'm' prefix
                                * on some non-move commands */
+    boolean menu_tab_sep;     /* Use tabs to separate option menu fields */
+    boolean news;             /* print news */
+    boolean num_pad;          /* use numbers for movement commands */
     boolean renameallowed;    /* can change hero name during role selection */
     boolean renameinprogress; /* we are changing hero name */
+    boolean status_updates;   /* allow updates to bottom status lines;
+                               * disable to avoid excessive noise when using
+                               * a screen reader (use ^X to review status) */
     boolean toptenwin;        /* ending list in window instead of stdout */
+    boolean use_background_glyph; /* use background glyph when appropriate */
+    boolean use_menu_color;   /* use color in menus; only if wc_color */
+#ifdef STATUS_HILITES
+    long hilite_delta;     /* number of moves to leave a temp hilite lit */
+    long unhilite_deadline; /* time when oldest temp hilite should be unlit */
+#endif
     boolean zerocomp;         /* write zero-compressed save files */
-    boolean rlecomp; /* run-length comp of levels when writing savefile */
+    boolean rlecomp;          /* alternative to zerocomp; run-length encoding
+                               * compression of levels when writing savefile */
     uchar num_pad_mode;
-    boolean echo;             /* 1 to echo characters */
-    boolean use_menu_color;       /* use color in menus; only if wc_color */
-    boolean use_status_hilites;   /* use color in status line */
-    boolean use_background_glyph; /* use background glyph when appropriate */
-    boolean hilite_pile;          /* mark piles of objects with a hilite */
-#if 0
-       boolean  DECgraphics;   /* use DEC VT-xxx extended character set */
-       boolean  IBMgraphics;   /* use IBM extended character set */
+#if 0   /* XXXgraphics superseded by symbol sets */
+    boolean  DECgraphics;       /* use DEC VT-xxx extended character set */
+    boolean  IBMgraphics;       /* use IBM extended character set */
 #ifdef MAC_GRAPHICS_ENV
-       boolean  MACgraphics;   /* use Macintosh extended character set, as
-                                  as defined in the special font HackFont */
+    boolean  MACgraphics;       /* use Macintosh extended character set, as
+                                   as defined in the special font HackFont */
 #endif
 #endif
     uchar bouldersym; /* symbol for boulder display */
@@ -252,12 +338,19 @@ struct instance_flags {
 #ifdef MSDOS
     boolean hasvga; /* has a vga adapter */
     boolean usevga; /* use the vga adapter */
+    boolean hasvesa; /* has a VESA-capable VGA adapter */
+    boolean usevesa; /* use the VESA-capable VGA adapter */
     boolean grmode; /* currently in graphics mode */
 #endif
 #ifdef LAN_FEATURES
     boolean lan_mail;         /* mail is initialized */
     boolean lan_mail_fetched; /* mail is awaiting display */
 #endif
+#ifdef TTY_TILES_ESCCODES
+    boolean vt_tiledata;     /* output console codes for tile support in TTY */
+#endif
+    boolean wizweight;        /* display weight of everything in wizard mode */
+
     /*
      * Window capability support.
      */
@@ -294,24 +387,24 @@ struct instance_flags {
     int wc_fontsiz_menu;    /* font size for the menu window       */
     int wc_fontsiz_text;    /* font size for text windows          */
     int wc_scroll_amount;   /* scroll this amount at scroll_margin */
-    int wc_scroll_margin;   /* scroll map when this far from
-                                    the edge */
+    int wc_scroll_margin;   /* scroll map when this far from the edge */
     int wc_map_mode;        /* specify map viewing options, mostly
-                                    for backward compatibility */
+                             * for backward compatibility */
     int wc_player_selection;    /* method of choosing character */
     boolean wc_splash_screen;   /* display an opening splash screen or not */
     boolean wc_popup_dialog;    /* put queries in pop up dialogs instead of
-                                        in the message window */
+                                 * in the message window */
     boolean wc_eight_bit_input; /* allow eight bit input               */
     boolean wc_mouse_support;   /* allow mouse support */
     boolean wc2_fullscreen;     /* run fullscreen */
     boolean wc2_softkeyboard;   /* use software keyboard */
     boolean wc2_wraptext;       /* wrap text */
     boolean wc2_selectsaved;    /* display a menu of user's saved games */
-    boolean wc2_darkgray; /* try to use dark-gray color for black glyphs */
-    boolean cmdassist;    /* provide detailed assistance for some commands */
-    boolean clicklook;    /* allow right-clicking for look */
-    boolean obsolete; /* obsolete options can point at this, it isn't used */
+    boolean wc2_darkgray;    /* try to use dark-gray color for black glyphs */
+    boolean wc2_hitpointbar;  /* show graphical bar representing hit points */
+    boolean cmdassist;     /* provide detailed assistance for some commands */
+    boolean clicklook;          /* allow right-clicking for look */
+    boolean obsolete;  /* obsolete options can point at this, it isn't used */
     struct autopickup_exception *autopickup_exceptions[2];
 #define AP_LEAVE 0
 #define AP_GRAB 1
@@ -322,8 +415,14 @@ struct instance_flags {
     /* copies of values in struct u, used during detection when the
        originals are temporarily cleared; kept here rather than
        locally so that they can be restored during a hangup save */
+    Bitfield(save_uswallow, 1);
     Bitfield(save_uinwater, 1);
     Bitfield(save_uburied, 1);
+    /* item types used to acomplish "special achievements"; find the target
+       object and you'll be flagged as having achieved something... */
+    short mines_prize_type;     /* luckstone */
+    short soko_prize_type1;     /* bag of holding or    */
+    short soko_prize_type2;     /* amulet of reflection */
 };
 
 /*
@@ -349,18 +448,30 @@ extern NEARDATA struct sysflag sysflags;
 #endif
 extern NEARDATA struct instance_flags iflags;
 
-/* last_msg values */
-#define PLNMSG_UNKNOWN 0             /* arbitrary */
-#define PLNMSG_ONE_ITEM_HERE 1       /* "you see <single item> here" */
-#define PLNMSG_TOWER_OF_FLAME 2      /* scroll of fire */
-#define PLNMSG_CAUGHT_IN_EXPLOSION 3 /* explode() feedback */
-#define PLNMSG_OBJ_GLOWS 4           /* "the <obj> glows <color>" */
+/* last_msg values
+ * Usage:
+ *  pline("some message");
+ *    pline: vsprintf + putstr + iflags.last_msg = PLNMSG_UNKNOWN;
+ *  iflags.last_msg = PLNMSG_some_message;
+ * and subsequent code can adjust the next message if it is affected
+ * by some_message.  The next message will clear iflags.last_msg.
+ */
+enum plnmsg_types {
+    PLNMSG_UNKNOWN = 0,         /* arbitrary */
+    PLNMSG_ONE_ITEM_HERE,       /* "you see <single item> here" */
+    PLNMSG_TOWER_OF_FLAME,      /* scroll of fire */
+    PLNMSG_CAUGHT_IN_EXPLOSION, /* explode() feedback */
+    PLNMSG_OBJ_GLOWS,           /* "the <obj> glows <color>" */
+    PLNMSG_OBJNAM_ONLY          /* xname/doname only, for #tip */
+};
 
 /* runmode options */
-#define RUN_TPORT 0 /* don't update display until movement stops */
-#define RUN_LEAP 1  /* update display every 7 steps */
-#define RUN_STEP 2  /* update display every single step */
-#define RUN_CRAWL 3 /* walk w/ extra delay after each update */
+enum runmode_types {
+    RUN_TPORT = 0, /* don't update display until movement stops */
+    RUN_LEAP,      /* update display every 7 steps */
+    RUN_STEP,      /* update display every single step */
+    RUN_CRAWL      /* walk w/ extra delay after each update */
+};
 
 /* paranoid confirmation prompting */
 /* any yes confirmations also require explicit no (or ESC) to reject */
@@ -381,15 +492,81 @@ extern NEARDATA struct instance_flags iflags;
 #define ParanoidRemove ((flags.paranoia_bits & PARANOID_REMOVE) != 0)
 /* breakwand: Applying a wand */
 #define ParanoidBreakwand ((flags.paranoia_bits & PARANOID_BREAKWAND) != 0)
+/* werechange: accepting randomly timed werecreature change to transform
+   from human to creature or vice versa while having polymorph control */
+#define ParanoidWerechange ((flags.paranoia_bits & PARANOID_WERECHANGE) != 0)
 
 /* command parsing, mainly dealing with number_pad handling;
    not saved and restored */
 
 #ifdef NHSTDC
 /* forward declaration sufficient to declare pointers */
-struct func_tab; /* from func_tab.h */
+struct ext_func_tab; /* from func_tab.h */
 #endif
 
+/* special key functions */
+enum nh_keyfunc {
+    NHKF_ESC = 0,
+    NHKF_DOAGAIN,
+
+    NHKF_REQMENU,
+
+    /* run ... clicklook need to be in a continuous block */
+    NHKF_RUN,
+    NHKF_RUN2,
+    NHKF_RUSH,
+    NHKF_FIGHT,
+    NHKF_FIGHT2,
+    NHKF_NOPICKUP,
+    NHKF_RUN_NOPICKUP,
+    NHKF_DOINV,
+    NHKF_TRAVEL,
+    NHKF_CLICKLOOK,
+
+    NHKF_REDRAW,
+    NHKF_REDRAW2,
+    NHKF_GETDIR_SELF,
+    NHKF_GETDIR_SELF2,
+    NHKF_GETDIR_HELP,
+    NHKF_COUNT,
+    NHKF_GETPOS_SELF,
+    NHKF_GETPOS_PICK,
+    NHKF_GETPOS_PICK_Q,  /* quick */
+    NHKF_GETPOS_PICK_O,  /* once */
+    NHKF_GETPOS_PICK_V,  /* verbose */
+    NHKF_GETPOS_SHOWVALID,
+    NHKF_GETPOS_AUTODESC,
+    NHKF_GETPOS_MON_NEXT,
+    NHKF_GETPOS_MON_PREV,
+    NHKF_GETPOS_OBJ_NEXT,
+    NHKF_GETPOS_OBJ_PREV,
+    NHKF_GETPOS_DOOR_NEXT,
+    NHKF_GETPOS_DOOR_PREV,
+    NHKF_GETPOS_UNEX_NEXT,
+    NHKF_GETPOS_UNEX_PREV,
+    NHKF_GETPOS_INTERESTING_NEXT,
+    NHKF_GETPOS_INTERESTING_PREV,
+    NHKF_GETPOS_VALID_NEXT,
+    NHKF_GETPOS_VALID_PREV,
+    NHKF_GETPOS_HELP,
+    NHKF_GETPOS_MENU,
+    NHKF_GETPOS_LIMITVIEW,
+    NHKF_GETPOS_MOVESKIP,
+
+    NUM_NHKF
+};
+
+enum gloctypes {
+    GLOC_MONS = 0,
+    GLOC_OBJS,
+    GLOC_DOOR,
+    GLOC_EXPLORE,
+    GLOC_INTERESTING,
+    GLOC_VALID,
+
+    NUM_GLOCS
+};
+
 /* commands[] is used to directly access cmdlist[] instead of looping
    through it to find the entry for a given input character;
    move_X is the character used for moving one step in direction X;
@@ -402,11 +579,12 @@ struct cmd {
     boolean num_pad;       /* same as iflags.num_pad except during updates */
     boolean pcHack_compat; /* for numpad:  affects 5, M-5, and M-0 */
     boolean phone_layout;  /* inverted keypad:  1,2,3 above, 7,8,9 below */
-    boolean swap_yz;       /* German keyboards; use z to move NW, y to zap */
+    boolean swap_yz;       /* QWERTZ keyboards; use z to move NW, y to zap */
     char move_W, move_NW, move_N, move_NE, move_E, move_SE, move_S, move_SW;
     const char *dirchars;      /* current movement/direction characters */
     const char *alphadirchars; /* same as dirchars if !numpad */
-    const struct func_tab *commands[256]; /* indexed by input character */
+    const struct ext_func_tab *commands[256]; /* indexed by input character */
+    char spkeys[NUM_NHKF];
 };
 
 extern NEARDATA struct cmd Cmd;
index bb5c16b..14460c9 100644 (file)
@@ -1,21 +1,23 @@
 /* NetHack 3.6 func_tab.h      $NHDT-Date: 1432512775 2015/05/25 00:12:55 $  $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2016. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef FUNC_TAB_H
 #define FUNC_TAB_H
 
-struct func_tab {
-    char f_char;
-    boolean can_if_buried;
-    int NDECL((*f_funct));
-    const char *f_text;
-};
+/* extended command flags */
+#define IFBURIED     0x01 /* can do command when buried */
+#define AUTOCOMPLETE 0x02 /* command autocompletes */
+#define WIZMODECMD   0x04 /* wizard-mode command */
+#define GENERALCMD   0x08 /* general command, does not take game time */
 
 struct ext_func_tab {
+    uchar key;
     const char *ef_txt, *ef_desc;
     int NDECL((*ef_funct));
-    boolean can_if_buried;
+    int flags;
+    const char *f_text;
 };
 
 extern struct ext_func_tab extcmdlist[];
index b7a61bd..420cd84 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 global.h        $NHDT-Date: 1449116298 2015/12/03 04:18:18 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.46 $ */
+/* NetHack 3.6 global.h        $NHDT-Date: 1524690661 2018/04/25 21:11:01 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef GLOBAL_H
@@ -7,9 +8,9 @@
 
 #include <stdio.h>
 
-/* #define BETA */ /* development or beta testing [MRS] */
+/* #define BETA  */ /* development or beta testing [MRS] */
 
-/* #define DEBUG */
+#define DEBUG 
 
 /*
  * Files expected to exist in the playground directory.
@@ -18,6 +19,7 @@
 #define RECORD "record"         /* file containing list of topscorers */
 #define HELP "help"             /* file containing command descriptions */
 #define SHELP "hh"              /* abbreviated form of the same */
+#define KEYHELP "keyhelp"       /* explanatory text for 'whatdoes' command */
 #define DEBUGHELP "wizhelp"     /* file containing debug mode cmds */
 #define RUMORFILE "rumors"      /* file with fortune cookies */
 #define ORACLEFILE "oracles"    /* file with oracular information */
@@ -318,9 +320,7 @@ struct savefile_info {
 #define PL_NSIZ 32 /* name of player, ghost, shopkeeper */
 #define PL_CSIZ 32 /* sizeof pl_character */
 #define PL_FSIZ 32 /* fruit name */
-#define PL_PSIZ                              \
-    63 /* player-given names for pets, other \
-        * monsters, objects */
+#define PL_PSIZ 63 /* player-given names for pets, other monsters, objects */
 
 #define MAXDUNGEON 16 /* current maximum number of dungeons */
 #define MAXLEVEL 32   /* max number of levels in one dungeon */
index 319f4d3..af35c2c 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 hack.h  $NHDT-Date: 1434056948 2015/06/11 21:09:08 $  $NHDT-Branch: master $:$NHDT-Revision: 1.66 $ */
+/* NetHack 3.6 hack.h  $NHDT-Date: 1490908464 2017/03/30 21:14:24 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.76 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2017. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef HACK_H
     }
 
 /* symbolic names for capacity levels */
-#define UNENCUMBERED 0
-#define SLT_ENCUMBER 1 /* Burdened */
-#define MOD_ENCUMBER 2 /* Stressed */
-#define HVY_ENCUMBER 3 /* Strained */
-#define EXT_ENCUMBER 4 /* Overtaxed */
-#define OVERLOADED 5   /* Overloaded */
+enum encumbrance_types {
+    UNENCUMBERED = 0,
+    SLT_ENCUMBER, /* Burdened */
+    MOD_ENCUMBER, /* Stressed */
+    HVY_ENCUMBER, /* Strained */
+    EXT_ENCUMBER, /* Overtaxed */
+    OVERLOADED    /* Overloaded */
+};
+
+/* weight increment of heavy iron ball */
+#define IRON_BALL_W_INCR 160
+
+/* number of turns it takes for vault guard to show up */
+#define VAULT_GUARD_TIME 30
+
+#define SHOP_DOOR_COST 400L /* cost of a destroyed shop door */
+#define SHOP_BARS_COST 300L /* cost of iron bars */
+#define SHOP_HOLE_COST 200L /* cost of making hole/trapdoor */
+#define SHOP_WALL_COST 200L /* cost of destroying a wall */
+#define SHOP_WALL_DMG  (10L * ACURRSTR) /* damaging a wall */
 
 /* hunger states - see hu_stat in eat.c */
-#define SATIATED 0
-#define NOT_HUNGRY 1
-#define HUNGRY 2
-#define WEAK 3
-#define FAINTING 4
-#define FAINTED 5
-#define STARVED 6
+enum hunger_state_types {
+    SATIATED = 0,
+    NOT_HUNGRY,
+    HUNGRY,
+    WEAK,
+    FAINTING,
+    FAINTED,
+    STARVED
+};
 
 /* Macros for how a rumor was delivered in outrumor() */
 #define BY_ORACLE 0
 #define BY_OTHER 9
 
 /* Macros for why you are no longer riding */
-#define DISMOUNT_GENERIC 0
-#define DISMOUNT_FELL 1
-#define DISMOUNT_THROWN 2
-#define DISMOUNT_POLY 3
-#define DISMOUNT_ENGULFED 4
-#define DISMOUNT_BONES 5
-#define DISMOUNT_BYCHOICE 6
+enum dismount_types {
+    DISMOUNT_GENERIC = 0,
+    DISMOUNT_FELL,
+    DISMOUNT_THROWN,
+    DISMOUNT_POLY,
+    DISMOUNT_ENGULFED,
+    DISMOUNT_BONES,
+    DISMOUNT_BYCHOICE
+};
 
 /* Special returns from mapglyph() */
-#define MG_CORPSE 0x01
-#define MG_INVIS 0x02
-#define MG_DETECT 0x04
-#define MG_PET 0x08
-#define MG_RIDDEN 0x10
-#define MG_STATUE 0x20
+#define MG_CORPSE  0x01
+#define MG_INVIS   0x02
+#define MG_DETECT  0x04
+#define MG_PET     0x08
+#define MG_RIDDEN  0x10
+#define MG_STATUE  0x20
 #define MG_OBJPILE 0x40  /* more than one stack of objects */
+#define MG_BW_LAVA 0x80  /* 'black & white lava': highlight lava if it
+                            can't be distringuished from water by color */
 
 /* sellobj_state() states */
 #define SELL_NORMAL (0)
 #define SELL_DONTSELL (2)
 
 /* alteration types--keep in synch with costly_alteration(mkobj.c) */
-#define COST_CANCEL 0   /* standard cancellation */
-#define COST_DRAIN 1    /* drain life upon an object */
-#define COST_UNCHRG 2   /* cursed charging */
-#define COST_UNBLSS 3   /* unbless (devalues holy water) */
-#define COST_UNCURS 4   /* uncurse (devalues unholy water) */
-#define COST_DECHNT 5   /* disenchant weapons or armor */
-#define COST_DEGRD 6    /* removal of rustproofing, dulling via engraving */
-#define COST_DILUTE 7   /* potion dilution */
-#define COST_ERASE 8    /* scroll or spellbook blanking */
-#define COST_BURN 9     /* dipped into flaming oil */
-#define COST_NUTRLZ 10  /* neutralized via unicorn horn */
-#define COST_DSTROY 11  /* wand breaking (bill first, useup later) */
-#define COST_SPLAT 12   /* cream pie to own face (ditto) */
-#define COST_BITE 13    /* start eating food */
-#define COST_OPEN 14    /* open tin */
-#define COST_BRKLCK 15  /* break box/chest's lock */
-#define COST_RUST 16    /* rust damage */
-#define COST_ROT 17     /* rotting attack */
-#define COST_CORRODE 18 /* acid damage */
+enum cost_alteration_types {
+    COST_CANCEL = 0,   /* standard cancellation */
+    COST_DRAIN,    /* drain life upon an object */
+    COST_UNCHRG,   /* cursed charging */
+    COST_UNBLSS,   /* unbless (devalues holy water) */
+    COST_UNCURS,   /* uncurse (devalues unholy water) */
+    COST_DECHNT,   /* disenchant weapons or armor */
+    COST_DEGRD,    /* removal of rustproofing, dulling via engraving */
+    COST_DILUTE,   /* potion dilution */
+    COST_ERASE,    /* scroll or spellbook blanking */
+    COST_BURN,     /* dipped into flaming oil */
+    COST_NUTRLZ,   /* neutralized via unicorn horn */
+    COST_DSTROY,   /* wand breaking (bill first, useup later) */
+    COST_SPLAT,    /* cream pie to own face (ditto) */
+    COST_BITE,     /* start eating food */
+    COST_OPEN,     /* open tin */
+    COST_BRKLCK,   /* break box/chest's lock */
+    COST_RUST,     /* rust damage */
+    COST_ROT,      /* rotting attack */
+    COST_CORRODE   /* acid damage */
+};
 
 /* bitmask flags for corpse_xname();
    PFX_THE takes precedence over ARTICLE, NO_PFX takes precedence over both */
 #define CXN_ARTICLE 8   /* include a/an/the prefix */
 #define CXN_NOCORPSE 16 /* suppress " corpse" suffix */
 
+/* getpos() return values */
+enum getpos_retval {
+    LOOK_TRADITIONAL = 0, /* '.' -- ask about "more info?" */
+    LOOK_QUICK,           /* ',' -- skip "more info?" */
+    LOOK_ONCE,            /* ';' -- skip and stop looping */
+    LOOK_VERBOSE          /* ':' -- show more info w/o asking */
+};
+
 /*
  * This is the way the game ends.  If these are rearranged, the arrays
  * in end.c and topten.c will need to be changed.  Some parts of the
  * code assume that PANIC separates the deaths from the non-deaths.
  */
-#define DIED 0
-#define CHOKING 1
-#define POISONING 2
-#define STARVING 3
-#define DROWNING 4
-#define BURNING 5
-#define DISSOLVED 6
-#define CRUSHING 7
-#define STONING 8
-#define TURNED_SLIME 9
-#define GENOCIDED 10
-#define PANICKED 11
-#define TRICKED 12
-#define QUIT 13
-#define ESCAPED 14
-#define ASCENDED 15
+enum game_end_types {
+    DIED = 0,
+    CHOKING,
+    POISONING,
+    STARVING,
+    DROWNING,
+    BURNING,
+    DISSOLVED,
+    CRUSHING,
+    STONING,
+    TURNED_SLIME,
+    GENOCIDED,
+    PANICKED,
+    TRICKED,
+    QUIT,
+    ESCAPED,
+    ASCENDED
+};
+
+typedef struct strbuf {
+    int    len;
+    char * str;
+    char   buf[256];
+} strbuf_t;
 
 #include "align.h"
 #include "dungeon.h"
 NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
 
 /* types of calls to bhit() */
-#define ZAPPED_WAND 0
-#define THROWN_WEAPON 1
-#define KICKED_WEAPON 2
-#define FLASHED_LIGHT 3
-#define INVIS_BEAM 4
+enum bhit_call_types {
+    ZAPPED_WAND = 0,
+    THROWN_WEAPON,
+    KICKED_WEAPON,
+    FLASHED_LIGHT,
+    INVIS_BEAM
+};
 
 /* attack mode for hmon() */
-#define HMON_MELEE 0   /* hand-to-hand */
-#define HMON_THROWN 1  /* normal ranged (or spitting while poly'd) */
-#define HMON_KICKED 2  /* alternate ranged */
-#define HMON_APPLIED 3 /* polearm, treated as ranged */
-#define HMON_DRAGGED 4 /* attached iron ball, pulled into mon */
+enum hmon_atkmode_types {
+    HMON_MELEE = 0, /* hand-to-hand */
+    HMON_THROWN,    /* normal ranged (or spitting while poly'd) */
+    HMON_KICKED,    /* alternate ranged */
+    HMON_APPLIED,   /* polearm, treated as ranged */
+    HMON_DRAGGED    /* attached iron ball, pulled into mon */
+};
 
 #define MATCH_WARN_OF_MON(mon)                                               \
     (Warn_of_mon && ((context.warntype.obj                                   \
@@ -253,6 +296,7 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
 #define BUC_UNCURSED 0x200
 #define BUC_UNKNOWN 0x400
 #define BUC_ALLBKNOWN (BUC_BLESSED | BUC_CURSED | BUC_UNCURSED)
+#define BUCX_TYPES (BUC_ALLBKNOWN | BUC_UNKNOWN)
 #define ALL_TYPES_SELECTED -2
 
 /* Flags to control find_mid() */
@@ -269,14 +313,15 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
 #define FORCETRAP 0x01     /* triggering not left to chance */
 #define NOWEBMSG 0x02      /* suppress stumble into web message */
 #define FORCEBUNGLE 0x04   /* adjustments appropriate for bungling */
-#define RECURSIVETRAP 0x08 /* trap changed into another type this same turn \
-                              */
+#define RECURSIVETRAP 0x08 /* trap changed into another type this same turn */
 #define TOOKPLUNGE 0x10    /* used '>' to enter pit below you */
+#define VIASITTING 0x20    /* #sit while at trap location (affects message) */
 
 /* Flags to control test_move in hack.c */
 #define DO_MOVE 0   /* really doing the move */
 #define TEST_MOVE 1 /* test a normal move (move there next) */
 #define TEST_TRAV 2 /* test a future travel location */
+#define TEST_TRAP 3 /* check if a future travel loc is a trap */
 
 /*** some utility macros ***/
 #define yn(query) yn_function(query, ynchars, 'n')
@@ -301,42 +346,64 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
 #define LAUNCH_KNOWN 0x80  /* the hero caused this by explicit action */
 
 /* Macros for explosion types */
-#define EXPL_DARK 0
-#define EXPL_NOXIOUS 1
-#define EXPL_MUDDY 2
-#define EXPL_WET 3
-#define EXPL_MAGICAL 4
-#define EXPL_FIERY 5
-#define EXPL_FROSTY 6
-#define EXPL_MAX 7
+enum explosion_types {
+    EXPL_DARK = 0,
+    EXPL_NOXIOUS,
+    EXPL_MUDDY,
+    EXPL_WET,
+    EXPL_MAGICAL,
+    EXPL_FIERY,
+    EXPL_FROSTY,
+    EXPL_MAX
+};
 
 /* enlightenment control flags */
 #define BASICENLIGHTENMENT 1 /* show mundane stuff */
 #define MAGICENLIGHTENMENT 2 /* show intrinsics and such */
 #define ENL_GAMEINPROGRESS 0
-#define ENL_GAMEOVERALIVE 1 /* ascension, escape, quit, trickery */
-#define ENL_GAMEOVERDEAD 2
+#define ENL_GAMEOVERALIVE  1 /* ascension, escape, quit, trickery */
+#define ENL_GAMEOVERDEAD   2
+
+/* control flags for sortloot() */
+#define SORTLOOT_PACK   0x01
+#define SORTLOOT_INVLET 0x02
+#define SORTLOOT_LOOT   0x04
+
+/* flags for xkilled() [note: meaning of first bit used to be reversed,
+   1 to give message and 0 to suppress] */
+#define XKILL_GIVEMSG   0
+#define XKILL_NOMSG     1
+#define XKILL_NOCORPSE  2
+#define XKILL_NOCONDUCT 4
+
+/* pline_flags; mask values for custompline()'s first argument */
+/* #define PLINE_ORDINARY 0 */
+#define PLINE_NOREPEAT   1
+#define OVERRIDE_MSGTYPE 2
+#define SUPPRESS_HISTORY 4
 
 /* Macros for messages referring to hands, eyes, feet, etc... */
-#define ARM 0
-#define EYE 1
-#define FACE 2
-#define FINGER 3
-#define FINGERTIP 4
-#define FOOT 5
-#define HAND 6
-#define HANDED 7
-#define HEAD 8
-#define LEG 9
-#define LIGHT_HEADED 10
-#define NECK 11
-#define SPINE 12
-#define TOE 13
-#define HAIR 14
-#define BLOOD 15
-#define LUNG 16
-#define NOSE 17
-#define STOMACH 18
+enum bodypart_types {
+    ARM = 0,
+    EYE,
+    FACE,
+    FINGER,
+    FINGERTIP,
+    FOOT,
+    HAND,
+    HANDED,
+    HEAD,
+    LEG,
+    LIGHT_HEADED,
+    NECK,
+    SPINE,
+    TOE,
+    HAIR,
+    BLOOD,
+    LUNG,
+    NOSE,
+    STOMACH
+};
 
 /* indices for some special tin types */
 #define ROTTEN_TIN 0
@@ -373,7 +440,8 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
 #define DISP_IN_GAME 3 /* may be set via extern program, displayed in game \
                           */
 #define SET_IN_GAME 4  /* may be set via extern program or set in the game */
-#define SET__IS_VALUE_VALID(s) ((s < SET_IN_SYS) || (s > SET_IN_GAME))
+#define SET_IN_WIZGAME 5  /* may be set set in the game if wizmode */
+#define SET__IS_VALUE_VALID(s) ((s < SET_IN_SYS) || (s > SET_IN_WIZGAME))
 
 #define FEATURE_NOTICE_VER(major, minor, patch)                    \
     (((unsigned long) major << 24) | ((unsigned long) minor << 16) \
diff --git a/include/integer.h b/include/integer.h
new file mode 100644 (file)
index 0000000..044da02
--- /dev/null
@@ -0,0 +1,41 @@
+/* NetHack 3.6 integer.h       $NHDT-Date: 1524689514 2018/04/25 20:51:54 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.0 $ */
+/*      Copyright (c) 2016 by Michael Allison          */
+/* NetHack may be freely redistributed.  See license for details. */
+
+/* integer.h -- provide sized integer types */
+
+#ifndef INTEGER_H
+#define INTEGER_H
+
+#if defined(__STDC__) && __STDC__ >= 199101L
+
+/* The compiler claims to conform to C99. Use stdint.h */
+#include <stdint.h>
+typedef uint8_t uint8;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+
+#else /* !C99 */
+
+/* Provide uint8, int16, uint16, int32 and uint32 */
+typedef unsigned char uint8;
+typedef short int16;
+typedef unsigned short uint16;
+
+#if defined(__WATCOMC__) && !defined(__386__)
+/* Open Watcom providing a 16 bit build for MS-DOS or OS/2 */
+/* int is 16 bits; use long for 32 bits */
+typedef long int32;
+typedef unsigned long uint32;
+#else
+/* Otherwise, assume either a 32- or 64-bit compiler */
+/* long may be 64 bits; use int for 32 bits */
+typedef int int32;
+typedef unsigned int uint32;
+#endif
+
+#endif /* !C99 */
+
+#endif /* INTEGER_H */
index b4dd30a..17fd8dd 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 lev.h   $NHDT-Date: 1432512781 2015/05/25 00:13:01 $  $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*     Common include file for save and restore routines */
@@ -25,10 +26,12 @@ struct container {
     genericptr_t list;
 };
 
-#define CONS_OBJ 0
-#define CONS_MON 1
-#define CONS_HERO 2
-#define CONS_TRAP 3
+enum bubble_contains_types {
+    CONS_OBJ = 0,
+    CONS_MON,
+    CONS_HERO,
+    CONS_TRAP
+};
 
 struct bubble {
     xchar x, y;   /* coordinates of the upper left corner */
index c504464..93a3377 100644 (file)
@@ -1,4 +1,5 @@
-/* NetHack 3.6 lint.h  $NHDT-Date: 1449269910 2015/12/04 22:58:30 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.3 $ */
+/* NetHack 3.6 lint.h  $NHDT-Date: 1524689514 2018/04/25 20:51:54 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.5 $ */
+/*      Copyright (c) 2016 by Robert Patrick Rankin               */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -22,7 +23,7 @@
 /* force an unused function argument to become used in an arbitrary
    manner in order to suppress warning about unused function arguments;
    viable for scalar and pointer arguments */
-#define nhUse(arg) nhUse_dummy += (unsigned) arg;
+#define nhUse(arg) nhUse_dummy += (unsigned) !(arg)
 extern unsigned nhUse_dummy;
 #else
 #define nhUse(arg) /*empty*/
index 078c796..da53c62 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 mac-carbon.h    $NHDT-Date: 1432512777 2015/05/25 00:12:57 $  $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 2003. */
+/*-Copyright (c) Kevin Hugo, 2003. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*     Compiler prefix file for the Macintosh Carbon port.
index 39dbc22..96e406b 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 mac-qt.h        $NHDT-Date: 1432512776 2015/05/25 00:12:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 2003. */
+/*-Copyright (c) Kevin Hugo, 2003. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*     Compiler prefix file for the Macintosh Qt port.
index 93a9e43..9f4ba46 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 mac-term.h      $NHDT-Date: 1432512775 2015/05/25 00:12:55 $  $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 2003. */
+/*-Copyright (c) Kevin Hugo, 2003. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*     Compiler prefix file for the MacOS X Terminal.app port.
index facd935..fbcd3ad 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 macconf.h       $NHDT-Date: 1432512782 2015/05/25 00:13:02 $  $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kevin Hugo, 2004. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifdef MAC
index a8a3cd8..b9b6ede 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 macwin.h        $NHDT-Date: 1447755970 2015/11/17 10:26:10 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kevin Hugo, 2003. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef MACWIN_H
index b8e8923..3b7772b 100644 (file)
@@ -1,4 +1,5 @@
-/* NetHack 3.6 mail.h  $NHDT-Date: 1432512777 2015/05/25 00:12:57 $  $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
+/* NetHack 3.6 mail.h  $NHDT-Date: 1524689515 2018/04/25 20:51:55 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.9 $ */
+/*      Copyright (c) 2015 by Kenneth Lorber              */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* used by ckmailstatus() to pass information to the mail-daemon in newmail()
index e2cde88..b4c1aa9 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 mextra.h        $NHDT-Date: 1432512781 2015/05/25 00:13:01 $  $NHDT-Branch: master $:$NHDT-Revision: 1.16 $ */
+/* NetHack 3.6 mextra.h        $NHDT-Date: 1451836000 2016/01/03 15:46:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.18 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef MEXTRA_H
 /*
  *  Adding new mextra structures:
  *
- *      1. Add the structure definition and any required macros in this file
- *         above the mextra struct.
- *      2. Add a pointer to your new struct to the mextra struct in this
- *file.
- *      3. Add a referencing macro at the bottom of this file after the
- *mextra
- *         struct (see MNAME, EGD, EPRI, ESHK, EMIN, or EDOG for examples).
- *      4. Create a newXX(mtmp) function and possibly a free_XX(mtmp)
- *function
- *         in an appropriate new or existing source file and add a prototype
- *         for it to include/extern.h.
+ *       1. Add the structure definition and any required macros in this
+ *          file above the mextra struct.
+ *       2. Add a pointer to your new struct to the mextra struct in this
+ *          file.
+ *       3. Add a referencing macro at bottom of this file after the mextra
+ *          struct (see MNAME, EGD, EPRI, ESHK, EMIN, or EDOG for examples).
+ *       4. Create a newXX(mtmp) function and possibly a free_XX(mtmp)
+ *          function in an appropriate new or existing source file and add
+ *          a prototype for it to include/extern.h.
  *
- *             void FDECL(newXX, (struct monst *));
- *             void FDECL(free_XX, (struct monst *));
+ *              void FDECL(newXX, (struct monst *));
+ *              void FDECL(free_XX, (struct monst *));
  *
- *               void
- *               newXX(mtmp)
- *               struct monst *mtmp;
- *               {
- *                   if (!mtmp->mextra) mtmp->mextra = newmextra();
- *                   if (!XX(mtmp)) {
- *                       XX(mtmp) = (struct XX *)alloc(sizeof(struct XX));
- *                       (void) memset((genericptr_t) XX(mtmp),
- *                                  0, sizeof(struct XX));
- *                   }
- *               }
+ *              void
+ *              newXX(mtmp)
+ *              struct monst *mtmp;
+ *              {
+ *                  if (!mtmp->mextra)
+ *                      mtmp->mextra = newmextra();
+ *                  if (!XX(mtmp)) {
+ *                      XX(mtmp) = (struct XX *) alloc(sizeof (struct XX));
+ *                      (void) memset((genericptr_t) XX(mtmp),
+ *                                    0, sizeof (struct XX));
+ *                  }
+ *              }
  *
- *      5. Consider adding a new makemon flag MM_XX flag to include/hack.h
- *and
- *         a corresponding change to makemon() if you require your structure
- *         to be added at monster creation time. Initialize your struct
- *         after a successful return from makemon().
+ *       5. Consider adding a new makemon flag MM_XX flag to include/hack.h
+ *          and a corresponding change to makemon() if you require your
+ *          structure to be added at monster creation time.  Initialize your
+ *          struct after a successful return from makemon().
  *
- *          src/makemon.c:  if (mmflags & MM_XX) newXX(mtmp);
- *          your new code:  mon = makemon(&mons[mnum], x, y, MM_XX);
+ *              src/makemon.c:  if (mmflags & MM_XX) newXX(mtmp);
+ *              your new code:  mon = makemon(&mons[mnum], x, y, MM_XX);
  *
- *      6. Adjust size_monst() in src/cmd.c appropriately.
- *      7. Adjust dealloc_mextra() in src/mon.c to clean up
- *         properly during monst deallocation.
- *      8. Adjust copy_mextra() in src/mon.c to make duplicate
- *         copies of your struct or data on another monst struct.
- *      9. Adjust restmon() in src/restore.c to deal with your
- *         struct or data during a restore.
- *     10. Adjust savemon() in src/save.c to deal with your
- *         struct or data during a save.
+ *       6. Adjust size_monst() in src/cmd.c appropriately.
+ *       7. Adjust dealloc_mextra() in src/mon.c to clean up
+ *          properly during monst deallocation.
+ *       8. Adjust copy_mextra() in src/mon.c to make duplicate
+ *          copies of your struct or data on another monst struct.
+ *       9. Adjust restmon() in src/restore.c to deal with your
+ *          struct or data during a restore.
+ *      10. Adjust savemon() in src/save.c to deal with your
+ *          struct or data during a save.
  */
 
 /***
- **    formerly vault.h -- vault guard extension
+ **     formerly vault.h -- vault guard extension
  */
 #define FCSIZ (ROWNO + COLNO)
 #define GD_EATGOLD 0x01
@@ -84,7 +83,7 @@ struct egd {
 };
 
 /***
- **    formerly epri.h -- temple priest extension
+ **     formerly epri.h -- temple priest extension
  */
 struct epri {
     aligntyp shralign; /* alignment of priest's shrine */
@@ -100,7 +99,7 @@ struct epri {
    (and emin extension) */
 
 /***
- **    formerly eshk.h -- shopkeeper extension
+ **     formerly eshk.h -- shopkeeper extension
  */
 #define REPAIR_DELAY 5 /* minimum delay between shop damage & repair */
 #define BILLSZ 200
@@ -135,7 +134,7 @@ struct eshk {
 };
 
 /***
- **    formerly emin.h -- minion extension
+ **     formerly emin.h -- minion extension
  */
 struct emin {
     aligntyp min_align; /* alignment of minion */
@@ -143,17 +142,19 @@ struct emin {
 };
 
 /***
- **    formerly edog.h -- pet extension
+ **     formerly edog.h -- pet extension
  */
-/*     various types of pet food, the lower, the better liked */
-#define DOGFOOD 0
-#define CADAVER 1
-#define ACCFOOD 2
-#define MANFOOD 3
-#define APPORT 4
-#define POISON 5
-#define UNDEF 6
-#define TABU 7
+/*      various types of pet food, the lower, the better liked */
+enum dogfood_types {
+    DOGFOOD = 0,
+    CADAVER,
+    ACCFOOD,
+    MANFOOD,
+    APPORT,
+    POISON,
+    UNDEF,
+    TABU
+};
 
 struct edog {
     long droptime;            /* moment dog dropped object */
@@ -169,7 +170,7 @@ struct edog {
 };
 
 /***
- **    mextra.h -- collection of all monster extensions
+ **     mextra.h -- collection of all monster extensions
  */
 struct mextra {
     char *mname;
@@ -190,6 +191,11 @@ struct mextra {
 #define MCORPSENM(mon) ((mon)->mextra->mcorpsenm)
 
 #define has_mname(mon) ((mon)->mextra && MNAME(mon))
+#define has_egd(mon)   ((mon)->mextra && EGD(mon))
+#define has_epri(mon)  ((mon)->mextra && EPRI(mon))
+#define has_eshk(mon)  ((mon)->mextra && ESHK(mon))
+#define has_emin(mon)  ((mon)->mextra && EMIN(mon))
+#define has_edog(mon)  ((mon)->mextra && EDOG(mon))
 #define has_mcorpsenm(mon) ((mon)->mextra && MCORPSENM(mon) != NON_PM)
 
 #endif /* MEXTRA_H */
index 74ccaeb..18259c7 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 mfndpos.h       $NHDT-Date: 1432512776 2015/05/25 00:12:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2005. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef MFNDPOS_H
index a0173db..ea8249f 100644 (file)
@@ -1,7 +1,9 @@
-/* NetHack 3.6 micro.h $NHDT-Date: 1432512781 2015/05/25 00:13:01 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
-/* micro.h - function declarations for various microcomputers */
+/* NetHack 3.6 micro.h $NHDT-Date: 1524689515 2018/04/25 20:51:55 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $ */
+/*      Copyright (c) 2015 by Kenneth Lorber              */
 /* NetHack may be freely redistributed.  See license for details. */
 
+/* micro.h - function declarations for various microcomputers */
+
 #ifndef MICRO_H
 #define MICRO_H
 
index 1141f36..9d72455 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 mkroom.h        $NHDT-Date: 1432512780 2015/05/25 00:13:00 $  $NHDT-Branch: master $:$NHDT-Revision: 1.13 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2016. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef MKROOM_H
@@ -51,33 +52,36 @@ extern struct mkroom *dnstairs_room, *upstairs_room, *sstairs_room;
 extern NEARDATA coord doors[DOORMAX];
 
 /* values for rtype in the room definition structure */
-#define OROOM 0      /* ordinary room */
-#define COURT 2      /* contains a throne */
-#define SWAMP 3      /* contains pools */
-#define VAULT 4      /* contains piles of gold */
-#define BEEHIVE 5    /* contains killer bees and royal jelly */
-#define MORGUE 6     /* contains corpses, undead and ghosts */
-#define BARRACKS 7   /* contains soldiers and their gear */
-#define ZOO 8        /* floor covered with treasure and monsters */
-#define DELPHI 9     /* contains Oracle and peripherals */
-#define TEMPLE 10    /* contains a shrine */
-#define LEPREHALL 11 /* leprechaun hall (Tom Proudfoot) */
-#define COCKNEST 12  /* cockatrice nest (Tom Proudfoot) */
-#define ANTHOLE 13   /* ants (Tom Proudfoot) */
-#define SHOPBASE 14  /* everything above this is a shop */
-#define ARMORSHOP 15 /* specific shop defines for level compiler */
-#define SCROLLSHOP 16
-#define POTIONSHOP 17
-#define WEAPONSHOP 18
-#define FOODSHOP 19
-#define RINGSHOP 20
-#define WANDSHOP 21
-#define TOOLSHOP 22
-#define BOOKSHOP 23
-#define FODDERSHOP 24 /* health food store */
-#define UNIQUESHOP 25 /* shops here & below not randomly gen'd. */
-#define CANDLESHOP 25
-#define MAXRTYPE 25 /* maximum valid room type */
+enum roomtype_types {
+    OROOM = 0,      /* ordinary room */
+    COURT = 2,      /* contains a throne */
+    SWAMP,      /* contains pools */
+    VAULT,      /* contains piles of gold */
+    BEEHIVE,    /* contains killer bees and royal jelly */
+    MORGUE,     /* contains corpses, undead and ghosts */
+    BARRACKS,   /* contains soldiers and their gear */
+    ZOO,        /* floor covered with treasure and monsters */
+    DELPHI,     /* contains Oracle and peripherals */
+    TEMPLE,     /* contains a shrine */
+    LEPREHALL,  /* leprechaun hall (Tom Proudfoot) */
+    COCKNEST,   /* cockatrice nest (Tom Proudfoot) */
+    ANTHOLE,    /* ants (Tom Proudfoot) */
+    SHOPBASE,   /* everything above this is a shop */
+    ARMORSHOP,  /* specific shop defines for level compiler */
+    SCROLLSHOP,
+    POTIONSHOP,
+    WEAPONSHOP,
+    FOODSHOP,
+    RINGSHOP,
+    WANDSHOP,
+    TOOLSHOP,
+    BOOKSHOP,
+    FODDERSHOP, /* health food store */
+    CANDLESHOP
+};
+
+#define MAXRTYPE (CANDLESHOP) /* maximum valid room type */
+#define UNIQUESHOP (CANDLESHOP) /* shops here & above not randomly gen'd. */
 
 /* Special type for search_special() */
 #define ANY_TYPE (-1)
index 7f62258..95153ce 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 mondata.h       $NHDT-Date: 1432512776 2015/05/25 00:12:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.26 $ */
+/* NetHack 3.6 mondata.h       $NHDT-Date: 1513297342 2017/12/15 00:22:22 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.33 $ */
 /* Copyright (c) 1989 Mike Threepoint                            */
 /* NetHack may be freely redistributed.  See license for details. */
 
 
 #define is_vampire(ptr) ((ptr)->mlet == S_VAMPIRE)
 
-#define nonliving(ptr)                                          \
-    (is_golem(ptr) || is_undead(ptr) || (ptr)->mlet == S_VORTEX \
-     || (ptr) == &mons[PM_MANES])
+/* used to vary a few messages */
+#define weirdnonliving(ptr) (is_golem(ptr) || (ptr)->mlet == S_VORTEX)
+#define nonliving(ptr) \
+    (is_undead(ptr) || (ptr) == &mons[PM_MANES] || weirdnonliving(ptr))
+
+/* no corpse (ie, blank scrolls) if killed by fire */
+#define completelyburns(ptr) \
+    ((ptr) == &mons[PM_PAPER_GOLEM] || (ptr) == &mons[PM_STRAW_GOLEM])
 
 /* Used for conduct with corpses, tins, and digestion attacks */
 /* G_NOCORPSE monsters might still be swallowed as a purple worm */
     (vegan(ptr)         \
      || ((ptr)->mlet == S_PUDDING && (ptr) != &mons[PM_BLACK_PUDDING]))
 
+/* monkeys are tameable via bananas but not pacifiable via food,
+   otherwise their theft attack could be nullified too easily;
+   dogs and cats can be tamed by anything they like to eat and are
+   pacified by any other food;
+   horses can be tamed by always-veggy food or lichen corpses but
+   not tamed or pacified by other corpses or tins of veggy critters */
 #define befriend_with_obj(ptr, obj) \
-    ((obj)->oclass == FOOD_CLASS && is_domestic(ptr))
+    (((ptr) == &mons[PM_MONKEY] || (ptr) == &mons[PM_APE])               \
+     ? (obj)->otyp == BANANA                                             \
+     : (is_domestic(ptr) && (obj)->oclass == FOOD_CLASS                  \
+        && ((ptr)->mlet != S_UNICORN                                     \
+            || objects[(obj)->otyp].oc_material == VEGGY                 \
+            || ((obj)->otyp == CORPSE && (obj)->corpsenm == PM_LICHEN))))
 
 #endif /* MONDATA_H */
index 3c88d01..cc655c9 100644 (file)
@@ -1,10 +1,15 @@
-/* NetHack 3.6 monst.h $NHDT-Date: 1432512777 2015/05/25 00:12:57 $  $NHDT-Branch: master $:$NHDT-Revision: 1.20 $ */
+/* NetHack 3.6 monst.h $NHDT-Date: 1461028522 2016/04/19 01:15:22 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.24 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2016. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef MONST_H
 #define MONST_H
 
+#ifndef MEXTRA_H
+#include "mextra.h"
+#endif
+
 /* The weapon_check flag is used two ways:
  * 1) When calling mon_wield_item, is 2-6 depending on what is desired.
  * 2) Between calls to mon_wield_item, is 0 or 1 depending on whether or not
  * that there are enough situations which might make a monster change its
  * weapon that this is impractical.  --KAA
  */
-#define NO_WEAPON_WANTED 0
-#define NEED_WEAPON 1
-#define NEED_RANGED_WEAPON 2
-#define NEED_HTH_WEAPON 3
-#define NEED_PICK_AXE 4
-#define NEED_AXE 5
-#define NEED_PICK_OR_AXE 6
+enum wpn_chk_flags {
+    NO_WEAPON_WANTED = 0,
+    NEED_WEAPON,
+    NEED_RANGED_WEAPON,
+    NEED_HTH_WEAPON,
+    NEED_PICK_AXE,
+    NEED_AXE,
+    NEED_PICK_OR_AXE
+};
 
 /* The following flags are used for the second argument to display_minventory
  * in invent.c:
  *
+ * PICK_NONE, PICK_ONE, PICK_ANY (wintype.h)  0, 1, 2
  * MINV_NOLET  If set, don't display inventory letters on monster's inventory.
  * MINV_ALL    If set, display all items in monster's inventory, otherwise
  *            just display wielded weapons and worn items.
  */
-#define MINV_NOLET 0x01
-#define MINV_ALL 0x02
-
-#ifndef MEXTRA_H
-#include "mextra.h"
-#endif
+#define MINV_PICKMASK 0x03 /* 1|2 */
+#define MINV_NOLET    0x04
+#define MINV_ALL      0x08
+
+enum m_ap_types {
+    M_AP_NOTHING = 0, /* mappearance unused--monster appears as itself */
+    M_AP_FURNITURE,   /* stairs, a door, an altar, etc. */
+    M_AP_OBJECT,      /* an object */
+    M_AP_MONSTER      /* a monster */
+};
 
 struct monst {
     struct monst *nmon;
     struct permonst *data;
     unsigned m_id;
-    short mnum;      /* permanent monster index number */
-    short cham;      /* if shapeshifter, orig mons[] idx goes here */
-    short movement;  /* movement points (derived from permonst definition and
-                        added effects */
-    uchar m_lev;     /* adjusted difficulty level of monster */
-    aligntyp malign; /* alignment of this monster, relative to the
-                        player (positive = good to kill) */
+    short mnum;           /* permanent monster index number */
+    short cham;           /* if shapeshifter, orig mons[] idx goes here */
+    short movement;       /* movement points (derived from permonst definition
+                             and added effects */
+    uchar m_lev;          /* adjusted difficulty level of monster */
+    aligntyp malign;      /* alignment of this monster, relative to the
+                             player (positive = good to kill) */
     xchar mx, my;
-    xchar mux, muy; /* where the monster thinks you are */
+    xchar mux, muy;       /* where the monster thinks you are */
 #define MTSZ 4
-    coord mtrack[MTSZ]; /* monster track */
+    coord mtrack[MTSZ];   /* monster track */
     int mhp, mhpmax;
     unsigned mappearance; /* for undetected mimics and the wiz */
-    uchar m_ap_type;      /* what mappearance is describing: */
-#define M_AP_NOTHING                                                 \
-    0                    /* mappearance is unused -- monster appears \
-                            as itself */
-#define M_AP_FURNITURE 1 /* stairs, a door, an altar, etc. */
-#define M_AP_OBJECT 2    /* an object */
-#define M_AP_MONSTER 3   /* a monster */
+    uchar m_ap_type;      /* what mappearance is describing, m_ap_types */
 
     schar mtame;                /* level of tameness, implies peaceful */
     unsigned short mintrinsics; /* low 8 correspond to mresists */
@@ -72,12 +78,12 @@ struct monst {
     Bitfield(perminvis, 1);   /* intrinsic minvis value */
     Bitfield(mcan, 1);        /* has been cancelled */
     Bitfield(mburied, 1);     /* has been buried */
-    Bitfield(mundetected, 1); /* not seen in present hiding place */
-                              /* implies one of M1_CONCEAL or M1_HIDE,
+    Bitfield(mundetected, 1); /* not seen in present hiding place;
+                               * implies one of M1_CONCEAL or M1_HIDE,
                                * but not mimic (that is, snake, spider,
                                * trapper, piercer, eel)
                                */
-    Bitfield(mcansee, 1);     /* cansee 1, temp.blinded 0, blind 0 */
+    Bitfield(mcansee, 1);   /* cansee 1, temp.blinded 0, blind 0 */
 
     Bitfield(mspeed, 2);    /* current speed */
     Bitfield(permspeed, 2); /* intrinsic mspeed value */
@@ -89,11 +95,11 @@ struct monst {
     Bitfield(mfleetim, 7);  /* timeout for mflee */
     Bitfield(msleeping, 1); /* asleep until woken */
 
-    Bitfield(mblinded, 7); /* cansee 0, temp.blinded n, blind 0 */
-    Bitfield(mstun, 1);    /* stunned (off balance) */
+    Bitfield(mblinded, 7);  /* cansee 0, temp.blinded n, blind 0 */
+    Bitfield(mstun, 1);     /* stunned (off balance) */
 
     Bitfield(mfrozen, 7);
-    Bitfield(mcanmove, 1); /* paralysis, similar to mblinded */
+    Bitfield(mcanmove, 1);  /* paralysis, similar to mblinded */
 
     Bitfield(mconf, 1);     /* confused */
     Bitfield(mpeaceful, 1); /* does not attack unprovoked */
@@ -102,13 +108,13 @@ struct monst {
     Bitfield(isshk, 1);     /* is shopkeeper */
     Bitfield(isminion, 1);  /* is a minion */
     Bitfield(isgd, 1);      /* is guard */
-    Bitfield(ispriest, 1);  /* is a priest */
+    Bitfield(ispriest, 1);  /* is an aligned priest or high priest */
 
-    Bitfield(iswiz, 1);  /* is the Wizard of Yendor */
-    Bitfield(wormno, 5); /* at most 31 worms on any level */
-/* 2 free bits */
+    Bitfield(iswiz, 1);     /* is the Wizard of Yendor */
+    Bitfield(wormno, 5);    /* at most 31 worms on any level */
+    /* 2 free bits */
 
-#define MAX_NUM_WORMS 32 /* should be 2^(wormno bitfield size) */
+#define MAX_NUM_WORMS 32    /* should be 2^(wormno bitfield size) */
 
     unsigned long mstrategy; /* for monsters with mflag3: current strategy */
 #ifdef NHSTDC
@@ -116,39 +122,39 @@ struct monst {
 #else
 #define STRAT_APPEARMSG 0x80000000L
 #endif
-#define STRAT_ARRIVE 0x40000000L /* just arrived on current level */
-#define STRAT_WAITFORU 0x20000000L
-#define STRAT_CLOSE 0x10000000L
-#define STRAT_WAITMASK (STRAT_CLOSE | STRAT_WAITFORU)
-#define STRAT_HEAL 0x08000000L
-#define STRAT_GROUND 0x04000000L
-#define STRAT_MONSTR 0x02000000L
-#define STRAT_PLAYER 0x01000000L
-#define STRAT_NONE 0x00000000L
+#define STRAT_ARRIVE    0x40000000L /* just arrived on current level */
+#define STRAT_WAITFORU  0x20000000L
+#define STRAT_CLOSE     0x10000000L
+#define STRAT_WAITMASK  (STRAT_CLOSE | STRAT_WAITFORU)
+#define STRAT_HEAL      0x08000000L
+#define STRAT_GROUND    0x04000000L
+#define STRAT_MONSTR    0x02000000L
+#define STRAT_PLAYER    0x01000000L
+#define STRAT_NONE      0x00000000L
 #define STRAT_STRATMASK 0x0f000000L
-#define STRAT_XMASK 0x00ff0000L
-#define STRAT_YMASK 0x0000ff00L
-#define STRAT_GOAL 0x000000ffL
-#define STRAT_GOALX(s) ((xchar)((s & STRAT_XMASK) >> 16))
-#define STRAT_GOALY(s) ((xchar)((s & STRAT_YMASK) >> 8))
-
-    long mtrapseen; /* bitmap of traps we've been trapped in */
-    long mlstmv;    /* for catching up with lost time */
+#define STRAT_XMASK     0x00ff0000L
+#define STRAT_YMASK     0x0000ff00L
+#define STRAT_GOAL      0x000000ffL
+#define STRAT_GOALX(s) ((xchar) ((s & STRAT_XMASK) >> 16))
+#define STRAT_GOALY(s) ((xchar) ((s & STRAT_YMASK) >> 8))
+
+    long mtrapseen;        /* bitmap of traps we've been trapped in */
+    long mlstmv;           /* for catching up with lost time */
     long mspare1;
-    struct obj *minvent;
+    struct obj *minvent;   /* mon's inventory */
 
-    struct obj *mw;
-    long misc_worn_check;
-    xchar weapon_check;
+    struct obj *mw;        /* mon's weapon */
+    long misc_worn_check;  /* mon's wornmask */
+    xchar weapon_check;    /* flag for whether to try switching weapons */
 
     int meating;           /* monster is eating timeout */
     struct mextra *mextra; /* point to mextra struct */
 };
 
-#define newmonst() (struct monst *) alloc(sizeof(struct monst))
+#define newmonst() (struct monst *) alloc(sizeof (struct monst))
 
 /* these are in mspeed */
-#define MSLOW 1 /* slow monster */
+#define MSLOW 1 /* slowed monster */
 #define MFAST 2 /* speeded monster */
 
 #define MON_WEP(mon) ((mon)->mw)
@@ -159,8 +165,19 @@ struct monst {
 #define is_vampshifter(mon)                                      \
     ((mon)->cham == PM_VAMPIRE || (mon)->cham == PM_VAMPIRE_LORD \
      || (mon)->cham == PM_VLAD_THE_IMPALER)
+
+/* mimic appearances that block vision/light */
+#define is_lightblocker_mappear(mon)                       \
+    (is_obj_mappear(mon, BOULDER)                          \
+     || ((mon)->m_ap_type == M_AP_FURNITURE                \
+         && ((mon)->mappearance == S_hcdoor                \
+             || (mon)->mappearance == S_vcdoor             \
+             || (mon)->mappearance < S_ndoor /* = walls */ \
+             || (mon)->mappearance == S_tree)))
 #define is_door_mappear(mon) ((mon)->m_ap_type == M_AP_FURNITURE \
-     && ((mon)->mappearance == S_hcdoor || (mon)->mappearance == S_vcdoor))
+                              && ((mon)->mappearance == S_hcdoor \
+                                  || (mon)->mappearance == S_vcdoor))
 #define is_obj_mappear(mon,otyp) ((mon)->m_ap_type == M_AP_OBJECT \
-     && (mon)->mappearance == (otyp))
+                                  && (mon)->mappearance == (otyp))
+
 #endif /* MONST_H */
index 9a78101..e4b68a0 100644 (file)
@@ -1,6 +1,7 @@
-/* NetHack 3.6  monsym.h        $NHDT-Date: 1432512780 2015/05/25 00:13:00 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
-/*      Monster symbols and creation information rev 1.0          */
+/* NetHack 3.6  monsym.h        $NHDT-Date: 1524689515 2018/04/25 20:51:55 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.11 $ */
+/*      Copyright (c) 2016 by Pasi Kallinen              */
 /* NetHack may be freely redistributed.  See license for details. */
+/*      Monster symbols and creation information rev 1.0          */
 
 #ifndef MONSYM_H
 #define MONSYM_H
  * them.  Monster class 0 is not used or defined so we can use it as a
  * NULL character.
  */
-/* clang-format off */
-#define S_ANT           1
-#define S_BLOB          2
-#define S_COCKATRICE    3
-#define S_DOG           4
-#define S_EYE           5
-#define S_FELINE        6
-#define S_GREMLIN       7
-#define S_HUMANOID      8
-#define S_IMP           9
-#define S_JELLY         10
-#define S_KOBOLD        11
-#define S_LEPRECHAUN    12
-#define S_MIMIC         13
-#define S_NYMPH         14
-#define S_ORC           15
-#define S_PIERCER       16
-#define S_QUADRUPED     17
-#define S_RODENT        18
-#define S_SPIDER        19
-#define S_TRAPPER       20
-#define S_UNICORN       21
-#define S_VORTEX        22
-#define S_WORM          23
-#define S_XAN           24
-#define S_LIGHT         25
-#define S_ZRUTY         26
-#define S_ANGEL         27
-#define S_BAT           28
-#define S_CENTAUR       29
-#define S_DRAGON        30
-#define S_ELEMENTAL     31
-#define S_FUNGUS        32
-#define S_GNOME         33
-#define S_GIANT         34
-#define S_invisible     35      /* non-class present in def_monsyms[] */
-#define S_JABBERWOCK    36
-#define S_KOP           37
-#define S_LICH          38
-#define S_MUMMY         39
-#define S_NAGA          40
-#define S_OGRE          41
-#define S_PUDDING       42
-#define S_QUANTMECH     43
-#define S_RUSTMONST     44
-#define S_SNAKE         45
-#define S_TROLL         46
-#define S_UMBER         47
-#define S_VAMPIRE       48
-#define S_WRAITH        49
-#define S_XORN          50
-#define S_YETI          51
-#define S_ZOMBIE        52
-#define S_HUMAN         53
-#define S_GHOST         54
-#define S_GOLEM         55
-#define S_DEMON         56
-#define S_EEL           57
-#define S_LIZARD        58
+enum mon_class_types {
+    S_ANT = 1,
+    S_BLOB,
+    S_COCKATRICE,
+    S_DOG,
+    S_EYE,
+    S_FELINE,
+    S_GREMLIN,
+    S_HUMANOID,
+    S_IMP,
+    S_JELLY,
+    S_KOBOLD,
+    S_LEPRECHAUN,
+    S_MIMIC,
+    S_NYMPH,
+    S_ORC,
+    S_PIERCER,
+    S_QUADRUPED,
+    S_RODENT,
+    S_SPIDER,
+    S_TRAPPER,
+    S_UNICORN,
+    S_VORTEX,
+    S_WORM,
+    S_XAN,
+    S_LIGHT,
+    S_ZRUTY,
+    S_ANGEL,
+    S_BAT,
+    S_CENTAUR,
+    S_DRAGON,
+    S_ELEMENTAL,
+    S_FUNGUS,
+    S_GNOME,
+    S_GIANT,
+    S_invisible,    /* non-class present in def_monsyms[] */
+    S_JABBERWOCK,
+    S_KOP,
+    S_LICH,
+    S_MUMMY,
+    S_NAGA,
+    S_OGRE,
+    S_PUDDING,
+    S_QUANTMECH,
+    S_RUSTMONST,
+    S_SNAKE,
+    S_TROLL,
+    S_UMBER,
+    S_VAMPIRE,
+    S_WRAITH,
+    S_XORN,
+    S_YETI,
+    S_ZOMBIE,
+    S_HUMAN,
+    S_GHOST,
+    S_GOLEM,
+    S_DEMON,
+    S_EEL,
+    S_LIZARD,
 
-#define S_WORM_TAIL     59
-#define S_MIMIC_DEF     60
-/* clang-format on */
+    S_WORM_TAIL,
+    S_MIMIC_DEF,
 
-#define MAXMCLASSES 61 /* number of monster classes */
+    MAXMCLASSES /* number of monster classes */
+};
 
 /*
  * Default characters for monsters.  These correspond to the monster classes
index 48b149b..534fa6e 100644 (file)
 #define SYSCF_FILE "sysconf" /* Use a file to hold the SYSCF configuration \
                                 */
 
+#define DUMPLOG      /* Enable dumplog files */
+/*#define DUMPLOG_FILE "nethack-%n-%d.log"*/
+#define DUMPLOG_MSG_COUNT 50
+
 #define USER_SOUNDS
 
 /*#define CHANGE_COLOR*/ /* allow palette changes */
 #define PORT_DEBUG /* include ability to debug international keyboard issues \
                       */
 
+#define RUNTIME_PORT_ID /* trigger run-time port identification for \
+                         * identification of exe CPU architecture   \
+                         */
+#define RUNTIME_PASTEBUF_SUPPORT
+
+
 #define SAFERHANGUP /* Define SAFERHANGUP to delay hangup processing   \
                      * until the main command loop. 'safer' because it \
                      * avoids certain cheats and also avoids losing    \
@@ -113,11 +123,6 @@ extern void FDECL(interject, (int));
 #endif
 #endif /* _MSC_VER */
 
-
-#define RUNTIME_PORT_ID /* trigger run-time port identification for \
-                         * identification of exe CPU architecture   \
-                         */
-
 /* The following is needed for prototypes of certain functions */
 #if defined(_MSC_VER)
 #include <process.h> /* Provides prototypes of exit(), spawn()      */
index 487907c..62e20b7 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 obj.h   $NHDT-Date: 1445126423 2015/10/18 00:00:23 $  $NHDT-Branch: master $:$NHDT-Revision: 1.50 $ */
+/* NetHack 3.6 obj.h   $NHDT-Date: 1508827590 2017/10/24 06:46:30 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.60 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef OBJ_H
@@ -40,12 +41,14 @@ struct obj {
     unsigned owt;
     long quan; /* number of items */
 
-    schar spe; /* quality of weapon, armor or ring (+ or -)
-                  number of charges for wand ( >= -1 )
-                  marks your eggs, tin variety and spinach tins
-                  royal coffers for a court ( == 2)
-                  tells which fruit a fruit is
-                  special for uball and amulet
+    schar spe; /* quality of weapon, weptool, armor or ring (+ or -);
+                  number of charges for wand or charged tool ( >= -1 );
+                  number of candles attached to candelabrum;
+                  marks your eggs, tin variety and spinach tins;
+                  Schroedinger's Box (1) or royal coffers for a court (2);
+                  tells which fruit a fruit is;
+                  special for uball and amulet;
+                  scroll of mail (normal==0, bones or wishing==1, written==2);
                   historic and gender for statues */
 #define STATUE_HISTORIC 0x01
 #define STATUE_MALE 0x02
@@ -95,9 +98,7 @@ struct obj {
     Bitfield(recharged, 3); /* number of times it's been recharged */
 #define on_ice recharged    /* corpse on ice */
     Bitfield(lamplit, 1);   /* a light-source -- can be lit */
-    Bitfield(
-        globby,
-        1); /* globby; will combine with like types on adjacent squares */
+    Bitfield(globby, 1);    /* combines with like types on adjacent squares */
     Bitfield(greased, 1);    /* covered with grease */
     Bitfield(nomerge, 1);    /* set temporarily to prevent merging */
     Bitfield(was_thrown, 1); /* thrown by hero since last picked up */
@@ -111,7 +112,7 @@ struct obj {
     int corpsenm;         /* type of corpse is mons[corpsenm] */
 #define leashmon corpsenm /* gets m_id of attached pet */
 #define fromsink corpsenm /* a potion from a sink */
-#define novelidx corpsenm /* 3.6.0 tribute - the index of the novel title */
+#define novelidx corpsenm /* 3.6 tribute - the index of the novel title */
 #define record_achieve_special corpsenm
     int usecount;           /* overloaded for various things that tally */
 #define spestudied usecount /* # of times a spellbook has been studied */
@@ -202,6 +203,8 @@ struct obj {
      && objects[otmp->otyp].oc_skill >= -P_SHURIKEN \
      && objects[otmp->otyp].oc_skill <= -P_BOW)
 #define uslinging() (uwep && objects[uwep->otyp].oc_skill == P_SLING)
+/* 'is_quest_artifact()' only applies to the current role's artifact */
+#define any_quest_artifact(o) ((o)->oartifact >= ART_ORB_OF_DETECTION)
 
 /* Armor */
 #define is_shield(otmp)          \
@@ -329,14 +332,31 @@ struct obj {
     ((obj)->otyp == LUCKSTONE || (obj)->otyp == LOADSTONE \
      || (obj)->otyp == FLINT || (obj)->otyp == TOUCHSTONE)
 
-/* misc */
+/* misc helpers, simple enough to be macros */
 #define is_flimsy(otmp)                           \
     (objects[(otmp)->otyp].oc_material <= LEATHER \
      || (otmp)->otyp == RUBBER_HOSE)
-
-/* helpers, simple enough to be macros */
 #define is_plural(o) \
-    ((o)->quan > 1 || (o)->oartifact == ART_EYES_OF_THE_OVERWORLD)
+    ((o)->quan != 1L                                                    \
+     /* "the Eyes of the Overworld" are plural, but                     \
+        "a pair of lenses named the Eyes of the Overworld" is not */    \
+     || ((o)->oartifact == ART_EYES_OF_THE_OVERWORLD                    \
+         && !undiscovered_artifact(ART_EYES_OF_THE_OVERWORLD)))
+#define pair_of(o) ((o)->otyp == LENSES || is_gloves(o) || is_boots(o))
+
+/* 'PRIZE' values override obj->corpsenm so prizes mustn't be object types
+   which use that field for monster type (or other overloaded purpose) */
+#define MINES_PRIZE 1
+#define SOKO_PRIZE1 2
+#define SOKO_PRIZE2 3
+#define is_mines_prize(o) \
+    ((o)->otyp == iflags.mines_prize_type                \
+     && (o)->record_achieve_special == MINES_PRIZE)
+#define is_soko_prize(o) \
+    (((o)->otyp == iflags.soko_prize_type1               \
+      && (o)->record_achieve_special == SOKO_PRIZE1)     \
+     || ((o)->otyp == iflags.soko_prize_type2            \
+         && (o)->record_achieve_special == SOKO_PRIZE2))
 
 /* Flags for get_obj_location(). */
 #define CONTAINED_TOO 0x1
@@ -361,21 +381,24 @@ struct obj {
 #define ER_DAMAGED 2   /* object was damaged in some way */
 #define ER_DESTROYED 3 /* object was destroyed */
 
+/* propeller method for potionhit() */
+#define POTHIT_HERO_BASH   0 /* wielded by hero */
+#define POTHIT_HERO_THROW  1 /* thrown by hero */
+#define POTHIT_MONST_THROW 2 /* thrown by a monster */
+#define POTHIT_OTHER_THROW 3 /* propelled by some other means [scatter()] */
+
 /*
  *  Notes for adding new oextra structures:
  *
  *      1. Add the structure definition and any required macros in an
- *appropriate
- *         header file that precedes this one.
- *      2. Add a pointer to your new struct to the oextra struct in this
- *file.
+ *          appropriate header file that precedes this one.
+ *      2. Add a pointer to your new struct to oextra struct in this file.
  *      3. Add a referencing macro to this file after the newobj macro above
  *         (see ONAME, OMONST, OMIN, OLONG, or OMAILCMD for examples).
  *      4. Add a testing macro after the set of referencing macros
  *         (see has_oname(), has_omonst(), has_omin(), has_olong(),
  *         has_omailcmd() for examples).
- *      5. Create a newXX(otmp) function and possibly a free_XX(otmp)
- *function
+ *      5. Create newXX(otmp) function and possibly free_XX(otmp) function
  *         in an appropriate new or existing source file and add a prototype
  *         for it to include/extern.h.  The majority of these are currently
  *         located in mkobj.c for convenience.
index 6e5e6ea..22fd028 100644 (file)
@@ -1,28 +1,62 @@
-/* NetHack 3.6 objclass.h      $NHDT-Date: 1447755971 2015/11/17 10:26:11 $  $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
+/* NetHack 3.6 objclass.h      $NHDT-Date: 1462067744 2016/05/01 01:55:44 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef OBJCLASS_H
 #define OBJCLASS_H
 
-/* definition of a class of objects */
+/* [misnamed] definition of a type of object */
+enum obj_material_types {
+    LIQUID = 1, /* currently only for venom */
+    WAX,
+    VEGGY, /* foodstuffs */
+    FLESH, /*   ditto    */
+    PAPER,
+    CLOTH,
+    LEATHER,
+    WOOD,
+    BONE,
+    DRAGON_HIDE, /* not leather! */
+    IRON,        /* Fe - includes steel */
+    METAL,       /* Sn, &c. */
+    COPPER,      /* Cu - includes brass */
+    SILVER,      /* Ag */
+    GOLD,        /* Au */
+    PLATINUM,    /* Pt */
+    MITHRIL,
+    PLASTIC,
+    GLASS,
+    GEMSTONE,
+    MINERAL
+};
+
+enum obj_armor_types {
+    ARM_SUIT = 0,
+    ARM_SHIELD,        /* needed for special wear function */
+    ARM_HELM,
+    ARM_GLOVES,
+    ARM_BOOTS,
+    ARM_CLOAK,
+    ARM_SHIRT
+};
 
 struct objclass {
-    short oc_name_idx;  /* index of actual name */
-    short oc_descr_idx; /* description when name unknown */
-    char *oc_uname;     /* called by user */
+    short oc_name_idx;              /* index of actual name */
+    short oc_descr_idx;             /* description when name unknown */
+    char *oc_uname;                 /* called by user */
     Bitfield(oc_name_known, 1);
-    Bitfield(oc_merge, 1);      /* merge otherwise equal objects */
-    Bitfield(oc_uses_known, 1); /* obj->known affects full description */
-                                /* otherwise, obj->dknown and obj->bknown */
-                                /* tell all, and obj->known should always */
-                                /* be set for proper merging behavior */
-    Bitfield(oc_pre_discovered, 1); /* Already known at start of game; */
-    /* won't be listed as a discovery. */
-    Bitfield(oc_magic, 1);   /* inherently magical object */
-    Bitfield(oc_charged, 1); /* may have +n or (n) charges */
-    Bitfield(oc_unique, 1);  /* special one-of-a-kind object */
-    Bitfield(oc_nowish, 1);  /* cannot wish for this object */
+    Bitfield(oc_merge, 1);          /* merge otherwise equal objects */
+    Bitfield(oc_uses_known, 1);     /* obj->known affects full description;
+                                       otherwise, obj->dknown and obj->bknown
+                                       tell all, and obj->known should always
+                                       be set for proper merging behavior. */
+    Bitfield(oc_pre_discovered, 1); /* Already known at start of game;
+                                       won't be listed as a discovery. */
+    Bitfield(oc_magic, 1);          /* inherently magical object */
+    Bitfield(oc_charged, 1);        /* may have +n or (n) charges */
+    Bitfield(oc_unique, 1);         /* special one-of-a-kind object */
+    Bitfield(oc_nowish, 1);         /* cannot wish for this object */
 
     Bitfield(oc_big, 1);
 #define oc_bimanual oc_big /* for weapons & tools used as weapons */
@@ -40,28 +74,7 @@ struct objclass {
 
     /*Bitfield(oc_subtyp,3);*/ /* Now too big for a bitfield... see below */
 
-    Bitfield(oc_material, 5);
-#define LIQUID 1 /* currently only for venom */
-#define WAX 2
-#define VEGGY 3 /* foodstuffs */
-#define FLESH 4 /*   ditto    */
-#define PAPER 5
-#define CLOTH 6
-#define LEATHER 7
-#define WOOD 8
-#define BONE 9
-#define DRAGON_HIDE 10 /* not leather! */
-#define IRON 11        /* Fe - includes steel */
-#define METAL 12       /* Sn, &c. */
-#define COPPER 13      /* Cu - includes brass */
-#define SILVER 14      /* Ag */
-#define GOLD 15        /* Au */
-#define PLATINUM 16    /* Pt */
-#define MITHRIL 17
-#define PLASTIC 18
-#define GLASS 19
-#define GEMSTONE 20
-#define MINERAL 21
+    Bitfield(oc_material, 5); /* one of obj_material_types */
 
 #define is_organic(otmp) (objects[otmp->otyp].oc_material <= WOOD)
 #define is_metallic(otmp)                    \
@@ -84,13 +97,6 @@ struct objclass {
     schar oc_subtyp;
 #define oc_skill oc_subtyp  /* Skills of weapons, spellbooks, tools, gems */
 #define oc_armcat oc_subtyp /* for armor */
-#define ARM_SHIELD 1        /* needed for special wear function */
-#define ARM_HELM 2
-#define ARM_GLOVES 3
-#define ARM_BOOTS 4
-#define ARM_CLOAK 5
-#define ARM_SHIRT 6
-#define ARM_SUIT 0
 
     uchar oc_oprop; /* property (invis, &c.) conveyed */
     char oc_class;  /* object class */
@@ -131,25 +137,28 @@ extern NEARDATA struct objdescr obj_descr[];
  * All objects have a class. Make sure that all classes have a corresponding
  * symbol below.
  */
-#define RANDOM_CLASS 0 /* used for generating random objects */
-#define ILLOBJ_CLASS 1
-#define WEAPON_CLASS 2
-#define ARMOR_CLASS 3
-#define RING_CLASS 4
-#define AMULET_CLASS 5
-#define TOOL_CLASS 6
-#define FOOD_CLASS 7
-#define POTION_CLASS 8
-#define SCROLL_CLASS 9
-#define SPBOOK_CLASS 10 /* actually SPELL-book */
-#define WAND_CLASS 11
-#define COIN_CLASS 12
-#define GEM_CLASS 13
-#define ROCK_CLASS 14
-#define BALL_CLASS 15
-#define CHAIN_CLASS 16
-#define VENOM_CLASS 17
-#define MAXOCLASSES 18
+enum obj_class_types {
+    RANDOM_CLASS = 0, /* used for generating random objects */
+    ILLOBJ_CLASS,
+    WEAPON_CLASS,
+    ARMOR_CLASS,
+    RING_CLASS,
+    AMULET_CLASS,
+    TOOL_CLASS,
+    FOOD_CLASS,
+    POTION_CLASS,
+    SCROLL_CLASS,
+    SPBOOK_CLASS, /* actually SPELL-book */
+    WAND_CLASS,
+    COIN_CLASS,
+    GEM_CLASS,
+    ROCK_CLASS,
+    BALL_CLASS,
+    CHAIN_CLASS,
+    VENOM_CLASS,
+
+    MAXOCLASSES
+};
 
 #define ALLOW_COUNT (MAXOCLASSES + 1) /* Can be used in the object class    */
 #define ALL_CLASSES (MAXOCLASSES + 2) /* input to getobj().                 */
index cda53ca..f033ef5 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 os2conf.h       $NHDT-Date: 1432512775 2015/05/25 00:12:55 $  $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* Copyright (c) Timo Hakulinen, 1990, 1991, 1992, 1993, 1996. */
 /* NetHack may be freely redistributed.  See license for details. */
 
index 64cc5e4..6037e01 100644 (file)
@@ -1,21 +1,22 @@
-/* NetHack 3.6 patchlevel.h    $NHDT-Date: 1447755971 2015/11/17 10:26:11 $  $NHDT-Branch: master $:$NHDT-Revision: 1.112 $ */
+/* NetHack 3.6 patchlevel.h    $NHDT-Date: 1524690061 2018/04/25 21:01:01 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.119 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
-/* NetHack 3.6.0 */
+/* NetHack 3.6.1 */
 #define VERSION_MAJOR 3
 #define VERSION_MINOR 6
 /*
  * PATCHLEVEL is updated for each release.
  */
-#define PATCHLEVEL 0
+#define PATCHLEVEL 1
 /*
  * Incrementing EDITLEVEL can be used to force invalidation of old bones
  * and save files.
  */
-#define EDITLEVEL 2
+#define EDITLEVEL 0
 
-#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2015"
+#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2018"
 #define COPYRIGHT_BANNER_B \
     "         By Stichting Mathematisch Centrum and M. Stephenson."
 /* COPYRIGHT_BANNER_C is generated by makedefs into date.h */
  * PP = patch level, ee = edit level, L = literal suffix "L",
  * with all four numbers specified as two hexadecimal digits.
  */
-/* #define VERSION_COMPATIBILITY 0x03050000L */
+#define VERSION_COMPATIBILITY 0x03060002L
 
 /****************************************************************************/
 /* Version 3.6.x */
 
+/*  Patch 1, April 27, 2018
+ *  Over four hundred and seventy bug fixes and improvements.
+ */
+
 /*
  *  NetHack 3.6.0, December 7, 2015
  *
index a8806cf..c5b46be 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 pcconf.h        $NHDT-Date: 1432512776 2015/05/25 00:12:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.17 $ */
+/* NetHack 3.6 pcconf.h        $NHDT-Date: 1457207019 2016/03/05 19:43:39 $  $NHDT-Branch: chasonr $:$NHDT-Revision: 1.19 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef PCCONF_H
@@ -79,6 +80,7 @@
 #if (defined(SCREEN_BIOS) || defined(SCREEN_DJGPPFAST)) && !defined(PC9800)
 #ifdef USE_TILES
 #define SCREEN_VGA /* Include VGA        graphics routines in the build */
+#define SCREEN_VESA
 #endif
 #endif
 #else
@@ -86,6 +88,7 @@
 #undef SCREEN_BIOS
 #undef SCREEN_DJGPPFAST
 #undef SCREEN_VGA
+#undef SCREEN_VESA
 #undef TERMLIB
 #define ANSI_DEFAULT
 #endif
 #endif
 /* SCREEN_8514, SCREEN_VESA are only placeholders presently - sub VGA instead
  */
-#if defined(SCREEN_8514) || defined(SCREEN_VESA)
+#if defined(SCREEN_8514)
 #undef SCREEN_8514
-#undef SCREEN_VESA
 #define SCREEN_VGA
 #endif
 /* Graphical tile sanity checks */
index a5c4555..cd1c73f 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 permonst.h      $NHDT-Date: 1432512778 2015/05/25 00:12:58 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef PERMONST_H
@@ -70,7 +71,7 @@ extern NEARDATA struct permonst mons[]; /* the master list of monster types */
 #define FAST_SPEED 15
 #define VERY_FAST 24
 
-#define NON_PM PM_PLAYERMON          /* "not a monster" */
+#define NON_PM (-1)                  /* "not a monster" */
 #define LOW_PM (NON_PM + 1)          /* first monster in mons[] */
 #define SPECIAL_PM PM_LONG_WORM_TAIL /* [normal] < ~ < [special] */
 /* mons[SPECIAL_PM] through mons[NUMMONS-1], inclusive, are
index e4d3ec7..e9f1fc0 100644 (file)
@@ -5,81 +5,87 @@
 #ifndef PROP_H
 #define PROP_H
 
-/*** What the properties are ***/
+/*** What the properties are ***
+ *
+ * note:  propertynames[] array in timeout.c has string values for these.
+ *        Property #0 is not used.
+ */
 /* Resistances to troubles */
-#define FIRE_RES 1
-#define COLD_RES 2
-#define SLEEP_RES 3
-#define DISINT_RES 4
-#define SHOCK_RES 5
-#define POISON_RES 6
-#define ACID_RES 7
-#define STONE_RES 8
-/* note: for the first eight properties, MR_xxx == (1 << (xxx_RES - 1)) */
-#define DRAIN_RES 9
-#define SICK_RES 10
-#define INVULNERABLE 11
-#define ANTIMAGIC 12
-/* Troubles */
-#define STUNNED 13
-#define CONFUSION 14
-#define BLINDED 15
-#define DEAF 16
-#define SICK 17
-#define STONED 18
-#define STRANGLED 19
-#define VOMITING 20
-#define GLIB 21
-#define SLIMED 22
-#define HALLUC 23
-#define HALLUC_RES 24
-#define FUMBLING 25
-#define WOUNDED_LEGS 26
-#define SLEEPY 27
-#define HUNGER 28
-/* Vision and senses */
-#define SEE_INVIS 29
-#define TELEPAT 30
-#define WARNING 31
-#define WARN_OF_MON 32
-#define WARN_UNDEAD 33
-#define SEARCHING 34
-#define CLAIRVOYANT 35
-#define INFRAVISION 36
-#define DETECT_MONSTERS 37
-/* Appearance and behavior */
-#define ADORNED 38
-#define INVIS 39
-#define DISPLACED 40
-#define STEALTH 41
-#define AGGRAVATE_MONSTER 42
-#define CONFLICT 43
-/* Transportation */
-#define JUMPING 44
-#define TELEPORT 45
-#define TELEPORT_CONTROL 46
-#define LEVITATION 47
-#define FLYING 48
-#define WWALKING 49
-#define SWIMMING 50
-#define MAGICAL_BREATHING 51
-#define PASSES_WALLS 52
-/* Physical attributes */
-#define SLOW_DIGESTION 53
-#define HALF_SPDAM 54
-#define HALF_PHDAM 55
-#define REGENERATION 56
-#define ENERGY_REGENERATION 57
-#define PROTECTION 58
-#define PROT_FROM_SHAPE_CHANGERS 59
-#define POLYMORPH 60
-#define POLYMORPH_CONTROL 61
-#define UNCHANGING 62
-#define FAST 63
-#define REFLECTING 64
-#define FREE_ACTION 65
-#define FIXED_ABIL 66
-#define LIFESAVED 67
+enum prop_types {
+    FIRE_RES = 1,
+    COLD_RES,
+    SLEEP_RES,
+    DISINT_RES,
+    SHOCK_RES,
+    POISON_RES,
+    ACID_RES,
+    STONE_RES,
+    /* note: for the first eight properties, MR_xxx == (1 << (xxx_RES - 1)) */
+    DRAIN_RES,
+    SICK_RES,
+    INVULNERABLE,
+    ANTIMAGIC,
+    /* Troubles */
+    STUNNED,
+    CONFUSION,
+    BLINDED,
+    DEAF,
+    SICK,
+    STONED,
+    STRANGLED,
+    VOMITING,
+    GLIB,
+    SLIMED,
+    HALLUC,
+    HALLUC_RES,
+    FUMBLING,
+    WOUNDED_LEGS,
+    SLEEPY,
+    HUNGER,
+    /* Vision and senses */
+    SEE_INVIS,
+    TELEPAT,
+    WARNING,
+    WARN_OF_MON,
+    WARN_UNDEAD,
+    SEARCHING,
+    CLAIRVOYANT,
+    INFRAVISION,
+    DETECT_MONSTERS,
+    /* Appearance and behavior */
+    ADORNED,
+    INVIS,
+    DISPLACED,
+    STEALTH,
+    AGGRAVATE_MONSTER,
+    CONFLICT,
+    /* Transportation */
+    JUMPING,
+    TELEPORT,
+    TELEPORT_CONTROL,
+    LEVITATION,
+    FLYING,
+    WWALKING,
+    SWIMMING,
+    MAGICAL_BREATHING,
+    PASSES_WALLS,
+    /* Physical attributes */
+    SLOW_DIGESTION,
+    HALF_SPDAM,
+    HALF_PHDAM,
+    REGENERATION,
+    ENERGY_REGENERATION,
+    PROTECTION,
+    PROT_FROM_SHAPE_CHANGERS,
+    POLYMORPH,
+    POLYMORPH_CONTROL,
+    UNCHANGING,
+    FAST,
+    REFLECTING,
+    FREE_ACTION,
+    FIXED_ABIL,
+    LIFESAVED
+};
 #define LAST_PROP (LIFESAVED)
 
 /*** Where the properties come from ***/
index 0d97bfe..5667c13 100644 (file)
@@ -1,4 +1,131 @@
 /* clang-format off */
+/* XPM */
+static const char *blind_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"40 40 5 1",
+/* colors */
+"  c #000000",
+". c None",
+"X c #909090",
+"o c #606060",
+"O c #303030",
+/* pixels */
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"....ooooooooooooooooooooooooooooooooX...",
+"....                                o...",
+"....                                o...",
+"....                                o...",
+"....                                o...",
+"......o            ..o            ......",
+"......X           O..X           O......",
+".......           o...           o......",
+".......o          ....o          .......",
+"........O        X.....O        X.......",
+".........O      X.......O      X........",
+"..........o   OX.........o   OX.........",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................",
+"........................................"
+};
+/* XPM */
+static const char *cha_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"40 40 14 1",
+/* colors */
+"  c #F85848",
+". c #949E9E",
+"X c #F8B090",
+"o c #E00028",
+"O c #D4D4D4",
+"+ c None",
+"@ c #B0B0B0",
+"# c #F82C24",
+"$ c #F89E6C",
+"% c #FF0000",
+"& c #909090",
+"* c #FFFFFF",
+"= c #CEAA90",
+"- c #DADAB6",
+/* pixels */
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"+++++++++++++++=#%#=+=#%% ++++++++++++++",
+"++++++++++++++ %O%%%#%$$%o%=++++++++++++",
+"+++++++++++++# +#%%o%%o%%%%% +++++++++++",
+"+++++++++++ %%%%%%%%%%%%%%%%o#=+++++++++",
+"+++++++++ o%%%%%%%%%%%%%%%%%%%%# +++++++",
+"++++++ #%%%%%%o%%%o%%o%%o%o%%%%%o%o  +++",
+"++=#%%o%%%#= =*+**O*+**O*+- = =%%%%#@+++",
+"++++ %=++*+*+**O****O****O*O*O*OO%=+++++",
+"+++++.%=OO+*O*OO****+****+*O*+O&%=@+++++",
+"++++++=%=*OO+**O**O*O**O*O*OO+$%=+++++++",
+"+++++++#% +*OOOO****+****@O+*#%=++++++++",
+"++++++++#%#*+**+O+OO+O+OOO*O#o#+++++++++",
+"+++++++++o% O**+****O****O*#%%=+++++++++",
+"+++++++++ %%#O*O****+****+ %o#++++++++++",
+"++++++++++o%% XO*O**O*O**#%%%+++++++++++",
+"++++++++++ %%%o%$-**+**$%%%%=+++++++++++",
+"+++++++++++o%%$X$%%%%%%#= o#++++++++++++",
+"++++++++++@ %%%o#O$$+$$$%%%=++++++++++++",
+"++++++++++++#o%%%%%%%%o%%%=@++++++++++++",
+"+++++++++++++ %%%%%%%%%%o=++++++++++++++",
+"+++++++++++++++= &  &  @++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++"
+};
+/* XPM */
+static const char *chaotic_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"40 40 9 1",
+/* colors */
+"  c #000000",
+". c #5C7A7A",
+"X c None",
+"o c #B0B0B0",
+"O c #909090",
+"+ c #788C8C",
+"@ c #606060",
+"# c #FFFFFF",
+"$ c #303030",
 /* pixels */
 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
@@ -819,6 +946,20 @@ static const char *pet_mark_small_xpm[] = {
 "..X.."
 };
 /* XPM */
+static const char *pile_mark_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"5 5 2 1",
+/* colors */
+". c None",
+"X c #00FF00",
+/* pixels */
+"..X..",
+"..X..",
+"XXXXX",
+"..X..",
+"..X.."
+};
+/* XPM */
 static const char *satiated_xpm[] = {
 /* width height ncolors chars_per_pixel */
 "40 40 23 1",
index 11b414d..7529384 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 qtext.h $NHDT-Date: 1432594167 2015/05/25 22:49:27 $  $NHDT-Branch: master $:$NHDT-Revision: 1.17 $ */
+/* NetHack 3.6 qtext.h $NHDT-Date: 1505170347 2017/09/11 22:52:27 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.18 $ */
 /* Copyright (c) Mike Stephenson 1991.                           */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -83,6 +83,7 @@ struct qtlists {
 
 #define QT_FIRSTGOAL 40
 #define QT_NEXTGOAL 41
+#define QT_ALTGOAL 42 /* alternate to QT_NEXTGOAL if artifact is absent */
 
 #define QT_FIRSTNEMESIS 50
 #define QT_NEXTNEMESIS 51
index 56b0f09..3fc9ce5 100644 (file)
@@ -1,5 +1,5 @@
 /**********************************************************************
-** $NHDT-Branch$:$NHDT-Revision$ $NHDT-Date$
+** $NHDT-Date: 1524683840 2018/04/25 19:17:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.5 $
 ** $Id: qttableview.h,v 1.2 2002/03/09 03:13:13 jwalz Exp $
 **
 ** Definition of QtTableView class
index 5e71048..9d80551 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 rm.h    $NHDT-Date: 1432512776 2015/05/25 00:12:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.41 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2017. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef RM_H
    defines array type_names[] which contains an entry for each of
    these, so needs to be kept in sync if any new types are added
    or existing ones renumbered.] */
-#define STONE 0
-#define VWALL 1
-#define HWALL 2
-#define TLCORNER 3
-#define TRCORNER 4
-#define BLCORNER 5
-#define BRCORNER 6
-#define CROSSWALL 7 /* For pretty mazes and special levels */
-#define TUWALL 8
-#define TDWALL 9
-#define TLWALL 10
-#define TRWALL 11
-#define DBWALL 12
-#define TREE 13 /* KMH */
-#define SDOOR 14
-#define SCORR 15
-#define POOL 16
-#define MOAT 17 /* pool that doesn't boil, adjust messages */
-#define WATER 18
-#define DRAWBRIDGE_UP 19
-#define LAVAPOOL 20
-#define IRONBARS 21 /* KMH */
-#define DOOR 22
-#define CORR 23
-#define ROOM 24
-#define STAIRS 25
-#define LADDER 26
-#define FOUNTAIN 27
-#define THRONE 28
-#define SINK 29
-#define GRAVE 30
-#define ALTAR 31
-#define ICE 32
-#define DRAWBRIDGE_DOWN 33
-#define AIR 34
-#define CLOUD 35
-
-#define MAX_TYPE 36
-#define INVALID_TYPE 127
+enum levl_typ_types {
+    STONE = 0,
+    VWALL,
+    HWALL,
+    TLCORNER,
+    TRCORNER,
+    BLCORNER,
+    BRCORNER,
+    CROSSWALL, /* For pretty mazes and special levels */
+    TUWALL,
+    TDWALL,
+    TLWALL,
+    TRWALL,
+    DBWALL,
+    TREE, /* KMH */
+    SDOOR,
+    SCORR,
+    POOL,
+    MOAT, /* pool that doesn't boil, adjust messages */
+    WATER,
+    DRAWBRIDGE_UP,
+    LAVAPOOL,
+    IRONBARS, /* KMH */
+    DOOR,
+    CORR,
+    ROOM,
+    STAIRS,
+    LADDER,
+    FOUNTAIN,
+    THRONE,
+    SINK,
+    GRAVE,
+    ALTAR,
+    ICE,
+    DRAWBRIDGE_DOWN,
+    AIR,
+    CLOUD,
+
+    MAX_TYPE,
+    INVALID_TYPE = 127
+};
 
 /*
  * Avoid using the level types in inequalities:
@@ -83,7 +86,8 @@
 #define IS_STWALL(typ) ((typ) <= DBWALL) /* STONE <= (typ) <= DBWALL */
 #define IS_ROCK(typ) ((typ) < POOL)      /* absolutely nonaccessible */
 #define IS_DOOR(typ) ((typ) == DOOR)
-#define IS_TREE(typ) \
+#define IS_DOORJOIN(typ) (IS_ROCK(typ) || (typ) == IRONBARS)
+#define IS_TREE(typ)                                            \
     ((typ) == TREE || (level.flags.arboreal && (typ) == STONE))
 #define ACCESSIBLE(typ) ((typ) >= DOOR) /* good position */
 #define IS_ROOM(typ) ((typ) >= ROOM)    /* ROOM, STAIRS, furniture.. */
  */
 
 /* begin dungeon characters */
-
-#define S_stone 0
-#define S_vwall 1
-#define S_hwall 2
-#define S_tlcorn 3
-#define S_trcorn 4
-#define S_blcorn 5
-#define S_brcorn 6
-#define S_crwall 7
-#define S_tuwall 8
-#define S_tdwall 9
-#define S_tlwall 10
-#define S_trwall 11
-#define S_ndoor 12
-#define S_vodoor 13
-#define S_hodoor 14
-#define S_vcdoor 15 /* closed door, vertical wall */
-#define S_hcdoor 16 /* closed door, horizontal wall */
-#define S_bars 17   /* KMH -- iron bars */
-#define S_tree 18   /* KMH */
-#define S_room 19
-#define S_darkroom 20
-#define S_corr 21
-#define S_litcorr 22
-#define S_upstair 23
-#define S_dnstair 24
-#define S_upladder 25
-#define S_dnladder 26
-#define S_altar 27
-#define S_grave 28
-#define S_throne 29
-#define S_sink 30
-#define S_fountain 31
-#define S_pool 32
-#define S_ice 33
-#define S_lava 34
-#define S_vodbridge 35
-#define S_hodbridge 36
-#define S_vcdbridge 37 /* closed drawbridge, vertical wall */
-#define S_hcdbridge 38 /* closed drawbridge, horizontal wall */
-#define S_air 39
-#define S_cloud 40
-#define S_water 41
+enum screen_symbols {
+    S_stone = 0,
+    S_vwall,
+    S_hwall,
+    S_tlcorn,
+    S_trcorn,
+    S_blcorn,
+    S_brcorn,
+    S_crwall,
+    S_tuwall,
+    S_tdwall,
+    S_tlwall,
+    S_trwall,
+    S_ndoor,
+    S_vodoor,
+    S_hodoor,
+    S_vcdoor, /* closed door, vertical wall */
+    S_hcdoor, /* closed door, horizontal wall */
+    S_bars,   /* KMH -- iron bars */
+    S_tree,   /* KMH */
+    S_room,
+    S_darkroom,
+    S_corr,
+    S_litcorr,
+    S_upstair,
+    S_dnstair,
+    S_upladder,
+    S_dnladder,
+    S_altar,
+    S_grave,
+    S_throne,
+    S_sink,
+    S_fountain,
+    S_pool,
+    S_ice,
+    S_lava,
+    S_vodbridge,
+    S_hodbridge,
+    S_vcdbridge, /* closed drawbridge, vertical wall */
+    S_hcdbridge, /* closed drawbridge, horizontal wall */
+    S_air,
+    S_cloud,
+    S_water,
 
 /* end dungeon characters, begin traps */
 
-#define S_arrow_trap 42
-#define S_dart_trap 43
-#define S_falling_rock_trap 44
-#define S_squeaky_board 45
-#define S_bear_trap 46
-#define S_land_mine 47
-#define S_rolling_boulder_trap 48
-#define S_sleeping_gas_trap 49
-#define S_rust_trap 50
-#define S_fire_trap 51
-#define S_pit 52
-#define S_spiked_pit 53
-#define S_hole 54
-#define S_trap_door 55
-#define S_teleportation_trap 56
-#define S_level_teleporter 57
-#define S_magic_portal 58
-#define S_web 59
-#define S_statue_trap 60
-#define S_magic_trap 61
-#define S_anti_magic_trap 62
-#define S_polymorph_trap 63
-#define S_vibrating_square 64
+    S_arrow_trap,
+    S_dart_trap,
+    S_falling_rock_trap,
+    S_squeaky_board,
+    S_bear_trap,
+    S_land_mine,
+    S_rolling_boulder_trap,
+    S_sleeping_gas_trap,
+    S_rust_trap,
+    S_fire_trap,
+    S_pit,
+    S_spiked_pit,
+    S_hole,
+    S_trap_door,
+    S_teleportation_trap,
+    S_level_teleporter,
+    S_magic_portal,
+    S_web,
+    S_statue_trap,
+    S_magic_trap,
+    S_anti_magic_trap,
+    S_polymorph_trap,
+    S_vibrating_square,
 
 /* end traps, begin special effects */
 
-#define S_vbeam 65  /* The 4 zap beam symbols.  Do NOT separate. */
-#define S_hbeam 66  /* To change order or add, see function     */
-#define S_lslant 67 /* zapdir_to_glyph() in display.c.     */
-#define S_rslant 68
-#define S_digbeam 69   /* dig beam symbol */
-#define S_flashbeam 70 /* camera flash symbol */
-#define S_boomleft 71  /* thrown boomerang, open left, e.g ')'    */
-#define S_boomright 72 /* thrown boomerang, open right, e.g. '('  */
-#define S_ss1 73       /* 4 magic shield glyphs */
-#define S_ss2 74
-#define S_ss3 75
-#define S_ss4 76
-#define S_poisoncloud 77
-#define S_goodpos 78 /* valid position for targeting */
+    S_vbeam,  /* The 4 zap beam symbols.  Do NOT separate. */
+    S_hbeam,  /* To change order or add, see function     */
+    S_lslant, /* zapdir_to_glyph() in display.c.           */
+    S_rslant,
+    S_digbeam,   /* dig beam symbol */
+    S_flashbeam, /* camera flash symbol */
+    S_boomleft,  /* thrown boomerang, open left, e.g ')'    */
+    S_boomright, /* thrown boomerang, open right, e.g. '('  */
+    S_ss1,       /* 4 magic shield glyphs */
+    S_ss2,
+    S_ss3,
+    S_ss4,
+    S_poisoncloud,
+    S_goodpos, /* valid position for targeting */
 
 /* The 8 swallow symbols.  Do NOT separate.  To change order or add, see */
 /* the function swallow_to_glyph() in display.c.                        */
-#define S_sw_tl 79 /* swallow top left [1]                     */
-#define S_sw_tc 80 /* swallow top center [2]   Order:  */
-#define S_sw_tr 81 /* swallow top right [3]            */
-#define S_sw_ml 82 /* swallow middle left [4]  1 2 3   */
-#define S_sw_mr 83 /* swallow middle right [6] 4 5 6   */
-#define S_sw_bl 84 /* swallow bottom left [7]  7 8 9   */
-#define S_sw_bc 85 /* swallow bottom center [8]                */
-#define S_sw_br 86 /* swallow bottom right [9]         */
-
-#define S_explode1 87 /* explosion top left                    */
-#define S_explode2 88 /* explosion top center                  */
-#define S_explode3 89 /* explosion top right            Ex.    */
-#define S_explode4 90 /* explosion middle left         */
-#define S_explode5 91 /* explosion middle center        /-\    */
-#define S_explode6 92 /* explosion middle right         |@|    */
-#define S_explode7 93 /* explosion bottom left  \-/    */
-#define S_explode8 94 /* explosion bottom center               */
-#define S_explode9 95 /* explosion bottom right                */
+    S_sw_tl, /* swallow top left [1]             */
+    S_sw_tc, /* swallow top center [2]    Order: */
+    S_sw_tr, /* swallow top right [3]            */
+    S_sw_ml, /* swallow middle left [4]   1 2 3  */
+    S_sw_mr, /* swallow middle right [6]  4 5 6  */
+    S_sw_bl, /* swallow bottom left [7]   7 8 9  */
+    S_sw_bc, /* swallow bottom center [8]        */
+    S_sw_br, /* swallow bottom right [9]         */
+
+    S_explode1, /* explosion top left                  */
+    S_explode2, /* explosion top center                        */
+    S_explode3, /* explosion top right    Ex.  */
+    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              */
 
 /* end effects */
 
-#define MAXPCHARS 96  /* maximum number of mapped characters */
-#define MAXDCHARS 42  /* maximum of mapped dungeon characters */
-#define MAXTCHARS 22  /* maximum of mapped trap characters */
-#define MAXECHARS 31  /* maximum of mapped effects characters */
+    MAXPCHARS   /* maximum number of mapped characters */
+};
+
+#define MAXDCHARS (S_water - S_stone + 1)  /* maximum of mapped dungeon characters */
+#define MAXTCHARS (S_vibrating_square - S_arrow_trap + 1)  /* maximum of mapped trap characters */
+#define MAXECHARS (S_explode9 - S_vbeam + 1)  /* maximum of mapped effects characters */
 #define MAXEXPCHARS 9 /* number of explosion characters */
 
 #define DARKROOMSYM (Is_rogue_level(&u.uz) ? S_stone : S_darkroom)
 
+#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
+#define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
+#define is_cmap_door(i) ((i) >= S_vodoor && (i) <= S_hcdoor)
+#define is_cmap_wall(i) ((i) >= S_stone && (i) <= S_trwall)
+#define is_cmap_room(i) ((i) >= S_room && (i) <= S_darkroom)
+#define is_cmap_corr(i) ((i) >= S_corr && (i) <= S_litcorr)
+#define is_cmap_furniture(i) ((i) >= S_upstair && (i) <= S_fountain)
+#define is_cmap_water(i) ((i) == S_pool || (i) == S_water)
+#define is_cmap_lava(i) ((i) == S_lava)
+
+
 struct symdef {
     uchar sym;
     const char *explanation;
@@ -285,6 +302,8 @@ extern const struct symdef defsyms[MAXPCHARS]; /* defaults */
 extern const struct symdef def_warnsyms[WARNCOUNT];
 extern int currentgraphics; /* from drawing.c */
 extern nhsym showsyms[];
+extern nhsym l_syms[];
+extern nhsym r_syms[];
 
 extern struct symsetentry symset[NUM_GRAPHICS]; /* from drawing.c */
 #define SYMHANDLING(ht) (symset[currentgraphics].handling == (ht))
index 1c174d5..a4a312a 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 skills.h        $NHDT-Date: 1432512778 2015/05/25 00:12:58 $  $NHDT-Branch: master $:$NHDT-Revision: 1.11 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
+/*-Copyright (c) Pasi Kallinen, 2017. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef SKILLS_H
@@ -9,8 +10,9 @@
  * in a separate file so it can be included in objects.c.
  */
 
-/* Code to denote that no skill is applicable */
-#define P_NONE 0
+enum p_skills {
+    /* Code to denote that no skill is applicable */
+    P_NONE = 0,
 
 /* Weapon Skills -- Stephen White
  * Order matters and are used in macros.
  * Update weapon.c if you amend any skills.
  * Also used for oc_subtyp.
  */
-#define P_DAGGER 1
-#define P_KNIFE 2
-#define P_AXE 3
-#define P_PICK_AXE 4
-#define P_SHORT_SWORD 5
-#define P_BROAD_SWORD 6
-#define P_LONG_SWORD 7
-#define P_TWO_HANDED_SWORD 8
-#define P_SCIMITAR 9
-#define P_SABER 10
-#define P_CLUB 11 /* Heavy-shafted bludgeon */
-#define P_MACE 12
-#define P_MORNING_STAR 13 /* Spiked bludgeon */
-#define P_FLAIL 14        /* Two pieces hinged or chained together */
-#define P_HAMMER 15       /* Heavy head on the end */
-#define P_QUARTERSTAFF 16 /* Long-shafted bludgeon */
-#define P_POLEARMS 17
-#define P_SPEAR 18 /* includes javelin */
-#define P_TRIDENT 19
-#define P_LANCE 20
-#define P_BOW 21
-#define P_SLING 22
-#define P_CROSSBOW 23
-#define P_DART 24
-#define P_SHURIKEN 25
-#define P_BOOMERANG 26
-#define P_WHIP 27
-#define P_UNICORN_HORN 28 /* last weapon */
+    P_DAGGER,
+    P_KNIFE,
+    P_AXE,
+    P_PICK_AXE,
+    P_SHORT_SWORD,
+    P_BROAD_SWORD,
+    P_LONG_SWORD,
+    P_TWO_HANDED_SWORD,
+    P_SCIMITAR,
+    P_SABER,
+    P_CLUB, /* Heavy-shafted bludgeon */
+    P_MACE,
+    P_MORNING_STAR, /* Spiked bludgeon */
+    P_FLAIL,        /* Two pieces hinged or chained together */
+    P_HAMMER,       /* Heavy head on the end */
+    P_QUARTERSTAFF, /* Long-shafted bludgeon */
+    P_POLEARMS,
+    P_SPEAR, /* includes javelin */
+    P_TRIDENT,
+    P_LANCE,
+    P_BOW,
+    P_SLING,
+    P_CROSSBOW,
+    P_DART,
+    P_SHURIKEN,
+    P_BOOMERANG,
+    P_WHIP,
+    P_UNICORN_HORN, /* last weapon */
+
+    /* Spell Skills added by Larry Stewart-Zerba */
+    P_ATTACK_SPELL,
+    P_HEALING_SPELL,
+    P_DIVINATION_SPELL,
+    P_ENCHANTMENT_SPELL,
+    P_CLERIC_SPELL,
+    P_ESCAPE_SPELL,
+    P_MATTER_SPELL,
+
+    /* Other types of combat */
+    P_BARE_HANDED_COMBAT, /* actually weaponless; gloves are ok */
+    P_TWO_WEAPON_COMBAT,
+    P_RIDING,             /* How well you control your steed */
+
+    P_NUM_SKILLS
+};
+
+#define P_MARTIAL_ARTS P_BARE_HANDED_COMBAT /* Role distinguishes */
+
 #define P_FIRST_WEAPON P_DAGGER
 #define P_LAST_WEAPON P_UNICORN_HORN
 
-/* Spell Skills added by Larry Stewart-Zerba */
-#define P_ATTACK_SPELL 29
-#define P_HEALING_SPELL 30
-#define P_DIVINATION_SPELL 31
-#define P_ENCHANTMENT_SPELL 32
-#define P_CLERIC_SPELL 33
-#define P_ESCAPE_SPELL 34
-#define P_MATTER_SPELL 35
 #define P_FIRST_SPELL P_ATTACK_SPELL
 #define P_LAST_SPELL P_MATTER_SPELL
 
-/* Other types of combat */
-#define P_BARE_HANDED_COMBAT 36 /* actually weaponless; gloves are ok */
-#define P_MARTIAL_ARTS P_BARE_HANDED_COMBAT /* Role distinguishes */
-#define P_TWO_WEAPON_COMBAT 37              /* Finally implemented */
-#define P_RIDING 38 /* How well you control your steed */
 #define P_LAST_H_TO_H P_RIDING
 #define P_FIRST_H_TO_H P_BARE_HANDED_COMBAT
 
-#define P_NUM_SKILLS (P_LAST_H_TO_H + 1)
-
 /* These roles qualify for a martial arts bonus */
 #define martial_bonus() (Role_if(PM_SAMURAI) || Role_if(PM_MONK))
 
  * with the current skill-1.  To work out for the UNSKILLED case,
  * a value of 0 needed.
  */
-#define P_ISRESTRICTED 0
-#define P_UNSKILLED 1
-#define P_BASIC 2
-#define P_SKILLED 3
-#define P_EXPERT 4
-#define P_MASTER 5       /* Unarmed combat/martial arts only */
-#define P_GRAND_MASTER 6 /* Unarmed combat/martial arts only */
+enum skill_levels {
+    P_ISRESTRICTED = 0,
+    P_UNSKILLED,
+    P_BASIC,
+    P_SKILLED,
+    P_EXPERT,
+    P_MASTER,       /* Unarmed combat/martial arts only */
+    P_GRAND_MASTER  /* Unarmed combat/martial arts only */
+};
 
 #define practice_needed_to_advance(level) ((level) * (level) *20)
 
index 03a68e7..7d5b7bf 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 sp_lev.h        $NHDT-Date: 1432512780 2015/05/25 00:13:00 $  $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */
+/* NetHack 3.6 sp_lev.h        $NHDT-Date: 1524287214 2018/04/21 05:06:54 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.23 $ */
 /* Copyright (c) 1989 by Jean-Christophe Collet                          */
 /* NetHack may be freely redistributed.  See license for details. */
 
    generate ways to escape from them */
 
 /* different level layout initializers */
-#define LVLINIT_NONE 0
-#define LVLINIT_SOLIDFILL 1
-#define LVLINIT_MAZEGRID 2
-#define LVLINIT_MINES 3
-#define LVLINIT_ROGUE 4
+enum lvlinit_types {
+    LVLINIT_NONE = 0,
+    LVLINIT_SOLIDFILL,
+    LVLINIT_MAZEGRID,
+    LVLINIT_MINES,
+    LVLINIT_ROGUE
+};
 
 /* max. layers of object containment */
 #define MAX_CONTAINMENT 10
@@ -143,43 +145,47 @@ enum opcode_defs {
  * mean.
  */
 /* MONSTER */
-#define SP_M_V_PEACEFUL 0
-#define SP_M_V_ALIGN 1
-#define SP_M_V_ASLEEP 2
-#define SP_M_V_APPEAR 3
-#define SP_M_V_NAME 4
-
-#define SP_M_V_FEMALE 5
-#define SP_M_V_INVIS 6
-#define SP_M_V_CANCELLED 7
-#define SP_M_V_REVIVED 8
-#define SP_M_V_AVENGE 9
-#define SP_M_V_FLEEING 10
-#define SP_M_V_BLINDED 11
-#define SP_M_V_PARALYZED 12
-#define SP_M_V_STUNNED 13
-#define SP_M_V_CONFUSED 14
-#define SP_M_V_SEENTRAPS 15
-
-#define SP_M_V_END 16 /* end of variable parameters */
+enum sp_mon_var_flags {
+    SP_M_V_PEACEFUL = 0,
+    SP_M_V_ALIGN,
+    SP_M_V_ASLEEP,
+    SP_M_V_APPEAR,
+    SP_M_V_NAME,
+    SP_M_V_FEMALE,
+    SP_M_V_INVIS,
+    SP_M_V_CANCELLED,
+    SP_M_V_REVIVED,
+    SP_M_V_AVENGE,
+    SP_M_V_FLEEING,
+    SP_M_V_BLINDED,
+    SP_M_V_PARALYZED,
+    SP_M_V_STUNNED,
+    SP_M_V_CONFUSED,
+    SP_M_V_SEENTRAPS,
+
+    SP_M_V_END
+};
 
 /* OBJECT */
-#define SP_O_V_SPE 0
-#define SP_O_V_CURSE 1
-#define SP_O_V_CORPSENM 2
-#define SP_O_V_NAME 3
-#define SP_O_V_QUAN 4
-#define SP_O_V_BURIED 5
-#define SP_O_V_LIT 6
-#define SP_O_V_ERODED 7
-#define SP_O_V_LOCKED 8
-#define SP_O_V_TRAPPED 9
-#define SP_O_V_RECHARGED 10
-#define SP_O_V_INVIS 11
-#define SP_O_V_GREASED 12
-#define SP_O_V_BROKEN 13
-#define SP_O_V_COORD 14
-#define SP_O_V_END 15 /* end of variable parameters */
+enum sp_obj_var_flags {
+    SP_O_V_SPE = 0,
+    SP_O_V_CURSE,
+    SP_O_V_CORPSENM,
+    SP_O_V_NAME,
+    SP_O_V_QUAN,
+    SP_O_V_BURIED,
+    SP_O_V_LIT,
+    SP_O_V_ERODED,
+    SP_O_V_LOCKED,
+    SP_O_V_TRAPPED,
+    SP_O_V_RECHARGED,
+    SP_O_V_INVIS,
+    SP_O_V_GREASED,
+    SP_O_V_BROKEN,
+    SP_O_V_COORD,
+
+    SP_O_V_END
+};
 
 /* When creating objects, we need to know whether
  * it's a container and/or contents.
@@ -218,45 +224,41 @@ enum opcode_defs {
 #define SP_COORD_IS_RANDOM 0x01000000
 /* Humidity flags for get_location() and friends, used with
  * SP_COORD_PACK_RANDOM() */
-#define DRY 0x1
-#define WET 0x2
-#define HOT 0x4
-#define SOLID 0x8
-#define ANY_LOC 0x10     /* even outside the level */
+#define DRY         0x01
+#define WET         0x02
+#define HOT         0x04
+#define SOLID       0x08
+#define ANY_LOC     0x10 /* even outside the level */
 #define NO_LOC_WARN 0x20 /* no complaints and set x & y to -1, if no loc */
+#define SPACELOC    0x40 /* like DRY, but accepts furniture too */
 
 #define SP_COORD_X(l) (l & 0xff)
 #define SP_COORD_Y(l) ((l >> 16) & 0xff)
-#define SP_COORD_PACK(x, y) (((x) &0xff) + (((y) &0xff) << 16))
+#define SP_COORD_PACK(x, y) (((x) & 0xff) + (((y) & 0xff) << 16))
 #define SP_COORD_PACK_RANDOM(f) (SP_COORD_IS_RANDOM | (f))
 
 #define SP_REGION_X1(l) (l & 0xff)
 #define SP_REGION_Y1(l) ((l >> 8) & 0xff)
 #define SP_REGION_X2(l) ((l >> 16) & 0xff)
 #define SP_REGION_Y2(l) ((l >> 24) & 0xff)
-#define SP_REGION_PACK(x1, y1, x2, y2)                         \
-    (((x1) &0xff) + (((y1) &0xff) << 8) + (((x2) &0xff) << 16) \
-     + (((y2) &0xff) << 24))
-
-#define SP_MONST_CLASS(l) (l & 0xff)
-#define SP_MONST_PM(l) ((l >> 8) & 0xffff)
-#define SP_MONST_PACK(m, c) (((m) << 8) + ((char) (c)))
+#define SP_REGION_PACK(x1, y1, x2, y2) \
+    (((x1) & 0xff) + (((y1) & 0xff) << 8) + (((x2) & 0xff) << 16) \
+     + (((y2) & 0xff) << 24))
 
-#define SP_OBJ_CLASS(l) (l & 0xff)
-#define SP_OBJ_TYP(l) ((l >> 8) & 0xffff)
-#define SP_OBJ_PACK(o, c) (((o) << 8) + ((char) (c)))
+/* permonst index, object index, and lit value might be negative;
+ * add 10 to accept -1 through -9 while forcing non-negative for bit shift
+ */
+#define SP_MONST_CLASS(l) ((l) & 0xff)
+#define SP_MONST_PM(l) ((((l) >> 8) & 0xffff) - 10)
+#define SP_MONST_PACK(pm, cls) (((10 + (pm)) << 8) | ((cls) & 0xff))
 
-#define SP_MAPCHAR_TYP(l) (l & 0xff)
-#define SP_MAPCHAR_LIT(l) ((l >> 8) & 0xff)
-#define SP_MAPCHAR_PACK(typ, lit) (((lit) << 8) + ((char) (typ)))
+#define SP_OBJ_CLASS(l) ((l) & 0xff)
+#define SP_OBJ_TYP(l) ((((l) >> 8) & 0xffff) - 10)
+#define SP_OBJ_PACK(ob, cls) (((10 + (ob)) << 8) | ((cls) & 0xff))
 
-struct opvar {
-    xchar spovartyp; /* one of SPOVAR_foo */
-    union {
-        char *str;
-        long l;
-    } vardata;
-};
+#define SP_MAPCHAR_TYP(l) ((l) & 0xff)
+#define SP_MAPCHAR_LIT(l) ((((l) >> 8) & 0xffff) - 10)
+#define SP_MAPCHAR_PACK(typ, lit) (((10 + (lit)) << 8) | ((typ) & 0xff))
 
 struct splev_var {
     struct splev_var *next;
@@ -348,7 +350,7 @@ typedef struct {
 typedef struct {
     packed_coord coord;
     xchar x, y, type;
-} trap;
+} spltrap;
 
 typedef struct {
     Str_or_Len name, appear_as;
@@ -486,61 +488,52 @@ struct lc_breakdef {
 #ifdef SPEC_LEV
 /* compiling lev_comp rather than nethack */
 #ifdef USE_OLDARGS
-#undef VA_ARGS
-#undef VA_DECL
-#undef VA_DECL2
-#undef VA_SHIFT
+#ifndef VA_TYPE
+typedef const char *vA;
+#define VA_TYPE
+#endif
+#undef VA_ARGS  /* redefine with the maximum number actually used */
+#undef VA_SHIFT /* ditto */
+#undef VA_PASS1
 #define VA_ARGS                                                         \
     arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, \
         arg12, arg13, arg14
-#define VA_DECL(typ1, var1)                                             \
-    (var1, VA_ARGS) typ1 var1;                                          \
-    char *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9, \
-        *arg10, *arg11, *arg12, *arg13, *arg14;                         \
-    {
-#define VA_DECL2(typ1, var1, typ2, var2)                                \
-    (var1, var2, VA_ARGS) typ1 var1;                                    \
-    typ2 var2;                                                          \
-    char *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9, \
-        *arg10, *arg11, *arg12, *arg13, *arg14;                         \
-    {
-/* unlike in the core, lev_comp's VA_SHIFT is completely safe,
-   because callers always pass all these arguments */
+/* Unlike in the core, lev_comp's VA_SHIFT should be completely safe,
+   because callers always pass all these arguments. */
 #define VA_SHIFT()                                                       \
     (arg1 = arg2, arg2 = arg3, arg3 = arg4, arg4 = arg5, arg5 = arg6,    \
      arg6 = arg7, arg7 = arg8, arg8 = arg9, arg9 = arg10, arg10 = arg11, \
      arg11 = arg12, arg12 = arg13, arg13 = arg14, arg14 = 0)
 /* standard NULL may be either (void *)0 or plain 0, both of
    which would need to be explicitly cast to (char *) here */
-typedef char *Va;
 #define VA_PASS1(a1)                                                         \
-    (Va) a1, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, \
-        (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0
+    (vA) a1, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, \
+        (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0
 #define VA_PASS2(a1, a2)                                              \
-    (Va) a1, (Va) a2, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, \
-        (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0
+    (vA) a1, (vA) a2, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, \
+        (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0
 #define VA_PASS3(a1, a2, a3)                                           \
-    (Va) a1, (Va) a2, (Va) a3, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, \
-        (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0
+    (vA) a1, (vA) a2, (vA) a3, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, \
+        (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0
 #define VA_PASS4(a1, a2, a3, a4)                                        \
-    (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) 0, (Va) 0, (Va) 0, (Va) 0, \
-        (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0
+    (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) 0, (vA) 0, (vA) 0, (vA) 0, \
+        (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0
 #define VA_PASS5(a1, a2, a3, a4, a5)                                     \
-    (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) a5, (Va) 0, (Va) 0, (Va) 0, \
-        (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0
+    (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) a5, (vA) 0, (vA) 0, (vA) 0, \
+        (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0
 #define VA_PASS7(a1, a2, a3, a4, a5, a6, a7)                               \
-    (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) a5, (Va) a6, (Va) a7, (Va) 0, \
-        (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0
+    (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) a5, (vA) a6, (vA) a7, (vA) 0, \
+        (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0
 #define VA_PASS8(a1, a2, a3, a4, a5, a6, a7, a8)                            \
-    (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) a5, (Va) a6, (Va) a7, (Va) a8, \
-        (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0
+    (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) a5, (vA) a6, (vA) a7, (vA) a8, \
+        (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0
 #define VA_PASS9(a1, a2, a3, a4, a5, a6, a7, a8, a9)                        \
-    (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) a5, (Va) a6, (Va) a7, (Va) a8, \
-        (Va) a9, (Va) 0, (Va) 0, (Va) 0, (Va) 0, (Va) 0
+    (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) a5, (vA) a6, (vA) a7, (vA) a8, \
+        (vA) a9, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0
 #define VA_PASS14(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13,   \
                   a14)                                                      \
-    (Va) a1, (Va) a2, (Va) a3, (Va) a4, (Va) a5, (Va) a6, (Va) a7, (Va) a8, \
-        (Va) a9, (Va) a10, (Va) a11, (Va) a12, (Va) a13, (Va) a14
+    (vA) a1, (vA) a2, (vA) a3, (vA) a4, (vA) a5, (vA) a6, (vA) a7, (vA) a8, \
+        (vA) a9, (vA) a10, (vA) a11, (vA) a12, (vA) a13, (vA) a14
 #else /*!USE_OLDARGS*/
 /* USE_STDARG and USE_VARARGS don't need to pass dummy arguments
    or cast real ones */
index 10b7c3c..17bbadb 100644 (file)
@@ -13,7 +13,11 @@ struct sysopt {
                                or "one or two" or "one, two, or three", &c */
     char *explorers;  /* like wizards, but for access to explore mode */
     char *shellers;   /* like wizards, for ! command (-DSHELL); also ^Z */
+    char *genericusers; /* usernames that prompt for user name */
     char *debugfiles; /* files to show debugplines in. '*' is all. */
+#ifdef DUMPLOG
+    char *dumplogfile; /* where the dump file is saved */
+#endif
     int env_dbgfl;    /*  1: debugfiles comes from getenv("DEBUGFILES")
                        *     so sysconf's DEBUGFILES shouldn't override it;
                        *  0: getenv() hasn't been attempted yet;
@@ -22,6 +26,8 @@ struct sysopt {
     int maxplayers;
     int seduce;
     int check_save_uid; /* restoring savefile checks UID? */
+    int check_plname; /* use plname for checking wizards/explorers/shellers */
+    int bones_pools;
 
     /* record file */
     int persmax;
index 21ccf8b..a3eb984 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 system.h        $NHDT-Date: 1449269772 2015/12/04 22:56:12 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.12 $ */
+/* NetHack 3.6 system.h        $NHDT-Date: 1501723401 2017/08/03 01:23:21 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.13 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2017. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef SYSTEM_H
@@ -489,8 +490,17 @@ E int FDECL(vprintf, (const char *, va_list));
 #endif
 #endif
 #else
+#ifdef vprintf
+#undef vprintf
+#endif
 #define vprintf printf
+#ifdef vfprintf
+#undef vfprintf
+#endif
 #define vfprintf fprintf
+#ifdef vsprintf
+#undef vsprintf
+#endif
 #define vsprintf sprintf
 #endif
 #endif /* NEED_VARARGS */
index c54cef2..f3f28a9 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 tcap.h  $NHDT-Date: 1432512774 2015/05/25 00:12:54 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1989. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* not named termcap.h because it may conflict with a system header */
index 1481354..802cbd8 100644 (file)
@@ -1,4 +1,5 @@
-/* NetHack 3.6 tile2x11.h      $NHDT-Date: 1432512778 2015/05/25 00:12:58 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
+/* NetHack 3.6 tile2x11.h      $NHDT-Date: 1524689515 2018/04/25 20:51:55 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $ */
+/*      Copyright (c) 2002 by David Cohrs              */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef TILE2X11_H
diff --git a/include/tileset.h b/include/tileset.h
new file mode 100644 (file)
index 0000000..2ab145e
--- /dev/null
@@ -0,0 +1,43 @@
+/* NetHack 3.6    tileset.h    $NHDT-Date: 1457207052 2016/03/05 19:44:12 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.0 $ */
+/* Copyright (c) Ray Chason, 2016. */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#ifndef TILESET_H
+#define TILESET_H
+
+struct Pixel {
+    unsigned char r, g, b, a;
+};
+
+struct TileImage {
+    /* Image data */
+    unsigned width, height;
+    struct Pixel *pixels; /* for direct color */
+    unsigned char *indexes; /* for paletted images */
+};
+
+boolean FDECL(read_tiles, (const char *filename, BOOLEAN_P true_color));
+const struct Pixel *NDECL(get_palette);
+void NDECL(free_tiles);
+const struct TileImage *FDECL(get_tile, (unsigned tile_index));
+
+/* Used internally by the tile set code */
+struct TileSetImage {
+    /* Image data */
+    unsigned width, height;
+    struct Pixel *pixels; /* for direct color */
+    unsigned char *indexes; /* for paletted images */
+    struct Pixel palette[256];
+    
+    /* Image description from the file */
+    char *image_desc;
+
+    /* Tile dimensions */
+    unsigned tile_width, tile_height;
+};
+
+boolean FDECL(read_bmp_tiles, (const char *filename, struct TileSetImage *image));
+boolean FDECL(read_gif_tiles, (const char *filename, struct TileSetImage *image));
+boolean FDECL(read_png_tiles, (const char *filename, struct TileSetImage *image));
+
+#endif
index e405b5e..0cb4c70 100644 (file)
@@ -9,10 +9,12 @@
 typedef void FDECL((*timeout_proc), (ANY_P *, long));
 
 /* kind of timer */
-#define TIMER_LEVEL 0   /* event specific to level */
-#define TIMER_GLOBAL 1  /* event follows current play */
-#define TIMER_OBJECT 2  /* event follows a object */
-#define TIMER_MONSTER 3 /* event follows a monster */
+enum timer_type {
+    TIMER_LEVEL = 0,   /* event specific to level */
+    TIMER_GLOBAL,  /* event follows current play */
+    TIMER_OBJECT,  /* event follows a object */
+    TIMER_MONSTER /* event follows a monster */
+};
 
 /* save/restore timer ranges */
 #define RANGE_LEVEL 0  /* save/restore timers staying on level */
@@ -22,14 +24,17 @@ typedef void FDECL((*timeout_proc), (ANY_P *, long));
  * Timeout functions.  Add a define here, then put it in the table
  * in timeout.c.  "One more level of indirection will fix everything."
  */
-#define ROT_ORGANIC 0 /* for buried organics */
-#define ROT_CORPSE 1
-#define REVIVE_MON 2
-#define BURN_OBJECT 3
-#define HATCH_EGG 4
-#define FIG_TRANSFORM 5
-#define MELT_ICE_AWAY 6
-#define NUM_TIME_FUNCS 7
+enum timeout_types {
+    ROT_ORGANIC = 0, /* for buried organics */
+    ROT_CORPSE,
+    REVIVE_MON,
+    BURN_OBJECT,
+    HATCH_EGG,
+    FIG_TRANSFORM,
+    MELT_ICE_AWAY,
+
+    NUM_TIME_FUNCS
+};
 
 /* used in timeout.c */
 typedef struct fe {
index 1ccf132..3f5ca4c 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 tosconf.h       $NHDT-Date: 1432512782 2015/05/25 00:13:02 $  $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifdef TOS
index 26ce81a..1caf7a6 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 tradstdc.h      $NHDT-Date: 1448210011 2015/11/22 16:33:31 $  $NHDT-Branch: master $:$NHDT-Revision: 1.27 $ */
+/* NetHack 3.6 tradstdc.h      $NHDT-Date: 1501803107 2017/08/03 23:31:47 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.29 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef TRADSTDC_H
 #define VA_END()      \
     va_end(the_args); \
     }
+#define VA_PASS1(a1) a1
 #if defined(ULTRIX_PROTO) && !defined(_VA_LIST_)
 #define _VA_LIST_ /* prevents multiple def in stdio.h */
 #endif
 #define VA_END()      \
     va_end(the_args); \
     }
+#define VA_PASS1(a1) a1
 #else
 
 /*USE_OLDARGS*/
+/*
+ * CAVEAT:  passing double (including float promoted to double) will
+ * almost certainly break this, as would any integer type bigger than
+ * sizeof (char *).
+ * NetHack avoids floating point, and any configuration able to use
+ * 'long long int' or I64P32 or the like should be using USE_STDARG.
+ */
+#ifndef VA_TYPE
+typedef const char *vA;
+#define VA_TYPE
+#endif
 #define VA_ARGS arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
 #define VA_DECL(typ1, var1)                                             \
-    (var1, VA_ARGS) typ1 var1;                                          \
-    char *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9; \
+    (var1, VA_ARGS) typ1 var1; vA VA_ARGS;                              \
     {
 #define VA_DECL2(typ1, var1, typ2, var2)                                \
-    (var1, var2, VA_ARGS) typ1 var1;                                    \
-    typ2 var2;                                                          \
-    char *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9; \
+    (var1, var2, VA_ARGS) typ1 var1; typ2 var2; vA VA_ARGS;             \
     {
 #define VA_START(x)
 #define VA_INIT(var1, typ1)
  */
 #define VA_SHIFT()                                                    \
     (arg1 = arg2, arg2 = arg3, arg3 = arg4, arg4 = arg5, arg5 = arg6, \
-     arg6 = arg7, arg7 = arg8, arg8 = arg9)
+     arg6 = arg7, arg7 = arg8, arg8 = arg9, arg9 = 0)
 #define VA_NEXT(var1, typ1) ((var1 = (typ1) arg1), VA_SHIFT(), var1)
 #define VA_END() }
+/* needed in pline.c, where full number of arguments is known and expected */
+#define VA_PASS1(a1)                                                  \
+    (vA) a1, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0, (vA) 0
 #endif
 #endif
 
@@ -380,7 +394,7 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */
  * append this to a prototype declaration (see pline() in extern.h).
  */
 #ifdef __GNUC__
-#if __GNUC__ >= 2
+#if (__GNUC__ >= 2) && !defined(USE_OLDARGS)
 #define PRINTF_F(f, v) __attribute__((format(printf, f, v)))
 #endif
 #if __GNUC__ >= 3
index 4b83f19..16d0968 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 trap.h  $NHDT-Date: 1432512776 2015/05/25 00:12:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2016. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* note for 3.1.0 and later: no longer manipulated by 'makedefs' */
@@ -53,30 +54,33 @@ extern struct trap *ftrap;
 /* Note: if adding/removing a trap, adjust trap_engravings[] in mklev.c */
 
 /* unconditional traps */
-#define NO_TRAP 0
-#define ARROW_TRAP 1
-#define DART_TRAP 2
-#define ROCKTRAP 3
-#define SQKY_BOARD 4
-#define BEAR_TRAP 5
-#define LANDMINE 6
-#define ROLLING_BOULDER_TRAP 7
-#define SLP_GAS_TRAP 8
-#define RUST_TRAP 9
-#define FIRE_TRAP 10
-#define PIT 11
-#define SPIKED_PIT 12
-#define HOLE 13
-#define TRAPDOOR 14
-#define TELEP_TRAP 15
-#define LEVEL_TELEP 16
-#define MAGIC_PORTAL 17
-#define WEB 18
-#define STATUE_TRAP 19
-#define MAGIC_TRAP 20
-#define ANTI_MAGIC 21
-#define POLY_TRAP 22
-#define VIBRATING_SQUARE 23
-#define TRAPNUM 24
+enum trap_types {
+    NO_TRAP = 0,
+    ARROW_TRAP,
+    DART_TRAP,
+    ROCKTRAP,
+    SQKY_BOARD,
+    BEAR_TRAP,
+    LANDMINE,
+    ROLLING_BOULDER_TRAP,
+    SLP_GAS_TRAP,
+    RUST_TRAP,
+    FIRE_TRAP,
+    PIT,
+    SPIKED_PIT,
+    HOLE,
+    TRAPDOOR,
+    TELEP_TRAP,
+    LEVEL_TELEP,
+    MAGIC_PORTAL,
+    WEB,
+    STATUE_TRAP,
+    MAGIC_TRAP,
+    ANTI_MAGIC,
+    POLY_TRAP,
+    VIBRATING_SQUARE,
+
+    TRAPNUM
+};
 
 #endif /* TRAP_H */
index cad1672..e4b2292 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 unixconf.h      $NHDT-Date: 1447755973 2015/11/17 10:26:13 $  $NHDT-Branch: master $:$NHDT-Revision: 1.24 $ */
+/* NetHack 3.6 unixconf.h      $NHDT-Date: 1520099325 2018/03/03 17:48:45 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.30 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifdef UNIX
@@ -36,7 +37,9 @@
 #define NETWORK        /* if running on a networked system */
                        /* e.g. Suns sharing a playground through NFS */
 /* #define SUNOS4 */   /* SunOS 4.x */
-/* #define LINUX */    /* Another Unix clone */
+#ifdef __linux__
+#define LINUX    /* Another Unix clone */
+#endif
 /* #define CYGWIN32 */ /* Unix on Win32 -- use with case sensitive defines */
 /* #define GENIX */    /* Yet Another Unix Clone */
 /* #define HISX */     /* Bull Unix for XPS Machines */
  */
 /* #define TIMED_DELAY */ /* usleep() */
 #endif
+#if defined(MACOSX) && !defined(TIMED_DELAY)
+#define TIMED_DELAY
+#endif
+
+/* #define AVOID_WIN_IOCTL */ /* ensure USE_WIN_IOCTL remains undefined */
 
 /*
  * If you define MAIL, then the player will be notified of new mail
 #endif
 #endif
 
+/* If SIMPLE_MAIL is defined, the mail spool file format is
+   "sender:message", one mail per line, and mails are
+   read within game, from demon-delivered mail scrolls.
+   The mail spool file will be deleted once the player
+   has read the message. */
+/* #define SIMPLE_MAIL */
+
+#ifndef MAILCKFREQ
+/* How often mail spool file is checked for new messages, in turns */
 #define MAILCKFREQ 50
+#endif
+
 #endif /* MAIL */
 
+/* If SERVER_ADMIN_MSG is defined and the file exists, players get
+   a message from the user defined in the file.  The file format
+   is "sender:message" all in one line. */
+/* #define SERVER_ADMIN_MSG "adminmsg" */
+#ifndef SERVER_ADMIN_MSG_CKFREQ
+/* How often admin message file is checked for new messages, in turns */
+#define SERVER_ADMIN_MSG_CKFREQ 25
+#endif
+
+
 /*
  * Some terminals or terminal emulators send two character sequence "ESC c"
  * when Alt+c is pressed.  The altmeta run-time option allows the user to
 /* #define COMPRESS_OPTIONS "-q" */
 #endif
 
+#ifndef FCMASK
 #define FCMASK 0660 /* file creation mask */
+#endif
 
 /* fcntl(2) is a POSIX-portable call for manipulating file descriptors.
  * Comment out the USE_FCNTL if for some reason you have a strange
 #endif /* LINUX */
 #endif /* GNOME_GRAPHICS */
 
+#ifdef __APPLE__
+# define RUNTIME_PASTEBUF_SUPPORT
+#endif
+
 #endif /* UNIXCONF_H */
 #endif /* UNIX */
index 75e732a..7674e85 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 vmsconf.h       $NHDT-Date: 1432512780 2015/05/25 00:13:00 $  $NHDT-Branch: master $:$NHDT-Revision: 1.22 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifdef VMS
index 887aed0..80febfb 100644 (file)
@@ -1,5 +1,5 @@
-/* NetHack 3.6 winX.h  $NHDT-Date: 1433806583 2015/06/08 23:36:23 $  $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
-/* Copyright (c) Dean Luick, 1992                                */
+/* NetHack 3.6 winX.h  $NHDT-Date: 1457079196 2016/03/04 08:13:16 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.23 $ */
+/* Copyright (c) Dean Luick, 1992                                 */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -62,7 +62,7 @@ struct text_map_info_t {
 
     int square_width,  /* Saved font information so      */
         square_height, /*   we can calculate the correct */
-        square_ascent, /*   placement of changes.        */
+        square_ascent, /*   placement of changes.        */
         square_lbearing;
 };
 
@@ -81,7 +81,7 @@ struct tile_map_info_t {
 
     int square_width,  /* Saved tile information so      */
         square_height, /*   we can calculate the correct */
-        square_ascent, /*   placement of changes.        */
+        square_ascent, /*   placement of changes.        */
         square_lbearing;
 };
 
@@ -116,16 +116,16 @@ struct mesg_info_t {
     struct line_element *head;       /* head of circular line queue */
     struct line_element *line_here;  /* current drawn line position */
     struct line_element *last_pause; /* point to the line after the prev */
-    /*     bottom of screen                    */
+                                     /*     bottom of screen             */
     struct line_element *last_pause_head; /* pointer to head of previous */
-    /* turn                                    */
+                                          /* turn                        */
     GC gc;           /* GC for text drawing */
     int char_width,  /* Saved font information so we can  */
         char_height, /*   calculate the correct placement */
-        char_ascent, /*   of changes.               */
+        char_ascent, /*   of changes.                     */
         char_lbearing;
-    Dimension viewport_width, /* Saved viewport size, so we can adjust */
-        viewport_height;      /*   the slider on a resize.              */
+    Dimension viewport_width,  /* Saved viewport size, so we can adjust */
+              viewport_height; /*   the slider on a resize.             */
     Boolean dirty;            /* Lines have been added to the window. */
 };
 
@@ -147,6 +147,7 @@ typedef struct x11_mi {
     char *str;           /* The text of the item. */
     int attr;            /* Attribute for the line. */
     boolean selected;    /* Been selected? */
+    boolean preselected; /*   in advance?  */
     char selector;       /* Char used to select this entry. */
     char gselector;      /* Group selector. */
 } x11_menu_item;
@@ -160,7 +161,7 @@ struct menu {
     String *list_pointer; /* String list. */
     Boolean *sensitive;   /* Active list. */
     char curr_selector;   /* Next keyboard accelerator to assign, */
-    /*   if 0, then we're out.         */
+                          /*   if 0, then we're out.              */
 };
 
 struct menu_info_t {
@@ -236,19 +237,19 @@ struct xwindow {
 
 #define MAX_WINDOWS 20 /* max number of open windows */
 
-#define NHW_NONE 0 /* Unallocated window type.  Must be        */
-/* different from any other NHW_* type. */
+#define NHW_NONE 0 /* Unallocated window type.  Must be    */
+                   /* different from any other NHW_* type. */
 
 #define NO_CLICK 0 /* No click occurred on the map window. Must */
-/* be different than CLICK_1 and CLICK_2.   */
+                   /* be different than CLICK_1 and CLICK_2.    */
 
 #define DEFAULT_MESSAGE_WIDTH 60 /* width in chars of the message window */
 
-#define DISPLAY_FILE_SIZE 35 /* Max number of lines in the default     */
-/* file display window.                        */
+#define DISPLAY_FILE_SIZE 35 /* Max number of lines in the default */
+                             /* file display window.               */
 
 #define MAX_KEY_STRING 64 /* String size for converting a keypress */
-/* event into a character(s)            */
+                          /* event into a character(s)             */
 
 #define DEFAULT_LINES_DISPLAYED 12 /* # of lines displayed message window */
 #define MAX_HISTORY 60             /* max history saved on message window */
@@ -264,11 +265,13 @@ E boolean exit_x_event;     /* exit condition for event loop */
 #define EXIT_ON_EXIT 2
 #define EXIT_ON_SENT_EVENT 3
 E int click_x, click_y, click_button, updated_inventory;
+E boolean plsel_ask_name;
 
 typedef struct {
-    Boolean slow;
-    Boolean autofocus;
-    Boolean message_line;
+    Boolean slow;             /* issue prompts between map and message wins */
+    Boolean autofocus;        /* grab pointer focus for popup windows */
+    Boolean message_line;     /* separate current turn mesgs from prev ones */
+    Boolean highlight_prompt; /* if 'slow', highlight yn prompts */
     Boolean double_tile_size; /* double tile size */
     String tile_file;         /* name of file to open for tiles */
 #ifdef X11LARGETILE
@@ -277,6 +280,7 @@ typedef struct {
 #endif
     String icon;              /* name of desired icon */
     int message_lines;        /* number of lines to attempt to show */
+    int extcmd_height_delta;  /* bottom margin for extended command menu */
     String pet_mark_bitmap;   /* X11 bitmap file used to mark pets */
     Pixel pet_mark_color;     /* color of pet mark */
     String pilemark_bitmap;   /* X11 bitmap file used to mark item piles */
@@ -307,7 +311,7 @@ E Widget
 FDECL(CreateDialog, (Widget, String, XtCallbackProc, XtCallbackProc));
 E void FDECL(SetDialogPrompt, (Widget, String));
 E String FDECL(GetDialogResponse, (Widget));
-E void FDECL(SetDialogResponse, (Widget, String));
+E void FDECL(SetDialogResponse, (Widget, String, unsigned));
 E void FDECL(positionpopup, (Widget, BOOLEAN_P));
 
 /* ### winX.c ### */
@@ -316,6 +320,7 @@ E Boolean FDECL(nhApproxColor, (Screen *, Colormap, char *, XColor *));
 E Dimension FDECL(nhFontHeight, (Widget));
 E char FDECL(key_event_to_char, (XKeyEvent *));
 E void FDECL(msgkey, (Widget, XtPointer, XEvent *));
+E void FDECL(highlight_yn, (BOOLEAN_P));
 E void FDECL(nh_XtPopup, (Widget, int, Widget));
 E void FDECL(nh_XtPopdown, (Widget));
 E void FDECL(win_X11_init, (int));
@@ -357,6 +362,13 @@ E void FDECL(algn_key,
 E void FDECL(ec_delete, (Widget, XEvent *, String *, Cardinal *));
 E void FDECL(ec_key, (Widget, XEvent *, String *,
                       Cardinal *)); /* extended command action */
+E void FDECL(plsel_quit, (Widget, XEvent *, String *,
+                      Cardinal *)); /* player selection dialog */
+E void FDECL(plsel_play, (Widget, XEvent *, String *,
+                      Cardinal *)); /* player selection dialog */
+E void FDECL(plsel_randomize, (Widget, XEvent *, String *,
+                      Cardinal *)); /* player selection dialog */
+E void NDECL(release_extended_cmds);
 
 /* ### winstatus.c ### */
 E void FDECL(create_status_window, (struct xwindow *, BOOLEAN_P, Widget));
index b76d9e1..3c19d4f 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 winprocs.h      $NHDT-Date: 1433806582 2015/06/08 23:36:22 $  $NHDT-Branch: master $:$NHDT-Revision: 1.36 $ */
+/* NetHack 3.6 winprocs.h      $NHDT-Date: 1502141230 2017/08/07 21:27:10 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.38 $ */
 /* Copyright (c) David Cohrs, 1992                               */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -13,8 +13,7 @@ struct window_procs {
                            * not start with '-'.  Names starting with
                            * '+' are reserved for processors. */
     unsigned long wincap; /* window port capability options supported */
-    unsigned long
-        wincap2; /* additional window port capability options supported */
+    unsigned long wincap2; /* additional window port capability options */
     void FDECL((*win_init_nhwindows), (int *, char **));
     void NDECL((*win_player_selection));
     void NDECL((*win_askname));
@@ -74,16 +73,11 @@ struct window_procs {
     void FDECL((*win_preference_update), (const char *));
     char *FDECL((*win_getmsghistory), (BOOLEAN_P));
     void FDECL((*win_putmsghistory), (const char *, BOOLEAN_P));
-#ifdef STATUS_VIA_WINDOWPORT
     void NDECL((*win_status_init));
     void NDECL((*win_status_finish));
     void FDECL((*win_status_enablefield),
                (int, const char *, const char *, BOOLEAN_P));
-    void FDECL((*win_status_update), (int, genericptr_t, int, int));
-#ifdef STATUS_HILITES
-    void FDECL((*win_status_threshold), (int, int, anything, int, int, int));
-#endif
-#endif
+    void FDECL((*win_status_update), (int, genericptr_t, int, int, int, unsigned long *));
     boolean NDECL((*win_can_suspend));
 };
 
@@ -161,107 +155,84 @@ extern
 #define preference_update (*windowprocs.win_preference_update)
 #define getmsghistory (*windowprocs.win_getmsghistory)
 #define putmsghistory (*windowprocs.win_putmsghistory)
-#ifdef STATUS_VIA_WINDOWPORT
 /* there is a status_initialize() in botl.c,
  * which calls win_status_init() directly; same with status_finish.
  */
 #define status_enablefield (*windowprocs.win_status_enablefield)
 #define status_update (*windowprocs.win_status_update)
-#ifdef STATUS_HILITES
-#define status_threshold (*windowprocs.win_status_threshold)
-#endif
-#endif
 
 /*
  * WINCAP
  * Window port preference capability bits.
  * Some day this might be better in its own wincap.h file.
  */
-#define WC_COLOR 0x01L      /* 01 Port can display things in color       */
-#define WC_HILITE_PET 0x02L /* 02 supports hilite pet                    */
-#define WC_ASCII_MAP 0x04L  /* 03 supports an ascii map                  */
-#define WC_TILED_MAP 0x08L  /* 04 supports a tiled map                   */
-#define WC_PRELOAD_TILES 0x10L /* 05 supports pre-loading tiles */
-#define WC_TILE_WIDTH 0x20L  /* 06 prefer this width of tile              */
-#define WC_TILE_HEIGHT 0x40L /* 07 prefer this height of tile             */
-#define WC_TILE_FILE 0x80L   /* 08 alternative tile file name             */
-#define WC_INVERSE 0x100L    /* 09 Port supports inverse video            */
-#define WC_ALIGN_MESSAGE \
-    0x200L /* 10 supports message alignmt top|b|l|r     */
-#define WC_ALIGN_STATUS 0x400L /* 11 supports status alignmt top|b|l|r */
-#define WC_VARY_MSGCOUNT \
-    0x800L                  /* 12 supports varying message window        */
-#define WC_FONT_MAP 0x1000L /* 13 supports specification of map win font */
-#define WC_FONT_MESSAGE \
-    0x2000L                    /* 14 supports specification of msg win font */
-#define WC_FONT_STATUS 0x4000L /* 15 supports specification of sts win font \
-                                  */
-#define WC_FONT_MENU 0x8000L   /* 16 supports specification of mnu win font */
-#define WC_FONT_TEXT 0x10000L  /* 17 supports specification of txt win font \
-                                  */
-#define WC_FONTSIZ_MAP \
-    0x20000L /* 18 supports specification of map win font */
-#define WC_FONTSIZ_MESSAGE \
-    0x40000L /* 19 supports specification of msg win font */
-#define WC_FONTSIZ_STATUS \
-    0x80000L /* 20 supports specification of sts win font */
-#define WC_FONTSIZ_MENU \
-    0x100000L /* 21 supports specification of mnu win font */
-#define WC_FONTSIZ_TEXT \
-    0x200000L /* 22 supports specification of txt win font */
-#define WC_SCROLL_MARGIN \
-    0x400000L /* 23 supports setting scroll margin for map */
-#define WC_SPLASH_SCREEN \
-    0x800000L /* 24 supports display of splash screen      */
-#define WC_POPUP_DIALOG \
-    0x1000000L /* 25 supports queries in pop dialogs        */
-#define WC_SCROLL_AMOUNT \
-    0x2000000L /* 26 scroll this amount at scroll margin    */
-#define WC_EIGHT_BIT_IN \
-    0x4000000L /* 27 8-bit character input                  */
-#define WC_PERM_INVENT \
-    0x8000000L /* 28 8-bit character input                  */
-#define WC_MAP_MODE \
-    0x10000000L /* 29 map_mode option                        */
-#define WC_WINDOWCOLORS \
-    0x20000000L /* 30 background color for message window    */
-#define WC_PLAYER_SELECTION \
-    0x40000000L /* 31 background color for message window    */
+/* clang-format off */
+#define WC_COLOR         0x00000001L /* 01 Port can display things in color  */
+#define WC_HILITE_PET    0x00000002L /* 02 supports hilite pet               */
+#define WC_ASCII_MAP     0x00000004L /* 03 supports an ascii map             */
+#define WC_TILED_MAP     0x00000008L /* 04 supports a tiled map              */
+#define WC_PRELOAD_TILES 0x00000010L /* 05 supports pre-loading tiles        */
+#define WC_TILE_WIDTH    0x00000020L /* 06 prefer this width of tile         */
+#define WC_TILE_HEIGHT   0x00000040L /* 07 prefer this height of tile        */
+#define WC_TILE_FILE     0x00000080L /* 08 alternative tile file name        */
+#define WC_INVERSE       0x00000100L /* 09 Port supports inverse video       */
+#define WC_ALIGN_MESSAGE 0x00000200L /* 10 supports mesg alignment top|b|l|r */
+#define WC_ALIGN_STATUS  0x00000400L /* 11 supports status alignmt top|b|l|r */
+#define WC_VARY_MSGCOUNT 0x00000800L /* 12 supports varying message window   */
+#define WC_FONT_MAP      0x00001000L /* 13 supports spec of map window font  */
+#define WC_FONT_MESSAGE  0x00002000L /* 14 supports spec of message font     */
+#define WC_FONT_STATUS   0x00004000L /* 15 supports spec of status font      */
+#define WC_FONT_MENU     0x00008000L /* 16 supports spec of menu font        */
+#define WC_FONT_TEXT     0x00010000L /* 17 supports spec of text window font */
+#define WC_FONTSIZ_MAP   0x00020000L /* 18 supports spec of map font size    */
+#define WC_FONTSIZ_MESSAGE 0x040000L /* 19 supports spec of mesg font size   */
+#define WC_FONTSIZ_STATUS 0x0080000L /* 20 supports spec of status font size */
+#define WC_FONTSIZ_MENU  0x00100000L /* 21 supports spec of menu font size   */
+#define WC_FONTSIZ_TEXT  0x00200000L /* 22 supports spec of text font size   */
+#define WC_SCROLL_MARGIN 0x00400000L /* 23 supports setting map scroll marg  */
+#define WC_SPLASH_SCREEN 0x00800000L /* 24 supports display of splash screen */
+#define WC_POPUP_DIALOG  0x01000000L /* 25 supports queries in popup dialogs */
+#define WC_SCROLL_AMOUNT 0x02000000L /* 26 scroll this amount at scroll marg */
+#define WC_EIGHT_BIT_IN  0x04000000L /* 27 8-bit character input             */
+#define WC_PERM_INVENT   0x08000000L /* 28 supports persistent inventory win */
+#define WC_MAP_MODE      0x10000000L /* 29 map_mode option                   */
+#define WC_WINDOWCOLORS  0x20000000L /* 30 background color for mesg window  */
+#define WC_PLAYER_SELECTION 0x40000000L /* 31 supports player selection      */
 #ifdef NHSTDC
-#define WC_MOUSE_SUPPORT \
-    0x80000000UL /* 32 mouse support                          */
+#define WC_MOUSE_SUPPORT 0x80000000UL /* 32 mouse support                    */
 #else
-#define WC_MOUSE_SUPPORT \
-    0x80000000L /* 32 mouse support                          */
+#define WC_MOUSE_SUPPORT 0x80000000L /* 32 mouse support                     */
 #endif
-/* no free bits */
+                                     /* no free bits */
 
-#define WC2_FULLSCREEN 0x01L /* 01 display full screen                    */
-#define WC2_SOFTKEYBOARD 0x02L /* 02 software keyboard */
-#define WC2_WRAPTEXT 0x04L /* 03 wrap long lines of text                */
-#define WC2_HILITE_STATUS \
-    0x08L /* 04 hilite fields in status                */
-#define WC2_SELECTSAVED 0x10L /* 05 saved game selection menu */
-#define WC2_DARKGRAY 0x20L /* 06 use bold black for black glyphs        */
-                           /* 26 free bits */
+#define WC2_FULLSCREEN    0x0001L /* 01 display full screen             */
+#define WC2_SOFTKEYBOARD  0x0002L /* 02 software keyboard               */
+#define WC2_WRAPTEXT      0x0004L /* 03 wrap long lines of text         */
+#define WC2_HILITE_STATUS 0x0008L /* 04 hilite fields in status         */
+#define WC2_SELECTSAVED   0x0010L /* 05 saved game selection menu       */
+#define WC2_DARKGRAY      0x0020L /* 06 use bold black for black glyphs */
+#define WC2_HITPOINTBAR   0x0040L /* 07 show bar representing hit points */
+#define WC2_FLUSH_STATUS  0x0080L /* 08 call status_update(BL_FLUSH)
+                                        after updating status window fields */
+                                  /* 24 free bits */
 
-#define ALIGN_LEFT 1
-#define ALIGN_RIGHT 2
-#define ALIGN_TOP 3
+#define ALIGN_LEFT   1
+#define ALIGN_RIGHT  2
+#define ALIGN_TOP    3
 #define ALIGN_BOTTOM 4
 
 /* player_selection */
-#define VIA_DIALOG 0
+#define VIA_DIALOG  0
 #define VIA_PROMPTS 1
 
 /* map_mode settings - deprecated */
-#define MAP_MODE_TILES 0
-#define MAP_MODE_ASCII4x6 1
-#define MAP_MODE_ASCII6x8 2
-#define MAP_MODE_ASCII8x8 3
-#define MAP_MODE_ASCII16x8 4
-#define MAP_MODE_ASCII7x12 5
-#define MAP_MODE_ASCII8x12 6
+#define MAP_MODE_TILES      0
+#define MAP_MODE_ASCII4x6   1
+#define MAP_MODE_ASCII6x8   2
+#define MAP_MODE_ASCII8x8   3
+#define MAP_MODE_ASCII16x8  4
+#define MAP_MODE_ASCII7x12  5
+#define MAP_MODE_ASCII8x12  6
 #define MAP_MODE_ASCII16x12 7
 #define MAP_MODE_ASCII12x16 8
 #define MAP_MODE_ASCII10x18 9
@@ -269,13 +240,13 @@ extern
 #define MAP_MODE_TILES_FIT_TO_SCREEN 11
 
 #if 0
-#define WC_SND_SOUND 0x01L   /* 01 Port has some sound capabilities       */
-#define WC_SND_SPEAKER 0x02L /* 02 Sound supported via built-in speaker   */
-#define WC_SND_STEREO 0x04L  /* 03 Stereo sound supported                 */
-#define WC_SND_RAW 0x08L     /* 04 Raw sound supported                    */
-#define WC_SND_WAVE 0x10L    /* 05 Wave support                           */
-#define WC_SND_MIDI 0x20L /* 06 Midi support                           */
-                                       /* 26 free bits */
+#define WC_SND_SOUND   0x0001L /* 01 Port has some sound capabilities     */
+#define WC_SND_SPEAKER 0x0002L /* 02 Sound supported via built-in speaker */
+#define WC_SND_STEREO  0x0004L /* 03 Stereo sound supported               */
+#define WC_SND_RAW     0x0008L /* 04 Raw sound supported                  */
+#define WC_SND_WAVE    0x0010L /* 05 Wave support                         */
+#define WC_SND_MIDI    0x0020L /* 06 Midi support                         */
+                               /* 26 free bits */
 #endif
 
 struct wc_Opt {
@@ -284,17 +255,17 @@ struct wc_Opt {
 };
 
 /* role selection by player_selection(); this ought to be in the core... */
-#define RS_NAME 0
-#define RS_ROLE 1
-#define RS_RACE 2
-#define RS_GENDER 3
+#define RS_NAME    0
+#define RS_ROLE    1
+#define RS_RACE    2
+#define RS_GENDER  3
 #define RS_ALGNMNT 4
-#define RS_filter 5
+#define RS_filter  5
 #define RS_menu_arg(x) (ROLE_RANDOM - ((x) + 1)) /* 0..5 -> -3..-8 */
 
 /* Choose_windows() may be called multiple times; these constants tell the
  * init function whether the window system is coming or going. */
-#define WININIT 0
+#define WININIT      0
 #define WININIT_UNDO 1
 
 #ifdef WINCHAIN
@@ -310,7 +281,9 @@ struct wc_Opt {
         nextdata is the Xprivate* for the next link in the chain
 */
 #define WINCHAIN_ALLOC 0
-#define WINCHAIN_INIT 1
+#define WINCHAIN_INIT  1
+
+/* clang-format on */
 
 #define CARGS void *
 
@@ -321,8 +294,7 @@ struct chain_procs {
                            * not start with '-'.  Names starting with
                            * '+' are reserved for processors. */
     unsigned long wincap; /* window port capability options supported */
-    unsigned long
-        wincap2; /* additional window port capability options supported */
+    unsigned long wincap2; /* additional window port capability options */
     void FDECL((*win_init_nhwindows), (CARGS, int *, char **));
     void FDECL((*win_player_selection), (CARGS));
     void FDECL((*win_askname), (CARGS));
@@ -383,17 +355,11 @@ struct chain_procs {
     void FDECL((*win_preference_update), (CARGS, const char *));
     char *FDECL((*win_getmsghistory), (CARGS, BOOLEAN_P));
     void FDECL((*win_putmsghistory), (CARGS, const char *, BOOLEAN_P));
-#ifdef STATUS_VIA_WINDOWPORT
     void FDECL((*win_status_init), (CARGS));
     void FDECL((*win_status_finish), (CARGS));
     void FDECL((*win_status_enablefield),
                (CARGS, int, const char *, const char *, BOOLEAN_P));
-    void FDECL((*win_status_update), (CARGS, int, genericptr_t, int, int));
-#ifdef STATUS_HILITES
-    void FDECL((*win_status_threshold),
-               (CARGS, int, int, anything, int, int, int));
-#endif
-#endif
+    void FDECL((*win_status_update), (CARGS, int, genericptr_t, int, int, int, unsigned long *));
     boolean FDECL((*win_can_suspend), (CARGS));
 };
 #endif /* WINCHAIN */
index 2469b5a..5db4c68 100644 (file)
@@ -221,13 +221,8 @@ E short FDECL(set_tty_font_name, (winid, char *));
 #endif
 E char *NDECL(tty_get_color_string);
 #endif
-#ifdef STATUS_VIA_WINDOWPORT
 E void NDECL(tty_status_init);
-E void FDECL(tty_status_update, (int, genericptr_t, int, int));
-#ifdef STATUS_HILITES
-E void FDECL(tty_status_threshold, (int, int, anything, int, int, int));
-#endif
-#endif
+E void FDECL(tty_status_update, (int, genericptr_t, int, int, int, unsigned long *));
 
 /* other defs that really should go away (they're tty specific) */
 E void NDECL(tty_start_screen);
index 960f652..3bb8234 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6  wintype.h       $NHDT-Date: 1433207914 2015/06/02 01:18:34 $  $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
+/* NetHack 3.6  wintype.h       $NHDT-Date: 1461028538 2016/04/19 01:15:38 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
 /* Copyright (c) David Cohrs, 1991                                */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -15,6 +15,7 @@ typedef union any {
     int a_int;
     char a_char;
     schar a_schar;
+    uchar a_uchar;
     unsigned int a_uint;
     long a_long;
     unsigned long a_ulong;
@@ -23,30 +24,33 @@ typedef union any {
     unsigned long *a_ulptr;
     unsigned *a_uptr;
     const char *a_string;
+    int NDECL((*a_nfunc));
+    unsigned long a_mask32; /* used by status highlighting */
     /* add types as needed */
 } anything;
 #define ANY_P union any /* avoid typedef in prototypes */
                         /* (buggy old Ultrix compiler) */
 
 /* symbolic names for the data types housed in anything */
-/* clang-format off */
-#define ANY_VOID         1
-#define ANY_OBJ          2      /* struct obj */
-#define ANY_MONST        3      /* struct monst (not used) */
-#define ANY_INT          4      /* int */
-#define ANY_CHAR         5      /* char */
-#define ANY_UCHAR        6      /* unsigned char */
-#define ANY_SCHAR        7      /* signed char */
-#define ANY_UINT         8      /* unsigned int */
-#define ANY_LONG         9      /* long */
-#define ANY_ULONG       10      /* unsigned long */
-#define ANY_IPTR        11      /* pointer to int */
-#define ANY_UPTR        12      /* pointer to unsigned int */
-#define ANY_LPTR        13      /* pointer to long */
-#define ANY_ULPTR       14      /* pointer to unsigned long */
-#define ANY_STR         15      /* pointer to null-terminated char string */
-#define ANY_MASK32      16      /* 32-bit mask (stored as unsigned long) */
-/* clang-format on */
+enum any_types {
+    ANY_VOID = 1,
+    ANY_OBJ,         /* struct obj */
+    ANY_MONST,       /* struct monst (not used) */
+    ANY_INT,         /* int */
+    ANY_CHAR,        /* char */
+    ANY_UCHAR,       /* unsigned char */
+    ANY_SCHAR,       /* signed char */
+    ANY_UINT,        /* unsigned int */
+    ANY_LONG,        /* long */
+    ANY_ULONG,       /* unsigned long */
+    ANY_IPTR,        /* pointer to int */
+    ANY_UPTR,        /* pointer to unsigned int */
+    ANY_LPTR,        /* pointer to long */
+    ANY_ULPTR,       /* pointer to unsigned long */
+    ANY_STR,         /* pointer to null-terminated char string */
+    ANY_NFUNC,       /* pointer to function taking no args, returning int */
+    ANY_MASK32       /* 32-bit mask (stored as unsigned long) */
+};
 
 /* menu return list */
 typedef struct mi {
@@ -56,6 +60,7 @@ typedef struct mi {
 #define MENU_ITEM_P struct mi
 
 /* select_menu() "how" argument types */
+/* [MINV_PICKMASK in monst.h assumes these have values of 0, 1, 2] */
 #define PICK_NONE 0 /* user picks nothing (display only) */
 #define PICK_ONE 1  /* only pick one */
 #define PICK_ANY 2  /* can pick any amount */
index e434f30..15fb5f9 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 you.h   $NHDT-Date: 1432512782 2015/05/25 00:13:02 $  $NHDT-Branch: master $:$NHDT-Revision: 1.29 $ */
+/* NetHack 3.6 you.h   $NHDT-Date: 1450231172 2015/12/16 01:59:32 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.30 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2016. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef YOU_H
@@ -27,9 +28,9 @@ struct RoleAdvance {
 };
 
 struct u_have {
-    Bitfield(amulet, 1);   /* carrying Amulet  */
-    Bitfield(bell, 1);     /* carrying Bell    */
-    Bitfield(book, 1);     /* carrying Book    */
+    Bitfield(amulet, 1);   /* carrying Amulet   */
+    Bitfield(bell, 1);     /* carrying Bell     */
+    Bitfield(book, 1);     /* carrying Book     */
     Bitfield(menorah, 1);  /* carrying Candelabrum */
     Bitfield(questart, 1); /* carrying the Quest Artifact */
     Bitfield(unused, 3);
@@ -68,18 +69,11 @@ struct u_achieve {
 };
 
 struct u_realtime {
-#if 0 /*C360-19*/
-    long
-        realtime; /* actual playing time up until the last restore, seconds */
-    time_t restored; /* time the game was started or restored */
-    time_t endtime;
-#else
     long   realtime;     /* accumulated playing time in seconds */
     time_t start_timing; /* time game was started or restored or 'realtime'
                             was last updated (savegamestate for checkpoint) */
     time_t finish_time;  /* end of 'realtime' interval: time of save or
                             end of game; used for topten/logfile/xlogfile */
-#endif
 };
 
 /* KMH, conduct --
@@ -131,16 +125,16 @@ struct Role {
     short questarti; /* index (ART_) of quest artifact (questpgr.c) */
 
     /*** Bitmasks ***/
-    short allow;             /* bit mask of allowed variations */
-#define ROLE_RACEMASK 0x0ff8 /* allowable races */
-#define ROLE_GENDMASK 0xf000 /* allowable genders */
-#define ROLE_MALE 0x1000
-#define ROLE_FEMALE 0x2000
-#define ROLE_NEUTER 0x4000
-#define ROLE_ALIGNMASK AM_MASK /* allowable alignments */
-#define ROLE_LAWFUL AM_LAWFUL
-#define ROLE_NEUTRAL AM_NEUTRAL
-#define ROLE_CHAOTIC AM_CHAOTIC
+    short allow;                  /* bit mask of allowed variations */
+#define ROLE_RACEMASK  0x0ff8     /* allowable races */
+#define ROLE_GENDMASK  0xf000     /* allowable genders */
+#define ROLE_MALE      0x1000
+#define ROLE_FEMALE    0x2000
+#define ROLE_NEUTER    0x4000
+#define ROLE_ALIGNMASK AM_MASK    /* allowable alignments */
+#define ROLE_LAWFUL    AM_LAWFUL
+#define ROLE_NEUTRAL   AM_NEUTRAL
+#define ROLE_CHAOTIC   AM_CHAOTIC
 
     /*** Attributes (from attrib.c and exper.c) ***/
     xchar attrbase[A_MAX];    /* lowest initial attributes */
@@ -209,9 +203,9 @@ struct Race {
     xchar attrmax[A_MAX];     /* maximum allowable attribute */
     struct RoleAdvance hpadv; /* hit point advancement */
     struct RoleAdvance enadv; /* energy advancement */
-#if 0                         /* DEFERRED */
-       int   nv_range;         /* night vision range */
-       int   xray_range;       /* X-ray vision range */
+#if 0 /* DEFERRED */
+    int   nv_range;           /* night vision range */
+    int   xray_range;         /* X-ray vision range */
 #endif
 
     /*** Properties in variable-length arrays ***/
@@ -238,14 +232,14 @@ struct Gender {
     const char *filecode; /* file code */
     short allow;          /* equivalent ROLE_ mask */
 };
-#define ROLE_GENDERS 2 /* number of permitted player genders */
-/* increment to 3 if you allow neuter roles */
+#define ROLE_GENDERS 2    /* number of permitted player genders
+                             increment to 3 if you allow neuter roles */
 
 extern const struct Gender genders[]; /* table of available genders */
-#define uhe() (genders[flags.female ? 1 : 0].he)
-#define uhim() (genders[flags.female ? 1 : 0].him)
-#define uhis() (genders[flags.female ? 1 : 0].his)
-#define mhe(mtmp) (genders[pronoun_gender(mtmp)].he)
+#define uhe()      (genders[flags.female ? 1 : 0].he)
+#define uhim()     (genders[flags.female ? 1 : 0].him)
+#define uhis()     (genders[flags.female ? 1 : 0].his)
+#define mhe(mtmp)  (genders[pronoun_gender(mtmp)].he)
 #define mhim(mtmp) (genders[pronoun_gender(mtmp)].him)
 #define mhis(mtmp) (genders[pronoun_gender(mtmp)].his)
 
@@ -257,33 +251,36 @@ struct Align {
     short allow;          /* equivalent ROLE_ mask */
     aligntyp value;       /* equivalent A_ value */
 };
-#define ROLE_ALIGNS 3 /* number of permitted player alignments */
+#define ROLE_ALIGNS 3     /* number of permitted player alignments */
 
 extern const struct Align aligns[]; /* table of available alignments */
 
+enum utraptypes {
+    TT_BEARTRAP = 0,
+    TT_PIT,
+    TT_WEB,
+    TT_LAVA,
+    TT_INFLOOR,
+    TT_BURIEDBALL
+};
+
 /*** Information about the player ***/
 struct you {
-    xchar ux, uy;
-    schar dx, dy, dz;  /* direction of move (or zap or ... ) */
-    schar di;          /* direction of FF */
-    xchar tx, ty;      /* destination of travel */
-    xchar ux0, uy0;    /* initial position FF */
-    d_level uz, uz0;   /* your level on this and the previous turn */
-    d_level utolev;    /* level monster teleported you to, or uz */
-    uchar utotype;     /* bitmask of goto_level() flags for utolev */
-    boolean umoved;    /* changed map location (post-move) */
-    int last_str_turn; /* 0: none, 1: half turn, 2: full turn */
-                       /* +: turn right, -: turn left */
-    int ulevel;        /* 1 to MAXULEV */
+    xchar ux, uy;       /* current map coordinates */
+    schar dx, dy, dz;   /* direction of move (or zap or ... ) */
+    schar di;           /* direction of FF */
+    xchar tx, ty;       /* destination of travel */
+    xchar ux0, uy0;     /* initial position FF */
+    d_level uz, uz0;    /* your level on this and the previous turn */
+    d_level utolev;     /* level monster teleported you to, or uz */
+    uchar utotype;      /* bitmask of goto_level() flags for utolev */
+    boolean umoved;     /* changed map location (post-move) */
+    int last_str_turn;  /* 0: none, 1: half turn, 2: full turn
+                           +: turn right, -: turn left */
+    int ulevel;         /* 1 to MAXULEV */
     int ulevelmax;
     unsigned utrap;     /* trap timeout */
-    unsigned utraptype; /* defined if utrap nonzero */
-#define TT_BEARTRAP 0
-#define TT_PIT 1
-#define TT_WEB 2
-#define TT_LAVA 3
-#define TT_INFLOOR 4
-#define TT_BURIEDBALL 5
+    unsigned utraptype; /* defined if utrap nonzero. one of utraptypes */
     char urooms[5];         /* rooms (roomno + 3) occupied now */
     char urooms0[5];        /* ditto, for previous position */
     char uentered[5];       /* rooms (roomno + 3) entered this turn */
@@ -317,16 +314,16 @@ struct you {
     int bc_order;     /* ball & chain order [see bc_order() in ball.c] */
     int bc_felt;      /* mask for ball/chain being felt */
 
-    int umonster; /* hero's "real" monster num */
-    int umonnum;  /* current monster number */
+    int umonster;               /* hero's "real" monster num */
+    int umonnum;                /* current monster number */
 
-    int mh, mhmax, mtimedone; /* for polymorph-self */
-    struct attribs macurr,    /* for monster attribs */
-        mamax;                /* for monster attribs */
-    int ulycn;                /* lycanthrope type */
+    int mh, mhmax, mtimedone;   /* for polymorph-self */
+    struct attribs macurr,      /* for monster attribs */
+                   mamax;       /* for monster attribs */
+    int ulycn;                  /* lycanthrope type */
 
     unsigned ucreamed;
-    unsigned uswldtim; /* time you have been swallowed */
+    unsigned uswldtim;          /* time you have been swallowed */
 
     Bitfield(uswallow, 1);      /* true if swallowed */
     Bitfield(uinwater, 1);      /* if you're currently in water (only
@@ -335,60 +332,62 @@ struct you {
     Bitfield(mfemale, 1);       /* saved human value of flags.female */
     Bitfield(uinvulnerable, 1); /* you're invulnerable (praying) */
     Bitfield(uburied, 1);       /* you're buried */
-    Bitfield(uedibility, 1); /* blessed food detection; sense unsafe food */
+    Bitfield(uedibility, 1);    /* blessed food detect; sense unsafe food */
     /* 1 free bit! */
 
-    unsigned udg_cnt;          /* how long you have been demigod */
-    struct u_achieve uachieve; /* achievements */
-    struct u_event uevent;     /* certain events have happened */
-    struct u_have uhave;       /* you're carrying special objects */
-    struct u_conduct uconduct; /* KMH, conduct */
+    unsigned udg_cnt;           /* how long you have been demigod */
+    struct u_achieve uachieve;  /* achievements */
+    struct u_event uevent;      /* certain events have happened */
+    struct u_have uhave;        /* you're carrying special objects */
+    struct u_conduct uconduct;  /* KMH, conduct */
     struct u_roleplay uroleplay;
-    struct attribs acurr, /* your current attributes (eg. str)*/
-        aexe,             /* for gain/loss via "exercise" */
-        abon,             /* your bonus attributes (eg. str) */
-        amax,             /* your max attributes (eg. str) */
-        atemp,            /* used for temporary loss/gain */
-        atime;            /* used for loss/gain countdown */
-    align ualign;         /* character alignment */
-#define CONVERT 2
+    struct attribs acurr,       /* your current attributes (eg. str)*/
+                    aexe,       /* for gain/loss via "exercise" */
+                    abon,       /* your bonus attributes (eg. str) */
+                    amax,       /* your max attributes (eg. str) */
+                   atemp,       /* used for temporary loss/gain */
+                   atime;       /* used for loss/gain countdown */
+    align ualign;               /* character alignment */
+#define CONVERT    2
 #define A_ORIGINAL 1
-#define A_CURRENT 0
+#define A_CURRENT  0
     aligntyp ualignbase[CONVERT]; /* for ualign conversion record */
     schar uluck, moreluck;        /* luck and luck bonus */
 #define Luck (u.uluck + u.moreluck)
-#define LUCKADD 3 /* added value when carrying luck stone */
-#define LUCKMAX 10
-#define LUCKMIN (-10)
+#define LUCKADD    3  /* value of u.moreluck when carrying luck stone;
+                         + when blessed or uncursed, - when cursed */
+#define LUCKMAX   10  /* maximum value of u.ulUck */
+#define LUCKMIN (-10) /* minimum value of u.uluck */
     schar uhitinc;
     schar udaminc;
     schar uac;
-    uchar uspellprot; /* protection by SPE_PROTECTION */
-    uchar usptime;    /* #moves until uspellprot-- */
-    uchar uspmtime;   /* #moves between uspellprot-- */
-    int uhp, uhpmax;
-    int uen, uenmax; /* magical energy - M. Stephenson */
-    xchar uhpinc[MAXULEV], ueninc[MAXULEV]; /* increases from level gain */
-    int ugangr;                             /* if the gods are angry at you */
-    int ugifts;                             /* number of artifacts bestowed */
-    int ublessed, ublesscnt;                /* blessing/duration from #pray */
+    uchar uspellprot;        /* protection by SPE_PROTECTION */
+    uchar usptime;           /* #moves until uspellprot-- */
+    uchar uspmtime;          /* #moves between uspellprot-- */
+    int uhp, uhpmax;         /* hit points, aka health */
+    int uen, uenmax;         /* magical energy - M. Stephenson */
+    xchar uhpinc[MAXULEV],   /* increases to uhpmax for each level gain */
+          ueninc[MAXULEV];   /* increases to uenmax for each level gain */
+    int ugangr;              /* if the gods are angry at you */
+    int ugifts;              /* number of artifacts bestowed */
+    int ublessed, ublesscnt; /* blessing/duration from #pray */
     long umoney0;
     long uspare1;
     long uexp, urexp;
-    long ucleansed; /* to record moves when player was cleansed */
-    long usleep;    /* sleeping; monstermove you last started */
+    long ucleansed;          /* to record moves when player was cleansed */
+    long usleep;             /* sleeping; monstermove you last started */
     int uinvault;
-    struct monst *ustuck;
-    struct monst *usteed;
-    long ugallop;
-    int urideturns;
-    int umortality;      /* how many times you died */
+    struct monst *ustuck;    /* engulfer or grabber, maybe grabbee if Upolyd */
+    struct monst *usteed;    /* mount when riding */
+    long ugallop;            /* turns steed will run after being kicked */
+    int urideturns;          /* time spent riding, for skill advancement */
+    int umortality;          /* how many times you died */
     int ugrave_arise;    /* you die and become something aside from a ghost */
-    int weapon_slots;    /* unused skill slots */
-    int skills_advanced; /* # of advances made so far */
+    int weapon_slots;        /* unused skill slots */
+    int skills_advanced;     /* # of advances made so far */
     xchar skill_record[P_SKILL_LIMIT]; /* skill advancements */
     struct skills weapon_skills[P_NUM_SKILLS];
-    boolean twoweap; /* KMH -- Using two-weapon combat */
+    boolean twoweap;         /* KMH -- Using two-weapon combat */
 
 }; /* end of `struct you' */
 
index 79fa70a..d71ec8b 100644 (file)
      && !BFlying)
 /* May touch surface; does not override any others */
 
-#define Wwalking (u.uprops[WWALKING].extrinsic && !Is_waterlevel(&u.uz))
+#define EWwalking u.uprops[WWALKING].extrinsic
+#define Wwalking (EWwalking && !Is_waterlevel(&u.uz))
 /* Don't get wet, can't go under water; overrides others except levitation */
 /* Wwalking is meaningless on water level */
 
index d553e13..9598dd2 100644 (file)
@@ -8,6 +8,6 @@
 /* JNetHack may be freely redistributed.  See license for details. */
 
 #define JVERSION_MAJOR 0
-#define JVERSION_MINOR 9
+#define JVERSION_MINOR 0
 #define JPATCHLEVEL    0
 #define JEDITLEVEL     0
index 3c54ceb..925f0a2 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 allmain.c       $NHDT-Date: 1446975459 2015/11/08 09:37:39 $  $NHDT-Branch: master $:$NHDT-Revision: 1.66 $ */
+/* NetHack 3.6 allmain.c       $NHDT-Date: 1518193644 2018/02/09 16:27:24 $  $NHDT-Branch: githash $:$NHDT-Revision: 1.86 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -18,6 +19,8 @@
 #ifdef POSITIONBAR
 STATIC_DCL void NDECL(do_positionbar);
 #endif
+STATIC_DCL void FDECL(regen_hp, (int));
+STATIC_DCL void FDECL(interrupt_multi, (const char *));
 
 void
 moveloop(resuming)
@@ -38,9 +41,6 @@ boolean resuming;
     monstr_init(); /* monster strengths */
     objects_init();
 
-    if (wizard)
-        add_debug_extended_commands();
-
     /* if a save file created in normal mode is now being restored in
        explore mode, treat it as normal restore followed by 'X' command
        to use up the save file and require confirmation for explore mode */
@@ -74,15 +74,12 @@ boolean resuming;
         context.rndencode = rnd(9000);
         set_wear((struct obj *) 0); /* for side-effects of starting gear */
         (void) pickup(1);      /* autopickup at initial location */
-    } else {                   /* restore old game */
-#ifndef WIN32
-        update_inventory(); /* for perm_invent */
-#endif
-        read_engr_at(u.ux, u.uy); /* subset of pickup() */
     }
-#ifdef WIN32
+    context.botlx = TRUE; /* for STATUS_HILITES */
     update_inventory(); /* for perm_invent */
-#endif
+    if (resuming) { /* restoring old game */
+        read_engr_at(u.ux, u.uy); /* subset of pickup() */
+    }
 
     (void) encumber_msg(); /* in case they auto-picked up something */
     if (defer_see_monsters) {
@@ -148,14 +145,13 @@ boolean resuming;
                         moveamt = youmonst.data->mmove;
 
                         if (Very_fast) { /* speed boots or potion */
-                            /* average movement is 1.67 times normal */
-                            moveamt += NORMAL_SPEED / 2;
-                            if (rn2(3) == 0)
-                                moveamt += NORMAL_SPEED / 2;
-                        } else if (Fast) {
-                            /* average movement is 1.33 times normal */
+                            /* gain a free action on 2/3 of turns */
                             if (rn2(3) != 0)
-                                moveamt += NORMAL_SPEED / 2;
+                                moveamt += NORMAL_SPEED;
+                        } else if (Fast) {
+                            /* gain a free action on 1/3 of turns */
+                            if (rn2(3) == 0)
+                                moveamt += NORMAL_SPEED;
                         }
                     }
 
@@ -202,60 +198,20 @@ boolean resuming;
 
                     /* One possible result of prayer is healing.  Whether or
                      * not you get healed depends on your current hit points.
-                     * If you are allowed to regenerate during the prayer, the
-                     * end-of-prayer calculation messes up on this.
+                     * If you are allowed to regenerate during the prayer,
+                     * the end-of-prayer calculation messes up on this.
                      * Another possible result is rehumanization, which
-                     * requires
-                     * that encumbrance and movement rate be recalculated.
+                     * requires that encumbrance and movement rate be
+                     * recalculated.
                      */
                     if (u.uinvulnerable) {
                         /* for the moment at least, you're in tiptop shape */
                         wtcap = UNENCUMBERED;
-                    } else if (Upolyd && youmonst.data->mlet == S_EEL
-                               && !is_pool(u.ux, u.uy)
-                               && !Is_waterlevel(&u.uz)) {
-                        /* eel out of water loses hp, same as for monsters;
-                           as hp gets lower, rate of further loss slows down
-                           */
-                        if (u.mh > 1 && rn2(u.mh) > rn2(8)
-                            && (!Half_physical_damage || !(moves % 2L))) {
-                            u.mh--;
-                            context.botl = 1;
-                        } else if (u.mh < 1)
-                            rehumanize();
-                    } else if (Upolyd && u.mh < u.mhmax) {
-                        if (u.mh < 1)
-                            rehumanize();
-                        else if (Regeneration
-                                 || (wtcap < MOD_ENCUMBER && !(moves % 20))) {
-                            context.botl = 1;
-                            u.mh++;
-                        }
-                    } else if (u.uhp < u.uhpmax
-                               && (wtcap < MOD_ENCUMBER || !u.umoved
-                                   || Regeneration)) {
-                        if (u.ulevel > 9 && !(moves % 3)) {
-                            int heal, Con = (int) ACURR(A_CON);
-
-                            if (Con <= 12) {
-                                heal = 1;
-                            } else {
-                                heal = rnd(Con);
-                                if (heal > u.ulevel - 9)
-                                    heal = u.ulevel - 9;
-                            }
-                            context.botl = 1;
-                            u.uhp += heal;
-                            if (u.uhp > u.uhpmax)
-                                u.uhp = u.uhpmax;
-                        } else if (Regeneration
-                                   || (u.ulevel <= 9
-                                       && !(moves
-                                            % ((MAXULEV + 12) / (u.ulevel + 2)
-                                               + 1)))) {
-                            context.botl = 1;
-                            u.uhp++;
-                        }
+                    } else if (!Upolyd ? (u.uhp < u.uhpmax)
+                                       : (u.mh < u.mhmax
+                                          || youmonst.data->mlet == S_EEL)) {
+                        /* maybe heal */
+                        regen_hp(wtcap);
                     }
 
                     /* moving around while encumbered is hard work */
@@ -277,7 +233,7 @@ boolean resuming;
                         }
                     }
 
-                    if ((u.uen < u.uenmax)
+                    if (u.uen < u.uenmax
                         && ((wtcap < MOD_ENCUMBER
                              && (!(moves % ((MAXULEV + 8 - u.ulevel)
                                             * (Role_if(PM_WIZARD) ? 3 : 4)
@@ -287,6 +243,8 @@ boolean resuming;
                         if (u.uen > u.uenmax)
                             u.uen = u.uenmax;
                         context.botl = 1;
+                        if (u.uen == u.uenmax)
+                            interrupt_multi("You feel full of energy.");
                     }
 
                     if (!u.uinvulnerable) {
@@ -313,10 +271,7 @@ boolean resuming;
                             change = 2;
                         if (change && !Unchanging) {
                             if (multi >= 0) {
-                                if (occupation)
-                                    stop_occupation();
-                                else
-                                    nomul(0);
+                                stop_occupation();
                                 if (change == 1)
                                     polyself(0);
                                 else
@@ -328,6 +283,9 @@ boolean resuming;
 
                     if (Searching && multi >= 0)
                         (void) dosearch0(1);
+                    if (Warning)
+                        warnreveal();
+                    mkot_trap_warn();
                     dosounds();
                     do_storms();
                     gethungry();
@@ -375,11 +333,12 @@ boolean resuming;
             /* once-per-hero-took-time things go here */
             /******************************************/
 
+            status_eval_next_unhilite();
             if (context.bypasses)
                 clear_bypasses();
             if ((u.uhave.amulet || Clairvoyant) && !In_endgame(&u.uz)
                 && !BClairvoyant && !(moves % 15) && !rn2(2))
-                do_vicinity_map();
+                do_vicinity_map((struct obj *) 0);
             if (u.utrap && u.utraptype == TT_LAVA)
                 sink_into_lava();
             /* when/if hero escapes from lava, he can't just stay there */
@@ -498,6 +457,76 @@ boolean resuming;
     }
 }
 
+/* maybe recover some lost health (or lose some when an eel out of water) */
+STATIC_OVL void
+regen_hp(wtcap)
+int wtcap;
+{
+    int heal = 0;
+    boolean reached_full = FALSE,
+            encumbrance_ok = (wtcap < MOD_ENCUMBER || !u.umoved);
+
+    if (Upolyd) {
+        if (u.mh < 1) { /* shouldn't happen... */
+            rehumanize();
+        } else if (youmonst.data->mlet == S_EEL
+                   && !is_pool(u.ux, u.uy) && !Is_waterlevel(&u.uz)) {
+            /* eel out of water loses hp, similar to monster eels;
+               as hp gets lower, rate of further loss slows down */
+            if (u.mh > 1 && !Regeneration && rn2(u.mh) > rn2(8)
+                && (!Half_physical_damage || !(moves % 2L)))
+                heal = -1;
+        } else if (u.mh < u.mhmax) {
+            if (Regeneration || (encumbrance_ok && !(moves % 20L)))
+                heal = 1;
+        }
+        if (heal) {
+            context.botl = 1;
+            u.mh += heal;
+            reached_full = (u.mh == u.mhmax);
+        }
+
+    /* !Upolyd */
+    } else {
+        /* [when this code was in-line within moveloop(), there was
+           no !Upolyd check here, so poly'd hero recovered lost u.uhp
+           once u.mh reached u.mhmax; that may have been convenient
+           for the player, but it didn't make sense for gameplay...] */
+        if (u.uhp < u.uhpmax && (encumbrance_ok || Regeneration)) {
+            if (u.ulevel > 9) {
+                if (!(moves % 3L)) {
+                    int Con = (int) ACURR(A_CON);
+
+                    if (Con <= 12) {
+                        heal = 1;
+                    } else {
+                        heal = rnd(Con);
+                        if (heal > u.ulevel - 9)
+                            heal = u.ulevel - 9;
+                    }
+                }
+            } else { /* u.ulevel <= 9 */
+                if (!(moves % (long) ((MAXULEV + 12) / (u.ulevel + 2) + 1)))
+                    heal = 1;
+            }
+            if (Regeneration && !heal)
+                heal = 1;
+
+            if (heal) {
+                context.botl = 1;
+                u.uhp += heal;
+                if (u.uhp > u.uhpmax)
+                    u.uhp = u.uhpmax;
+                /* stop voluntary multi-turn activity if now fully healed */
+                reached_full = (u.uhp == u.uhpmax);
+            }
+        }
+    }
+
+    if (reached_full)
+        interrupt_multi("You are in full health.");
+}
+
 void
 stop_occupation()
 {
@@ -511,6 +540,8 @@ stop_occupation()
         context.botl = 1; /* in case u.uhs changed */
         nomul(0);
         pushch(0);
+    } else if (multi >= 0) {
+        nomul(0);
     }
 }
 
@@ -518,13 +549,16 @@ void
 display_gamewindows()
 {
     WIN_MESSAGE = create_nhwindow(NHW_MESSAGE);
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
     status_initialize(0);
 #else
     WIN_STATUS = create_nhwindow(NHW_STATUS);
 #endif
     WIN_MAP = create_nhwindow(NHW_MAP);
     WIN_INVEN = create_nhwindow(NHW_MENU);
+    /* in case of early quit where WIN_INVEN could be destroyed before
+       ever having been used, use it here to pacify the Qt interface */
+    start_menu(WIN_INVEN), end_menu(WIN_INVEN, (char *) 0);
 
 #ifdef MAC
     /* This _is_ the right place for this - maybe we will
@@ -539,7 +573,7 @@ display_gamewindows()
      * The mac port is not DEPENDENT on the order of these
      * displays, but it looks a lot better this way...
      */
-#ifndef STATUS_VIA_WINDOWPORT
+#ifndef STATUS_HILITES
     display_nhwindow(WIN_STATUS, FALSE);
 #endif
     display_nhwindow(WIN_MESSAGE, FALSE);
@@ -564,7 +598,7 @@ newgame()
     context.tribute.enabled = TRUE;   /* turn on 3.6 tributes    */
     context.tribute.tributesz = sizeof(struct tribute_info);
 
-    for (i = 0; i < NUMMONS; i++)
+    for (i = LOW_PM; i < NUMMONS; i++)
         mvitals[i].mvflags = mons[i].geno & G_NOCORPSE;
 
     init_objects(); /* must be before u_init() */
@@ -607,24 +641,13 @@ newgame()
         com_pager(1);
     }
 
-#if 1 /*C360-19*/
     urealtime.realtime = 0L;
     urealtime.start_timing = getnow();
-#endif
 #ifdef INSURANCE
     save_currentstate();
 #endif
     program_state.something_worth_saving++; /* useful data now exists */
 
-#if 0 /*C360-19*/
-    urealtime.realtime = 0L;
-#if defined(BSD) && !defined(POSIX_TYPES)
-    (void) time((long *) &urealtime.restored);
-#else
-    (void) time(&urealtime.restored);
-#endif
-
-#endif
     /* Success! */
     welcome(TRUE);
     return;
@@ -638,6 +661,13 @@ boolean new_game; /* false => restoring an old game */
     char buf[BUFSZ];
     boolean currentgend = Upolyd ? u.mfemale : flags.female;
 
+    /* skip "welcome back" if restoring a doomed character */
+    if (!new_game && Upolyd && ugenocided()) {
+        /* death via self-genocide is pending */
+        pline("You're back, but you still feel %s inside.", udeadinside());
+        return;
+    }
+
     /*
      * The "welcome back" message always describes your innate form
      * even when polymorphed or wearing a helm of opposite alignment.
@@ -736,4 +766,99 @@ do_positionbar()
 }
 #endif
 
+STATIC_DCL void
+interrupt_multi(msg)
+const char *msg;
+{
+    if (multi > 0 && !context.travel && !context.run) {
+        nomul(0);
+        if (flags.verbose && msg)
+            Norep("%s", msg);
+    }
+}
+
+/*
+ * Argument processing helpers - for xxmain() to share
+ * and call.
+ *
+ * These should return TRUE if the argument matched,
+ * whether the processing of the argument was
+ * successful or not.
+ *
+ * Most of these do their thing, then after returning
+ * to xxmain(), the code exits without starting a game.
+ *
+ */
+
+static struct early_opt earlyopts[] = {
+    {ARG_DEBUG, "debug", 5, FALSE},
+    {ARG_VERSION, "version", 4, TRUE},
+};
+
+boolean
+argcheck(argc, argv, e_arg)
+int argc;
+char *argv[];
+enum earlyarg e_arg;
+{
+    int i, idx;
+    boolean match = FALSE;
+    char *userea = (char *)0;
+    const char *dashdash = "";
+
+    for (idx = 0; idx < SIZE(earlyopts); idx++) {
+        if (earlyopts[idx].e == e_arg)
+            break;
+    }
+    if ((idx >= SIZE(earlyopts)) || (argc <= 1))
+            return FALSE;
+
+    for (i = 1; i < argc; ++i) {
+        if (argv[i][0] != '-')
+            continue;
+        if (argv[i][1] == '-') {
+            userea = &argv[i][2];
+            dashdash = "-";
+        } else {
+            userea = &argv[i][1];
+        }
+        match = match_optname(userea, earlyopts[idx].name,
+                    earlyopts[idx].minlength, earlyopts[idx].valallowed);
+        if (match) break;
+    }
+
+    if (match) {
+        switch(e_arg) {
+            case ARG_DEBUG:
+                        break;
+            case ARG_VERSION: {
+                        boolean insert_into_pastebuf = FALSE;
+                        const char *extended_opt = index(userea,':');
+
+                        if (!extended_opt)
+                            extended_opt = index(userea, '=');
+
+                        if (extended_opt) {
+                            extended_opt++;
+                            if (match_optname(extended_opt, "paste",
+                                                   5, FALSE)) {
+                                insert_into_pastebuf = TRUE;
+                            } else {
+                                raw_printf(
+                     "-%sversion can only be extended with -%sversion:paste.\n",
+                                            dashdash, dashdash);
+                                return TRUE;
+                           }
+                       }
+                        early_version_info(insert_into_pastebuf);
+                        return TRUE;
+                        break;
+            }
+            default:
+                        break;
+        }
+    };
+    return FALSE;
+}
+
 /*allmain.c*/
index 2d51fc7..c6944ab 100644 (file)
@@ -1,12 +1,12 @@
-/* NetHack 3.6 alloc.c $NHDT-Date: 1446975460 2015/11/08 09:37:40 $  $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */
+/* NetHack 3.6 alloc.c $NHDT-Date: 1454376505 2016/02/02 01:28:25 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* to get the malloc() prototype from system.h */
 #define ALLOC_C /* comment line for pre-compiled headers */
 /* since this file is also used in auxiliary programs, don't include all the
- * function declarations for all of nethack
- */
+   function declarations for all of nethack */
 #define EXTERN_H /* comment line for pre-compiled headers */
 #include "config.h"
 
@@ -23,9 +23,7 @@ static boolean tried_heaplog = FALSE;
 #endif
 
 long *FDECL(alloc, (unsigned int));
-extern void
-VDECL(panic, (const char *, ...))
-PRINTF_F(1, 2);
+extern void VDECL(panic, (const char *, ...)) PRINTF_F(1, 2);
 
 long *
 alloc(lth)
index 0ab5920..c6f0000 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 apply.c $NHDT-Date: 1446808436 2015/11/06 11:13:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.210 $ */
+/* NetHack 3.6 apply.c $NHDT-Date: 1519598527 2018/02/25 22:42:07 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.243 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -17,13 +18,13 @@ STATIC_DCL boolean FDECL(its_dead, (int, int, int *));
 STATIC_DCL int FDECL(use_stethoscope, (struct obj *));
 STATIC_DCL void FDECL(use_whistle, (struct obj *));
 STATIC_DCL void FDECL(use_magic_whistle, (struct obj *));
-STATIC_DCL void FDECL(use_leash, (struct obj *));
+STATIC_DCL int FDECL(use_leash, (struct obj *));
 STATIC_DCL int FDECL(use_mirror, (struct obj *));
 STATIC_DCL void FDECL(use_bell, (struct obj **));
 STATIC_DCL void FDECL(use_candelabrum, (struct obj *));
 STATIC_DCL void FDECL(use_candle, (struct obj **));
 STATIC_DCL void FDECL(use_lamp, (struct obj *));
-STATIC_DCL void FDECL(light_cocktail, (struct obj *));
+STATIC_DCL void FDECL(light_cocktail, (struct obj **));
 STATIC_PTR void FDECL(display_jump_positions, (int));
 STATIC_DCL void FDECL(use_tinning_kit, (struct obj *));
 STATIC_DCL void FDECL(use_figurine, (struct obj **));
@@ -41,7 +42,10 @@ STATIC_DCL boolean FDECL(figurine_location_checks, (struct obj *,
                                                     coord *, BOOLEAN_P));
 STATIC_DCL void FDECL(add_class, (char *, CHAR_P));
 STATIC_DCL void FDECL(setapplyclasses, (char *));
+STATIC_PTR boolean FDECL(check_jump, (genericptr_t, int, int));
 STATIC_DCL boolean FDECL(is_valid_jump_pos, (int, int, int, BOOLEAN_P));
+STATIC_DCL boolean FDECL(get_valid_jump_position, (int, int));
+STATIC_DCL boolean FDECL(get_valid_polearm_position, (int, int));
 STATIC_DCL boolean FDECL(find_poleable_mon, (coord *, int, int));
 
 #ifdef AMIGA
@@ -314,6 +318,13 @@ int rx, ry, *resp;
     } else if (corpse) {
         boolean here = (rx == u.ux && ry == u.uy),
                 one = (corpse->quan == 1L && !more_corpses), reviver = FALSE;
+        int visglyph, corpseglyph;
+
+        visglyph = glyph_at(rx, ry);
+        corpseglyph = obj_to_glyph(corpse);
+
+        if (Blind && (visglyph != corpseglyph))
+            map_object(corpse, TRUE);
 
         if (Role_if(PM_HEALER)) {
             /* ok to reset `corpse' here; we're done with it */
@@ -432,6 +443,8 @@ register struct obj *obj;
     context.stethoscope_move = moves;
     context.stethoscope_movement = youmonst.movement;
 
+    bhitpos.x = u.ux, bhitpos.y = u.uy; /* tentative, reset below */
+    notonhead = u.uswallow;
     if (u.usteed && u.dz > 0) {
         if (interference) {
 /*JP
@@ -499,6 +512,10 @@ register struct obj *obj;
         const char *mnm = x_monnam(mtmp, ARTICLE_A, (const char *) 0,
                                    SUPPRESS_IT | SUPPRESS_INVISIBLE, FALSE);
 
+        /* bhitpos needed by mstatusline() iff mtmp is a long worm */
+        bhitpos.x = rx, bhitpos.y = ry;
+        notonhead = (mtmp->mx != rx || mtmp->my != ry);
+
         if (mtmp->mundetected) {
             if (!canspotmon(mtmp))
 /*JP
@@ -523,7 +540,7 @@ register struct obj *obj;
             }
             seemimic(mtmp);
 /*JP
-            pline("That %s is really %s", what, mnm);
+            pline("That %s is really %s.", what, mnm);
 */
             pline("\82±\82Ì%s\82Í\8eÀ\8dÛ\82É\82Í%s\81D", what, mnm);
         } else if (flags.verbose && !canspotmon(mtmp)) {
@@ -532,19 +549,18 @@ register struct obj *obj;
 */
             pline("\82±\82±\82É\82Í%s\82ª\82¢\82é\81D", mnm);
         }
+
         mstatusline(mtmp);
         if (!canspotmon(mtmp))
             map_invisible(rx, ry);
         return res;
     }
-    if (glyph_is_invisible(levl[rx][ry].glyph)) {
-        unmap_object(rx, ry);
-        newsym(rx, ry);
+    if (unmap_invisible(rx,ry))
 /*JP
         pline_The("invisible monster must have moved.");
 */
         pline_The("\8c©\82¦\82È\82¢\89ö\95¨\82Í\88Ú\93®\82µ\82Ä\82µ\82Ü\82Á\82½\82æ\82¤\82¾\81D");
-    }
+
     lev = &levl[rx][ry];
     switch (lev->typ) {
     case SDOOR:
@@ -595,11 +611,17 @@ struct obj *obj;
 */
         You("%s\82ð\92Ê\82µ\82Ä\96A\82ð\8fo\82µ\82½\81D", xname(obj));
     } else {
+        if (Deaf)
+            You_feel("rushing air tickle your %s.",
+                        body_part(NOSE));
+        else
 /*JP
         You(whistle_str, obj->cursed ? "shrill" : "high");
 */
         You(whistle_str, obj->cursed ? "\95s\8bC\96¡\82È" : "\82©\82ñ\8d\82\82¢");
         wake_nearby();
+        if (obj->cursed)
+            vault_summon_gd();
     }
 }
 
@@ -744,6 +766,10 @@ unleash_all()
 
 #define MAXLEASHED 2
 
+/* TODO:
+ *  This ought to exclude various other things, such as lights and gas
+ *  spore, is_whirly() critters, ethereal creatures, possibly others.
+ */
 static boolean
 leashable(mtmp)
 struct monst *mtmp;
@@ -752,26 +778,40 @@ struct monst *mtmp;
 }
 
 /* ARGSUSED */
-STATIC_OVL void
+STATIC_OVL int
 use_leash(obj)
 struct obj *obj;
 {
     coord cc;
-    register struct monst *mtmp;
+    struct monst *mtmp;
     int spotmon;
 
+    if (u.uswallow) {
+        /* if the leash isn't in use, assume we're trying to leash
+           the engulfer; if it is use, distinguish between removing
+           it from the engulfer versus from some other creature
+           (note: the two in-use cases can't actually occur; all
+           leashes are released when the hero gets engulfed) */
+        You_cant((!obj->leashmon
+                  ? "leash %s from inside."
+                  : (obj->leashmon == (int) u.ustuck->m_id)
+                    ? "unleash %s from inside."
+                    : "unleash anything from inside %s."),
+                 noit_mon_nam(u.ustuck));
+        return 0;
+    }
     if (!obj->leashmon && number_leashed() >= MAXLEASHED) {
 /*JP
         You("cannot leash any more pets.");
 */
         You("\82±\82ê\88È\8fã\83y\83b\83g\82É\95R\82ð\82©\82¯\82ç\82ê\82È\82¢\81D");
-        return;
+        return 0;
     }
 
     if (!get_adjacent_loc((char *) 0, (char *) 0, u.ux, u.uy, &cc))
-        return;
+        return 0;
 
-    if ((cc.x == u.ux) && (cc.y == u.uy)) {
+    if (cc.x == u.ux && cc.y == u.uy) {
         if (u.usteed && u.dz > 0) {
             mtmp = u.usteed;
             spotmon = 1;
@@ -781,48 +821,51 @@ struct obj *obj;
         pline("Leash yourself?  Very funny...");
 */
         pline("\8e©\95ª\82ð\94\9b\82é\81H\95Ï\82È\82Ì\81D\81D\81D");
-        return;
+        return 0;
     }
 
+    /*
+     * From here on out, return value is 1 == a move is used.
+     */
+
     if (!(mtmp = m_at(cc.x, cc.y))) {
 /*JP
         There("is no creature there.");
 */
         pline("\82»\82±\82É\82Í\90\82«\95¨\82Í\82¢\82È\82¢\81D");
-        return;
+        (void) unmap_invisible(cc.x, cc.y);
+        return 1;
     }
 
     spotmon = canspotmon(mtmp);
-got_target:
-
-    if (!mtmp->mtame) {
-        if (!spotmon)
-/*JP
-            There("is no creature there.");
-*/
-            pline("\82»\82±\82É\82Í\90\82«\95¨\82Í\82¢\82È\82¢\81D");
-        else
+ got_target:
+
+    if (!spotmon && !glyph_is_invisible(levl[cc.x][cc.y].glyph)) {
+        /* for the unleash case, we don't verify whether this unseen
+           monster is the creature attached to the current leash */
+        You("fail to %sleash something.", obj->leashmon ? "un" : "");
+        /* trying again will work provided the monster is tame
+           (and also that it doesn't change location by retry time) */
+        map_invisible(cc.x, cc.y);
+    } else if (!mtmp->mtame) {
 #if 0 /*JP*/
-            pline("%s %s leashed!", Monnam(mtmp),
-                  (!obj->leashmon) ? "cannot be" : "is not");
+        pline("%s %s leashed!", Monnam(mtmp),
+              (!obj->leashmon) ? "cannot be" : "is not");
 #else
-          pline("%s\82Í\95R\82Å%s\81I", Monnam(mtmp),
-                  (!obj->leashmon) ? "\8c\8b\82×\82È\82¢" : "\8c\8b\82Î\82ê\82Ä\82¢\82È\82¢");
+        pline("%s\82Í\95R\82Å%s\81I", Monnam(mtmp),
+              (!obj->leashmon) ? "\8c\8b\82×\82È\82¢" : "\8c\8b\82Î\82ê\82Ä\82¢\82È\82¢");
 #endif
-        return;
-    }
-    if (!obj->leashmon) {
+    } else if (!obj->leashmon) {
+        /* applying a leash which isn't currently in use */
         if (mtmp->mleashed) {
 #if 0 /*JP*/
             pline("This %s is already leashed.",
-                  spotmon ? l_monnam(mtmp) : "monster");
+                  spotmon ? l_monnam(mtmp) : "creature");
 #else
             pline("%s\82Í\82·\82Å\82É\8c\8b\82Ñ\82Â\82¯\82ç\82ê\82Ä\82¢\82é\81D",
                   spotmon ? l_monnam(mtmp) : "\89ö\95¨");
 #endif
-            return;
-        }
-        if (!leashable(mtmp)) {
+        } else if (!leashable(mtmp)) {
 #if 0 /*JP*/
             pline("The leash won't fit onto %s%s.", spotmon ? "your " : "",
                   l_monnam(mtmp));
@@ -830,47 +873,44 @@ got_target:
             pline("\95R\82Í%s\82É\8d\87\82í\82È\82¢\81D",
                   l_monnam(mtmp));
 #endif
-            return;
-        }
-
+        } else {
 #if 0 /*JP*/
-        You("slip the leash around %s%s.", spotmon ? "your " : "",
-            l_monnam(mtmp));
+            You("slip the leash around %s%s.", spotmon ? "your " : "",
+                l_monnam(mtmp));
 #else
-        You("%s\82ð\95R\82Å\8c\8b\82Ñ\82Â\82¯\82½\81D",
-            l_monnam(mtmp));
+            You("%s\82ð\95R\82Å\8c\8b\82Ñ\82Â\82¯\82½\81D",
+                l_monnam(mtmp));
 #endif
-        mtmp->mleashed = 1;
-        obj->leashmon = (int) mtmp->m_id;
-        mtmp->msleeping = 0;
-        return;
-    }
-    if (obj->leashmon != (int) mtmp->m_id) {
+            mtmp->mleashed = 1;
+            obj->leashmon = (int) mtmp->m_id;
+            mtmp->msleeping = 0;
+        }
+    } else {
+        /* applying a leash which is currently in use */
+        if (obj->leashmon != (int) mtmp->m_id) {
 /*JP
         pline("This leash is not attached to that creature.");
 */
         pline("\82±\82Ì\95R\82Í\82»\82ê\82É\82Í\8c\8b\82Î\82ê\82Ä\82¢\82È\82¢\81D");
-        return;
-    } else {
-        if (obj->cursed) {
+        } else if (obj->cursed) {
 /*JP
             pline_The("leash would not come off!");
 */
             pline("\95R\82ª\82Í\82¸\82ê\82È\82¢\81I");
-            obj->bknown = TRUE;
-            return;
-        }
-        mtmp->mleashed = 0;
-        obj->leashmon = 0;
+            obj->bknown = 1;
+        } else {
+            mtmp->mleashed = 0;
+            obj->leashmon = 0;
 #if 0 /*JP*/
-        You("remove the leash from %s%s.", spotmon ? "your " : "",
-            l_monnam(mtmp));
+            You("remove the leash from %s%s.",
+                spotmon ? "your " : "", l_monnam(mtmp));
 #else
-        You("%s\82©\82ç\95R\82ð\82Í\82¸\82µ\82½\81D",
-            l_monnam(mtmp));
+            You("%s\82©\82ç\95R\82ð\82Í\82¸\82µ\82½\81D",
+                l_monnam(mtmp));
 #endif
+        }
     }
-    return;
+    return 1;
 }
 
 /* assuming mtmp->mleashed has been checked */
@@ -963,7 +1003,7 @@ register xchar x, y;
                        that's the result of his actions; gain experience,
                        lose pacifism, take alignment and luck hit, make
                        corpse less likely to remain tame after revival */
-                    xkilled(mtmp, 0); /* no "you kill it" message */
+                    xkilled(mtmp, XKILL_NOMSG);
                     /* life-saving doesn't ordinarily reset this */
                     if (mtmp->mhp > 0)
                         u.uconduct.killer = save_pacifism;
@@ -1023,8 +1063,6 @@ beautiful()
 #endif
 }
 
-#define WEAK 3 /* from eat.c */
-
 /*JP
 static const char look_str[] = "look %s.";
 */
@@ -1640,6 +1678,9 @@ struct obj **optr;
             end_burn(obj, TRUE);
         /* candles are now gone */
         useupall(obj);
+        /* candelabrum's weight is changing */
+        otmp->owt = weight(otmp);
+        update_inventory();
     }
 }
 
@@ -1834,9 +1875,10 @@ struct obj *obj;
 }
 
 STATIC_OVL void
-light_cocktail(obj)
-struct obj *obj; /* obj is a potion of oil */
+light_cocktail(optr)
+struct obj **optr;
 {
+    struct obj *obj = *optr; /* obj is a potion of oil */
     char buf[BUFSZ];
     boolean split1off;
 
@@ -1857,7 +1899,7 @@ struct obj *obj; /* obj is a potion of oil */
          * but its easy.
          */
         freeinv(obj);
-        (void) addinv(obj);
+        *optr = addinv(obj);
         return;
     } else if (Underwater) {
 /*JP
@@ -1904,6 +1946,7 @@ struct obj *obj; /* obj is a potion of oil */
         if (obj)
             obj->nomerge = 0;
     }
+    *optr = obj;
 }
 
 static NEARDATA const char cuddly[] = { TOOL_CLASS, GEM_CLASS, 0 };
@@ -1975,7 +2018,48 @@ dojump()
     return jump(0);
 }
 
-boolean
+enum jump_trajectory {
+    jAny  = 0, /* any direction => magical jump */
+    jHorz = 1,
+    jVert = 2,
+    jDiag = 3  /* jHorz|jVert */
+};
+
+/* callback routine for walk_path() */
+STATIC_PTR boolean
+check_jump(arg, x, y)
+genericptr arg;
+int x, y;
+{
+    int traj = *(int *) arg;
+    struct rm *lev = &levl[x][y];
+
+    if (Passes_walls)
+        return TRUE;
+    if (IS_STWALL(lev->typ))
+        return FALSE;
+    if (IS_DOOR(lev->typ)) {
+        if (closed_door(x, y))
+            return FALSE;
+        if ((lev->doormask & D_ISOPEN) != 0 && traj != jAny
+            /* reject diagonal jump into or out-of or through open door */
+            && (traj == jDiag
+                /* reject horizontal jump through horizontal open door
+                   and non-horizontal (ie, vertical) jump through
+                   non-horizontal (vertical) open door */
+                || ((traj & jHorz) != 0) == (lev->horizontal != 0)))
+            return FALSE;
+        /* empty doorways aren't restricted */
+    }
+    /* let giants jump over boulders (what about Flying?
+       and is there really enough head room for giants to jump
+       at all, let alone over something tall?) */
+    if (sobj_at(BOULDER, x, y) && !throws_rocks(youmonst.data))
+        return FALSE;
+    return TRUE;
+}
+
+STATIC_OVL boolean
 is_valid_jump_pos(x, y, magic, showmsg)
 int x, y, magic;
 boolean showmsg;
@@ -1997,26 +2081,75 @@ boolean showmsg;
 */
             pline("\89\93\82·\82¬\82é\81I");
         return FALSE;
-    } else if (!cansee(x, y)) {
+    } else if (!isok(x, y)) {
         if (showmsg)
 /*JP
-            You("cannot see where to land!");
+            You("cannot jump there!");
 */
-            You("\92\85\92n\93_\82ª\8c©\82¦\82È\82¢\81I");
+            You("\82»\82±\82É\82Í\94ò\82×\82È\82¢\81I");
         return FALSE;
-    } else if (!isok(x, y)) {
+    } else if (!cansee(x, y)) {
         if (showmsg)
 /*JP
-            You("cannot jump there!");
+            You("cannot see where to land!");
 */
-            You("\82»\82±\82É\82Í\94ò\82×\82È\82¢\81I");
+            You("\92\85\92n\93_\82ª\8c©\82¦\82È\82¢\81I");
         return FALSE;
+    } else {
+        coord uc, tc;
+        struct rm *lev = &levl[u.ux][u.uy];
+        /* we want to categorize trajectory for use in determining
+           passage through doorways: horizonal, vertical, or diagonal;
+           since knight's jump and other irregular directions are
+           possible, we flatten those out to simplify door checks */
+        int diag, traj,
+            dx = x - u.ux, dy = y - u.uy,
+            ax = abs(dx), ay = abs(dy);
+
+        /* diag: any non-orthogonal destination classifed as diagonal */
+        diag = (magic || Passes_walls || (!dx && !dy)) ? jAny
+               : !dy ? jHorz : !dx ? jVert : jDiag;
+        /* traj: flatten out the trajectory => some diagonals re-classified */
+        if (ax >= 2 * ay)
+            ay = 0;
+        else if (ay >= 2 * ax)
+            ax = 0;
+        traj = (magic || Passes_walls || (!ax && !ay)) ? jAny
+               : !ay ? jHorz : !ax ? jVert : jDiag;
+        /* walk_path doesn't process the starting spot;
+           this is iffy:  if you're starting on a closed door spot,
+           you _can_ jump diagonally from doorway (without needing
+           Passes_walls); that's intentional but is it correct? */
+        if (diag == jDiag && IS_DOOR(lev->typ)
+            && (lev->doormask & D_ISOPEN) != 0
+            && (traj == jDiag
+                || ((traj & jHorz) != 0) == (lev->horizontal != 0))) {
+            if (showmsg)
+                You_cant("jump diagonally out of a doorway.");
+            return FALSE;
+        }
+        uc.x = u.ux, uc.y = u.uy;
+        tc.x = x, tc.y = y; /* target */
+        if (!walk_path(&uc, &tc, check_jump, (genericptr_t) &traj)) {
+            if (showmsg)
+                There("is an obstacle preventing that jump.");
+            return FALSE;
+        }
     }
     return TRUE;
 }
 
 static int jumping_is_magic;
 
+STATIC_OVL boolean
+get_valid_jump_position(x,y)
+int x,y;
+{
+    return (isok(x, y)
+            && (ACCESSIBLE(levl[x][y].typ) || Passes_walls)
+            && is_valid_jump_pos(x, y, jumping_is_magic, FALSE));
+}
+
 void
 display_jump_positions(state)
 int state;
@@ -2030,8 +2163,7 @@ int state;
             for (dy = -4; dy <= 4; dy++) {
                 x = dx + (int) u.ux;
                 y = dy + (int) u.uy;
-                if (isok(x, y) && ACCESSIBLE(levl[x][y].typ)
-                    && is_valid_jump_pos(x, y, jumping_is_magic, FALSE))
+                if (get_valid_jump_position(x, y))
                     tmp_at(x, y);
             }
     } else {
@@ -2045,6 +2177,17 @@ int magic; /* 0=Physical, otherwise skill level */
 {
     coord cc;
 
+    /* attempt "jumping" spell if hero has no innate jumping ability */
+    if (!magic && !Jumping) {
+        int sp_no;
+
+        for (sp_no = 0; sp_no < MAXSPELL; ++sp_no)
+            if (spl_book[sp_no].sp_id == NO_SPELL)
+                break;
+            else if (spl_book[sp_no].sp_id == SPE_JUMPING)
+                return spelleffects(sp_no, FALSE);
+    }
+
     if (!magic && (nolimbs(youmonst.data) || slithy(youmonst.data))) {
         /* normally (nolimbs || slithy) implies !Jumping,
            but that isn't necessarily the case for knights */
@@ -2173,7 +2316,7 @@ int magic; /* 0=Physical, otherwise skill level */
     cc.x = u.ux;
     cc.y = u.uy;
     jumping_is_magic = magic;
-    getpos_sethilite(display_jump_positions);
+    getpos_sethilite(display_jump_positions, get_valid_jump_position);
 /*JP
     if (getpos(&cc, TRUE, "the desired position") < 0)
 */
@@ -2217,9 +2360,9 @@ int magic; /* 0=Physical, otherwise skill level */
                 break;
             case TT_LAVA:
 /*JP
-                You("pull yourself above the lava!");
+                You("pull yourself above the %s!", hliquid("lava"));
 */
-                You("\97n\8aâ\82©\82ç\94ò\82Ñ\8fo\82½\81I");
+                You("%s\82©\82ç\94ò\82Ñ\8fo\82½\81I", hliquid("\97n\8aâ"));
                 u.utrap = 0;
                 return 1;
             case TT_BURIEDBALL:
@@ -2258,8 +2401,12 @@ int magic; /* 0=Physical, otherwise skill level */
             temp = -temp;
         if (range < temp)
             range = temp;
-        (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range);
-        teleds(cc.x, cc.y, TRUE);
+        (void) walk_path(&uc, &cc, hurtle_jump, (genericptr_t) &range);
+        /* hurtle_jump -> hurtle_step results in <u.ux,u.uy> == <cc.x,cc.y>
+         * and usually moves the ball if punished, but does not handle all
+         * the effects of landing on the final position.
+         */
+        teleds(cc.x, cc.y, FALSE);
         sokoban_guilt();
         nomul(-1);
 /*JP
@@ -2385,11 +2532,13 @@ struct obj *obj;
                 verbalize(you_buy_it);
             useupf(corpse, 1L);
         }
-/*JP
-        can = hold_another_object(can, "You make, but cannot pick up, %s.",
-*/
-        can = hold_another_object(can, "\8aÊ\8bl\82É\82Å\82«\82½\82ª\81C%s\82ð\8e\9d\82Â\82±\82Æ\82ª\82Å\82«\82È\82¢\81D",
-                                  doname(can), (const char *) 0);
+#if 0 /*JP*/
+        (void) hold_another_object(can, "You make, but cannot pick up, %s.",
+                                   doname(can), (const char *) 0);
+#else
+        (void) hold_another_object(can, "\8aÊ\8bl\82É\82Å\82«\82½\82ª\81C%s\82ð\8e\9d\82Â\82±\82Æ\82ª\82Å\82«\82È\82¢\81D",
+                                   doname(can), (const char *) 0);
+#endif
     } else
         impossible("Tinning failed.");
 }
@@ -2444,6 +2593,7 @@ struct obj *obj;
 */
                 pline("\89½\82à\8bN\82«\82È\82©\82Á\82½\82æ\82¤\82¾\81D");
             make_deaf((HDeaf & TIMEOUT) + lcount, TRUE);
+            context.botl = TRUE;
             break;
         }
         return;
@@ -2485,9 +2635,8 @@ struct obj *obj;
         if (ABASE(idx) >= AMAX(idx))
             continue;
         val_limit = AMAX(idx);
-        /* don't recover strength lost from hunger */
-        if (idx == A_STR && u.uhs >= WEAK)
-            val_limit--;
+        /* this used to adjust 'val_limit' for A_STR when u.uhs was
+           WEAK or worse, but that's handled via ATEMP(A_STR) now */
         if (Fixed_abil) {
             /* potion/spell of restore ability override sustain ability
                intrinsic but unicorn horn usage doesn't */
@@ -2635,8 +2784,9 @@ long timeout;
     if (mtmp) {
         char and_vanish[BUFSZ];
         struct obj *mshelter = level.objects[mtmp->mx][mtmp->my];
-        Sprintf(monnambuf, "%s", an(m_monnam(mtmp)));
 
+        /* [m_monnam() yields accurate mon type, overriding hallucination] */
+        Sprintf(monnambuf, "%s", an(m_monnam(mtmp)));
         /*JP:TODO:and_vanish\82Í\96¢\8f\88\97\9d*/
         and_vanish[0] = '\0';
         if ((mtmp->minvis && !See_invisible)
@@ -2697,14 +2847,16 @@ long timeout;
         case OBJ_MINVENT:
             if (cansee_spot && !silent && !suppress_see) {
                 struct monst *mon;
+
                 mon = figurine->ocarry;
                 /* figurine carrying monster might be invisible */
-                if (canseemon(figurine->ocarry)) {
+                if (canseemon(figurine->ocarry)
+                    && (!mon->wormno || cansee(mon->mx, mon->my)))
 /*JP
                     Sprintf(carriedby, "%s pack", s_suffix(a_monnam(mon)));
 */
-                    Sprintf(carriedby, "%s\82Ì\8a\93", s_suffix(a_monnam(mon)));
-                else if (is_pool(mon->mx, mon->my))
+                    Sprintf(carriedby, "%s\82Ì\8a\93", a_monnam(mon));
+                else if (is_pool(mon->mx, mon->my))
 /*JP
                     Strcpy(carriedby, "empty water");
 */
@@ -2923,20 +3075,6 @@ struct obj *obj;
     update_inventory();
 }
 
-static struct trapinfo {
-    struct obj *tobj;
-    xchar tx, ty;
-    int time_needed;
-    boolean force_bungle;
-} trapinfo;
-
-void
-reset_trapset()
-{
-    trapinfo.tobj = 0;
-    trapinfo.force_bungle = 0;
-}
-
 /* touchstones - by Ken Arnold */
 STATIC_OVL void
 use_stone(tstone)
@@ -3128,6 +3266,20 @@ struct obj *tstone;
     return;
 }
 
+static struct trapinfo {
+    struct obj *tobj;
+    xchar tx, ty;
+    int time_needed;
+    boolean force_bungle;
+} trapinfo;
+
+void
+reset_trapset()
+{
+    trapinfo.tobj = 0;
+    trapinfo.force_bungle = 0;
+}
+
 /* Place a landmine/bear trap.  Helge Hafting */
 STATIC_OVL void
 use_trap(otmp)
@@ -3532,7 +3684,7 @@ struct obj *obj;
                 pline1(msg_slipsfree);
             }
             if (mtmp)
-                wakeup(mtmp);
+                wakeup(mtmp, TRUE);
         } else
             pline1(msg_snap);
 
@@ -3601,9 +3753,8 @@ struct obj *obj;
                         int hitu, hitvalu;
 
                         hitvalu = 8 + otmp->spe;
-                        hitu = thitu(hitvalu,
-                                     dmgval(otmp, &youmonst),
-                                     otmp, (char *)0);
+                        hitu = thitu(hitvalu, dmgval(otmp, &youmonst),
+                                     &otmp, (char *)0);
                         if (hitu) {
 /*JP
                             pline_The("%s hits you as you try to snatch it!",
@@ -3640,19 +3791,23 @@ struct obj *obj;
 #endif
                         instapetrify(kbuf);
                     }
-                    otmp = hold_another_object(
-/*JP
-                        otmp, "You drop %s!", doname(otmp), (const char *) 0);
-*/
-                        otmp, "%s\82ð\97\8e\82µ\82½\81I", doname(otmp), (const char *) 0);
+#if 0 /*JP:T*/
+                    (void) hold_another_object(otmp, "You drop %s!",
+                                               doname(otmp), (const char *) 0);
+#else
+                    (void) hold_another_object(otmp, "%s\82ð\97\8e\82µ\82½\81I",
+                                               doname(otmp), (const char *) 0);
+#endif
                     break;
                 default:
                     /* to floor beneath mon */
-/*JP
+#if 0 /*JP*/
                     You("yank %s from %s %s!", the(onambuf),
-*/
-                    You("%s\82ð%s\82Ì%s\82©\82ç\82Ð\82Á\82Ï\82Á\82½\81I", the(xname(otmp)),
                         s_suffix(mon_nam(mtmp)), mon_hand);
+#else
+                    You("%s\82ð%s\82Ì%s\82©\82ç\82Ð\82Á\82Ï\82Á\82½\81I", the(xname(otmp)),
+                        mon_nam(mtmp), mon_hand);
+#endif
                     obj_no_longer_held(otmp);
                     place_object(otmp, mtmp->mx, mtmp->my);
                     stackobj(otmp);
@@ -3661,7 +3816,7 @@ struct obj *obj;
             } else {
                 pline1(msg_slipsfree);
             }
-            wakeup(mtmp);
+            wakeup(mtmp, TRUE);
         } else {
             if (mtmp->m_ap_type && !Protection_from_shape_changers
                 && !sensemon(mtmp))
@@ -3738,6 +3893,15 @@ int min_range, max_range;
 static int polearm_range_min = -1;
 static int polearm_range_max = -1;
 
+STATIC_OVL boolean
+get_valid_polearm_position(x,y)
+int x,y;
+{
+    return (isok(x, y) && ACCESSIBLE(levl[x][y].typ)
+            && distu(x, y) >= polearm_range_min
+            && distu(x, y) <= polearm_range_max);
+}
+
 void
 display_polearm_positions(state)
 int state;
@@ -3751,9 +3915,7 @@ int state;
             for (dy = -4; dy <= 4; dy++) {
                 x = dx + (int) u.ux;
                 y = dy + (int) u.uy;
-                if (isok(x, y) && ACCESSIBLE(levl[x][y].typ)
-                    && distu(x, y) >= polearm_range_min
-                    && distu(x, y) <= polearm_range_max) {
+                if (get_valid_polearm_position(x, y)) {
                     tmp_at(x, y);
                 }
             }
@@ -3823,7 +3985,7 @@ struct obj *obj;
         cc.x = hitm->mx;
         cc.y = hitm->my;
     }
-    getpos_sethilite(display_polearm_positions);
+    getpos_sethilite(display_polearm_positions, get_valid_polearm_position);
 /*JP
     if (getpos(&cc, TRUE, "the spot to hit") < 0)
 */
@@ -3885,11 +4047,7 @@ struct obj *obj;
         }
     } else {
         /* no monster here and no statue seen or remembered here */
-        if (glyph_is_invisible(glyph)) {
-            /* now you know that nothing is there... */
-            unmap_object(bhitpos.x, bhitpos.y);
-            newsym(bhitpos.x, bhitpos.y);
-        }
+        (void) unmap_invisible(bhitpos.x, bhitpos.y);
 /*JP
         You("miss; there is no one there to hit.");
 */
@@ -4189,11 +4347,13 @@ struct obj *obj;
         You("%s\82ð\89ó\82·\82¾\82¯\82Ì\97Í\82ª\82È\82¢\81I", xname(obj));
         return 0;
     }
-/*JP
-    pline("Raising %s high above your %s, you break it in two!", yname(obj),
-*/
-    You("%s\82ð%s\82Ì\8fã\82É\8d\82\82­\8cf\82°\81C\93ñ\82Â\82É\82Ö\82µ\90Ü\82Á\82½\81I", xname(obj),
+#if 0 /*JP:T*/
+    pline("Raising %s high above your %s, you %s it in two!", yname(obj),
+          body_part(HEAD), is_fragile ? "snap" : "break");
+#else
+    pline("%s\82ð%s\82Ì\8fã\82É\8d\82\82­\8cf\82°\81C\93ñ\82Â\82É\82Ö\82µ\90Ü\82Á\82½\81I", yname(obj),
           body_part(HEAD));
+#endif
 
     /* [ALI] Do this first so that wand is removed from bill. Otherwise,
      * the freeinv() below also hides it from setpaid() which causes problems.
@@ -4242,10 +4402,12 @@ struct obj *obj;
         goto wanexpl;
     case WAN_FIRE:
         expltype = EXPL_FIERY;
+        /*FALLTHRU*/
     case WAN_COLD:
         if (expltype == EXPL_MAGICAL)
             expltype = EXPL_FROSTY;
         dmg *= 2;
+        /*FALLTHRU*/
     case WAN_MAGIC_MISSILE:
     wanexpl:
         explode(u.ux, u.uy, -(obj->otyp), dmg, WAND_CLASS, expltype);
@@ -4517,7 +4679,7 @@ doapply()
     case SACK:
     case BAG_OF_HOLDING:
     case OILSKIN_SACK:
-        res = use_container(&obj, 1);
+        res = use_container(&obj, 1, FALSE);
         break;
     case BAG_OF_TRICKS:
         (void) bagotricks(obj, FALSE, (int *) 0);
@@ -4538,7 +4700,7 @@ doapply()
         use_tinning_kit(obj);
         break;
     case LEASH:
-        use_leash(obj);
+        res = use_leash(obj);
         break;
     case SADDLE:
         res = use_saddle(obj);
@@ -4593,7 +4755,7 @@ doapply()
         use_lamp(obj);
         break;
     case POT_OIL:
-        light_cocktail(obj);
+        light_cocktail(&obj);
         break;
     case EXPENSIVE_CAMERA:
         res = use_camera(obj);
@@ -4608,30 +4770,8 @@ doapply()
         res = dowrite(obj);
         break;
     case TIN_OPENER:
-        if (!carrying(TIN)) {
-/*JP
-            You("have no tin to open.");
-*/
-            You("\8aÊ\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81D");
-            goto xit;
-        }
-/*JP
-        You("cannot open a tin without eating or discarding its contents.");
-*/
-        pline("\92\86\90g\82ð\90H\82×\82é\82©\81C\8eÌ\82Ä\82é\82©\82µ\82È\82¢\82Æ\8aÊ\82ð\8aJ\82¯\82ç\82ê\82È\82¢\81D");
-        if (flags.verbose)
-/*JP
-            pline("In order to eat, use the 'e' command.");
-*/
-            pline("\90H\82×\82é\82É\82Í\81C'e'\83R\83}\83\93\83h\82ð\8eg\82¦\82Î\82æ\82¢\81D");
-        if (obj != uwep)
-            pline(
-/*JP
-          "Opening the tin will be much easier if you wield the tin opener.");
-*/
-          "\8aÊ\90Ø\82è\82ð\91\95\94õ\82µ\82Ä\82¢\82ê\82Î\81C\82¸\82Á\82Æ\8aÈ\92P\82É\8aJ\82¯\82é\82±\82Æ\82ª\82Å\82«\82é\81D");
-        goto xit;
-
+        res = use_tin_opener(obj);
+        break;
     case FIGURINE:
         use_figurine(&obj);
         break;
@@ -4676,7 +4816,6 @@ doapply()
         pline("Sorry, I don't know how to use that.");
 */
         pline("\82»\82ê\82ð\82Ç\82¤\82â\82Á\82Ä\8eg\82¤\82ñ\82¾\82¢\81H");
-    xit:
         nomul(0);
         return 0;
     }
index 38c5dd3..96487f4 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 artifact.c      $NHDT-Date: 1446369462 2015/11/01 09:17:42 $  $NHDT-Branch: master $:$NHDT-Revision: 1.96 $ */
+/* NetHack 3.6 artifact.c      $NHDT-Date: 1509836679 2017/11/04 23:04:39 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.106 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -26,16 +27,16 @@ extern boolean notonhead; /* for long worms */
 #define get_artifact(o) \
     (((o) && (o)->oartifact) ? &artilist[(int) (o)->oartifact] : 0)
 
-STATIC_DCL boolean
-FDECL(bane_applies, (const struct artifact *, struct monst *));
+STATIC_DCL boolean FDECL(bane_applies, (const struct artifact *,
+                                        struct monst *));
 STATIC_DCL int FDECL(spec_applies, (const struct artifact *, struct monst *));
 STATIC_DCL int FDECL(arti_invoke, (struct obj *));
-STATIC_DCL boolean
-FDECL(Mb_hit, (struct monst * magr, struct monst *mdef, struct obj *, int *,
-               int, BOOLEAN_P, char *));
+STATIC_DCL boolean FDECL(Mb_hit, (struct monst * magr, struct monst *mdef,
+                                struct obj *, int *, int, BOOLEAN_P, char *));
 STATIC_DCL unsigned long FDECL(abil_to_spfx, (long *));
 STATIC_DCL uchar FDECL(abil_to_adtyp, (long *));
 STATIC_DCL boolean FDECL(untouchable, (struct obj *, BOOLEAN_P));
+STATIC_DCL int FDECL(count_surround_traps, (int, int));
 
 /* The amount added to the victim's total hit points to insure that the
    victim will be killed even after damage bonus/penalty adjustments.
@@ -470,12 +471,13 @@ boolean being_worn;
  */
 void
 set_artifact_intrinsic(otmp, on, wp_mask)
-register struct obj *otmp;
+struct obj *otmp;
 boolean on;
 long wp_mask;
 {
     long *mask = 0;
-    register const struct artifact *oart = get_artifact(otmp);
+    register const struct artifact *art, *oart = get_artifact(otmp);
+    register struct obj *obj;
     register uchar dtyp;
     register long spfx;
 
@@ -497,19 +499,21 @@ long wp_mask;
         mask = &EDisint_resistance;
     else if (dtyp == AD_DRST)
         mask = &EPoison_resistance;
+    else if (dtyp == AD_DRLI)
+        mask = &EDrain_resistance;
 
     if (mask && wp_mask == W_ART && !on) {
-        /* find out if some other artifact also confers this intrinsic */
-        /* if so, leave the mask alone */
-        register struct obj *obj;
-        for (obj = invent; obj; obj = obj->nobj)
+        /* find out if some other artifact also confers this intrinsic;
+           if so, leave the mask alone */
+        for (obj = invent; obj; obj = obj->nobj) {
             if (obj != otmp && obj->oartifact) {
-                register const struct artifact *art = get_artifact(obj);
-                if (art->cary.adtyp == dtyp) {
+                art = get_artifact(obj);
+                if (art && art->cary.adtyp == dtyp) {
                     mask = (long *) 0;
                     break;
                 }
             }
+        }
     }
     if (mask) {
         if (on)
@@ -522,11 +526,11 @@ long wp_mask;
     spfx = (wp_mask != W_ART) ? oart->spfx : oart->cspfx;
     if (spfx && wp_mask == W_ART && !on) {
         /* don't change any spfx also conferred by other artifacts */
-        register struct obj *obj;
         for (obj = invent; obj; obj = obj->nobj)
             if (obj != otmp && obj->oartifact) {
-                register const struct artifact *art = get_artifact(obj);
-                spfx &= ~art->cspfx;
+                art = get_artifact(obj);
+                if (art)
+                    spfx &= ~art->cspfx;
             }
     }
 
@@ -660,16 +664,17 @@ struct monst *mon;
         return 1;
 
     yours = (mon == &youmonst);
-    /* all quest artifacts are self-willed; it this ever changes, `badclass'
+    /* all quest artifacts are self-willed; if this ever changes, `badclass'
        will have to be extended to explicitly include quest artifacts */
     self_willed = ((oart->spfx & SPFX_INTEL) != 0);
     if (yours) {
         badclass = self_willed
                    && ((oart->role != NON_PM && !Role_if(oart->role))
                        || (oart->race != NON_PM && !Race_if(oart->race)));
-        badalign =
-            (oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE
-            && (oart->alignment != u.ualign.type || u.ualign.record < 0);
+        badalign = ((oart->spfx & SPFX_RESTR) != 0
+                    && oart->alignment != A_NONE
+                    && (oart->alignment != u.ualign.type
+                        || u.ualign.record < 0));
     } else if (!is_covetous(mon->data) && !is_mplayer(mon->data)) {
         badclass = self_willed && oart->role != NON_PM
                    && oart != &artilist[ART_EXCALIBUR];
@@ -959,8 +964,18 @@ winid tmpwin; /* supplied by dodiscover() */
  * stun attack.  As of 3.4.1, those effects can occur but
  * will be slightly less likely than they were in 3.3.x.]
  */
+
+enum mb_effect_indices {
+    MB_INDEX_PROBE = 0,
+    MB_INDEX_STUN,
+    MB_INDEX_SCARE,
+    MB_INDEX_CANCEL,
+
+    NUM_MB_INDICES
+};
+
 #define MB_MAX_DIEROLL 8 /* rolls above this aren't magical */
-static const char *const mb_verb[2][4] = {
+static const char *const mb_verb[2][NUM_MB_INDICES] = {
 #if 0 /*JP*/
     { "probe", "stun", "scare", "cancel" },
     { "prod", "amaze", "tickle", "purge" },
@@ -970,10 +985,6 @@ static const char *const mb_verb[2][4] = {
     { "\97ã\82Ü\82µ", "\8bÁ\82©\82¹", "\82­\82·\82®\82Á", "\90´\82ß" },
 #endif
 };
-#define MB_INDEX_PROBE 0
-#define MB_INDEX_STUN 1
-#define MB_INDEX_SCARE 2
-#define MB_INDEX_CANCEL 3
 
 /* called when someone is being hit by Magicbane */
 STATIC_OVL boolean
@@ -986,7 +997,7 @@ boolean vis;               /* whether the action can be seen */
 char *hittee;              /* target's name: "you" or mon_nam(mdef) */
 {
     struct permonst *old_uasmon;
-#if 0 /*JP*/
+#if 0 /*JP*//* not used */
     const char *verb, *fakename;
 #else
     const char *verb;
@@ -1153,7 +1164,7 @@ char *hittee;              /* target's name: "you" or mon_nam(mdef) */
             mdef->mconf = 1;
     }
 
-#if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\95s\97v*/
+#if 0 /*JP*//* not used */
     /* now give message(s) describing side-effects;
        don't let vtense() be fooled by assigned name ending in 's' */
     fakename = youdefend ? "you" : "mon";
@@ -1430,11 +1441,13 @@ int dieroll; /* needed for Magicbane and vorpal blades */
                     return (boolean) (youattack || vis);
                 }
                 if (noncorporeal(mdef->data) || amorphous(mdef->data)) {
-/*JP
+#if 0 /*JP*/
                     pline("%s slices through %s %s.", wepdesc,
-*/
-                    pline("%s\82Í%s\82Ì%s\82ð\90Ø\82è\97\8e\82µ\82½\81D", wepdesc,
                           s_suffix(mon_nam(mdef)), mbodypart(mdef, NECK));
+#else
+                    pline("%s\82Í%s\82Ì%s\82ð\90Ø\82è\97\8e\82µ\82½\81D", wepdesc,
+                          mon_nam(mdef), mbodypart(mdef, NECK));
+#endif
                     return TRUE;
                 }
                 *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
@@ -1684,8 +1697,8 @@ struct obj *obj;
                 obj->age = 0;
                 return 0;
             }
-            b_effect =
-                obj->blessed && (Role_switch == oart->role || !oart->role);
+            b_effect = (obj->blessed && (oart->role == Role_switch
+                                         || oart->role == NON_PM));
             recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0);
             update_inventory();
             break;
@@ -1786,13 +1799,12 @@ struct obj *obj;
             } else
                 otmp->quan += rnd(5);
             otmp->owt = weight(otmp);
-            otmp =
 #if 0 /*JP*/
-                hold_another_object(otmp, "Suddenly %s out.",
-                                    aobjnam(otmp, "fall"), (const char *) 0);
+            otmp = hold_another_object(otmp, "Suddenly %s out.",
+                                       aobjnam(otmp, "fall"), (char *) 0);
 #else
-                hold_another_object(otmp, "\93Ë\91R%s\82ª\97\8e\82¿\82½\81D",
-                                    xname(otmp), 0);
+            otmp = hold_another_object(otmp, "\93Ë\91R%s\82ª\97\8e\82¿\82½\81D",
+                                       xname(otmp), 0);
 #endif
             break;
         }
@@ -1974,6 +1986,7 @@ long *abil;
         { &EAntimagic, AD_MAGM },
         { &EDisint_resistance, AD_DISN },
         { &EPoison_resistance, AD_DRST },
+        { &EDrain_resistance, AD_DRLI },
     };
     int k;
 
@@ -2028,7 +2041,6 @@ long *abil;
     long wornmask = (W_ARM | W_ARMC | W_ARMH | W_ARMS
                      | W_ARMG | W_ARMF | W_ARMU
                      | W_AMUL | W_RINGL | W_RINGR | W_TOOL
-                     /* [do W_ART and W_ARTI actually belong here?] */
                      | W_ART | W_ARTI);
 
     if (u.twoweap)
@@ -2044,7 +2056,9 @@ long *abil;
 
             if (art) {
                 if (dtyp) {
-                    if (art->cary.adtyp == dtyp || art->defn.adtyp == dtyp)
+                    if (art->cary.adtyp == dtyp /* carried */
+                        || (art->defn.adtyp == dtyp /* defends while worn */
+                            && (obj->owornmask & ~(W_ART | W_ARTI))))
                         return obj;
                 }
                 if (spfx) {
@@ -2177,8 +2191,7 @@ boolean loseit;    /* whether to drop it if hero can longer touch it */
     if (touch_artifact(obj, &youmonst)) {
         char buf[BUFSZ];
         int dmg = 0, tmp;
-        boolean ag =
-                    (objects[obj->otyp].oc_material == SILVER && Hate_silver),
+        boolean ag = (objects[obj->otyp].oc_material == SILVER && Hate_silver),
                 bane = bane_applies(get_artifact(obj), &youmonst);
 
         /* nothing else to do if hero can successfully handle this object */
@@ -2315,11 +2328,15 @@ int dropflag; /* 0==don't drop, 1==drop all, 2==drop weapon */
 
     dropit = (dropflag > 0); /* drop all or drop weapon */
     /* check secondary weapon first, before possibly unwielding primary */
-    if (u.twoweap)
+    if (u.twoweap) {
+        bypass_obj(uswapwep); /* so loop below won't process it again */
         (void) untouchable(uswapwep, dropit);
+    }
     /* check primary weapon next so that they're handled together */
-    if (uwep)
+    if (uwep) {
+        bypass_obj(uwep); /* so loop below won't process it again */
         (void) untouchable(uwep, dropit);
+    }
 
     /* in case someone is daft enough to add artifact or silver saddle */
     if (u.usteed && (obj = which_armor(u.usteed, W_SADDLE)) != 0) {
@@ -2357,4 +2374,105 @@ int dropflag; /* 0==don't drop, 1==drop all, 2==drop weapon */
         clear_bypasses(); /* reset upon final exit */
 }
 
+static int mkot_trap_warn_count = 0;
+
+STATIC_OVL int
+count_surround_traps(x, y)
+int x, y;
+{
+    struct rm *levp;
+    struct obj *otmp;
+    struct trap *ttmp;
+    int dx, dy, glyph, ret = 0;
+
+    for (dx = x - 1; dx < x + 2; ++dx)
+        for (dy = y - 1; dy < y + 2; ++dy) {
+            if (!isok(dx, dy))
+                continue;
+            /* If a trap is shown here, don't count it; the hero
+             * should be expecting it.  But if there is a trap here
+             * that's not shown, either undiscovered or covered by
+             * something, do count it.
+             */
+            glyph = glyph_at(dx, dy);
+            if (glyph_is_trap(glyph))
+                continue;
+            if ((ttmp = t_at(dx, dy)) != 0) {
+                ++ret;
+                continue;
+            }
+            levp = &levl[dx][dy];
+            if (IS_DOOR(levp->typ) && (levp->doormask & D_TRAPPED) != 0) {
+                ++ret;
+                continue;
+            }
+            for (otmp = level.objects[dx][dy]; otmp; otmp = otmp->nexthere)
+                if (Is_container(otmp) && otmp->otrapped) {
+                    ++ret; /* we're counting locations, so just */
+                    break; /* count the first one in a pile     */
+                }
+        }
+    /*
+     * [Shouldn't we also check inventory for a trapped container?
+     * Even if its trap has already been found, there's no 'tknown'
+     * flag to help hero remember that so we have nothing comparable
+     * to a shown glyph to justify skipping it.]
+     */
+    return ret;
+}
+
+/* sense adjacent traps if wielding MKoT without wearing gloves */
+void
+mkot_trap_warn()
+{
+    static const char *const heat[7] = {
+        "cool", "slightly warm", "warm", "very warm",
+        "hot", "very hot", "like fire"
+    };
+
+    if (!uarmg && uwep && uwep->oartifact == ART_MASTER_KEY_OF_THIEVERY) {
+        int idx, ntraps = count_surround_traps(u.ux, u.uy);
+
+        if (ntraps != mkot_trap_warn_count) {
+            idx = min(ntraps, SIZE(heat) - 1);
+            pline_The("Key feels %s%c", heat[idx], (ntraps > 3) ? '!' : '.');
+        }
+        mkot_trap_warn_count = ntraps;
+    } else
+        mkot_trap_warn_count = 0;
+}
+
+/* Master Key is magic key if its bless/curse state meets our criteria:
+   not cursed for rogues or blessed for non-rogues */
+boolean
+is_magic_key(mon, obj)
+struct monst *mon; /* if null, non-rogue is assumed */
+struct obj *obj;
+{
+    if (((obj && obj->oartifact == ART_MASTER_KEY_OF_THIEVERY)
+         && ((mon == &youmonst) ? Role_if(PM_ROGUE)
+                                : (mon && mon->data == &mons[PM_ROGUE])))
+        ? !obj->cursed : obj->blessed)
+        return TRUE;
+    return FALSE;
+}
+
+/* figure out whether 'mon' (usually youmonst) is carrying the magic key */
+struct obj *
+has_magic_key(mon)
+struct monst *mon; /* if null, hero assumed */
+{
+    struct obj *o;
+    short key = artilist[ART_MASTER_KEY_OF_THIEVERY].otyp;
+
+    if (!mon)
+        mon = &youmonst;
+    for (o = ((mon == &youmonst) ? invent : mon->minvent); o;
+         o = nxtobj(o, key, FALSE)) {
+        if (is_magic_key(mon, o))
+            return o;
+    }
+    return (struct obj *) 0;
+}
+
 /*artifact.c*/
index 94bb78e..67f07a8 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 attrib.c        $NHDT-Date: 1449269911 2015/12/04 22:58:31 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */
+/* NetHack 3.6 attrib.c        $NHDT-Date: 1494034337 2017/05/06 01:32:17 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.62 $ */
 /*      Copyright 1988, 1989, 1990, 1992, M. Stephenson           */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -31,6 +31,15 @@ static const char
                            "\8aÔ\94²\82¯\82¾", "\95s\8aí\97p\82¾",
                            "\82Ð\8eã\82¾","\8fX\82¢" };
 #endif
+/* also used by enlightenment for non-abbreviated status info */
+const char
+#if 0 /*JP*/
+    *const attrname[] = { "strength", "intelligence", "wisdom",
+                          "dexterity", "constitution", "charisma" };
+#else
+    *const attrname[] = { "\8b­\82³", "\92m\97Í", "\8c«\82³",
+                          "\91f\91\81\82³", "\91Ï\8bv\97Í", "\96£\97Í" };
+#endif
 
 static const struct innate {
     schar ulevel;
@@ -175,16 +184,28 @@ static const struct innate {
                  { 0, 0, 0, 0 } },
 
   /* Intrinsics conferred by race */
+  dwa_abil[] = { { 1, &HInfravision, "", "" },
+                 { 0, 0, 0, 0 } },
+
+  elf_abil[] = { { 1, &HInfravision, "", "" },
 /*JP
-    elf_abil[] = { { 4, &(HSleep_resistance), "awake", "tired" },
+                 { 4, &HSleep_resistance, "awake", "tired" },
 */
-    elf_abil[] = { { 4, &(HSleep_resistance), "\96Ú\82ª\8ao\82ß\82½", "\96°\82­\82È\82Á\82½" },
-                   { 0, 0, 0, 0 } },
+                 { 4, &(HSleep_resistance), "\96Ú\82ª\8ao\82ß\82½", "\96°\82­\82È\82Á\82½" },
+                 { 0, 0, 0, 0 } },
 
-  orc_abil[] = { { 1, &(HPoison_resistance), "", "" }, { 0, 0, 0, 0 } };
+  gno_abil[] = { { 1, &HInfravision, "", "" },
+                 { 0, 0, 0, 0 } },
+
+  orc_abil[] = { { 1, &HInfravision, "", "" },
+                 { 1, &HPoison_resistance, "", "" },
+                 { 0, 0, 0, 0 } },
+
+  hum_abil[] = { { 0, 0, 0, 0 } };
 
 STATIC_DCL void NDECL(exerper);
 STATIC_DCL void FDECL(postadjabil, (long *));
+STATIC_DCL const struct innate *FDECL(role_abil, (int));
 STATIC_DCL const struct innate *FDECL(check_innate_abil, (long *, long));
 STATIC_DCL int FDECL(innately, (long *));
 
@@ -194,7 +215,7 @@ adjattrib(ndx, incr, msgflg)
 int ndx, incr;
 int msgflg; /* positive => no message, zero => message, and */
 {           /* negative => conditional (msg if change made) */
-    int old_acurr;
+    int old_acurr, old_abase;
     boolean abonflg;
     const char *attrstr;
 
@@ -211,6 +232,7 @@ int msgflg; /* positive => no message, zero => message, and */
     }
 
     old_acurr = ACURR(ndx);
+    old_abase = ABASE(ndx);
     if (incr > 0) {
         ABASE(ndx) += incr;
         if (ABASE(ndx) > AMAX(ndx)) {
@@ -235,14 +257,19 @@ int msgflg; /* positive => no message, zero => message, and */
         abonflg = (ABON(ndx) > 0);
     }
     if (ACURR(ndx) == old_acurr) {
-        if (msgflg == 0 && flags.verbose)
+        if (msgflg == 0 && flags.verbose) {
+            if (ABASE(ndx) == old_abase)
 #if 0 /*JP*/
-            pline("You're %s as %s as you can get.",
-                  abonflg ? "currently" : "already", attrstr);
+                pline("You're %s as %s as you can get.",
+                      abonflg ? "currently" : "already", attrstr);
 #else
-            You("%s\8f\\95ª\82É%s\81D",
-                  abonflg ? "\8d¡\82Ì\82Æ\82±\82ë" : "\8aù\82É", attrstr);
+                You("%s\8f\\95ª\82É%s\81D",
+                      abonflg ? "\8d¡\82Ì\82Æ\82±\82ë" : "\8aù\82É", attrstr);
 #endif
+            else /* current stayed the same but base value changed */
+                Your("innate %s has %s.", attrname[ndx],
+                     (incr > 0) ? "improved" : "declined");
+        }
         return FALSE;
     }
 
@@ -341,19 +368,31 @@ int typ;         /* which attribute */
 boolean exclaim; /* emphasis */
 {
     void VDECL((*func), (const char *, ...)) = poiseff[typ].delivery_func;
+    const char *msg_txt = poiseff[typ].effect_msg;
+
+    /*
+     * "You feel weaker" or "you feel very sick" aren't appropriate when
+     * wearing or wielding something (gauntlets of power, Ogresmasher)
+     * which forces the attribute to maintain its maximum value.
+     * Phrasing for other attributes which might have fixed values
+     * (dunce cap) is such that we don't need message fixups for them.
+     */
+    if (typ == A_STR && ACURR(A_STR) == STR19(25))
+        msg_txt = "innately weaker";
+    else if (typ == A_CON && ACURR(A_CON) == 25)
+        msg_txt = "sick inside";
 
 /*JP
-    (*func)("%s%c", poiseff[typ].effect_msg, exclaim ? '!' : '.');
+    (*func)("%s%c", msg_txt, exclaim ? '!' : '.');
 */
-    (*func)("%s%s", poiseff[typ].effect_msg, exclaim ? "\81I" : "\81D");
+    (*func)("%s%s", msg_txt, exclaim ? "\81I" : "\81D");
 }
 
-/* called when an attack or trap has poisoned the hero (used to be in mon.c)
- */
+/* called when an attack or trap has poisoned hero (used to be in mon.c) */
 void
 poisoned(reason, typ, pkiller, fatal, thrown_weapon)
 const char *reason,    /* controls what messages we display */
-    *pkiller;          /* for score+log file if fatal */
+           *pkiller;   /* for score+log file if fatal */
 int typ, fatal;        /* if fatal is 0, limit damage to adjattrib */
 boolean thrown_weapon; /* thrown weapons are less deadly */
 {
@@ -373,7 +412,8 @@ boolean thrown_weapon; /* thrown weapons are less deadly */
 
         /* avoid "The" Orcus's sting was poisoned... */
 #if 0 /*JP*/
-        pline("%s%s %s poisoned!", isupper(*reason) ? "" : "The ", reason,
+        pline("%s%s %s poisoned!",
+              isupper((uchar) *reason) ? "" : "The ", reason,
               plural ? "were" : "was");
 #else
         pline("%s\82Í\93Å\82É\82¨\82©\82³\82ê\82Ä\82¢\82é\81I", reason);
@@ -411,6 +451,7 @@ boolean thrown_weapon; /* thrown weapons are less deadly */
     if (i == 0 && typ != A_CHA) {
         /* instant kill */
         u.uhp = -1;
+        context.botl = TRUE;
 /*JP
         pline_The("poison was deadly...");
 */
@@ -489,20 +530,27 @@ set_moreluck()
 void
 restore_attrib()
 {
-    int i;
+    int i, equilibrium;;
 
-    for (i = 0; i < A_MAX; i++) { /* all temporary losses/gains */
+    /*
+     * Note:  this gets called on every turn but ATIME() is never set
+     * to non-zero anywhere, and ATEMP() is only used for strength loss
+     * from hunger, so it doesn't actually do anything.
+     */
 
-        if (ATEMP(i) && ATIME(i)) {
+    for (i = 0; i < A_MAX; i++) { /* all temporary losses/gains */
+        equilibrium = (i == A_STR && u.uhs >= WEAK) ? -1 : 0;
+        if (ATEMP(i) != equilibrium && ATIME(i) != 0) {
             if (!(--(ATIME(i)))) { /* countdown for change */
-                ATEMP(i) += ATEMP(i) > 0 ? -1 : 1;
-
+                ATEMP(i) += (ATEMP(i) > 0) ? -1 : 1;
+                context.botl = 1;
                 if (ATEMP(i)) /* reset timer */
                     ATIME(i) = 100 / ACURR(A_CON);
             }
         }
     }
-    (void) encumber_msg();
+    if (context.botl)
+        (void) encumber_msg();
 }
 
 #define AVAL 50 /* tune value for exercise gains */
@@ -807,6 +855,36 @@ long *ability;
 }
 
 STATIC_OVL const struct innate *
+role_abil(r)
+int r;
+{
+    const struct {
+        short role;
+        const struct innate *abil;
+    } roleabils[] = {
+        { PM_ARCHEOLOGIST, arc_abil },
+        { PM_BARBARIAN, bar_abil },
+        { PM_CAVEMAN, cav_abil },
+        { PM_HEALER, hea_abil },
+        { PM_KNIGHT, kni_abil },
+        { PM_MONK, mon_abil },
+        { PM_PRIEST, pri_abil },
+        { PM_RANGER, ran_abil },
+        { PM_ROGUE, rog_abil },
+        { PM_SAMURAI, sam_abil },
+        { PM_TOURIST, tou_abil },
+        { PM_VALKYRIE, val_abil },
+        { PM_WIZARD, wiz_abil },
+        { 0, 0 }
+    };
+    int i;
+
+    for (i = 0; roleabils[i].abil && roleabils[i].role != r; i++)
+        continue;
+    return roleabils[i].abil;
+}
+
+STATIC_OVL const struct innate *
 check_innate_abil(ability, frommask)
 long *ability;
 long frommask;
@@ -814,60 +892,24 @@ long frommask;
     const struct innate *abil = 0;
 
     if (frommask == FROMEXPER)
-        switch (Role_switch) {
-        case PM_ARCHEOLOGIST:
-            abil = arc_abil;
-            break;
-        case PM_BARBARIAN:
-            abil = bar_abil;
-            break;
-        case PM_CAVEMAN:
-            abil = cav_abil;
-            break;
-        case PM_HEALER:
-            abil = hea_abil;
-            break;
-        case PM_KNIGHT:
-            abil = kni_abil;
-            break;
-        case PM_MONK:
-            abil = mon_abil;
-            break;
-        case PM_PRIEST:
-            abil = pri_abil;
-            break;
-        case PM_RANGER:
-            abil = ran_abil;
-            break;
-        case PM_ROGUE:
-            abil = rog_abil;
-            break;
-        case PM_SAMURAI:
-            abil = sam_abil;
-            break;
-        case PM_TOURIST:
-            abil = tou_abil;
-            break;
-        case PM_VALKYRIE:
-            abil = val_abil;
-            break;
-        case PM_WIZARD:
-            abil = wiz_abil;
-            break;
-        default:
-            break;
-        }
+        abil = role_abil(Role_switch);
     else if (frommask == FROMRACE)
         switch (Race_switch) {
+        case PM_DWARF:
+            abil = dwa_abil;
+            break;
         case PM_ELF:
             abil = elf_abil;
             break;
+        case PM_GNOME:
+            abil = gno_abil;
+            break;
         case PM_ORC:
             abil = orc_abil;
             break;
         case PM_HUMAN:
-        case PM_DWARF:
-        case PM_GNOME:
+            abil = hum_abil;
+            break;
         default:
             break;
         }
@@ -880,31 +922,54 @@ long frommask;
     return (struct innate *) 0;
 }
 
-/*
- * returns 1 if FROMRACE or FROMEXPER and exper level == 1
- * returns 2 if FROMEXPER and exper level > 1
- * otherwise returns 0
- */
+/* reasons for innate ability */
+#define FROM_NONE 0
+#define FROM_ROLE 1 /* from experience at level 1 */
+#define FROM_RACE 2
+#define FROM_INTR 3 /* intrinsically (eating some corpse or prayer reward) */
+#define FROM_EXP  4 /* from experience for some level > 1 */
+#define FROM_FORM 5
+#define FROM_LYCN 6
+
+/* check whether particular ability has been obtained via innate attribute */
 STATIC_OVL int
 innately(ability)
 long *ability;
 {
     const struct innate *iptr;
 
+    if ((iptr = check_innate_abil(ability, FROMEXPER)) != 0)
+        return (iptr->ulevel == 1) ? FROM_ROLE : FROM_EXP;
     if ((iptr = check_innate_abil(ability, FROMRACE)) != 0)
-        return 1;
-    else if ((iptr = check_innate_abil(ability, FROMEXPER)) != 0)
-        return (iptr->ulevel == 1) ? 1 : 2;
-    return 0;
+        return FROM_RACE;
+    if ((*ability & FROMOUTSIDE) != 0L)
+        return FROM_INTR;
+    if ((*ability & FROMFORM) != 0L)
+        return FROM_FORM;
+    return FROM_NONE;
 }
 
 int
 is_innate(propidx)
 int propidx;
 {
+    int innateness;
+
+    /* innately() would report FROM_FORM for this; caller wants specificity */
+    if (propidx == DRAIN_RES && u.ulycn >= LOW_PM)
+        return FROM_LYCN;
+    if (propidx == FAST && Very_fast)
+        return FROM_NONE; /* can't become very fast innately */
+    if ((innateness = innately(&u.uprops[propidx].intrinsic)) != FROM_NONE)
+        return innateness;
+    if (propidx == JUMPING && Role_if(PM_KNIGHT)
+        /* knight has intrinsic jumping, but extrinsic is more versatile so
+           ignore innateness if equipment is going to claim responsibility */
+        && !u.uprops[propidx].extrinsic)
+        return FROM_ROLE;
     if (propidx == BLINDED && !haseyes(youmonst.data))
-        return 1;
-    return innately(&u.uprops[propidx].intrinsic);
+        return FROM_FORM;
+    return FROM_NONE;
 }
 
 char *
@@ -930,31 +995,59 @@ int propidx; /* special cases can have negative values */
             char *p;
 #endif
             struct obj *obj = (struct obj *) 0;
-            int innate = is_innate(propidx);
+            int innateness = is_innate(propidx);
 
-            if (innate == 2)
+            /*
+             * Properties can be obtained from multiple sources and we
+             * try to pick the most significant one.  Classification
+             * priority is not set in stone; current precedence is:
+             * "from the start" (from role or race at level 1),
+             * "from outside" (eating corpse, divine reward, blessed potion),
+             * "from experience" (from role or race at level 2+),
+             * "from current form" (while polymorphed),
+             * "from timed effect" (potion or spell),
+             * "from worn/wielded equipment" (Firebrand, elven boots, &c),
+             * "from carried equipment" (mainly quest artifacts).
+             * There are exceptions.  Versatile jumping from spell or boots
+             * takes priority over knight's innate but limited jumping.
+             */
+            if (propidx == BLINDED && u.uroleplay.blind)
 /*JP
-                Strcpy(buf, " because of your experience");
+                Sprintf(buf, " from birth");
 */
-                Strcpy(buf, "\8co\8c±\82É\82æ\82Á\82Ä");
-            else if (innate == 1)
+                Sprintf(buf, "\90\82Ü\82ê\82Ä\82©\82ç\82¸\82Á\82Æ");
+            else if (innateness == FROM_ROLE || innateness == FROM_RACE)
 /*JP
                 Strcpy(buf, " innately");
 */
                 Strcpy(buf, "\90\82Ü\82ê\82È\82ª\82ç\82É");
+            else if (innateness == FROM_INTR) /* [].intrinsic & FROMOUTSIDE */
+                Strcpy(buf, " intrinsically");
+            else if (innateness == FROM_EXP)
+/*JP
+                Strcpy(buf, " because of your experience");
+*/
+                Strcpy(buf, "\8co\8c±\82É\82æ\82Á\82Ä");
+            else if (innateness == FROM_LYCN)
+                Strcpy(buf, " due to your lycanthropy");
+            else if (innateness == FROM_FORM)
+                Strcpy(buf, " from current creature form");
+            else if (propidx == FAST && Very_fast)
+                Sprintf(buf, because_of,
+                        ((HFast & TIMEOUT) != 0L) ? "a potion or spell"
+                          : ((EFast & W_ARMF) != 0L && uarmf->dknown
+                             && objects[uarmf->otyp].oc_name_known)
+                              ? ysimple_name(uarmf) /* speed boots */
+                                : EFast ? "worn equipment"
+                                  : something);
             else if (wizard
-                     && (obj = what_gives(&u.uprops[propidx].extrinsic)))
+                     && (obj = what_gives(&u.uprops[propidx].extrinsic)) != 0)
                 Sprintf(buf, because_of, obj->oartifact
                                              ? bare_artifactname(obj)
 /*JP
                                              : ysimple_name(obj));
 */
                                              : simpleonames(obj));
-            else if (propidx == BLINDED && u.uroleplay.blind)
-/*JP
-                Sprintf(buf, " from birth");
-*/
-                Sprintf(buf, "\90\82Ü\82ê\82Ä\82©\82ç\82¸\82Á\82Æ");
             else if (propidx == BLINDED && Blindfolded_only)
 /*JP
                 Sprintf(buf, because_of, ysimple_name(ublindf));
@@ -1011,50 +1104,7 @@ int oldlevel, newlevel;
     register const struct innate *abil, *rabil;
     long prevabil, mask = FROMEXPER;
 
-    switch (Role_switch) {
-    case PM_ARCHEOLOGIST:
-        abil = arc_abil;
-        break;
-    case PM_BARBARIAN:
-        abil = bar_abil;
-        break;
-    case PM_CAVEMAN:
-        abil = cav_abil;
-        break;
-    case PM_HEALER:
-        abil = hea_abil;
-        break;
-    case PM_KNIGHT:
-        abil = kni_abil;
-        break;
-    case PM_MONK:
-        abil = mon_abil;
-        break;
-    case PM_PRIEST:
-        abil = pri_abil;
-        break;
-    case PM_RANGER:
-        abil = ran_abil;
-        break;
-    case PM_ROGUE:
-        abil = rog_abil;
-        break;
-    case PM_SAMURAI:
-        abil = sam_abil;
-        break;
-    case PM_TOURIST:
-        abil = tou_abil;
-        break;
-    case PM_VALKYRIE:
-        abil = val_abil;
-        break;
-    case PM_WIZARD:
-        abil = wiz_abil;
-        break;
-    default:
-        abil = 0;
-        break;
-    }
+    abil = role_abil(Role_switch);
 
     switch (Race_switch) {
     case PM_ELF:
@@ -1194,13 +1244,16 @@ int x;
 #ifdef WIN32_BUG
             return (x = ((tmp <= 3) ? 3 : tmp));
 #else
-        return (schar) ((tmp <= 3) ? 3 : tmp);
+            return (schar) ((tmp <= 3) ? 3 : tmp);
 #endif
     } else if (x == A_CHA) {
         if (tmp < 18
             && (youmonst.data->mlet == S_NYMPH || u.umonnum == PM_SUCCUBUS
                 || u.umonnum == PM_INCUBUS))
             return (schar) 18;
+    } else if (x == A_CON) {
+        if (uwep && uwep->oartifact == ART_OGRESMASHER)
+            return (schar) 25;
     } else if (x == A_INT || x == A_WIS) {
         /* yes, this may raise int/wis if player is sufficiently
          * stupid.  there are lower levels of cognition than "dunce".
@@ -1246,6 +1299,9 @@ int attrindx;
         /* lower limit for Str can also be 25 */
         if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER)
             lolimit = hilimit;
+    } else if (attrindx == A_CON) {
+        if (uwep && uwep->oartifact == ART_OGRESMASHER)
+            lolimit = hilimit;
     }
     /* this exception is hypothetical; the only other worn item affecting
        Int or Wis is another helmet so can't be in use at the same time */
index 2dc0709..ef699bc 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 ball.c  $NHDT-Date: 1446808438 2015/11/06 11:13:58 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */
+/* NetHack 3.6 ball.c  $NHDT-Date: 1450402033 2015/12/18 01:27:13 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.29 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) David Cohrs, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -642,11 +643,13 @@ drag:
             You("\93S\8b\85\82É\82®\82¢\82Æ\88ø\82Á\82Ï\82ç\82ê\82½\81I");
             if ((victim = m_at(uchain->ox, uchain->oy)) != 0) {
                 int tmp;
+                int dieroll = rnd(20);
 
                 tmp = -2 + Luck + find_mac(victim);
                 tmp += omon_adj(victim, uball, TRUE);
-                if (tmp >= rnd(20))
-                    (void) hmon(victim, uball, HMON_DRAGGED);
+
+                if (tmp >= dieroll)
+                    (void) hmon(victim, uball, HMON_DRAGGED, dieroll);
                 else
                     miss(xname(uball), victim);
 
@@ -761,9 +764,9 @@ xchar x, y;
                 break;
             case TT_LAVA:
 /*JP
-                pline(pullmsg, "lava");
+                pline(pullmsg, hliquid("lava"));
 */
-                pline(pullmsg, "\97n\8aâ");
+                pline(pullmsg, hliquid("\97n\8aâ"));
                 break;
             case TT_BEARTRAP: {
                 register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
@@ -877,6 +880,9 @@ drag_down()
 */
         You("\93S\8b\85\82ð\8eè\82©\82ç\97\8e\82µ\82Ä\82µ\82Ü\82Á\82½\81D");
 
+    cls();  /* previous level is still displayed although you
+               went down the stairs. Avoids bug C343-20 */
+
     if (forward) {
         if (rn2(6)) {
 /*JP
index 2008d5e..8554aaf 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 bones.c $NHDT-Date: 1449269914 2015/12/04 22:58:34 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.66 $ */
+/* NetHack 3.6 bones.c $NHDT-Date: 1508827591 2017/10/24 06:46:31 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.71 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -50,14 +51,10 @@ STATIC_OVL void
 goodfruit(id)
 int id;
 {
-    register struct fruit *f;
+    struct fruit *f = fruit_from_indx(-id);
 
-    for (f = ffruit; f; f = f->nextf) {
-        if (f->fid == -id) {
-            f->fid = id;
-            return;
-        }
-    }
+    if (f)
+        f->fid = id;
 }
 
 STATIC_OVL void
@@ -123,15 +120,18 @@ boolean restore;
                 free_oname(otmp);
             }
 
-            if (otmp->otyp == SLIME_MOLD)
+            if (otmp->otyp == SLIME_MOLD) {
                 goodfruit(otmp->spe);
 #ifdef MAIL
-            else if (otmp->otyp == SCR_MAIL)
-                otmp->spe = 1;
+            } else if (otmp->otyp == SCR_MAIL) {
+                /* 0: delivered in-game via external event;
+                   1: from bones or wishing; 2: written with marker */
+                if (otmp->spe == 0)
+                    otmp->spe = 1;
 #endif
-            else if (otmp->otyp == EGG)
-                otmp->spe = 0;
-            else if (otmp->otyp == TIN) {
+            } else if (otmp->otyp == EGG) {
+                otmp->spe = 0; /* not "laid by you" in next game */
+            else if (otmp->otyp == TIN) {
                 /* make tins of unique monster's meat be empty */
                 if (otmp->corpsenm >= LOW_PM
                     && unique_corpstat(&mons[otmp->corpsenm]))
@@ -139,24 +139,30 @@ boolean restore;
             } else if (otmp->otyp == CORPSE || otmp->otyp == STATUE) {
                 int mnum = otmp->corpsenm;
 
-                /* Discard incarnation details of unique
-                   monsters (by passing null instead of otmp
-                   for object), shopkeepers (by passing false
-                   for revival flag), temple priests, and
-                   vault guards in order to prevent corpse
-                   revival or statue reanimation. */
+                /* Discard incarnation details of unique monsters
+                   (by passing null instead of otmp for object),
+                   shopkeepers (by passing false for revival flag),
+                   temple priests, and vault guards in order to
+                   prevent corpse revival or statue reanimation. */
                 if (has_omonst(otmp)
                     && cant_revive(&mnum, FALSE, (struct obj *) 0)) {
                     free_omonst(otmp);
-                    /* mnum is now either human_zombie or
-                       doppelganger; for corpses of uniques,
-                       we need to force the transformation
-                       now rather than wait until a revival
-                       attempt, otherwise eating this corpse
+                    /* mnum is now either human_zombie or doppelganger;
+                       for corpses of uniques, we need to force the
+                       transformation now rather than wait until a
+                       revival attempt, otherwise eating this corpse
                        would behave as if it remains unique */
                     if (mnum == PM_DOPPELGANGER && otmp->otyp == CORPSE)
                         set_corpsenm(otmp, mnum);
                 }
+            } else if ((otmp->otyp == iflags.mines_prize_type
+                        && !Is_mineend_level(&u.uz))
+                       || ((otmp->otyp == iflags.soko_prize_type1
+                            || otmp->otyp == iflags.soko_prize_type2)
+                           && !Is_sokoend_level(&u.uz))) {
+                /* "special prize" in this game becomes ordinary object
+                   if loaded into another game */
+                otmp->record_achieve_special = NON_PM;
             } else if (otmp->otyp == AMULET_OF_YENDOR) {
                 /* no longer the real Amulet */
                 otmp->otyp = FAKE_AMULET_OF_YENDOR;
@@ -189,8 +195,8 @@ sanitize_name(namebuf)
 char *namebuf;
 {
     int c;
-    boolean strip_8th_bit =
-        !strcmp(windowprocs.name, "tty") && !iflags.wc_eight_bit_input;
+    boolean strip_8th_bit = (!strcmp(windowprocs.name, "tty")
+                             && !iflags.wc_eight_bit_input);
 
     /* it's tempting to skip this for single-user platforms, since
        only the current player could have left these bones--except
@@ -487,7 +493,7 @@ make_bones:
     Sprintf(newbones->who, "%s-%.3s-%.3s-%.3s-%.3s", plname, urole.filecode,
             urace.filecode, genders[flags.female].filecode,
             aligns[1 - u.ualign.type].filecode);
-    formatkiller(newbones->how, sizeof newbones->how, how);
+    formatkiller(newbones->how, sizeof newbones->how, how, TRUE);
     Strcpy(newbones->when, yyyymmddhhmmss(when));
     /* final resting place, used to decide when bones are discovered */
     newbones->frpx = u.ux, newbones->frpy = u.uy;
@@ -564,7 +570,7 @@ getbones()
 {
     register int fd;
     register int ok;
-    char c, *bonesid, oldbonesid[10];
+    char c, *bonesid, oldbonesid[40]; /* was [10]; more should be safer */
 
     if (discover) /* save bones files for real games */
         return 0;
@@ -602,7 +608,15 @@ getbones()
         }
         mread(fd, (genericptr_t) &c, sizeof c); /* length incl. '\0' */
         mread(fd, (genericptr_t) oldbonesid, (unsigned) c); /* DD.nnn */
-        if (strcmp(bonesid, oldbonesid) != 0) {
+        if (strcmp(bonesid, oldbonesid) != 0
+            /* from 3.3.0 through 3.6.0, bones in the quest branch stored
+               a bogus bonesid in the file; 3.6.1 fixed that, but for
+               3.6.0 bones to remain compatible, we need an extra test;
+               once compatibility with 3.6.x goes away, this can too
+               (we don't try to make this conditional upon the value of
+               VERSION_COMPATIBILITY because then we'd need patchlevel.h) */
+            && (strlen(bonesid) <= 2
+                || strcmp(bonesid + 2, oldbonesid) != 0)) {
             char errbuf[BUFSZ];
 
 /*JP
index b143a14..fbae5fa 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 botl.c  $NHDT-Date: 1447978683 2015/11/20 00:18:03 $  $NHDT-Branch: master $:$NHDT-Revision: 1.69 $ */
+/* NetHack 3.6 botl.c  $NHDT-Date: 1506903619 2017/10/02 00:20:19 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.81 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -22,16 +23,33 @@ const char *const enc_stat[] = { "",     "
 
 STATIC_OVL NEARDATA int mrank_sz = 0; /* loaded by max_rank_sz (from u_init) */
 STATIC_DCL const char *NDECL(rank);
+#ifdef STATUS_HILITES
+STATIC_DCL void NDECL(bot_via_windowport);
+#endif
 
-#ifndef STATUS_VIA_WINDOWPORT
+static char *
+get_strength_str()
+{
+    static char buf[32];
+    int st = ACURR(A_STR);
+
+    if (st > 18) {
+        if (st > STR18(100))
+            Sprintf(buf, "%2d", st - 100);
+        else if (st < STR18(100))
+            Sprintf(buf, "18/%02d", st - 18);
+        else
+            Sprintf(buf, "18/**");
+    } else
+        Sprintf(buf, "%-1d", st);
 
-STATIC_DCL void NDECL(bot1);
-STATIC_DCL void NDECL(bot2);
+    return buf;
+}
 
-STATIC_OVL void
-bot1()
+char *
+do_statusline1()
 {
-    char newbot1[MAXCO];
+    static char newbot1[BUFSZ];
     register char *nb;
     register int i, j;
 
@@ -68,33 +86,18 @@ bot1()
     j = (int) ((nb + 2) - newbot1); /* strlen(newbot1) but less computation */
     if ((i - j) > 0)
         Sprintf(nb = eos(nb), "%*s", i - j, " "); /* pad with spaces */
-    if (ACURR(A_STR) > 18) {
-        if (ACURR(A_STR) > STR18(100))
-/*JP
-            Sprintf(nb = eos(nb), "St:%2d ", ACURR(A_STR) - 100);
-*/
-            Sprintf(nb = eos(nb), "\8b­:%2d ", ACURR(A_STR) - 100);
-        else if (ACURR(A_STR) < STR18(100))
-/*JP
-            Sprintf(nb = eos(nb), "St:18/%02d ", ACURR(A_STR) - 18);
-*/
-            Sprintf(nb = eos(nb), "\8b­:18/%02d ", ACURR(A_STR) - 18);
-        else
-/*JP
-            Sprintf(nb = eos(nb), "St:18/** ");
-*/
-            Sprintf(nb = eos(nb), "\8b­:18/** ");
-    } else
-/*JP
-        Sprintf(nb = eos(nb), "St:%-1d ", ACURR(A_STR));
-*/
-        Sprintf(nb = eos(nb), "\8b­:%-1d ", ACURR(A_STR));
-/*JP
-    Sprintf(nb = eos(nb), "Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d",
-*/
-    Sprintf(nb = eos(nb), "\91\81:%-1d \91Ï:%-1d \92m:%-1d \8c«:%-1d \96£:%-1d ",
+
+#if 0 /*JP*/
+    Sprintf(nb = eos(nb), "St:%s Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d",
+            get_strength_str(),
             ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS),
             ACURR(A_CHA));
+#else
+    Sprintf(nb = eos(nb), "\8b­:%s \91\81:%-1d \91Ï:%-1d \92m:%-1d \8c«:%-1d \96£:%-1d ",
+            get_strength_str(),
+            ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS),
+            ACURR(A_CHA));
+#endif
 #if 0 /*JP*/
     Sprintf(nb = eos(nb),
             (u.ualign.type == A_CHAOTIC)
@@ -113,108 +116,206 @@ bot1()
 */
         Sprintf(nb = eos(nb), "%ld\93_", botl_score());
 #endif
-    curs(WIN_STATUS, 1, 0);
-    putstr(WIN_STATUS, 0, newbot1);
+    return newbot1;
 }
 
-STATIC_OVL void
-bot2()
+void
+check_gold_symbol()
+{
+    int goldch, goldoc;
+    unsigned int goldos;
+    int goldglyph = objnum_to_glyph(GOLD_PIECE);
+    (void) mapglyph(goldglyph, &goldch, &goldoc, &goldos, 0, 0);
+    iflags.invis_goldsym = ((char)goldch <= ' ');
+}
+
+char *
+do_statusline2()
 {
-    char newbot2[MAXCO];
+    static char newbot2[BUFSZ], /* MAXCO: botl.h */
+         /* dungeon location (and gold), hero health (HP, PW, AC),
+            experience (HD if poly'd, else Exp level and maybe Exp points),
+            time (in moves), varying number of status conditions */
+         dloc[QBUFSZ], hlth[QBUFSZ], expr[QBUFSZ], tmmv[QBUFSZ], cond[QBUFSZ];
     register char *nb;
-    int hp, hpmax;
-    int cap = near_capacity();
+    unsigned dln, dx, hln, xln, tln, cln;
+    int hp, hpmax, cap;
+    long money;
+
+    /*
+     * Various min(x,9999)'s are to avoid having excessive values
+     * violate the field width assumptions in botl.h and should not
+     * impact normal play.  Particularly 64-bit long for gold which
+     * could require many more digits if someone figures out a way
+     * to get and carry a really large (or negative) amount of it.
+     * Turn counter is also long, but we'll risk that.
+     */
 
+    /* dungeon location plus gold */
+    (void) describe_level(dloc); /* includes at least one trailing space */
+    if ((money = money_cnt(invent)) < 0L)
+        money = 0L; /* ought to issue impossible() and then discard gold */
+    Sprintf(eos(dloc), "%s:%-2ld", /* strongest hero can lift ~300000 gold */
+            (iflags.in_dumplog || iflags.invis_goldsym) ? "$"
+            : encglyph(objnum_to_glyph(GOLD_PIECE)),
+            min(money, 999999L));
+    dln = strlen(dloc);
+    /* '$' encoded as \GXXXXNNNN is 9 chars longer than display will need */
+    dx = strstri(dloc, "\\G") ? 9 : 0;
+
+    /* health and armor class (has trailing space for AC 0..9) */
     hp = Upolyd ? u.mh : u.uhp;
     hpmax = Upolyd ? u.mhmax : u.uhpmax;
-
     if (hp < 0)
         hp = 0;
-    (void) describe_level(newbot2);
-/*JP
-    Sprintf(nb = eos(newbot2), "%s:%-2ld HP:%d(%d) Pw:%d(%d) AC:%-2d",
-*/
-    Sprintf(nb = eos(newbot2), "%s:%-2ld \91Ì:%d(%d) \96\82:%d(%d) \8aZ:%-2d",
-            encglyph(objnum_to_glyph(GOLD_PIECE)), money_cnt(invent), hp,
-            hpmax, u.uen, u.uenmax, u.uac);
+#if 0 /*JP*/
+    Sprintf(hlth, "HP:%d(%d) Pw:%d(%d) AC:%-2d",
+            min(hp, 9999), min(hpmax, 9999),
+            min(u.uen, 9999), min(u.uenmax, 9999), u.uac);
+#else
+    Sprintf(hlth, "\91Ì:%d(%d) \96\82:%d(%d) \8aZ:%-2d",
+            min(hp, 9999), min(hpmax, 9999),
+            min(u.uen, 9999), min(u.uenmax, 9999), u.uac);
+#endif
+    hln = strlen(hlth);
 
+    /* experience */
     if (Upolyd)
-        Sprintf(nb = eos(nb), " HD:%d", mons[u.umonnum].mlevel);
+        Sprintf(expr, "HD:%d", mons[u.umonnum].mlevel);
     else if (flags.showexp)
 /*JP
-        Sprintf(nb = eos(nb), " Xp:%u/%-1ld", u.ulevel, u.uexp);
+        Sprintf(expr, "Xp:%u/%-1ld", u.ulevel, u.uexp);
 */
-        Sprintf(nb = eos(nb), " \8co\8c±:%u/%-1ld", u.ulevel,u.uexp);
+        Sprintf(expr, "\8co\8c±:%u/%-1ld", u.ulevel, u.uexp);
     else
 /*JP
-        Sprintf(nb = eos(nb), " Exp:%u", u.ulevel);
+        Sprintf(expr, "Exp:%u", u.ulevel);
 */
-        Sprintf(nb = eos(nb), " \8co\8c±:%u", u.ulevel);
+        Sprintf(expr, "\8co\8c±:%u", u.ulevel);
+    xln = strlen(expr);
 
+    /* time/move counter */
     if (flags.time)
 /*JP
-        Sprintf(nb = eos(nb), " T:%ld", moves);
+        Sprintf(tmmv, "T:%ld", moves);
 */
-        Sprintf(nb = eos(nb), " \95à:%ld", moves);
-    if (strcmp(hu_stat[u.uhs], "        ")) {
-        Sprintf(nb = eos(nb), " ");
-        Strcat(newbot2, hu_stat[u.uhs]);
-    }
-    if (Confusion)
+        Sprintf(tmmv, "\95à:%ld", moves);
+    else
+        tmmv[0] = '\0';
+    tln = strlen(tmmv);
+
+    /* status conditions; worst ones first */
+    cond[0] = '\0'; /* once non-empty, cond will have a leading space */
+    nb = cond;
+    /*
+     * Stoned, Slimed, Strangled, and both types of Sick are all fatal
+     * unless remedied before timeout expires.  Should we order them by
+     * shortest time left?  [Probably not worth the effort, since it's
+     * unusual for more than one of them to apply at a time.]
+     */
+    if (Stoned)
+        Strcpy(nb = eos(nb), " Stone");
+    if (Slimed)
 /*JP
-        Sprintf(nb = eos(nb), " Conf");
+        Strcpy(nb = eos(nb), " Slime");
 */
-        Sprintf(nb = eos(nb), " \8d¬\97\90");
+        Strcpy(nb = eos(nb), " \82Ç\82ë\82Ç\82ë");
+    if (Strangled)
+        Strcpy(nb = eos(nb), " Strngl");
     if (Sick) {
         if (u.usick_type & SICK_VOMITABLE)
 /*JP
-            Sprintf(nb = eos(nb), " FoodPois");
+            Strcpy(nb = eos(nb), " FoodPois");
 */
-            Sprintf(nb = eos(nb), " \90H\93Å");
+            Strcpy(nb = eos(nb), " \90H\93Å");
         if (u.usick_type & SICK_NONVOMITABLE)
 /*JP
-            Sprintf(nb = eos(nb), " Ill");
+            Strcpy(nb = eos(nb), " TermIll");
 */
-            Sprintf(nb = eos(nb), " \95a\8bC");
+            Strcpy(nb = eos(nb), " \95a\8bC");
     }
+    if (u.uhs != NOT_HUNGRY)
+        Sprintf(nb = eos(nb), " %s", hu_stat[u.uhs]);
+    if ((cap = near_capacity()) > UNENCUMBERED)
+        Sprintf(nb = eos(nb), " %s", enc_stat[cap]);
     if (Blind)
 /*JP
-        Sprintf(nb = eos(nb), " Blind");
+        Strcpy(nb = eos(nb), " Blind");
 */
-        Sprintf(nb = eos(nb), " \96Ó\96Ú");
+        Strcpy(nb = eos(nb), " \96Ó\96Ú");
+    if (Deaf)
+        Strcpy(nb = eos(nb), " Deaf");
     if (Stunned)
 /*JP
-        Sprintf(nb = eos(nb), " Stun");
+        Strcpy(nb = eos(nb), " Stun");
 */
-        Sprintf(nb = eos(nb), " á¿\9dò");
-    if (Hallucination)
+        Strcpy(nb = eos(nb), " á¿\9dò");
+    if (Confusion)
 /*JP
-        Sprintf(nb = eos(nb), " Hallu");
+        Strcpy(nb = eos(nb), " Conf");
 */
-        Sprintf(nb = eos(nb), " \8c\8ao");
-    if (Slimed)
+        Strcpy(nb = eos(nb), " \8d¬\97\90");
+    if (Hallucination)
 /*JP
-        Sprintf(nb = eos(nb), " Slime");
+        Strcpy(nb = eos(nb), " Hallu");
 */
-        Sprintf(nb = eos(nb), " \82Ç\82ë\82Ç\82ë");
-    if (cap > UNENCUMBERED)
-        Sprintf(nb = eos(nb), " %s", enc_stat[cap]);
-    curs(WIN_STATUS, 1, 1);
-    putmixed(WIN_STATUS, 0, newbot2);
+        Strcpy(nb = eos(nb), " \8c\8ao");
+    /* levitation and flying are mutually exclusive; riding is not */
+    if (Levitation)
+        Strcpy(nb = eos(nb), " Lev");
+    if (Flying)
+        Strcpy(nb = eos(nb), " Fly");
+    if (u.usteed)
+        Strcpy(nb = eos(nb), " Ride");
+    cln = strlen(cond);
+
+    /*
+     * Put the pieces together.  If they all fit, keep the traditional
+     * sequence.  Otherwise, move least important parts to the end in
+     * case the interface side of things has to truncate.  Note that
+     * dloc[] contains '$' encoded in ten character sequence \GXXXXNNNN
+     * so we want to test its display length rather than buffer length.
+     *
+     * We don't have an actual display limit here, so have to go by the
+     * width of the map.  Since we're reordering rather than truncating,
+     * wider displays can still show wider status than the map if the
+     * interface supports that.
+     */
+    if ((dln - dx) + 1 + hln + 1 + xln + 1 + tln + 1 + cln <= COLNO) {
+        Sprintf(newbot2, "%s %s %s %s %s", dloc, hlth, expr, tmmv, cond);
+    } else {
+        if (dln + 1 + hln + 1 + xln + 1 + tln + 1 + cln + 1 > MAXCO) {
+            panic("bot2: second status line exceeds MAXCO (%u > %d)",
+                  (dln + 1 + hln + 1 + xln + 1 + tln + 1 + cln + 1), MAXCO);
+        } else if ((dln - dx) + 1 + hln + 1 + xln + 1 + cln <= COLNO) {
+            Sprintf(newbot2, "%s %s %s %s %s", dloc, hlth, expr, cond, tmmv);
+        } else if ((dln - dx) + 1 + hln + 1 + cln <= COLNO) {
+            Sprintf(newbot2, "%s %s %s %s %s", dloc, hlth, cond, expr, tmmv);
+        } else {
+            Sprintf(newbot2, "%s %s %s %s %s", hlth, cond, dloc, expr, tmmv);
+        }
+        /* only two or three consecutive spaces available to squeeze out */
+        mungspaces(newbot2);
+    }
+    return newbot2;
 }
 
 void
 bot()
 {
-    if (youmonst.data) {
-        bot1();
-        bot2();
+    if (youmonst.data && iflags.status_updates) {
+#ifdef STATUS_HILITES
+        bot_via_windowport();
+#else
+        curs(WIN_STATUS, 1, 0);
+        putstr(WIN_STATUS, 0, do_statusline1());
+        curs(WIN_STATUS, 1, 1);
+        putmixed(WIN_STATUS, 0, do_statusline2());
+#endif
     }
     context.botl = context.botlx = 0;
 }
 
-#endif /* !STATUS_VIA_WINDOWPORT */
-
 /* convert experience level (1..30) to rank index (0..8) */
 int
 xlev_to_rank(xlev)
@@ -370,164 +471,179 @@ char *buf;
     return ret;
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
+/* =======================================================================*/
+/*  statusnew routines                                                    */
 /* =======================================================================*/
 
 /* structure that tracks the status details in the core */
+
+#ifdef STATUS_HILITES
+struct hilite_s {
+    enum statusfields fld;
+    boolean set;
+    unsigned anytype;
+    anything value;
+    int behavior;
+    char textmatch[QBUFSZ];
+    enum relationships rel;
+    int coloridx;
+    struct hilite_s *next;
+};
+
+struct condmap {
+    const char *id;
+    unsigned long bitmask;
+};
+#endif /* STATUS_HILITES */
+
 struct istat_s {
-    long time;
+    const char *fldname;
+    const char *fldfmt;
+    long time;  /* moves when this field hilite times out */
+    boolean chg; /* need to recalc time? */
     unsigned anytype;
     anything a;
     char *val;
     int valwidth;
     enum statusfields idxmax;
     enum statusfields fld;
+#ifdef STATUS_HILITES
+    struct hilite_s *thresholds;
+#endif
 };
 
 
 STATIC_DCL void NDECL(init_blstats);
 STATIC_DCL char *FDECL(anything_to_s, (char *, anything *, int));
-STATIC_DCL void FDECL(s_to_anything, (anything *, char *, int));
 STATIC_OVL int FDECL(percentage, (struct istat_s *, struct istat_s *));
 STATIC_OVL int FDECL(compare_blstats, (struct istat_s *, struct istat_s *));
+STATIC_DCL boolean FDECL(evaluate_and_notify_windowport_field,
+                         (int, boolean *, int, int));
+STATIC_DCL void FDECL(evaluate_and_notify_windowport, (boolean *, int, int));
 
 #ifdef STATUS_HILITES
-STATIC_DCL boolean FDECL(assign_hilite, (char *, char *, char *, char *,
-                                         BOOLEAN_P));
-STATIC_DCL const char *FDECL(clridx_to_s, (char *, int));
+STATIC_DCL boolean FDECL(hilite_reset_needed, (struct istat_s *, long));
+STATIC_DCL void FDECL(s_to_anything, (anything *, char *, int));
+STATIC_DCL boolean FDECL(is_ltgt_percentnumber, (const char *));
+STATIC_DCL boolean FDECL(has_ltgt_percentnumber, (const char *));
+STATIC_DCL boolean FDECL(parse_status_hl2, (char (*)[QBUFSZ],BOOLEAN_P));
+STATIC_DCL boolean FDECL(parse_condition, (char (*)[QBUFSZ], int));
+STATIC_DCL void FDECL(merge_bestcolor, (int *, int));
+STATIC_DCL void FDECL(get_hilite_color, (int, int, genericptr_t, int,
+                                                int, int *));
+STATIC_DCL unsigned long FDECL(match_str2conditionbitmask, (const char *));
+STATIC_DCL unsigned long FDECL(str2conditionbitmask, (char *));
+STATIC_DCL void FDECL(split_clridx, (int, int *, int *));
+STATIC_DCL char *FDECL(hlattr2attrname, (int, char *, int));
+STATIC_DCL void FDECL(status_hilite_linestr_add, (int, struct hilite_s *,
+                                            unsigned long, const char *));
+
+STATIC_DCL void NDECL(status_hilite_linestr_done);
+STATIC_DCL int FDECL(status_hilite_linestr_countfield, (int));
+STATIC_DCL void NDECL(status_hilite_linestr_gather_conditions);
+STATIC_DCL void NDECL(status_hilite_linestr_gather);
+STATIC_DCL char *FDECL(status_hilite2str, (struct hilite_s *));
+STATIC_DCL boolean FDECL(status_hilite_menu_add, (int));
+#define has_hilite(i) (blstats[0][(i)].thresholds)
 #endif
 
+#define INIT_BLSTAT(name, fmtstr, anytyp, wid, fld)                     \
+    { name, fmtstr, 0L, FALSE, anytyp,  { (genericptr_t) 0 }, (char *) 0, \
+      wid,  -1, fld }
+#define INIT_BLSTATP(name, fmtstr, anytyp, wid, maxfld, fld)            \
+    { name, fmtstr, 0L, FALSE, anytyp,  { (genericptr_t) 0 }, (char *) 0, \
+      wid,  maxfld, fld }
+
 /* If entries are added to this, botl.h will require updating too */
 STATIC_DCL struct istat_s initblstats[MAXBLSTATS] = {
-    { 0L, ANY_STR,  { (genericptr_t) 0 }, (char *) 0, 80,  0, BL_TITLE},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_STR},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_DX},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_CO},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_IN},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_WI},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_CH},
-    { 0L, ANY_STR,  { (genericptr_t) 0 }, (char *) 0, 40,  0, BL_ALIGN},
-    { 0L, ANY_LONG, { (genericptr_t) 0 }, (char *) 0, 20,  0, BL_SCORE},
-    { 0L, ANY_LONG, { (genericptr_t) 0 }, (char *) 0, 20,  0, BL_CAP},
-    { 0L, ANY_LONG, { (genericptr_t) 0 }, (char *) 0, 30,  0, BL_GOLD},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  BL_ENEMAX, BL_ENE},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_ENEMAX},
-    { 0L, ANY_LONG, { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_XP},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_AC},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_HD},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 20,  0, BL_TIME},
-    { 0L, ANY_UINT, { (genericptr_t) 0 }, (char *) 0, 40,  0, BL_HUNGER},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  BL_HPMAX, BL_HP},
-    { 0L, ANY_INT,  { (genericptr_t) 0 }, (char *) 0, 10,  0, BL_HPMAX},
-    { 0L, ANY_STR,  { (genericptr_t) 0 }, (char *) 0, 80,  0, BL_LEVELDESC},
-    { 0L, ANY_LONG, { (genericptr_t) 0 }, (char *) 0, 20,  0, BL_EXP},
-    { 0L, ANY_MASK32,
-                    { (genericptr_t) 0 }, (char *) 0,  0,  0, BL_CONDITION}
+    INIT_BLSTAT("title", "%s", ANY_STR, 80, BL_TITLE),
+    INIT_BLSTAT("strength", " St:%s", ANY_INT, 10, BL_STR),
+    INIT_BLSTAT("dexterity", " Dx:%s", ANY_INT,  10, BL_DX),
+    INIT_BLSTAT("constitution", " Co:%s", ANY_INT, 10, BL_CO),
+    INIT_BLSTAT("intelligence", " In:%s", ANY_INT, 10, BL_IN),
+    INIT_BLSTAT("wisdom", " Wi:%s", ANY_INT, 10, BL_WI),
+    INIT_BLSTAT("charisma", " Ch:%s", ANY_INT, 10, BL_CH),
+    INIT_BLSTAT("alignment", " %s", ANY_STR, 40, BL_ALIGN),
+    INIT_BLSTAT("score", " S:%s", ANY_LONG, 20, BL_SCORE),
+    INIT_BLSTAT("carrying-capacity", " %s", ANY_LONG, 20, BL_CAP),
+    INIT_BLSTAT("gold", " %s", ANY_LONG, 30, BL_GOLD),
+    INIT_BLSTATP("power", " Pw:%s", ANY_INT, 10, BL_ENEMAX, BL_ENE),
+    INIT_BLSTAT("power-max", "(%s)", ANY_INT, 10, BL_ENEMAX),
+    INIT_BLSTAT("experience-level", " Xp:%s", ANY_LONG, 10, BL_XP),
+    INIT_BLSTAT("armor-class", " AC:%s", ANY_INT, 10, BL_AC),
+    INIT_BLSTAT("HD", " HD:%s", ANY_INT, 10, BL_HD),
+    INIT_BLSTAT("time", " T:%s", ANY_INT, 20, BL_TIME),
+    INIT_BLSTAT("hunger", " %s", ANY_UINT, 40, BL_HUNGER),
+    INIT_BLSTATP("hitpoints", " HP:%s", ANY_INT, 10, BL_HPMAX, BL_HP),
+    INIT_BLSTAT("hitpoints-max", "(%s)", ANY_INT, 10, BL_HPMAX),
+    INIT_BLSTAT("dungeon-level", "%s", ANY_STR, 80, BL_LEVELDESC),
+    INIT_BLSTAT("experience", "/%s", ANY_LONG, 20, BL_EXP),
+    INIT_BLSTAT("condition", "%s", ANY_MASK32, 0, BL_CONDITION)
 };
 
-static struct fieldid_t {
-        const char *fieldname;
-        enum statusfields fldid;
-} fieldids[] = {
-        {"title",               BL_TITLE},
-        {"strength",            BL_STR},
-        {"dexterity",           BL_DX},
-        {"constitution",        BL_CO},
-        {"intelligence",        BL_IN},
-        {"wisdom",              BL_WI},
-        {"charisma",            BL_CH},
-        {"alignment",           BL_ALIGN},
-        {"score",               BL_SCORE},
-        {"carrying-capacity",   BL_CAP},
-        {"gold",                BL_GOLD},
-        {"power",               BL_ENE},
-        {"power-max",           BL_ENEMAX},
-        {"experience-level",    BL_XP},
-        {"armor-class",         BL_AC},
-        {"HD",                  BL_HD},
-        {"time",                BL_TIME},
-        {"hunger",              BL_HUNGER},
-        {"hitpoints",           BL_HP},
-        {"hitpoints-max",       BL_HPMAX},
-        {"dungeon-level",       BL_LEVELDESC},
-        {"experience",          BL_EXP},
-        {"condition",           BL_CONDITION},
-};
+#undef INIT_BLSTATP
+#undef INIT_BLSTAT
 
 struct istat_s blstats[2][MAXBLSTATS];
 static boolean blinit = FALSE, update_all = FALSE;
+static boolean valset[MAXBLSTATS];
+unsigned long blcolormasks[CLR_MAX];
+static long bl_hilite_moves = 0L;
+
+/* we don't put this next declaration in #ifdef STATUS_HILITES.
+ * In the absence of STATUS_HILITES, each array
+ * element will be 0 however, and quite meaningless,
+ * but we need to pass the first array element as
+ * the final argument of status_update, with or
+ * without STATUS_HILITES.
+ */
+unsigned long cond_hilites[BL_ATTCLR_MAX];
 
 void
-bot()
+bot_via_windowport()
 {
     char buf[BUFSZ];
     register char *nb;
-    static int idx = 0, idx_p, idxmax;
-    boolean updated = FALSE;
-    unsigned anytype;
-    int i, pc, chg, cap;
-    struct istat_s *curr, *prev;
-    boolean valset[MAXBLSTATS], chgval = FALSE;
+    static int i, idx = 0, idx_p, cap;
+    long money;
 
     if (!blinit)
         panic("bot before init.");
-    if (!youmonst.data) {
-        context.botl = context.botlx = 0;
-        update_all = FALSE;
-        return;
-    }
 
-    cap = near_capacity();
     idx_p = idx;
     idx = 1 - idx; /* 0 -> 1, 1 -> 0 */
 
     /* clear the "value set" indicators */
-    (void) memset((genericptr_t) valset, 0, MAXBLSTATS * sizeof(boolean));
+    (void) memset((genericptr_t) valset, 0, MAXBLSTATS * sizeof (boolean));
+
+    /*
+     * Note: min(x,9999) - we enforce the same maximum on hp, maxhp,
+     * pw, maxpw, and gold as basic status formatting so that the two
+     * modes of status display don't produce different information.
+     */
 
     /*
      *  Player name and title.
      */
-    buf[0] = '\0';
-    Strcpy(buf, plname);
-    if ('a' <= buf[0] && buf[0] <= 'z')
-        buf[0] += 'A' - 'a';
-    buf[10] = 0;
-    Sprintf(nb = eos(buf), " the ");
+    Strcpy(nb = buf, plname);
+    nb[0] = highc(nb[0]);
+    nb[10] = '\0';
+    Sprintf(nb = eos(nb), " the ");
     if (Upolyd) {
-        char mbot[BUFSZ];
-        int k = 0;
-
-        Strcpy(mbot, mons[u.umonnum].mname);
-        while (mbot[k] != 0) {
-            if ((k == 0 || (k > 0 && mbot[k - 1] == ' ')) && 'a' <= mbot[k]
-                && mbot[k] <= 'z')
-                mbot[k] += 'A' - 'a';
-            k++;
-        }
-        Sprintf1(nb = eos(nb), mbot);
+        for (i = 0, nb = strcpy(eos(nb), mons[u.umonnum].mname); nb[i]; i++)
+            if (i == 0 || nb[i - 1] == ' ')
+                nb[i] = highc(nb[i]);
     } else
-        Sprintf1(nb = eos(nb), rank());
+        Strcpy(nb = eos(nb), rank());
     Sprintf(blstats[idx][BL_TITLE].val, "%-29s", buf);
     valset[BL_TITLE] = TRUE; /* indicate val already set */
 
     /* Strength */
-
-    buf[0] = '\0';
     blstats[idx][BL_STR].a.a_int = ACURR(A_STR);
-    if (ACURR(A_STR) > 18) {
-        if (ACURR(A_STR) > STR18(100))
-            Sprintf(buf, "%2d", ACURR(A_STR) - 100);
-        else if (ACURR(A_STR) < STR18(100))
-            Sprintf(buf, "18/%02d", ACURR(A_STR) - 18);
-        else
-            Sprintf(buf, "18/**");
-    } else
-        Sprintf(buf, "%-1d", ACURR(A_STR));
-    Strcpy(blstats[idx][BL_STR].val, buf);
+    Strcpy(blstats[idx][BL_STR].val, get_strength_str());
     valset[BL_STR] = TRUE; /* indicate val already set */
 
     /*  Dexterity, constitution, intelligence, wisdom, charisma. */
-
     blstats[idx][BL_DX].a.a_int = ACURR(A_DEX);
     blstats[idx][BL_CO].a.a_int = ACURR(A_CON);
     blstats[idx][BL_IN].a.a_int = ACURR(A_INT);
@@ -535,130 +651,200 @@ bot()
     blstats[idx][BL_CH].a.a_int = ACURR(A_CHA);
 
     /* Alignment */
-
-    Strcpy(blstats[idx][BL_ALIGN].val,
-           (u.ualign.type == A_CHAOTIC)
-               ? "Chaotic"
-               : (u.ualign.type == A_NEUTRAL) ? "Neutral" : "Lawful");
+    Strcpy(blstats[idx][BL_ALIGN].val, (u.ualign.type == A_CHAOTIC)
+                                          ? "Chaotic"
+                                          : (u.ualign.type == A_NEUTRAL)
+                                               ? "Neutral"
+                                               : "Lawful");
 
     /* Score */
-
     blstats[idx][BL_SCORE].a.a_long =
 #ifdef SCORE_ON_BOTL
-        botl_score();
-#else
-        0;
+        flags.showscore ? botl_score() :
 #endif
-    /*  Hit points  */
+        0L;
 
-    blstats[idx][BL_HP].a.a_int = Upolyd ? u.mh : u.uhp;
-    blstats[idx][BL_HPMAX].a.a_int = Upolyd ? u.mhmax : u.uhpmax;
-    if (blstats[idx][BL_HP].a.a_int < 0)
-        blstats[idx][BL_HP].a.a_int = 0;
+    /*  Hit points  */
+    i = Upolyd ? u.mh : u.uhp;
+    if (i < 0)
+        i = 0;
+    blstats[idx][BL_HP].a.a_int = min(i, 9999);
+    i = Upolyd ? u.mhmax : u.uhpmax;
+    blstats[idx][BL_HPMAX].a.a_int = min(i, 9999);
 
     /*  Dungeon level. */
-
     (void) describe_level(blstats[idx][BL_LEVELDESC].val);
     valset[BL_LEVELDESC] = TRUE; /* indicate val already set */
 
     /* Gold */
-
-    blstats[idx][BL_GOLD].a.a_long = money_cnt(invent);
+    if ((money = money_cnt(invent)) < 0L)
+        money = 0L; /* ought to issue impossible() and then discard gold */
+    blstats[idx][BL_GOLD].a.a_long = min(money, 999999L);
     /*
      * The tty port needs to display the current symbol for gold
      * as a field header, so to accommodate that we pass gold with
      * that already included. If a window port needs to use the text
      * gold amount without the leading "$:" the port will have to
-     * add 2 to the value pointer it was passed in status_update()
+     * skip past ':' to the value pointer it was passed in status_update()
      * for the BL_GOLD case.
      *
      * Another quirk of BL_GOLD is that the field display may have
      * changed if a new symbol set was loaded, or we entered or left
      * the rogue level.
+     *
+     * The currency prefix is encoded as ten character \GXXXXNNNN
+     * sequence.
      */
-
     Sprintf(blstats[idx][BL_GOLD].val, "%s:%ld",
             encglyph(objnum_to_glyph(GOLD_PIECE)),
             blstats[idx][BL_GOLD].a.a_long);
     valset[BL_GOLD] = TRUE; /* indicate val already set */
 
     /* Power (magical energy) */
-
-    blstats[idx][BL_ENE].a.a_int = u.uen;
-    blstats[idx][BL_ENEMAX].a.a_int = u.uenmax;
+    blstats[idx][BL_ENE].a.a_int = min(u.uen, 9999);
+    blstats[idx][BL_ENEMAX].a.a_int = min(u.uenmax, 9999);
 
     /* Armor class */
-
     blstats[idx][BL_AC].a.a_int = u.uac;
 
     /* Monster level (if Upolyd) */
-
-    if (Upolyd)
-        blstats[idx][BL_HD].a.a_int = mons[u.umonnum].mlevel;
-    else
-        blstats[idx][BL_HD].a.a_int = 0;
+    blstats[idx][BL_HD].a.a_int = Upolyd ? (int) mons[u.umonnum].mlevel : 0;
 
     /* Experience */
-
     blstats[idx][BL_XP].a.a_int = u.ulevel;
     blstats[idx][BL_EXP].a.a_int = u.uexp;
 
     /* Time (moves) */
-
     blstats[idx][BL_TIME].a.a_long = moves;
 
     /* Hunger */
-
     blstats[idx][BL_HUNGER].a.a_uint = u.uhs;
-    *(blstats[idx][BL_HUNGER].val) = '\0';
-    if (strcmp(hu_stat[u.uhs], "        ") != 0)
-        Strcpy(blstats[idx][BL_HUNGER].val, hu_stat[u.uhs]);
+    Strcpy(blstats[idx][BL_HUNGER].val,
+           (u.uhs != NOT_HUNGRY) ? hu_stat[u.uhs] : "");
     valset[BL_HUNGER] = TRUE;
 
     /* Carrying capacity */
-
-    *(blstats[idx][BL_CAP].val) = '\0';
+    cap = near_capacity();
     blstats[idx][BL_CAP].a.a_int = cap;
-    if (cap > UNENCUMBERED)
-        Strcpy(blstats[idx][BL_CAP].val, enc_stat[cap]);
+    Strcpy(blstats[idx][BL_CAP].val,
+           (cap > UNENCUMBERED) ? enc_stat[cap] : "");
     valset[BL_CAP] = TRUE;
 
     /* Conditions */
-
+    blstats[idx][BL_CONDITION].a.a_ulong = 0L;
+    if (Stoned)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_STONE;
+    if (Slimed)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_SLIME;
+    if (Strangled)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_STRNGL;
+    if (Sick && (u.usick_type & SICK_VOMITABLE) != 0)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_FOODPOIS;
+    if (Sick && (u.usick_type & SICK_NONVOMITABLE) != 0)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_TERMILL;
+    /*
+     * basic formatting puts hunger status and encumbrance here
+     */
     if (Blind)
         blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_BLIND;
-    else
-        blstats[idx][BL_CONDITION].a.a_ulong &= ~BL_MASK_BLIND;
-
+    if (Deaf)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_DEAF;
+    if (Stunned)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_STUN;
     if (Confusion)
         blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_CONF;
-    else
-        blstats[idx][BL_CONDITION].a.a_ulong &= ~BL_MASK_CONF;
+    if (Hallucination)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_HALLU;
+    /* levitation and flying are mututally exclusive */
+    if (Levitation)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_LEV;
+    if (Flying)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_FLY;
+    if (u.usteed)
+        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_RIDE;
+    evaluate_and_notify_windowport(valset, idx, idx_p);
+}
 
-    if (Sick && u.usick_type & SICK_VOMITABLE)
-        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_FOODPOIS;
-    else
-        blstats[idx][BL_CONDITION].a.a_ulong &= ~BL_MASK_FOODPOIS;
+STATIC_OVL boolean
+evaluate_and_notify_windowport_field(fld, valsetlist, idx, idx_p)
+int fld, idx, idx_p;
+boolean *valsetlist;
+{
+    static int oldrndencode = 0;
+    int pc, chg, color = NO_COLOR;
+    unsigned anytype;
+    boolean updated = FALSE, reset;
+    struct istat_s *curr = NULL, *prev = NULL;
+    enum statusfields idxmax;
 
-    if (Sick && u.usick_type & SICK_NONVOMITABLE)
-        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_ILL;
-    else
-        blstats[idx][BL_CONDITION].a.a_ulong &= ~BL_MASK_ILL;
+    /*
+     *  Now pass the changed values to window port.
+     */
+    anytype = blstats[idx][fld].anytype;
+    curr = &blstats[idx][fld];
+    prev = &blstats[idx_p][fld];
+    color = NO_COLOR;
+
+    chg = update_all ? 0 : compare_blstats(prev, curr);
+
+    /* Temporary? hack: moveloop()'s prolog for a new game sets
+     * context.rndencode after the status window has been init'd,
+     * so $:0 has already been encoded and cached by the window
+     * port.  Without this hack, gold's \G sequence won't be
+     * recognized and ends up being displayed as-is for 'update_all'.
+     */
+    if (context.rndencode != oldrndencode && fld == BL_GOLD) {
+        chg = 2;
+        oldrndencode = context.rndencode;
+    }
 
-    if (Hallucination)
-        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_HALLU;
-    else
-        blstats[idx][BL_CONDITION].a.a_ulong &= ~BL_MASK_HALLU;
+    reset = FALSE;
+#ifdef STATUS_HILITES
+    if (!update_all && !chg) {
+        reset = hilite_reset_needed(prev, bl_hilite_moves);
+        if (reset)
+          curr->time = prev->time = 0L;
+    }
+#endif
 
-    if (Stunned)
-        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_STUNNED;
-    else
-        blstats[idx][BL_CONDITION].a.a_ulong &= ~BL_MASK_STUNNED;
+    if (update_all || chg || reset) {
+        idxmax = curr->idxmax;
+        pc = (idxmax > BL_FLUSH) ? percentage(curr, &blstats[idx][idxmax]) : 0;
 
-    if (Slimed)
-        blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_SLIMED;
-    else
-        blstats[idx][BL_CONDITION].a.a_ulong &= ~BL_MASK_SLIMED;
+        if (!valsetlist[fld])
+            (void) anything_to_s(curr->val, &curr->a, anytype);
+
+        if (anytype != ANY_MASK32) {
+#ifdef STATUS_HILITES
+            if ((chg || *curr->val)) {
+                get_hilite_color(idx, fld, (genericptr_t)&curr->a,
+                                 chg, pc, &color);
+                if (chg == 2) {
+                    color = NO_COLOR;
+                    chg = 0;
+                }
+            }
+#endif /* STATUS_HILITES */
+            status_update(fld, (genericptr_t) curr->val,
+                          chg, pc, color, &cond_hilites[0]);
+        } else {
+            /* Color for conditions is done through cond_hilites[] */
+            status_update(fld, (genericptr_t) &curr->a.a_ulong, chg, pc,
+                          color, &cond_hilites[0]);
+        }
+        curr->chg = prev->chg = TRUE;
+        updated = TRUE;
+    }
+    return updated;
+}
+
+static void
+evaluate_and_notify_windowport(valsetlist, idx, idx_p)
+int idx, idx_p;
+boolean *valsetlist;
+{
+    int i;
+    boolean updated = FALSE;
 
     /*
      *  Now pass the changed values to window port.
@@ -670,28 +856,8 @@ bot()
             || ((i == BL_HD) && !Upolyd)
             || ((i == BL_XP || i == BL_EXP) && Upolyd))
             continue;
-        anytype = blstats[idx][i].anytype;
-        curr = &blstats[idx][i];
-        prev = &blstats[idx_p][i];
-        chg = 0;
-        if (update_all || ((chg = compare_blstats(prev, curr)) != 0)
-            || ((chgval = (valset[i] && strcmp(blstats[idx][i].val,
-                                               blstats[idx_p][i].val)))
-                != 0)) {
-            idxmax = blstats[idx][i].idxmax;
-            pc = (idxmax) ? percentage(curr, &blstats[idx][idxmax]) : 0;
-            if (!valset[i])
-                (void) anything_to_s(curr->val, &curr->a, anytype);
-            if (anytype != ANY_MASK32) {
-                status_update(i, (genericptr_t) curr->val,
-                              valset[i] ? chgval : chg, pc);
-            } else {
-                status_update(i,
-                              /* send pointer to mask */
-                              (genericptr_t) &curr->a.a_ulong, chg, 0);
-            }
+        if (evaluate_and_notify_windowport_field(i, valsetlist, idx, idx_p))
             updated = TRUE;
-        }
     }
     /*
      * It is possible to get here, with nothing having been pushed
@@ -704,158 +870,78 @@ bot()
      * To work around it, we call status_update() with fictitious
      * index of BL_FLUSH (-1).
      */
-    if (context.botlx && !updated)
-        status_update(BL_FLUSH, (genericptr_t) 0, 0, 0);
+    if ((context.botlx && !updated)
+        || (windowprocs.wincap2 & WC2_FLUSH_STATUS) != 0L)
+        status_update(BL_FLUSH, (genericptr_t) 0, 0, 0,
+                      NO_COLOR, &cond_hilites[0]);
 
     context.botl = context.botlx = 0;
     update_all = FALSE;
 }
 
 void
+status_eval_next_unhilite()
+{
+    int i;
+    struct istat_s *curr = NULL;
+    long next_unhilite, this_unhilite;
+
+    bl_hilite_moves = moves;
+    /* figure out when the next unhilight needs to be performed */
+    next_unhilite = 0L;
+    for (i = 0; i < MAXBLSTATS; ++i) {
+        curr = &blstats[0][i]; /* blstats[0][*].time == blstats[1][*].time */
+
+        if (curr->chg) {
+            struct istat_s *prev = &blstats[1][i];
+
+#ifdef STATUS_HILITES
+            curr->time = prev->time = (bl_hilite_moves + iflags.hilite_delta);
+#endif
+            curr->chg = prev->chg = FALSE;
+        }
+
+        this_unhilite = curr->time;
+        if (this_unhilite > 0L
+            && (next_unhilite == 0L || this_unhilite < next_unhilite)
+#ifdef STATUS_HILITES
+            && hilite_reset_needed(curr, this_unhilite + 1L)
+#endif
+            )
+            next_unhilite = this_unhilite;
+    }
+    if (next_unhilite > 0L && next_unhilite < bl_hilite_moves)
+        context.botl = TRUE;
+}
+
+void
 status_initialize(reassessment)
 boolean
     reassessment; /* TRUE = just reassess fields w/o other initialization*/
 {
     int i;
-    const char *fieldfmt = (const char *)0;
-    const char *fieldname = (const char *)0;
+    const char *fieldfmt = (const char *) 0;
+    const char *fieldname = (const char *) 0;
 
     if (!reassessment) {
+        if (blinit)
+            impossible("2nd status_initialize with full init.");
         init_blstats();
         (*windowprocs.win_status_init)();
         blinit = TRUE;
-#ifdef STATUS_HILITES
-        status_notify_windowport(TRUE);
-#endif
     }
     for (i = 0; i < MAXBLSTATS; ++i) {
         enum statusfields fld = initblstats[i].fld;
-
-        switch (fld) {
-        case BL_TITLE:
-            fieldfmt = "%s";
-            fieldname = "title";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_STR:
-            fieldfmt = " St:%s";
-            fieldname = "strength";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_DX:
-            fieldfmt = " Dx:%s";
-            fieldname = "dexterity";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_CO:
-            fieldfmt = " Co:%s";
-            fieldname = "constitution";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_IN:
-            fieldfmt = " In:%s";
-            fieldname = "intelligence";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_WI:
-            fieldfmt = " Wi:%s";
-            fieldname = "wisdom";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_CH:
-            fieldfmt = " Ch:%s";
-            fieldname = "charisma";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_ALIGN:
-            fieldfmt = " %s";
-            fieldname = "alignment";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_SCORE:
-            fieldfmt = " S:%s";
-            fieldname = "score";
-            status_enablefield(fld, fieldname, fieldfmt,
-                               (!flags.showscore) ? FALSE : TRUE);
-            break;
-        case BL_CAP:
-            fieldfmt = " %s";
-            fieldname = "carrying-capacity";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_GOLD:
-            fieldfmt = " %s";
-            fieldname = "gold";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_ENE:
-            fieldfmt = " Pw:%s";
-            fieldname = "power";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_ENEMAX:
-            fieldfmt = "(%s)";
-            fieldname = "power-max";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_XP:
-            fieldfmt = " Xp:%s";
-            fieldname = "experience-level";
-            status_enablefield(fld, fieldname, fieldfmt,
-                                   (Upolyd) ? FALSE : TRUE);
-            break;
-        case BL_AC:
-            fieldfmt = " AC:%s";
-            fieldname = "armor-class";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_HD:
-            fieldfmt = " HD:%s";
-            fieldname = "HD";
-            status_enablefield(fld, fieldname, fieldfmt,
-                                   (!Upolyd) ? FALSE : TRUE);
-            break;
-        case BL_TIME:
-            fieldfmt = " T:%s";
-            fieldname = "time";
-            status_enablefield(fld, fieldname, fieldfmt,
-                                   (!flags.time) ? FALSE : TRUE);
-            break;
-        case BL_HUNGER:
-            fieldfmt = " %s";
-            fieldname = "hunger";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_HP:
-            fieldfmt = " HP:%s";
-            fieldname = "hitpoints";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_HPMAX:
-            fieldfmt = "(%s)";
-            fieldname = "hitpoint-max";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_LEVELDESC:
-            fieldfmt = "%s";
-            fieldname = "dungeon-level";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_EXP:
-            fieldfmt = "/%s";
-            fieldname = "experience";
-            status_enablefield(fld, fieldname, fieldfmt,
-                                  (!flags.showexp || Upolyd) ? FALSE : TRUE);
-            break;
-        case BL_CONDITION:
-            fieldfmt = "%S";
-            fieldname = "condition";
-            status_enablefield(fld, fieldname, fieldfmt, TRUE);
-            break;
-        case BL_FLUSH:
-        default:
-            break;
-        }
+        boolean fldenabled = (fld == BL_SCORE) ? flags.showscore
+            : (fld == BL_XP) ? (boolean) !Upolyd
+            : (fld == BL_HD) ? (boolean) Upolyd
+            : (fld == BL_TIME) ? flags.time
+            : (fld == BL_EXP) ? (boolean) (flags.showexp && !Upolyd)
+            : TRUE;
+
+        fieldname = initblstats[i].fldname;
+        fieldfmt = initblstats[i].fldfmt;
+        status_enablefield(fld, fieldname, fieldfmt, fldenabled);
     }
     update_all = TRUE;
 }
@@ -871,9 +957,22 @@ status_finish()
     /* free memory that we alloc'd now */
     for (i = 0; i < MAXBLSTATS; ++i) {
         if (blstats[0][i].val)
-            free((genericptr_t) blstats[0][i].val);
+            free((genericptr_t) blstats[0][i].val), blstats[0][i].val = 0;
         if (blstats[1][i].val)
-            free((genericptr_t) blstats[1][i].val);
+            free((genericptr_t) blstats[1][i].val), blstats[1][i].val = 0;
+#ifdef STATUS_HILITES
+        if (blstats[0][i].thresholds) {
+            struct hilite_s *temp = blstats[0][i].thresholds,
+                            *next = (struct hilite_s *)0;
+            while (temp) {
+                next = temp->next;
+                free(temp);
+                blstats[0][i].thresholds = (struct hilite_s *)0;
+                blstats[1][i].thresholds = blstats[0][i].thresholds;
+                temp = next;
+            }
+       }
+#endif /* STATUS_HILITES */
     }
 }
 
@@ -891,6 +990,9 @@ init_blstats()
     initalready = TRUE;
     for (i = BEFORE; i <= NOW; ++i) {
         for (j = 0; j < MAXBLSTATS; ++j) {
+#ifdef STATUS_HILITES
+            struct hilite_s *keep_hilite_chain = blstats[i][j].thresholds;
+#endif
             blstats[i][j] = initblstats[j];
             blstats[i][j].a = zeroany;
             if (blstats[i][j].valwidth) {
@@ -898,24 +1000,119 @@ init_blstats()
                 blstats[i][j].val[0] = '\0';
             } else
                 blstats[i][j].val = (char *) 0;
+#ifdef STATUS_HILITES
+            if (keep_hilite_chain)
+                blstats[i][j].thresholds = keep_hilite_chain;
+#endif
         }
     }
 }
 
-STATIC_OVL char *
-anything_to_s(buf, a, anytype)
-char *buf;
-anything *a;
-int anytype;
+/*
+ * This compares the previous stat with the current stat,
+ * and returns one of the following results based on that:
+ *
+ *   if prev_value < new_value (stat went up, increased)
+ *      return 1
+ *
+ *   if prev_value > new_value (stat went down, decreased)
+ *      return  -1
+ *
+ *   if prev_value == new_value (stat stayed the same)
+ *      return 0
+ *
+ *   Special cases:
+ *     - for bitmasks, 0 = stayed the same, 1 = changed
+ *     - for strings,  0 = stayed the same, 1 = changed
+ *
+ */
+STATIC_OVL int
+compare_blstats(bl1, bl2)
+struct istat_s *bl1, *bl2;
 {
-    if (!buf)
-        return (char *) 0;
+    int anytype, result = 0;
 
-    switch (anytype) {
-    case ANY_ULONG:
-        Sprintf(buf, "%lu", a->a_ulong);
-        break;
-    case ANY_MASK32:
+    if (!bl1 || !bl2) {
+        panic("compare_blstat: bad istat pointer %s, %s",
+              fmt_ptr((genericptr_t) bl1), fmt_ptr((genericptr_t) bl2));
+    }
+
+    anytype = bl1->anytype;
+    if ((!bl1->a.a_void || !bl2->a.a_void)
+        && (anytype == ANY_IPTR || anytype == ANY_UPTR || anytype == ANY_LPTR
+            || anytype == ANY_ULPTR)) {
+        panic("compare_blstat: invalid pointer %s, %s",
+              fmt_ptr((genericptr_t) bl1->a.a_void),
+              fmt_ptr((genericptr_t) bl2->a.a_void));
+    }
+
+    switch (anytype) {
+    case ANY_INT:
+        result = (bl1->a.a_int < bl2->a.a_int)
+                     ? 1
+                     : (bl1->a.a_int > bl2->a.a_int) ? -1 : 0;
+        break;
+    case ANY_IPTR:
+        result = (*bl1->a.a_iptr < *bl2->a.a_iptr)
+                     ? 1
+                     : (*bl1->a.a_iptr > *bl2->a.a_iptr) ? -1 : 0;
+        break;
+    case ANY_LONG:
+        result = (bl1->a.a_long < bl2->a.a_long)
+                     ? 1
+                     : (bl1->a.a_long > bl2->a.a_long) ? -1 : 0;
+        break;
+    case ANY_LPTR:
+        result = (*bl1->a.a_lptr < *bl2->a.a_lptr)
+                     ? 1
+                     : (*bl1->a.a_lptr > *bl2->a.a_lptr) ? -1 : 0;
+        break;
+    case ANY_UINT:
+        result = (bl1->a.a_uint < bl2->a.a_uint)
+                     ? 1
+                     : (bl1->a.a_uint > bl2->a.a_uint) ? -1 : 0;
+        break;
+    case ANY_UPTR:
+        result = (*bl1->a.a_uptr < *bl2->a.a_uptr)
+                     ? 1
+                     : (*bl1->a.a_uptr > *bl2->a.a_uptr) ? -1 : 0;
+        break;
+    case ANY_ULONG:
+        result = (bl1->a.a_ulong < bl2->a.a_ulong)
+                     ? 1
+                     : (bl1->a.a_ulong > bl2->a.a_ulong) ? -1 : 0;
+        break;
+    case ANY_ULPTR:
+        result = (*bl1->a.a_ulptr < *bl2->a.a_ulptr)
+                     ? 1
+                     : (*bl1->a.a_ulptr > *bl2->a.a_ulptr) ? -1 : 0;
+        break;
+    case ANY_STR:
+        result = sgn(strcmp(bl1->val, bl2->val));
+        break;
+    case ANY_MASK32:
+        result = (bl1->a.a_ulong != bl2->a.a_ulong);
+        break;
+    default:
+        result = 1;
+    }
+    return result;
+}
+
+STATIC_OVL char *
+anything_to_s(buf, a, anytype)
+char *buf;
+anything *a;
+int anytype;
+{
+    if (!buf)
+        return (char *) 0;
+
+    switch (anytype) {
+    case ANY_ULONG:
+        Sprintf(buf, "%lu", a->a_ulong);
+        break;
+    case ANY_MASK32:
         Sprintf(buf, "%lx", a->a_ulong);
         break;
     case ANY_LONG:
@@ -948,6 +1145,7 @@ int anytype;
     return buf;
 }
 
+#ifdef STATUS_HILITES
 STATIC_OVL void
 s_to_anything(a, buf, anytype)
 anything *a;
@@ -995,85 +1193,7 @@ int anytype;
     }
     return;
 }
-
-STATIC_OVL int
-compare_blstats(bl1, bl2)
-struct istat_s *bl1, *bl2;
-{
-    int anytype, result = 0;
-
-    if (!bl1 || !bl2) {
-        panic("compare_blstat: bad istat pointer %s, %s",
-              fmt_ptr((genericptr_t) bl1), fmt_ptr((genericptr_t) bl2));
-    }
-
-    anytype = bl1->anytype;
-    if ((!bl1->a.a_void || !bl2->a.a_void)
-        && (anytype == ANY_IPTR || anytype == ANY_UPTR || anytype == ANY_LPTR
-            || anytype == ANY_ULPTR)) {
-        panic("compare_blstat: invalid pointer %s, %s",
-              fmt_ptr((genericptr_t) bl1->a.a_void),
-              fmt_ptr((genericptr_t) bl2->a.a_void));
-    }
-
-    switch (anytype) {
-    case ANY_INT:
-        result = (bl1->a.a_int < bl2->a.a_int)
-                     ? 1
-                     : (bl1->a.a_int > bl2->a.a_int) ? -1 : 0;
-        break;
-    case ANY_IPTR:
-        result = (*bl1->a.a_iptr < *bl2->a.a_iptr)
-                     ? 1
-                     : (*bl1->a.a_iptr > *bl2->a.a_iptr) ? -1 : 0;
-        break;
-    case ANY_LONG:
-        result = (bl1->a.a_long < bl2->a.a_long)
-                     ? 1
-                     : (bl1->a.a_long > bl2->a.a_long) ? -1 : 0;
-        break;
-    case ANY_LPTR:
-        result = (*bl1->a.a_lptr < *bl2->a.a_lptr)
-                     ? 1
-                     : (*bl1->a.a_lptr > *bl2->a.a_lptr) ? -1 : 0;
-        break;
-    case ANY_UINT:
-        result = (bl1->a.a_uint < bl2->a.a_uint)
-                     ? 1
-                     : (bl1->a.a_uint > bl2->a.a_uint) ? -1 : 0;
-        break;
-    case ANY_UPTR:
-        result = (*bl1->a.a_uptr < *bl2->a.a_uptr)
-                     ? 1
-                     : (*bl1->a.a_uptr > *bl2->a.a_uptr) ? -1 : 0;
-        break;
-    case ANY_ULONG:
-        result = (bl1->a.a_ulong < bl2->a.a_ulong)
-                     ? 1
-                     : (bl1->a.a_ulong > bl2->a.a_ulong) ? -1 : 0;
-        break;
-    case ANY_ULPTR:
-        result = (*bl1->a.a_ulptr < *bl2->a.a_ulptr)
-                     ? 1
-                     : (*bl1->a.a_ulptr > *bl2->a.a_ulptr) ? -1 : 0;
-        break;
-    case ANY_STR:
-        if (strcmp(bl1->val, bl2->val) == 0)
-            result = 0;
-        else
-            result = 1;
-        break;
-    case ANY_MASK32:
-        if (bl1->a.a_ulong == bl2->a.a_ulong)
-            result = 0;
-        else
-            result = 1;
-        break;
-    default:
-        result = 1;
-    }
-    return result;
-}
+#endif /* STATUS_HILITES */
 
 STATIC_OVL int
 percentage(bl, maxbl)
@@ -1081,6 +1201,10 @@ struct istat_s *bl, *maxbl;
 {
     int result = 0;
     int anytype;
+    int ival;
+    long lval;
+    unsigned uval;
+    unsigned long ulval;
 
     if (!bl || !maxbl) {
         impossible("percentage: bad istat pointer %s, %s",
@@ -1088,35 +1212,51 @@ struct istat_s *bl, *maxbl;
         return 0;
     }
 
+    ival = 0, lval = 0L, uval = 0U, ulval = 0UL;
     anytype = bl->anytype;
     if (maxbl->a.a_void) {
         switch (anytype) {
         case ANY_INT:
-            result = ((100 * bl->a.a_int) / maxbl->a.a_int);
+            ival = bl->a.a_int;
+            result = ((100 * ival) / maxbl->a.a_int);
             break;
         case ANY_LONG:
-            result = (int) ((100L * bl->a.a_long) / maxbl->a.a_long);
+            lval  = bl->a.a_long;
+            result = (int) ((100L * lval) / maxbl->a.a_long);
             break;
         case ANY_UINT:
-            result = (int) ((100U * bl->a.a_uint) / maxbl->a.a_uint);
+            uval = bl->a.a_uint;
+            result = (int) ((100U * uval) / maxbl->a.a_uint);
             break;
         case ANY_ULONG:
-            result = (int) ((100UL * bl->a.a_ulong) / maxbl->a.a_ulong);
+            ulval = bl->a.a_ulong;
+            result = (int) ((100UL * ulval) / maxbl->a.a_ulong);
             break;
         case ANY_IPTR:
-            result = ((100 * (*bl->a.a_iptr)) / (*maxbl->a.a_iptr));
+            ival = *bl->a.a_iptr;
+            result = ((100 * ival) / (*maxbl->a.a_iptr));
             break;
         case ANY_LPTR:
-            result = (int) ((100L * (*bl->a.a_lptr)) / (*maxbl->a.a_lptr));
+            lval = *bl->a.a_lptr;
+            result = (int) ((100L * lval) / (*maxbl->a.a_lptr));
             break;
         case ANY_UPTR:
-            result = (int) ((100U * (*bl->a.a_uptr)) / (*maxbl->a.a_uptr));
+            uval = *bl->a.a_uptr;
+            result = (int) ((100U * uval) / (*maxbl->a.a_uptr));
             break;
         case ANY_ULPTR:
-            result = (int) ((100UL * (*bl->a.a_ulptr)) / (*maxbl->a.a_ulptr));
+            ulval = *bl->a.a_ulptr;
+            result = (int) ((100UL * ulval) / (*maxbl->a.a_ulptr));
             break;
         }
     }
+    /* don't let truncation from integer division produce a zero result
+       from a non-zero input; note: if we ever change to something like
+       ((((1000 * val) / max) + 5) / 10) for a rounded result, we'll
+       also need to check for and convert false 100 to 99 */
+    if (result == 0 && (ival != 0 || lval != 0L || uval != 0U || ulval != 0UL))
+        result = 1;
+
     return result;
 }
 
@@ -1127,49 +1267,304 @@ struct istat_s *bl, *maxbl;
 /* Core status hiliting support */
 /****************************************************************************/
 
-struct hilite_s {
-    boolean set;
-    unsigned anytype;
-    anything threshold;
-    int behavior;
-    int coloridx[2];
+struct hilite_s status_hilites[MAXBLSTATS];
+
+static struct fieldid_t {
+    const char *fieldname;
+    enum statusfields fldid;
+} fieldids_alias[] = {
+    {"characteristics", BL_CHARACTERISTICS},
+    {"dx",       BL_DX},
+    {"co",       BL_CO},
+    {"con",      BL_CO},
+    {"points",   BL_SCORE},
+    {"cap",      BL_CAP},
+    {"pw",       BL_ENE},
+    {"pw-max",   BL_ENEMAX},
+    {"xl",       BL_XP},
+    {"xplvl",    BL_XP},
+    {"ac",       BL_AC},
+    {"hit-dice", BL_HD},
+    {"turns",    BL_TIME},
+    {"hp",       BL_HP},
+    {"hp-max",   BL_HPMAX},
+    {"dgn",      BL_LEVELDESC},
+    {"xp",       BL_EXP},
+    {"exp",      BL_EXP},
+    {"flags",    BL_CONDITION},
+    {0,          BL_FLUSH}
 };
 
-struct hilite_s status_hilites[MAXBLSTATS];
+/* field name to bottom line index */
+STATIC_OVL enum statusfields
+fldname_to_bl_indx(name)
+const char *name;
+{
+    int i, nmatches = 0, fld = 0;
+
+    if (name && *name) {
+        /* check matches to canonical names */
+        for (i = 0; i < SIZE(initblstats); i++)
+            if (fuzzymatch(initblstats[i].fldname, name, " -_", TRUE)) {
+                fld = initblstats[i].fld;
+                nmatches++;
+            }
+
+        if (!nmatches) {
+            /* check aliases */
+            for (i = 0; fieldids_alias[i].fieldname; i++)
+                if (fuzzymatch(fieldids_alias[i].fieldname, name,
+                               " -_", TRUE)) {
+                    fld = fieldids_alias[i].fldid;
+                    nmatches++;
+                }
+        }
+
+        if (!nmatches) {
+            /* check partial matches to canonical names */
+            int len = (int) strlen(name);
+            for (i = 0; i < SIZE(initblstats); i++)
+                if (!strncmpi(name, initblstats[i].fldname, len)) {
+                    fld = initblstats[i].fld;
+                    nmatches++;
+                }
+        }
+
+    }
+    return (nmatches == 1) ? fld : BL_FLUSH;
+}
+
+STATIC_OVL boolean
+hilite_reset_needed(bl_p, augmented_time)
+struct istat_s *bl_p;
+long augmented_time;
+{
+    struct hilite_s *tl = bl_p->thresholds;
+
+    /*
+     * This 'multi' handling may need some tuning...
+     */
+    if (multi)
+        return FALSE;
+
+    if (bl_p->time == 0 || bl_p->time >= augmented_time)
+        return FALSE;
+
+    while (tl) {
+        /* only this style times out */
+        if (tl->behavior == BL_TH_UPDOWN)
+            return TRUE;
+        tl = tl->next;
+    }
+
+    return FALSE;
+}
+
+/* called by options handling when 'statushilites' boolean is toggled */
+void
+reset_status_hilites()
+{
+    if (iflags.hilite_delta) {
+        int i;
+
+        for (i = 0; i < MAXBLSTATS; ++i)
+            blstats[0][i].time = blstats[1][i].time = 0L;
+        update_all = TRUE;
+    }
+    context.botlx = TRUE;
+}
+
+STATIC_OVL void
+merge_bestcolor(bestcolor, newcolor)
+int *bestcolor;
+int newcolor;
+{
+    int natr = HL_UNDEF, nclr = NO_COLOR;
+
+    split_clridx(newcolor, &nclr, &natr);
+
+    if (nclr != NO_COLOR)
+        *bestcolor = (*bestcolor & 0xff00) | nclr;
+
+    if (natr != HL_UNDEF) {
+        if (natr == HL_NONE)
+            *bestcolor = *bestcolor & 0x00ff; /* reset all attributes */
+        else
+            *bestcolor |= (natr << 8); /* merge attributes */
+    }
+}
+
+/*
+ * get_hilite_color
+ * 
+ * Figures out, based on the value and the
+ * direction it is moving, the color that the field
+ * should be displayed in.
+ *
+ *
+ * Provide get_hilite_color() with the following
+ * to work with:
+ *     actual value vp
+ *          useful for BL_TH_VAL_ABSOLUTE
+ *     indicator of down, up, or the same (-1, 1, 0) chg
+ *          useful for BL_TH_UPDOWN or change detection
+ *     percentage (current value percentage of max value) pc
+ *          useful for BL_TH_VAL_PERCENTAGE
+ *
+ * Get back:
+ *     color     based on user thresholds set in config file.
+ *               The rightmost 8 bits contain a color index.
+ *               The 8 bits to the left of that contain
+ *               the attribute bits.
+ *                   color = 0x00FF
+ *                   attrib= 0xFF00
+ */
+
+STATIC_OVL void
+get_hilite_color(idx, fldidx, vp, chg, pc, colorptr)
+int idx, fldidx, chg, pc;
+genericptr_t vp;
+int *colorptr;
+{
+    int bestcolor = NO_COLOR;
+    struct hilite_s *hl;
+    anything *value = (anything *)vp;
+    char *txtstr, *cmpstr;
+
+    if (!colorptr || fldidx < 0 || fldidx >= MAXBLSTATS)
+        return;
+
+    if (blstats[idx][fldidx].thresholds) {
+        /* there are hilites set here */
+        int max_pc = 0, min_pc = 100;
+        int max_val = 0, min_val = LARGEST_INT;
+        boolean exactmatch = FALSE;
+
+        hl = blstats[idx][fldidx].thresholds;
+
+        while (hl) {
+            switch (hl->behavior) {
+            case BL_TH_VAL_PERCENTAGE:
+                if (hl->rel == EQ_VALUE && pc == hl->value.a_int) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    min_pc = max_pc = hl->value.a_int;
+                    exactmatch = TRUE;
+                } else if (hl->rel == LT_VALUE && !exactmatch
+                           && (hl->value.a_int >= pc)
+                           && (hl->value.a_int <= min_pc)) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    min_pc = hl->value.a_int;
+                } else if (hl->rel == GT_VALUE && !exactmatch
+                           && (hl->value.a_int <= pc)
+                           && (hl->value.a_int >= max_pc)) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    max_pc = hl->value.a_int;
+                }
+                break;
+            case BL_TH_UPDOWN:
+                if (chg < 0 && hl->rel == LT_VALUE) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                } else if (chg > 0 && hl->rel == GT_VALUE) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                } else if (hl->rel == EQ_VALUE && chg) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    min_val = max_val = hl->value.a_int;
+                }
+                break;
+            case BL_TH_VAL_ABSOLUTE:
+                if (hl->rel == EQ_VALUE && hl->value.a_int == value->a_int) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    min_val = max_val = hl->value.a_int;
+                    exactmatch = TRUE;
+                } else if (hl->rel == LT_VALUE && !exactmatch
+                           && (hl->value.a_int >= value->a_int)
+                           && (hl->value.a_int < min_val)) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    min_val = hl->value.a_int;
+                } else if (hl->rel == GT_VALUE && !exactmatch
+                           && (hl->value.a_int <= value->a_int)
+                           && (hl->value.a_int > max_val)) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                    max_val = hl->value.a_int;
+                }
+                break;
+            case BL_TH_TEXTMATCH:
+                txtstr = dupstr(blstats[idx][fldidx].val);
+                cmpstr = txtstr;
+                if (fldidx == BL_TITLE) {
+                    int len = (strlen(plname) + sizeof(" the"));
+                    cmpstr += len;
+                }
+                (void) trimspaces(cmpstr);
+                if (hl->rel == TXT_VALUE && hl->textmatch[0] &&
+                    !strcmpi(hl->textmatch, cmpstr)) {
+                    merge_bestcolor(&bestcolor, hl->coloridx);
+                }
+                free(txtstr);
+                break;
+            case BL_TH_ALWAYS_HILITE:
+                merge_bestcolor(&bestcolor, hl->coloridx);
+                break;
+            case BL_TH_NONE:
+                break;
+            default:
+                break;
+            }
+            hl = hl->next;
+       }
+    }
+    *colorptr = bestcolor;
+    return;
+}
+
+STATIC_OVL void
+split_clridx(idx, coloridx, attrib)
+int idx;
+int *coloridx, *attrib;
+{
+    if (idx && coloridx && attrib) {
+           *coloridx = idx & 0x00FF;
+           *attrib = (idx & 0xFF00) >> 8;
+    }
+}
+
 
 /*
  * This is the parser for the hilite options
- * Example:
- *    OPTION=hilite_status: hitpoints/10%/red/normal
  *
- * set_hilite_status() separates each hilite entry into its 4 component
- * strings, then calls assign_hilite() to make the adjustments.
+ * parse_status_hl1() separates each hilite entry into
+ * a set of field threshold/action component strings,
+ * then calls parse_status_hl2() to parse further
+ * and configure the hilite.
  */
 boolean
-set_status_hilites(op, from_configfile)
+parse_status_hl1(op, from_configfile)
 char *op;
 boolean from_configfile;
 {
-    char hsbuf[4][QBUFSZ];
+#define MAX_THRESH 21
+    char hsbuf[MAX_THRESH][QBUFSZ];
     boolean rslt, badopt = FALSE;
-    int fldnum, num = 0, ccount = 0;
+    int i, fldnum, ccount = 0;
     char c;
 
-    num = fldnum = 0;
-    hsbuf[0][0] = hsbuf[1][0] = hsbuf[2][0] = hsbuf[3][0] = '\0';
-    while (*op && fldnum < 4 && ccount < (QBUFSZ - 2)) {
+    fldnum = 0;
+    for (i = 0; i < MAX_THRESH; ++i) {
+        hsbuf[i][0] = '\0';
+    }
+    while (*op && fldnum < MAX_THRESH && ccount < (QBUFSZ - 2)) {
         c = lowc(*op);
         if (c == ' ') {
-            if (fldnum >= 2) {
-                rslt = assign_hilite(&hsbuf[0][0], &hsbuf[1][0], &hsbuf[2][0],
-                                     &hsbuf[3][0], from_configfile);
+            if (fldnum >= 1) {
+                rslt = parse_status_hl2(hsbuf, from_configfile);
                 if (!rslt) {
                     badopt = TRUE;
                     break;
                 }
             }
-            hsbuf[0][0] = hsbuf[1][0] = '\0';
-            hsbuf[2][0] = hsbuf[3][0] = '\0';
+            for (i = 0; i < MAX_THRESH; ++i) {
+                hsbuf[i][0] = '\0';
+            }
             fldnum = 0;
             ccount = 0;
         } else if (c == '/') {
@@ -1181,9 +1576,8 @@ boolean from_configfile;
         }
         op++;
     }
-    if (fldnum >= 2 && !badopt) {
-        rslt = assign_hilite(&hsbuf[0][0], &hsbuf[1][0], &hsbuf[2][0],
-                             &hsbuf[3][0], from_configfile);
+    if (fldnum >= 1 && !badopt) {
+        rslt = parse_status_hl2(hsbuf, from_configfile);
         if (!rslt)
             badopt = TRUE;
     }
@@ -1192,463 +1586,1739 @@ boolean from_configfile;
     return TRUE;
 }
 
-void
-clear_status_hilites(from_configfile)
-boolean from_configfile;
+/* is str in the format of "(<>)?[0-9]+%?" regex */
+STATIC_OVL boolean
+is_ltgt_percentnumber(str)
+const char *str;
 {
-    int i;
-    anything it;
-    it = zeroany;
-    for (i = 0; i < MAXBLSTATS; ++i) {
-        (void) memset((genericptr_t) &status_hilites[i], 0,
-                      sizeof(struct hilite_s));
-        /* notify window port */
-        if (!from_configfile)
-            status_threshold(i, blstats[0][i].anytype, it, 0, 0, 0);
-    }
+    const char *s = str;
+
+    if (*s == '<' || *s == '>') s++;
+    while (digit(*s)) s++;
+    if (*s == '%') s++;
+
+    return (*s == '\0');
 }
 
+/* does str only contain "<>0-9%" chars */
 STATIC_OVL boolean
-assign_hilite(sa, sb, sc, sd, from_configfile)
-char *sa, *sb, *sc, *sd;
-boolean from_configfile;
+has_ltgt_percentnumber(str)
+const char *str;
 {
-    char *tmp, *how;
-    int i = -1, dt = -1, idx = -1;
-    int coloridx[2] = { -1, -1 };
-    boolean inverse[2] = { FALSE, FALSE };
-    boolean bold[2] = { FALSE, FALSE };
-    boolean normal[2] = { 0, 0 };
-    boolean percent = FALSE, down_up = FALSE, changed = FALSE;
-    anything threshold;
-    enum statusfields fld = BL_FLUSH;
-    threshold.a_void = 0;
-
-    /* Example:
-     *  hilite_status: hitpoints/10%/red/normal
-     */
+    const char *s = str;
 
-    /* field name to statusfield */
-    for (i = 0; sa && i < SIZE(fieldids); ++i) {
-        if (strcmpi(sa, fieldids[i].fieldname) == 0) {
-            idx = i;
-            fld = fieldids[i].fldid;
-            break;
+    while (*s) {
+        if (!index("<>0123456789%", *s))
+            return FALSE;
+        s++;
+    }
+    return TRUE;
+}
+
+/* splitsubfields(): splits str in place into '+' or '&' separated strings.
+ * returns number of strings, or -1 if more than maxsf or MAX_SUBFIELDS
+ */
+#define MAX_SUBFIELDS 16
+STATIC_OVL int
+splitsubfields(str, sfarr, maxsf)
+char *str;
+char ***sfarr;
+int maxsf;
+{
+    static char *subfields[MAX_SUBFIELDS];
+    char *st = (char *) 0;
+    int sf = 0;
+
+    if (!str)
+        return 0;
+    for (sf = 0; sf < MAX_SUBFIELDS; ++sf)
+        subfields[sf] = (char *) 0;
+
+    maxsf = (maxsf == 0) ? MAX_SUBFIELDS : min(maxsf, MAX_SUBFIELDS);
+
+    if (index(str, '+') || index(str, '&')) {
+        char *c = str;
+
+        sf = 0;
+        st = c;
+        while (*c && sf < maxsf) {
+            if (*c == '&' || *c == '+') {
+                *c = '\0';
+                subfields[sf] = st;
+                st = c+1;
+                sf++;
+            }
+            c++;
         }
+        if (sf >= maxsf - 1)
+            return -1;
+        if (!*c && c != st)
+            subfields[sf++] = st;
+    } else {
+        sf = 1;
+        subfields[0] = str;
     }
-    if (idx == -1)
-        return FALSE;
-    status_hilites[idx].set = FALSE; /* mark it "unset" */
+    *sfarr = subfields;
+    return sf;
+}
+#undef MAX_SUBFIELDS
 
-    /* threshold */
-    if (!sb)
-        return FALSE;
-    if ((strcmpi(sb, "updown") == 0) || (strcmpi(sb, "downup") == 0)
-        || (strcmpi(sb, "up") == 0) || (strcmpi(sb, "down") == 0)) {
-        down_up = TRUE;
-    } else if ((strcmpi(sb, "changed") == 0)
-               && (fld == BL_TITLE || fld == BL_ALIGN || fld == BL_LEVELDESC
-                   || fld == BL_CONDITION)) {
-        changed = TRUE; /* changed is only thing allowed */
+boolean
+is_fld_arrayvalues(str, arr, arrmin, arrmax, retidx)
+const char *str;
+const char *const *arr;
+int arrmin, arrmax;
+int *retidx;
+{
+    int i;
+
+    for (i = arrmin; i < arrmax; i++)
+        if (!strcmpi(str, arr[i])) {
+            *retidx = i;
+            return TRUE;
+        }
+    return FALSE;
+}
+
+int
+query_arrayvalue(querystr, arr, arrmin, arrmax)
+const char *querystr;
+const char *const *arr;
+int arrmin, arrmax;
+{
+    int i, res, ret = arrmin - 1;
+    winid tmpwin;
+    anything any;
+    menu_item *picks = (menu_item *) 0;
+    int adj = (arrmin > 0) ? 1 : arrmax;
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    for (i = arrmin; i < arrmax; i++) {
+        any = zeroany;
+        any.a_int = i + adj;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 arr[i], MENU_UNSELECTED);
+    }
+
+    end_menu(tmpwin, querystr);
+
+    res = select_menu(tmpwin, PICK_ONE, &picks);
+    destroy_nhwindow(tmpwin);
+    if (res > 0) {
+        ret = picks->item.a_int - adj;
+        free((genericptr_t) picks);
+    }
+
+    return ret;
+}
+
+void
+status_hilite_add_threshold(fld, hilite)
+int fld;
+struct hilite_s *hilite;
+{
+    struct hilite_s *new_hilite;
+
+    if (!hilite)
+        return;
+
+    /* alloc and initialize a new hilite_s struct */
+    new_hilite = (struct hilite_s *) alloc(sizeof(struct hilite_s));
+    *new_hilite = *hilite;   /* copy struct */
+
+    new_hilite->set = TRUE;
+    new_hilite->fld = fld;
+    new_hilite->next = (struct hilite_s *)0;
+
+    /* Does that status field currently have any hilite thresholds? */
+    if (!blstats[0][fld].thresholds) {
+        blstats[0][fld].thresholds = new_hilite;
     } else {
-        tmp = sb;
-        while (*tmp) {
-            if (*tmp == '%') {
-                *tmp = '\0';
-                percent = TRUE;
-                break;
-            } else if (!index("0123456789", *tmp))
+        struct hilite_s *temp_hilite = blstats[0][fld].thresholds;
+        new_hilite->next = temp_hilite;
+        blstats[0][fld].thresholds = new_hilite;
+        /* sort_hilites(fld) */
+    }
+    /* current and prev must both point at the same hilites */
+    blstats[1][fld].thresholds = blstats[0][fld].thresholds;
+}
+
+
+STATIC_OVL boolean
+parse_status_hl2(s, from_configfile)
+char (*s)[QBUFSZ];
+boolean from_configfile;
+{
+    char *tmp, *how;
+    int sidx = 0, i = -1, dt = -1;
+    int coloridx = -1, successes = 0;
+    int disp_attrib = 0;
+    boolean percent = FALSE, changed = FALSE, numeric = FALSE;
+    boolean down= FALSE, up = FALSE;
+    boolean gt = FALSE, lt = FALSE, eq = FALSE, neq = FALSE;
+    boolean txtval = FALSE;
+    boolean always = FALSE;
+    const char *txt;
+    enum statusfields fld = BL_FLUSH;
+    struct hilite_s hilite;
+    char tmpbuf[BUFSZ];
+    const char *aligntxt[] = {"chaotic", "neutral", "lawful"};
+    /* hu_stat[] from eat.c has trailing spaces which foul up comparisons */
+    const char *hutxt[] = {"Satiated", "", "Hungry", "Weak",
+                           "Fainting", "Fainted", "Starved"};
+
+    /* Examples:
+        3.6.1:
+      OPTION=hilite_status: hitpoints/<10%/red
+      OPTION=hilite_status: hitpoints/<10%/red/<5%/purple/1/red+blink+inverse
+      OPTION=hilite_status: experience/down/red/up/green
+      OPTION=hilite_status: cap/strained/yellow/overtaxed/orange
+      OPTION=hilite_status: title/always/blue
+      OPTION=hilite_status: title/blue
+    */
+
+    /* field name to statusfield */
+    fld = fldname_to_bl_indx(s[sidx]);
+
+    if (fld == BL_CHARACTERISTICS) {
+        boolean res = FALSE;
+
+        /* recursively set each of strength, dexterity, constitution, &c */
+        for (fld = BL_STR; fld <= BL_CH; fld++) {
+            Strcpy(s[sidx], initblstats[fld].fldname);
+            res = parse_status_hl2(s, from_configfile);
+            if (!res)
                 return FALSE;
-            tmp++;
         }
-        if (strlen(sb) > 0) {
-            dt = blstats[0][idx].anytype;
-            if (percent)
-                dt = ANY_INT;
-            (void) s_to_anything(&threshold, sb, dt);
-        } else
-            return FALSE;
-        if (percent && (threshold.a_int < 1 || threshold.a_int > 100))
+        return TRUE;
+    }
+    if (fld == BL_FLUSH) {
+        config_error_add("Unknown status field '%s'", s[sidx]);
+        return FALSE;
+    }
+    if (fld == BL_CONDITION)
+        return parse_condition(s, sidx);
+
+    ++sidx;
+    while(s[sidx]) {
+        char buf[BUFSZ], **subfields;
+        int sf = 0;     /* subfield count */
+        int kidx;
+
+        txt = (const char *)0;
+        percent = changed = numeric = FALSE;
+        down = up = FALSE;
+        gt = eq = lt = neq = txtval = FALSE;
+        always = FALSE;
+
+        /* threshold value */
+        if (!s[sidx][0])
+            return TRUE;
+
+        memset((genericptr_t) &hilite, 0, sizeof(struct hilite_s));
+        hilite.set = FALSE; /* mark it "unset" */
+        hilite.fld = fld;
+
+        if (*s[sidx+1] == '\0' || !strcmpi(s[sidx], "always")) {
+            /* "field/always/color" OR "field/color" */
+            always = TRUE;
+            if (*s[sidx+1] == '\0')
+                sidx--;
+            goto do_rel;
+        } else if (!strcmpi(s[sidx], "up") || !strcmpi(s[sidx], "down")) {
+            if (!strcmpi(s[sidx], "down"))
+                down = TRUE;
+            else
+                up = TRUE;
+            changed = TRUE;
+            goto do_rel;
+       } else if (fld == BL_CAP
+                   && is_fld_arrayvalues(s[sidx], enc_stat,
+                                         SLT_ENCUMBER, OVERLOADED+1, &kidx)) {
+            txt = enc_stat[kidx];
+            txtval = TRUE;
+           goto do_rel;
+        } else if (fld == BL_ALIGN
+                   && is_fld_arrayvalues(s[sidx], aligntxt, 0, 3, &kidx)) {
+            txt = aligntxt[kidx];
+            txtval = TRUE;
+            goto do_rel;
+        } else if (fld == BL_HUNGER
+                   && is_fld_arrayvalues(s[sidx], hutxt,
+                                         SATIATED, STARVED+1, &kidx)) {
+            txt = hu_stat[kidx];   /* store hu_stat[] val, not hutxt[] */
+            txtval = TRUE;
+            goto do_rel;
+        } else if (!strcmpi(s[sidx], "changed")) {
+            changed = TRUE;
+            goto do_rel;
+        } else if (is_ltgt_percentnumber(s[sidx])) {
+            tmp = s[sidx];
+            if (strchr(tmp, '%'))
+               percent = TRUE;
+            if (strchr(tmp, '<'))
+                lt = TRUE;
+            if (strchr(tmp, '>'))
+                gt = TRUE;
+            (void) stripchars(tmpbuf, "%<>", tmp);
+            tmp = tmpbuf;
+            while (*tmp) {
+                if (!index("0123456789", *tmp))
+                    return FALSE;
+                tmp++;
+            }
+            numeric = TRUE;
+            tmp = tmpbuf;
+            if (strlen(tmp) > 0) {
+                dt = initblstats[fld].anytype;
+                if (percent)
+                    dt = ANY_INT;
+                (void) s_to_anything(&hilite.value, tmp, dt);
+            } else
+                return FALSE;
+            if (!hilite.value.a_void && (strcmp(tmp, "0") != 0))
+               return FALSE;
+        } else if (initblstats[fld].anytype == ANY_STR) {
+            txt = s[sidx];
+            txtval = TRUE;
+            goto do_rel;
+        } else {
+            config_error_add(has_ltgt_percentnumber(s[sidx])
+                 ? "Wrong format '%s', expected a threshold number or percent"
+                 : "Unknown behavior '%s'", s[sidx]);
             return FALSE;
-        if (!threshold.a_void && (strcmp(sb, "0") != 0))
+        }
+do_rel:
+        /* relationships { LT_VALUE, GT_VALUE, EQ_VALUE} */
+        if (gt)
+            hilite.rel = GT_VALUE;
+        else if (eq)
+            hilite.rel = EQ_VALUE;
+        else if (lt)
+            hilite.rel = LT_VALUE;
+        else if (percent)
+            hilite.rel = EQ_VALUE;
+        else if (numeric)
+            hilite.rel = EQ_VALUE;
+        else if (down)
+            hilite.rel = LT_VALUE;
+        else if (up)
+            hilite.rel = GT_VALUE;
+        else if (changed)
+            hilite.rel = EQ_VALUE;
+        else if (txtval)
+            hilite.rel = TXT_VALUE;
+        else
+            hilite.rel = LT_VALUE;
+
+        if (initblstats[fld].anytype == ANY_STR
+            && (percent || numeric)) {
+            config_error_add("Field '%s' does not support numeric values",
+                             initblstats[fld].fldname);
             return FALSE;
-    }
+        }
 
-    /* actions */
-    for (i = 0; i < 2; ++i) {
-        if (!i)
-            how = sc;
-        else
-            how = sd;
-        if (!how) {
-            if (!i)
+        if (percent) {
+            if (initblstats[fld].idxmax <= BL_FLUSH) {
+                config_error_add("Cannot use percent with '%s'",
+                                 initblstats[fld].fldname);
                 return FALSE;
-            else
-                break; /* sc is mandatory; sd is not */
+            } else if ((hilite.value.a_int < 0)
+                       || (hilite.value.a_int == 0
+                           && hilite.rel == LT_VALUE)
+                       || (hilite.value.a_int > 100)
+                       || (hilite.value.a_int == 100
+                           && hilite.rel == GT_VALUE)) {
+                config_error_add("Illegal percentage value");
+                return FALSE;
+            }
         }
 
-        if (strcmpi(how, "bold") == 0) {
-            bold[i] = TRUE;
-        } else if (strcmpi(how, "inverse") == 0) {
-            inverse[i] = TRUE;
-        } else if (strcmpi(how, "normal") == 0) {
-            normal[i] = TRUE;
-        } else {
-            int k;
-            char colorname[BUFSZ];
-            for (k = 0; k < CLR_MAX; ++k) {
-                /* we have to make a copy to change space to dash */
-                (void) strcpy(colorname, c_obj_colors[k]);
-                for (tmp = index(colorname, ' '); tmp;
-                     tmp = index(colorname, ' '))
-                    *tmp = '-';
-                if (strcmpi(how, colorname) == 0) {
-                    coloridx[i] = k;
-                    break;
-                }
-            }
-            if (k >= CLR_MAX)
+        /* actions */
+        sidx++;
+        how = s[sidx];
+        if (!how) {
+            if (!successes)
                 return FALSE;
         }
+        coloridx = -1;
+        Strcpy(buf, how);
+        sf = splitsubfields(buf, &subfields, 0);
+
+        if (sf < 1)
+            return FALSE;
+
+        disp_attrib = HL_UNDEF;
+
+        for (i = 0; i < sf; ++i) {
+            int a = match_str2attr(subfields[i], FALSE);
+            if (a == ATR_DIM)
+                disp_attrib |= HL_DIM;
+            else if (a == ATR_BLINK)
+                disp_attrib |= HL_BLINK;
+            else if (a == ATR_ULINE)
+                disp_attrib |= HL_ULINE;
+            else if (a == ATR_INVERSE)
+                disp_attrib |= HL_INVERSE;
+            else if (a == ATR_BOLD)
+                disp_attrib |= HL_BOLD;
+            else if (a == ATR_NONE)
+                disp_attrib = HL_NONE;
+            else {
+                int c = match_str2clr(subfields[i]);
+
+                if (c >= CLR_MAX || coloridx != -1)
+                    return FALSE;
+                coloridx = c;
+           }
+        }
+        if (coloridx == -1)
+            coloridx = NO_COLOR;
+
+        /* Assign the values */
+        hilite.coloridx = coloridx | (disp_attrib << 8);
+
+        if (always)
+            hilite.behavior = BL_TH_ALWAYS_HILITE;
+        else if (percent)
+            hilite.behavior = BL_TH_VAL_PERCENTAGE;
+        else if (changed)
+            hilite.behavior = BL_TH_UPDOWN;
+        else if (numeric)
+            hilite.behavior = BL_TH_VAL_ABSOLUTE;
+        else if (txtval)
+            hilite.behavior = BL_TH_TEXTMATCH;
+        else if (hilite.value.a_void)
+            hilite.behavior = BL_TH_VAL_ABSOLUTE;
+       else
+            hilite.behavior = BL_TH_NONE;
+
+        hilite.anytype = dt;
+
+        if (hilite.behavior == BL_TH_TEXTMATCH && txt
+            && strlen(txt) < QBUFSZ-1) {
+            Strcpy(hilite.textmatch, txt);
+            (void) trimspaces(hilite.textmatch);
+        }
+
+        status_hilite_add_threshold(fld, &hilite);
+
+        successes++;
+        sidx++;
     }
 
-    /* Assign the values */
+    return TRUE;
+}
 
-    for (i = 0; i < 2; ++i) {
-        if (inverse[i])
-            status_hilites[idx].coloridx[i] = BL_HILITE_INVERSE;
-        else if (bold[i])
-            status_hilites[idx].coloridx[i] = BL_HILITE_BOLD;
-        else if (coloridx[i])
-            status_hilites[idx].coloridx[i] = coloridx[i];
-        else
-            status_hilites[idx].coloridx[i] = BL_HILITE_NONE;
+
+
+const struct condmap valid_conditions[] = {
+    {"stone",    BL_MASK_STONE},
+    {"slime",    BL_MASK_SLIME},
+    {"strngl",   BL_MASK_STRNGL},
+    {"foodPois", BL_MASK_FOODPOIS},
+    {"termIll",  BL_MASK_TERMILL},
+    {"blind",    BL_MASK_BLIND},
+    {"deaf",     BL_MASK_DEAF},
+    {"stun",     BL_MASK_STUN},
+    {"conf",     BL_MASK_CONF},
+    {"hallu",    BL_MASK_HALLU},
+    {"lev",      BL_MASK_LEV},
+    {"fly",      BL_MASK_FLY},
+    {"ride",     BL_MASK_RIDE},
+};
+
+const struct condmap condition_aliases[] = {
+    {"strangled",      BL_MASK_STRNGL},
+    {"all",            BL_MASK_STONE | BL_MASK_SLIME | BL_MASK_STRNGL |
+                       BL_MASK_FOODPOIS | BL_MASK_TERMILL |
+                       BL_MASK_BLIND | BL_MASK_DEAF | BL_MASK_STUN |
+                       BL_MASK_CONF | BL_MASK_HALLU |
+                       BL_MASK_LEV | BL_MASK_FLY | BL_MASK_RIDE },
+    {"major_troubles", BL_MASK_STONE | BL_MASK_SLIME | BL_MASK_STRNGL |
+                       BL_MASK_FOODPOIS | BL_MASK_TERMILL},
+    {"minor_troubles", BL_MASK_BLIND | BL_MASK_DEAF | BL_MASK_STUN |
+                       BL_MASK_CONF | BL_MASK_HALLU},
+    {"movement",       BL_MASK_LEV | BL_MASK_FLY | BL_MASK_RIDE}
+};
+
+unsigned long
+query_conditions()
+{
+    int i,res;
+    unsigned long ret = 0UL;
+    winid tmpwin;
+    anything any;
+    menu_item *picks = (menu_item *) 0;
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    for (i = 0; i < SIZE(valid_conditions); i++) {
+        any = zeroany;
+        any.a_ulong = valid_conditions[i].bitmask;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 valid_conditions[i].id, MENU_UNSELECTED);
     }
 
-    if (percent)
-        status_hilites[idx].behavior = BL_TH_VAL_PERCENTAGE;
-    else if (down_up)
-        status_hilites[idx].behavior = BL_TH_UPDOWN;
-    else if (threshold.a_void)
-        status_hilites[idx].behavior = BL_TH_VAL_ABSOLUTE;
-    else
-        status_hilites[idx].behavior = BL_TH_NONE;
+    end_menu(tmpwin, "Choose status conditions");
 
-    if (status_hilites[idx].behavior != BL_TH_NONE) {
-        status_hilites[idx].threshold = threshold;
-        status_hilites[idx].set = TRUE;
+    res = select_menu(tmpwin, PICK_ANY, &picks);
+    destroy_nhwindow(tmpwin);
+    if (res > 0) {
+        for (i = 0; i < res; i++)
+            ret |= picks[i].item.a_ulong;
+        free((genericptr_t) picks);
     }
-    status_hilites[idx].anytype = dt;
+    return ret;
+}
 
-    /* Now finally, we notify the window port */
-    if (!from_configfile)
-        status_threshold(idx, status_hilites[idx].anytype,
-                        status_hilites[idx].threshold,
-                        status_hilites[idx].behavior,
-                        status_hilites[idx].coloridx[0],
-                        status_hilites[idx].coloridx[1]);
+STATIC_OVL char *
+conditionbitmask2str(ul)
+unsigned long ul;
+{
+    static char buf[BUFSZ];
+    int i;
+    boolean first = TRUE;
+    const char *alias = (char *) 0;
+
+
+    buf[0] = '\0';
+    if (!ul)
+        return buf;
+
+    for (i = 1; i < SIZE(condition_aliases); i++)
+        if (condition_aliases[i].bitmask == ul)
+            alias = condition_aliases[i].id;
+
+    for (i = 0; i < SIZE(valid_conditions); i++)
+        if ((valid_conditions[i].bitmask & ul) != 0UL) {
+            Sprintf(eos(buf), "%s%s", (first) ? "" : "+",
+                    valid_conditions[i].id);
+            first = FALSE;
+        }
+
+    if (!first && alias)
+        Sprintf(buf, "%s", alias);
+
+    return buf;
+}
+
+STATIC_OVL unsigned long
+match_str2conditionbitmask(str)
+const char *str;
+{
+    int i, nmatches = 0;
+    unsigned long mask = 0UL;
+
+    if (str && *str) {
+        /* check matches to canonical names */
+        for (i = 0; i < SIZE(valid_conditions); i++)
+            if (fuzzymatch(valid_conditions[i].id, str, " -_", TRUE)) {
+                mask |= valid_conditions[i].bitmask;
+                nmatches++;
+            }
 
+        if (!nmatches) {
+            /* check aliases */
+            for (i = 0; i < SIZE(condition_aliases); i++)
+                if (fuzzymatch(condition_aliases[i].id, str, " -_", TRUE)) {
+                    mask |= condition_aliases[i].bitmask;
+                    nmatches++;
+                }
+        }
+
+        if (!nmatches) {
+            /* check partial matches to aliases */
+            int len = (int) strlen(str);
+            for (i = 0; i < SIZE(condition_aliases); i++)
+                if (!strncmpi(str, condition_aliases[i].id, len)) {
+                    mask |= condition_aliases[i].bitmask;
+                    nmatches++;
+                }
+        }
+    }
+
+    return mask;
+}
+
+STATIC_OVL unsigned long
+str2conditionbitmask(str)
+char *str;
+{
+    unsigned long conditions_bitmask = 0UL;
+    char **subfields;
+    int i, sf;
+
+    sf = splitsubfields(str, &subfields, SIZE(valid_conditions));
+
+    if (sf < 1)
+        return 0UL;
+
+    for (i = 0; i < sf; ++i) {
+        unsigned long bm = match_str2conditionbitmask(subfields[i]);
+
+        if (!bm) {
+            config_error_add("Unknown condition '%s'", subfields[i]);
+            return 0UL;
+        }
+        conditions_bitmask |= bm;
+    }
+    return conditions_bitmask;
+}
+
+STATIC_OVL boolean
+parse_condition(s, sidx)
+char (*s)[QBUFSZ];
+int sidx;
+{
+    int i;
+    int coloridx = NO_COLOR;
+    char *tmp, *how;
+    unsigned long conditions_bitmask = 0UL;
+    boolean success = FALSE;
+
+    if (!s)
+        return FALSE;
+
+    /*3.6.1:
+      OPTION=hilite_status: condition/stone+slime+foodPois/red&inverse */
+
+    sidx++;
+    while(s[sidx]) {
+        int sf = 0;     /* subfield count */
+        char buf[BUFSZ], **subfields;
+
+        tmp = s[sidx];
+        if (!*tmp) {
+            if (!success)
+                config_error_add("Missing condition(s)");
+            return success;
+       }
+
+        Strcpy(buf, tmp);
+        conditions_bitmask = str2conditionbitmask(buf);
+
+        if (!conditions_bitmask)
+            return FALSE;
+
+        /*
+         * We have the conditions_bitmask with bits set for
+         * each ailment we want in a particular color and/or
+         * attribute, but we need to assign it to an arry of
+         * bitmasks indexed by the color chosen
+         *        (0 to (CLR_MAX - 1))
+         * and/or attributes chosen
+         *        (HL_ATTCLR_DIM to (BL_ATTCLR_MAX - 1))
+         * We still have to parse the colors and attributes out.
+         */
+
+        /* actions */
+        sidx++;
+        how = s[sidx];
+        if (!how || !*how) {
+            config_error_add("Missing color+attribute");
+            return FALSE;
+        }
+
+        Strcpy(buf, how);
+        sf = splitsubfields(buf, &subfields, 0);
+
+        /*
+         * conditions_bitmask now has bits set representing
+         * the conditions that player wants represented, but
+         * now we parse out *how* they will be represented.
+         *
+         * Only 1 colour is allowed, but potentially multiple
+         * attributes are allowed.
+         *
+         * We have the following additional array offsets to
+         * use for storing the attributes beyond the end of
+         * the color indexes, all of which are less than CLR_MAX.
+         * HL_ATTCLR_DIM        = CLR_MAX
+         * HL_ATTCLR_BLINK      = CLR_MAX + 1
+         * HL_ATTCLR_ULINE      = CLR_MAX + 2
+         * HL_ATTCLR_INVERSE    = CLR_MAX + 3
+         * HL_ATTCLR_BOLD       = CLR_MAX + 4
+         * HL_ATTCLR_MAX        = CLR_MAX + 5 (this is past array boundary)
+         *
+         */
+
+        for (i = 0; i < sf; ++i) {
+            int a = match_str2attr(subfields[i], FALSE);
+            if (a == ATR_DIM)
+                cond_hilites[HL_ATTCLR_DIM] |= conditions_bitmask;
+            else if (a == ATR_BLINK)
+                cond_hilites[HL_ATTCLR_BLINK] |= conditions_bitmask;
+            else if (a == ATR_ULINE)
+                cond_hilites[HL_ATTCLR_ULINE] |= conditions_bitmask;
+            else if (a == ATR_INVERSE)
+                cond_hilites[HL_ATTCLR_INVERSE] |= conditions_bitmask;
+            else if (a == ATR_BOLD)
+                cond_hilites[HL_ATTCLR_BOLD] |= conditions_bitmask;
+            else if (a == ATR_NONE) {
+                cond_hilites[HL_ATTCLR_DIM]     = 0UL;
+                cond_hilites[HL_ATTCLR_BLINK]   = 0UL;
+                cond_hilites[HL_ATTCLR_ULINE]   = 0UL;
+                cond_hilites[HL_ATTCLR_INVERSE] = 0UL;
+                cond_hilites[HL_ATTCLR_BOLD]    = 0UL;
+            } else {
+                int k = match_str2clr(subfields[i]);
+
+                if (k >= CLR_MAX)
+                    return FALSE;
+                coloridx = k;
+           }
+        }
+        /* set the bits in the appropriate member of the
+           condition array according to color chosen as index */
+
+        cond_hilites[coloridx] |= conditions_bitmask;
+        success = TRUE;
+        sidx++;
+    }
     return TRUE;
 }
 
 void
-status_notify_windowport(all)
-boolean all;
+clear_status_hilites()
 {
-    int idx;
-    anything it;
-
-    it = zeroany;
-    for (idx = 0; idx < MAXBLSTATS; ++idx) {
-        if (status_hilites[idx].set)
-            status_threshold(idx, status_hilites[idx].anytype,
-                            status_hilites[idx].threshold,
-                            status_hilites[idx].behavior,
-                            status_hilites[idx].coloridx[0],
-                            status_hilites[idx].coloridx[1]);
-        else
-            status_threshold(idx, blstats[0][idx].anytype, it, 0, 0, 0);
+    int i;
 
+    for (i = 0; i < MAXBLSTATS; ++i) {
+        if (blstats[0][i].thresholds) {
+            struct hilite_s *temp = blstats[0][i].thresholds,
+                            *next = (struct hilite_s *)0;
+            while (temp) {
+                next = temp->next;
+                free(temp);
+                blstats[0][i].thresholds = (struct hilite_s *)0;
+                blstats[1][i].thresholds = blstats[0][i].thresholds;
+                temp = next;
+            }
+       }
     }
 }
 
-/*
- * get_status_hilites
- *
- * Returns a string containing all the status hilites in the
- * same format that is used to specify a status hilite preference
- * in the config file.
- */
-char *
-get_status_hilites(buf, bufsiz)
+STATIC_OVL char *
+hlattr2attrname(attrib, buf, bufsz)
+int attrib, bufsz;
 char *buf;
-int bufsiz;
 {
-    int i, j, k, coloridx;
-    const char *text = (char *) 0;
-    char tmp[BUFSZ], colorname[BUFSZ];
-    boolean val_percentage, val_absolute, up_down;
-    boolean added_one = FALSE;
+    if (attrib && buf) {
+        char attbuf[BUFSZ];
+        int k, first = 0;
+
+        attbuf[0] = '\0';
+        if (attrib & HL_NONE) {
+            Strcpy(buf, "normal");
+            return buf;
+        }
 
-    if (!buf)
-        return (char *) 0;
-    *buf = '\0';
+        if (attrib & HL_BOLD)
+            Strcat(attbuf, first++ ? "+bold" : "bold");
+        if (attrib & HL_INVERSE)
+            Strcat(attbuf, first++ ? "+inverse" : "inverse");
+        if (attrib & HL_ULINE)
+            Strcat(attbuf, first++ ? "+underline" : "underline");
+        if (attrib & HL_BLINK)
+            Strcat(attbuf, first++ ? "+blink" : "blink");
+        if (attrib & HL_DIM)
+            Strcat(attbuf, first++ ? "+dim" : "dim");
+
+        k = strlen(attbuf);
+        if (k < (bufsz - 1))
+            Strcpy(buf, attbuf);
+        return buf;
+    }
+    return (char *) 0;
+}
 
-    bufsiz--; /* required trailing null */
-    for (i = 0; i < MAXBLSTATS; ++i) {
-        val_percentage = val_absolute = up_down = FALSE;
-        if (status_hilites[i].set) {
-            if (!added_one)
-                added_one = TRUE;
-            else {
-                Strcat(buf, " ");
-                bufsiz--;
-            }
-            k = strlen(fieldids[i].fieldname);
-            if (k < bufsiz) {
-                Strcat(buf, fieldids[i].fieldname);
-                bufsiz -= k;
-            }
-            if (bufsiz > 1) {
-                Strcat(buf, "/");
-                bufsiz--;
-            }
-            if (status_hilites[i].behavior == BL_TH_VAL_PERCENTAGE) {
-                val_percentage = TRUE;
-            } else if (status_hilites[i].behavior == BL_TH_VAL_ABSOLUTE) {
-                val_absolute = TRUE;
-            } else if (status_hilites[i].behavior == BL_TH_UPDOWN) {
-                up_down = TRUE;
-                text = "updown";
-            }
 
-            if (status_hilites[i].behavior != BL_TH_UPDOWN) {
-                anything_to_s(tmp, &status_hilites[i].threshold,
-                          blstats[0][i].anytype);
-                text = tmp;
-            }
-            k = strlen(text);
-            if (k < (bufsiz - 1)) {
-                Strcat(buf, text);
-                if (val_percentage)
-                    Strcat(buf, "%"), k++;
-                bufsiz -= k;
-            }
-            for (j = 0; j < 2; ++j) {
-                if (bufsiz > 1) {
-                    Strcat(buf, "/");
-                    bufsiz--;
-                }
-                coloridx = status_hilites[i].coloridx[j];
-                if (coloridx < 0) {
-                    if (coloridx == BL_HILITE_BOLD)
-                        text = "bold";
-                    else if (coloridx == BL_HILITE_INVERSE)
-                        text = "inverse";
-                    else
-                        text = "normal";
-                } else {
-                    char *blank;
-                    (void) strcpy(colorname, c_obj_colors[coloridx]);
-                    for (blank = index(colorname, ' '); blank;
-                         blank = index(colorname, ' '))
-                        *blank = '-';
-                    text = colorname;
-                }
-                k = strlen(text);
-                if (k < bufsiz) {
-                    Strcat(buf, text);
-                    bufsiz -= k;
+struct _status_hilite_line_str {
+    int id;
+    int fld;
+    struct hilite_s *hl;
+    unsigned long mask;
+    char str[BUFSZ];
+    struct _status_hilite_line_str *next;
+};
+
+struct _status_hilite_line_str *status_hilite_str =
+    (struct _status_hilite_line_str *) 0;
+static int status_hilite_str_id = 0;
+
+STATIC_OVL void
+status_hilite_linestr_add(fld, hl, mask, str)
+int fld;
+struct hilite_s *hl;
+unsigned long mask;
+const char *str;
+{
+    struct _status_hilite_line_str *tmp = (struct _status_hilite_line_str *)
+        alloc(sizeof(struct _status_hilite_line_str));
+    struct _status_hilite_line_str *nxt = status_hilite_str;
+
+    (void) memset(tmp, 0, sizeof(struct _status_hilite_line_str));
+
+    ++status_hilite_str_id;
+    tmp->fld = fld;
+    tmp->hl = hl;
+    tmp->mask = mask;
+    (void) stripchars(tmp->str, " ", str);
+
+    tmp->id = status_hilite_str_id;
+
+    if (nxt) {
+        while (nxt && nxt->next)
+            nxt = nxt->next;
+        nxt->next = tmp;
+    } else {
+        tmp->next = (struct _status_hilite_line_str *) 0;
+        status_hilite_str = tmp;
+    }
+}
+
+STATIC_OVL void
+status_hilite_linestr_done()
+{
+    struct _status_hilite_line_str *tmp = status_hilite_str;
+    struct _status_hilite_line_str *nxt;
+
+    while (tmp) {
+        nxt = tmp->next;
+        free(tmp);
+        tmp = nxt;
+    }
+    status_hilite_str = (struct _status_hilite_line_str *) 0;
+    status_hilite_str_id = 0;
+}
+
+STATIC_OVL int
+status_hilite_linestr_countfield(fld)
+int fld;
+{
+    struct _status_hilite_line_str *tmp = status_hilite_str;
+    int count = 0;
+
+    while (tmp) {
+        if (tmp->fld == fld || fld == BL_FLUSH)
+            count++;
+        tmp = tmp->next;
+    }
+    return count;
+}
+
+int
+count_status_hilites(VOID_ARGS)
+{
+    int count;
+    status_hilite_linestr_gather();
+    count = status_hilite_linestr_countfield(BL_FLUSH);
+    status_hilite_linestr_done();
+    return count;
+}
+
+STATIC_OVL void
+status_hilite_linestr_gather_conditions()
+{
+    int i;
+    struct _cond_map {
+        unsigned long bm;
+        unsigned long clratr;
+    } cond_maps[SIZE(valid_conditions)];
+
+    (void)memset(cond_maps, 0,
+                 sizeof(struct _cond_map) * SIZE(valid_conditions));
+
+    for (i = 0; i < SIZE(valid_conditions); i++) {
+        int clr = NO_COLOR;
+        int atr = HL_NONE;
+        int j;
+        for (j = 0; j < CLR_MAX; j++)
+            if (cond_hilites[j] & valid_conditions[i].bitmask)
+                clr = j;
+        if (cond_hilites[HL_ATTCLR_DIM] & valid_conditions[i].bitmask)
+            atr |= HL_DIM;
+        if (cond_hilites[HL_ATTCLR_BOLD] & valid_conditions[i].bitmask)
+            atr |= HL_BOLD;
+        if (cond_hilites[HL_ATTCLR_BLINK] & valid_conditions[i].bitmask)
+            atr |= HL_BLINK;
+        if (cond_hilites[HL_ATTCLR_ULINE] & valid_conditions[i].bitmask)
+            atr |= HL_ULINE;
+        if (cond_hilites[HL_ATTCLR_INVERSE] & valid_conditions[i].bitmask)
+            atr |= HL_INVERSE;
+
+        if (clr != NO_COLOR || atr != HL_NONE) {
+            unsigned long ca = clr | (atr << 8);
+            boolean added_condmap = FALSE;
+            for (j = 0; j < SIZE(valid_conditions); j++)
+                if (cond_maps[j].clratr == ca) {
+                    cond_maps[j].bm |= valid_conditions[i].bitmask;
+                    added_condmap = TRUE;
+                    break;
                 }
+            if (!added_condmap) {
+                for (j = 0; j < SIZE(valid_conditions); j++)
+                    if (!cond_maps[j].bm) {
+                        cond_maps[j].bm = valid_conditions[i].bitmask;
+                        cond_maps[j].clratr = ca;
+                        break;
+                    }
             }
         }
     }
-    return buf;
+
+    for (i = 0; i < SIZE(valid_conditions); i++)
+        if (cond_maps[i].bm) {
+            int clr = NO_COLOR, atr = HL_NONE;
+            split_clridx(cond_maps[i].clratr, &clr, &atr);
+            if (clr != NO_COLOR || atr != HL_NONE) {
+                char clrbuf[BUFSZ];
+                char attrbuf[BUFSZ];
+                char condbuf[BUFSZ];
+                char *tmpattr;
+                (void) stripchars(clrbuf, " ", clr2colorname(clr));
+                tmpattr = hlattr2attrname(atr, attrbuf, BUFSZ);
+                if (tmpattr)
+                    Sprintf(eos(clrbuf), "&%s", tmpattr);
+                Sprintf(condbuf, "condition/%s/%s",
+                        conditionbitmask2str(cond_maps[i].bm), clrbuf);
+                status_hilite_linestr_add(BL_CONDITION, 0,
+                                          cond_maps[i].bm, condbuf);
+            }
+        }
 }
 
-STATIC_OVL const char *
-clridx_to_s(buf, idx)
-char *buf;
-int idx;
+STATIC_OVL void
+status_hilite_linestr_gather()
 {
-    static const char *a[] = { "bold", "inverse", "normal" };
-    char* p = 0;
+    int i;
+    struct hilite_s *hl;
 
-    if (buf) {
-        buf[0] = '\0';
-        if (idx < 0 && idx >= BL_HILITE_BOLD)
-            Strcpy(buf, a[idx + 3]);
-        else if (idx >= 0 && idx < CLR_MAX)
-            Strcpy(buf, c_obj_colors[idx]);
-        /* replace spaces with - */
-        for(p = buf; *p; p++)
-            if(*p == ' ') *p = '-';
+    status_hilite_linestr_done();
+
+    for (i = 0; i < MAXBLSTATS; i++) {
+        hl = blstats[0][i].thresholds;
+        while (hl) {
+            status_hilite_linestr_add(i, hl, 0UL, status_hilite2str(hl));
+            hl = hl->next;
+        }
     }
+
+    status_hilite_linestr_gather_conditions();
+}
+
+
+char *
+status_hilite2str(hl)
+struct hilite_s *hl;
+{
+    static char buf[BUFSZ];
+    int clr = 0, attr = 0;
+    char behavebuf[BUFSZ];
+    char clrbuf[BUFSZ];
+    char attrbuf[BUFSZ];
+    char *tmpattr;
+
+    if (!hl)
+        return (char *) 0;
+
+    behavebuf[0] = '\0';
+    clrbuf[0] = '\0';
+
+    switch (hl->behavior) {
+    case BL_TH_VAL_PERCENTAGE:
+        if (hl->rel == LT_VALUE)
+            Sprintf(behavebuf, "<%i%%", hl->value.a_int);
+        else if (hl->rel == GT_VALUE)
+            Sprintf(behavebuf, ">%i%%", hl->value.a_int);
+        else if (hl->rel == EQ_VALUE)
+            Sprintf(behavebuf, "%i%%", hl->value.a_int);
+        else
+            impossible("hl->behavior=percentage, rel error");
+        break;
+    case BL_TH_UPDOWN:
+        if (hl->rel == LT_VALUE)
+            Sprintf(behavebuf, "down");
+        else if (hl->rel == GT_VALUE)
+            Sprintf(behavebuf, "up");
+        else if (hl->rel == EQ_VALUE)
+            Sprintf(behavebuf, "changed");
+        else
+            impossible("hl->behavior=updown, rel error");
+        break;
+    case BL_TH_VAL_ABSOLUTE:
+        if (hl->rel == LT_VALUE)
+            Sprintf(behavebuf, "<%i", hl->value.a_int);
+        else if (hl->rel == GT_VALUE)
+            Sprintf(behavebuf, ">%i", hl->value.a_int);
+        else if (hl->rel == EQ_VALUE)
+            Sprintf(behavebuf, "%i", hl->value.a_int);
+        else
+            impossible("hl->behavior=absolute, rel error");
+        break;
+    case BL_TH_TEXTMATCH:
+        if (hl->rel == TXT_VALUE && hl->textmatch[0])
+            Sprintf(behavebuf, "%s", hl->textmatch);
+        else
+            impossible("hl->behavior=textmatch, rel or textmatch error");
+        break;
+    case BL_TH_CONDITION:
+        if (hl->rel == EQ_VALUE)
+            Sprintf(behavebuf, "%s", conditionbitmask2str(hl->value.a_ulong));
+        else
+            impossible("hl->behavior=condition, rel error");
+        break;
+    case BL_TH_ALWAYS_HILITE:
+        Sprintf(behavebuf, "always");
+        break;
+    case BL_TH_NONE:
+        break;
+    default:
+        break;
+    }
+
+    split_clridx(hl->coloridx, &clr, &attr);
+    if (clr != NO_COLOR)
+        (void) stripchars(clrbuf, " ", clr2colorname(clr));
+    if (attr != HL_UNDEF) {
+        tmpattr = hlattr2attrname(attr, attrbuf, BUFSZ);
+        if (tmpattr)
+            Sprintf(eos(clrbuf), "%s%s",
+                    (clr != NO_COLOR) ? "&" : "",
+                    tmpattr);
+    }
+    Sprintf(buf, "%s/%s/%s", initblstats[hl->fld].fldname, behavebuf, clrbuf);
+
     return buf;
 }
 
-boolean
-status_hilite_menu()
+int
+status_hilite_menu_choose_field()
 {
-    int i, j, k, pick_cnt, pick_idx, opt_idx;
-    menu_item *statfield_picks = (menu_item *) 0;
-    const char *fieldname;
-    int field_picks[MAXBLSTATS], res;
-    struct hilite_s hltemp[MAXBLSTATS];
-    char buf[BUFSZ], thresholdbuf[BUFSZ], below[BUFSZ], above[BUFSZ];
     winid tmpwin;
+    int i, res, fld = BL_FLUSH;
     anything any;
+    menu_item *picks = (menu_item *) 0;
 
     tmpwin = create_nhwindow(NHW_MENU);
     start_menu(tmpwin);
+
     for (i = 0; i < MAXBLSTATS; i++) {
-        (void) memset(&hltemp[i], 0, sizeof(struct hilite_s));
-        fieldname = fieldids[i].fieldname;
-        any.a_int = i + 1;
-        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, fieldname,
-                 MENU_UNSELECTED);
-        field_picks[i] = 0;
-    }
-    end_menu(tmpwin, "Change hilite on which status field(s):");
-    if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &statfield_picks)) > 0) {
-        for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
-            opt_idx = statfield_picks[pick_idx].item.a_int - 1;
-            field_picks[opt_idx] = 1;
-        }
-        free((genericptr_t) statfield_picks);
-        statfield_picks = (menu_item *) 0;
+        any = zeroany;
+        any.a_int = (i+1);
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 initblstats[i].fldname, MENU_UNSELECTED);
     }
+
+    end_menu(tmpwin, "Select a hilite field:");
+
+    res = select_menu(tmpwin, PICK_ONE, &picks);
     destroy_nhwindow(tmpwin);
-    if (pick_cnt < 0)
+    if (res > 0) {
+        fld = picks->item.a_int - 1;
+        free((genericptr_t) picks);
+    }
+    return fld;
+}
+
+int
+status_hilite_menu_choose_behavior(fld)
+int fld;
+{
+    winid tmpwin;
+    int res = 0, beh = BL_TH_NONE-1;
+    anything any;
+    menu_item *picks = (menu_item *) 0;
+    char buf[BUFSZ];
+    int at;
+    int onlybeh = BL_TH_NONE, nopts = 0;
+
+    if (fld <= BL_FLUSH || fld >= MAXBLSTATS)
+        return BL_TH_NONE;
+
+    at = initblstats[fld].anytype;
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    if (fld != BL_CONDITION) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_ALWAYS_HILITE;
+        Sprintf(buf, "Always highlight %s", initblstats[fld].fldname);
+        add_menu(tmpwin, NO_GLYPH, &any, 'a', 0, ATR_NONE,
+                 buf, MENU_UNSELECTED);
+        nopts++;
+    }
+
+    if (fld == BL_CONDITION) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_CONDITION;
+        add_menu(tmpwin, NO_GLYPH, &any, 'b', 0, ATR_NONE,
+                 "Bitmask of conditions", MENU_UNSELECTED);
+        nopts++;
+    }
+
+    if (fld != BL_CONDITION) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_UPDOWN;
+        Sprintf(buf, "%s value changes", initblstats[fld].fldname);
+        add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, ATR_NONE,
+                 buf, MENU_UNSELECTED);
+        nopts++;
+    }
+
+    if (fld != BL_CAP && fld != BL_HUNGER && (at == ANY_INT || at == ANY_LONG || at == ANY_UINT)) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_VAL_ABSOLUTE;
+        add_menu(tmpwin, NO_GLYPH, &any, 'n', 0, ATR_NONE,
+                 "Number threshold", MENU_UNSELECTED);
+        nopts++;
+    }
+
+    if (initblstats[fld].idxmax > BL_FLUSH) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_VAL_PERCENTAGE;
+        add_menu(tmpwin, NO_GLYPH, &any, 'p', 0, ATR_NONE,
+                 "Percentage threshold", MENU_UNSELECTED);
+        nopts++;
+    }
+
+    if (initblstats[fld].anytype == ANY_STR || fld == BL_CAP || fld == BL_HUNGER) {
+        any = zeroany;
+        any.a_int = onlybeh = BL_TH_TEXTMATCH;
+        Sprintf(buf, "%s text match", initblstats[fld].fldname);
+        add_menu(tmpwin, NO_GLYPH, &any, 't', 0, ATR_NONE,
+                 buf, MENU_UNSELECTED);
+        nopts++;
+    }
+
+    Sprintf(buf, "Select %s field hilite behavior:", initblstats[fld].fldname);
+    end_menu(tmpwin, buf);
+
+    if (nopts > 1) {
+        res = select_menu(tmpwin, PICK_ONE, &picks);
+        if (res == 0) /* none chosen*/
+            beh = BL_TH_NONE;
+        else if (res == -1) /* menu cancelled */
+            beh = (BL_TH_NONE - 1);
+    } else if (onlybeh != BL_TH_NONE)
+        beh = onlybeh;
+    destroy_nhwindow(tmpwin);
+    if (res > 0) {
+        beh = picks->item.a_int;
+        free((genericptr_t) picks);
+    }
+    return beh;
+}
+
+int
+status_hilite_menu_choose_updownboth(fld, str)
+int fld;
+const char *str;
+{
+    int res, ret = -2;
+    winid tmpwin;
+    char buf[BUFSZ];
+    anything any;
+    menu_item *picks = (menu_item *) 0;
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    if (str)
+        Sprintf(buf, "%s or less", str);
+    else
+        Sprintf(buf, "Value goes down");
+    any = zeroany;
+    any.a_int = 10 + LT_VALUE;
+    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+             buf, MENU_UNSELECTED);
+
+    if (str)
+        Sprintf(buf, "Exactly %s", str);
+    else
+        Sprintf(buf, "Value changes");
+    any = zeroany;
+    any.a_int = 10 + EQ_VALUE;
+    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+             buf, MENU_UNSELECTED);
+
+    if (str)
+        Sprintf(buf, "%s or more", str);
+    else
+        Sprintf(buf, "Value goes up");
+    any = zeroany;
+    any.a_int = 10 + GT_VALUE;
+    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+             buf, MENU_UNSELECTED);
+
+    Sprintf(buf, "Select field %s value:", initblstats[fld].fldname);
+    end_menu(tmpwin, buf);
+
+    res = select_menu(tmpwin, PICK_ONE, &picks);
+    destroy_nhwindow(tmpwin);
+    if (res > 0) {
+        ret = picks->item.a_int - 10;
+        free((genericptr_t) picks);
+    }
+
+    return ret;
+}
+
+STATIC_OVL boolean
+status_hilite_menu_add(origfld)
+int origfld;
+{
+    int fld;
+    int behavior;
+    int lt_gt_eq = 0;
+    int clr = NO_COLOR, atr = HL_UNDEF;
+    struct hilite_s hilite;
+    unsigned long cond = 0UL;
+    char colorqry[BUFSZ];
+    char attrqry[BUFSZ];
+
+choose_field:
+    fld = origfld;
+    if (fld == BL_FLUSH) {
+        fld = status_hilite_menu_choose_field();
+        if (fld == BL_FLUSH)
+            return FALSE;
+    }
+
+    if (fld == BL_FLUSH)
         return FALSE;
 
-    for (i = 0; i < MAXBLSTATS; i++) {
-        if (field_picks[i]) {
-            menu_item *pick = (menu_item *) 0;
-            Sprintf(buf, "Threshold behavior options for %s:",
-                    fieldids[i].fieldname);
-            tmpwin = create_nhwindow(NHW_MENU);
-            start_menu(tmpwin);
-            if (i == BL_CONDITION) {
-                any = zeroany;
-                any.a_int = BL_TH_CONDITION + 1;
-                add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, ATR_NONE,
-                         "Condition bitmask threshold.", MENU_UNSELECTED);
+    colorqry[0] = '\0';
+    attrqry[0] = '\0';
+
+    memset((genericptr_t) &hilite, 0, sizeof(struct hilite_s));
+    hilite.set = FALSE; /* mark it "unset" */
+    hilite.fld = fld;
+
+choose_behavior:
+
+    behavior = status_hilite_menu_choose_behavior(fld);
+
+    if (behavior == (BL_TH_NONE-1)) {
+        return FALSE;
+    } else if (behavior == BL_TH_NONE) {
+        if (origfld == BL_FLUSH)
+            goto choose_field;
+        else
+            return FALSE;
+    }
+
+    hilite.behavior = behavior;
+
+choose_value:
+
+    if (behavior == BL_TH_VAL_PERCENTAGE
+        || behavior == BL_TH_VAL_ABSOLUTE) {
+        char inbuf[BUFSZ] = DUMMY, buf[BUFSZ];
+        int val;
+        boolean skipltgt = FALSE;
+        boolean gotnum = FALSE;
+        char *inp = inbuf;
+        char *numstart = inbuf;
+
+        inbuf[0] = '\0';
+        Sprintf(buf, "Enter %svalue for %s threshold:",
+                (behavior == BL_TH_VAL_PERCENTAGE) ? "percentage " : "",
+                initblstats[fld].fldname);
+        getlin(buf, inbuf);
+        if (inbuf[0] == '\0' || inbuf[0] == '\033')
+            goto choose_behavior;
+
+        inp = trimspaces(inbuf);
+        if (!*inp)
+            goto choose_behavior;
+
+        /* allow user to enter "<50%" or ">50" or just "50" */
+        if (*inp == '>' || *inp == '<' || *inp == '=') {
+            lt_gt_eq = (*inp == '>') ? GT_VALUE
+                : (*inp == '<') ? LT_VALUE : EQ_VALUE;
+            skipltgt = TRUE;
+            *inp = ' ';
+            inp++;
+            numstart++;
+        }
+        while (digit(*inp)) {
+            inp++;
+            gotnum = TRUE;
+        }
+        if (*inp == '%') {
+            behavior = BL_TH_VAL_PERCENTAGE;
+            *inp = '\0';
+        } else if (!*inp) {
+            behavior = BL_TH_VAL_ABSOLUTE;
+        } else {
+            /* some random characters */
+            pline("\"%s\" is not a recognized number.", inp);
+            goto choose_value;
+        }
+        if (!gotnum) {
+            pline("Is that an invisible number?");
+            goto choose_value;
+        }
+
+        val = atoi(numstart);
+        if (behavior == BL_TH_VAL_PERCENTAGE) {
+            if (initblstats[fld].idxmax == -1) {
+                pline("Field '%s' does not support percentage values.",
+                      initblstats[fld].fldname);
+                behavior = BL_TH_VAL_ABSOLUTE;
+                goto choose_value;
             }
-            any = zeroany;
-            any.a_int = BL_TH_NONE + 1;
-            add_menu(tmpwin, NO_GLYPH, &any, 'n', 0, ATR_NONE, "None",
-                     MENU_UNSELECTED);
-            if (i != BL_CONDITION) {
-                if (blstats[0][i].idxmax > 0) {
-                    any = zeroany;
-                    any.a_int = BL_TH_VAL_PERCENTAGE + 1;
-                    add_menu(tmpwin, NO_GLYPH, &any, 'p', 0, ATR_NONE,
-                             "Percentage threshold.", MENU_UNSELECTED);
+            if (val < 0 || val > 100) {
+                pline("Not a valid percent value.");
+                goto choose_value;
+            }
+        }
+
+        if (!skipltgt) {
+            lt_gt_eq = status_hilite_menu_choose_updownboth(fld, inbuf);
+            if (lt_gt_eq == -2)
+                goto choose_value;
+        }
+
+        Sprintf(colorqry, "Choose a color for when %s is %s%s:",
+                initblstats[fld].fldname,
+                numstart,
+                (lt_gt_eq == EQ_VALUE) ? ""
+                : (lt_gt_eq == LT_VALUE) ? " or less"
+                : " or more");
+
+        Sprintf(attrqry, "Choose attribute for when %s is %s%s:",
+                initblstats[fld].fldname,
+                inbuf,
+                (lt_gt_eq == EQ_VALUE) ? ""
+                : (lt_gt_eq == LT_VALUE) ? " or less"
+                : " or more");
+
+        hilite.rel = lt_gt_eq;
+        hilite.value.a_int = val;
+    } else if (behavior == BL_TH_UPDOWN) {
+        lt_gt_eq = status_hilite_menu_choose_updownboth(fld, (char *)0);
+        if (lt_gt_eq == -2)
+            goto choose_behavior;
+        Sprintf(colorqry, "Choose a color for when %s %s:",
+                initblstats[fld].fldname,
+                (lt_gt_eq == EQ_VALUE) ? "changes"
+                : (lt_gt_eq == LT_VALUE) ? "decreases"
+                : "increases");
+        Sprintf(attrqry, "Choose attribute for when %s %s:",
+                initblstats[fld].fldname,
+                (lt_gt_eq == EQ_VALUE) ? "changes"
+                : (lt_gt_eq == LT_VALUE) ? "decreases"
+                : "increases");
+        hilite.rel = lt_gt_eq;
+    } else if (behavior == BL_TH_CONDITION) {
+        cond = query_conditions();
+        if (!cond) {
+            if (origfld == BL_FLUSH)
+                goto choose_field;
+            else
+                return FALSE;
+        }
+        Sprintf(colorqry, "Choose a color for conditions %s:",
+                conditionbitmask2str(cond));
+        Sprintf(attrqry, "Choose attribute for conditions %s:",
+                conditionbitmask2str(cond));
+    } else if (behavior == BL_TH_TEXTMATCH) {
+        char qry_buf[BUFSZ];
+        Sprintf(qry_buf, "%s %s text value to match:",
+                (fld == BL_CAP
+                 || fld == BL_ALIGN
+                 || fld == BL_HUNGER
+                 || fld == BL_TITLE) ? "Choose" : "Enter",
+                initblstats[fld].fldname);
+        if (fld == BL_CAP) {
+            int rv = query_arrayvalue(qry_buf,
+                                      enc_stat,
+                                      SLT_ENCUMBER, OVERLOADED+1);
+            if (rv < SLT_ENCUMBER)
+                goto choose_behavior;
+
+            hilite.rel = TXT_VALUE;
+            Strcpy(hilite.textmatch, enc_stat[rv]);
+        } else if (fld == BL_ALIGN) {
+            const char *aligntxt[] = {"chaotic", "neutral", "lawful"};
+            int rv = query_arrayvalue(qry_buf,
+                                      aligntxt, 0, 3);
+            if (rv < 0)
+                goto choose_behavior;
+
+            hilite.rel = TXT_VALUE;
+            Strcpy(hilite.textmatch, aligntxt[rv]);
+        } else if (fld == BL_HUNGER) {
+            const char *hutxt[] = {"Satiated", (char *)0, "Hungry", "Weak",
+                                   "Fainting", "Fainted", "Starved"};
+            int rv = query_arrayvalue(qry_buf,
+                                      hutxt,
+                                      SATIATED, STARVED+1);
+            if (rv < SATIATED)
+                goto choose_behavior;
+
+            hilite.rel = TXT_VALUE;
+            Strcpy(hilite.textmatch, hutxt[rv]);
+        } else if (fld == BL_TITLE) {
+            const char *rolelist[9];
+            int i, rv;
+
+            for (i = 0; i < 9; i++)
+                rolelist[i] = (flags.female && urole.rank[i].f)
+                    ? urole.rank[i].f : urole.rank[i].m;
+
+            rv = query_arrayvalue(qry_buf, rolelist, 0, 9);
+            if (rv < 0)
+                goto choose_behavior;
+
+            hilite.rel = TXT_VALUE;
+            Strcpy(hilite.textmatch, rolelist[rv]);
+        } else {
+            char inbuf[BUFSZ] = DUMMY;
+
+            inbuf[0] = '\0';
+            getlin(qry_buf, inbuf);
+            if (inbuf[0] == '\0' || inbuf[0] == '\033')
+                goto choose_behavior;
+
+            hilite.rel = TXT_VALUE;
+            if (strlen(inbuf) < QBUFSZ-1)
+                Strcpy(hilite.textmatch, inbuf);
+            else
+                return FALSE;
+        }
+        Sprintf(colorqry, "Choose a color for when %s is '%s':",
+                initblstats[fld].fldname, hilite.textmatch);
+        Sprintf(colorqry, "Choose attribute for when %s is '%s':",
+                initblstats[fld].fldname, hilite.textmatch);
+    } else if (behavior == BL_TH_ALWAYS_HILITE) {
+        Sprintf(colorqry, "Choose a color to always hilite %s:",
+                initblstats[fld].fldname);
+        Sprintf(attrqry, "Choose attribute to always hilite %s:",
+                initblstats[fld].fldname);
+    }
+
+choose_color:
+
+    clr = query_color(colorqry);
+    if (clr == -1) {
+        if (behavior != BL_TH_ALWAYS_HILITE)
+            goto choose_value;
+        else
+            goto choose_behavior;
+    }
+
+    atr = query_attr(attrqry); /* FIXME: pick multiple attrs */
+    if (atr == -1)
+        goto choose_color;
+    if (atr == ATR_DIM)
+        atr = HL_DIM;
+    else if (atr == ATR_BLINK)
+        atr = HL_BLINK;
+    else if (atr == ATR_ULINE)
+        atr = HL_ULINE;
+    else if (atr == ATR_INVERSE)
+        atr = HL_INVERSE;
+    else if (atr == ATR_BOLD)
+        atr = HL_BOLD;
+    else if (atr == ATR_NONE)
+        atr = HL_NONE;
+    else
+        atr = HL_UNDEF;
+
+    if (clr == -1)
+        clr = NO_COLOR;
+
+    if (behavior == BL_TH_CONDITION) {
+        char clrbuf[BUFSZ];
+        char attrbuf[BUFSZ];
+        char *tmpattr;
+        if (atr == HL_DIM)
+            cond_hilites[HL_ATTCLR_DIM] |= cond;
+        else if (atr == HL_BLINK)
+            cond_hilites[HL_ATTCLR_BLINK] |= cond;
+        else if (atr == HL_ULINE)
+            cond_hilites[HL_ATTCLR_ULINE] |= cond;
+        else if (atr == HL_INVERSE)
+            cond_hilites[HL_ATTCLR_INVERSE] |= cond;
+        else if (atr == HL_BOLD)
+            cond_hilites[HL_ATTCLR_BOLD] |= cond;
+        else if (atr == HL_NONE) {
+            cond_hilites[HL_ATTCLR_DIM]     = 0UL;
+            cond_hilites[HL_ATTCLR_BLINK]   = 0UL;
+            cond_hilites[HL_ATTCLR_ULINE]   = 0UL;
+            cond_hilites[HL_ATTCLR_INVERSE] = 0UL;
+            cond_hilites[HL_ATTCLR_BOLD]    = 0UL;
+        }
+        cond_hilites[clr] |= cond;
+        (void) stripchars(clrbuf, " ", clr2colorname(clr));
+        tmpattr = hlattr2attrname(atr, attrbuf, BUFSZ);
+        if (tmpattr)
+            Sprintf(eos(clrbuf), "&%s", tmpattr);
+        pline("Added hilite condition/%s/%s",
+              conditionbitmask2str(cond), clrbuf);
+    } else {
+        hilite.coloridx = clr | (atr << 8);
+        hilite.anytype = initblstats[fld].anytype;
+
+        status_hilite_add_threshold(fld, &hilite);
+        pline("Added hilite %s", status_hilite2str(&hilite));
+    }
+    reset_status_hilites();
+    return TRUE;
+}
+
+boolean
+status_hilite_remove(id)
+int id;
+{
+    struct _status_hilite_line_str *hlstr = status_hilite_str;
+
+    while (hlstr && hlstr->id != id) {
+        hlstr = hlstr->next;
+    }
+
+    if (!hlstr)
+        return FALSE;
+
+    if (hlstr->fld == BL_CONDITION) {
+        int i;
+
+        for (i = 0; i < CLR_MAX; i++)
+            cond_hilites[i] &= ~hlstr->mask;
+        cond_hilites[HL_ATTCLR_DIM] &= ~hlstr->mask;
+        cond_hilites[HL_ATTCLR_BOLD] &= ~hlstr->mask;
+        cond_hilites[HL_ATTCLR_BLINK] &= ~hlstr->mask;
+        cond_hilites[HL_ATTCLR_ULINE] &= ~hlstr->mask;
+        cond_hilites[HL_ATTCLR_INVERSE] &= ~hlstr->mask;
+        return TRUE;
+    } else {
+        int fld = hlstr->fld;
+        struct hilite_s *hl = blstats[0][fld].thresholds;
+        struct hilite_s *hlprev = (struct hilite_s *) 0;
+
+        if (hl) {
+            while (hl) {
+                if (hlstr->hl == hl) {
+                    if (hlprev)
+                        hlprev->next = hl->next;
+                    else {
+                        blstats[0][fld].thresholds = hl->next;
+                        blstats[1][fld].thresholds =
+                            blstats[0][fld].thresholds;
+                    }
+                    free(hl);
+                    return TRUE;
                 }
-                any = zeroany;
-                any.a_int = BL_TH_UPDOWN + 1;
-                add_menu(tmpwin, NO_GLYPH, &any, 'u', 0, ATR_NONE,
-                         "UpDown threshold.", MENU_UNSELECTED);
-                any = zeroany;
-                any.a_int = BL_TH_VAL_ABSOLUTE + 1;
-                add_menu(tmpwin, NO_GLYPH, &any, 'v', 0, ATR_NONE,
-                         "Value threshold.", MENU_UNSELECTED);
+                hlprev = hl;
+                hl = hl->next;
             }
-            end_menu(tmpwin, buf);
-            if ((res = select_menu(tmpwin, PICK_ONE, &pick)) > 0) {
-                hltemp[i].behavior = pick->item.a_int - 1;
-                free((genericptr_t) pick);
+        }
+    }
+    return FALSE;
+}
+
+boolean
+status_hilite_menu_fld(fld)
+int fld;
+{
+    winid tmpwin;
+    int i, res;
+    menu_item *picks = (menu_item *) 0;
+    anything any;
+    int count = status_hilite_linestr_countfield(fld);
+    struct _status_hilite_line_str *hlstr;
+    char buf[BUFSZ];
+    boolean acted = FALSE;
+
+    if (!count) {
+        if (status_hilite_menu_add(fld)) {
+            status_hilite_linestr_done();
+            status_hilite_linestr_gather();
+            count = status_hilite_linestr_countfield(fld);
+        } else
+            return FALSE;
+    }
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    if (count) {
+        hlstr = status_hilite_str;
+        while (hlstr) {
+            if (hlstr->fld == fld) {
+                any = zeroany;
+                any.a_int = hlstr->id;
+                add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                         hlstr->str, MENU_UNSELECTED);
             }
-            destroy_nhwindow(tmpwin);
-            if (res < 0)
-                return FALSE;
+            hlstr = hlstr->next;
+        }
+    } else {
+        any = zeroany;
+        Sprintf(buf, "No current hilites for %s", initblstats[fld].fldname);
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
+    }
 
-            if (hltemp[i].behavior == BL_TH_UPDOWN) {
-                Sprintf(below, "%s decreases", fieldids[i].fieldname);
-                Sprintf(above, "%s increases", fieldids[i].fieldname);
-            } else if (hltemp[i].behavior) {
-                /* Have them enter the threshold*/
-                Sprintf(
-                    buf, "Set %s threshold to what%s?", fieldids[i].fieldname,
-                    (hltemp[i].behavior == BL_TH_VAL_PERCENTAGE)
-                        ? " percentage"
-                        : (hltemp[i].behavior == BL_TH_CONDITION) ? " mask"
-                                                                  : "");
-                getlin(buf, thresholdbuf);
-                if (thresholdbuf[0] == '\033')
-                    return FALSE;
-                (void) s_to_anything(&hltemp[i].threshold, thresholdbuf,
-                                     blstats[0][i].anytype);
-                if (!hltemp[i].threshold.a_void)
-                    return FALSE;
+    /* separator line */
+    any = zeroany;
+    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+
+    if (count) {
+        any = zeroany;
+        any.a_int = -1;
+        add_menu(tmpwin, NO_GLYPH, &any, 'X', 0, ATR_NONE,
+                 "Remove selected hilites", MENU_UNSELECTED);
+    }
+
+    any = zeroany;
+    any.a_int = -2;
+    add_menu(tmpwin, NO_GLYPH, &any, 'Z', 0, ATR_NONE,
+             "Add a new hilite", MENU_UNSELECTED);
+
+
+    Sprintf(buf, "Current %s hilites:", initblstats[fld].fldname);
+    end_menu(tmpwin, buf);
 
-                Sprintf(below, "%s falls below %s%s", fieldids[i].fieldname,
-                        thresholdbuf,
-                        (hltemp[i].behavior == BL_TH_VAL_PERCENTAGE) ? "%"
-                                                                     : "");
-                Sprintf(above, "%s rises above %s%s", fieldids[i].fieldname,
-                        thresholdbuf,
-                        (hltemp[i].behavior == BL_TH_VAL_PERCENTAGE) ? "%"
-                                                                     : "");
+    if ((res = select_menu(tmpwin, PICK_ANY, &picks)) > 0) {
+        int mode = 0;
+        for (i = 0; i < res; i++) {
+            int idx = picks[i].item.a_int;
+            if (idx == -1) {
+                /* delete selected hilites */
+                if (mode)
+                    goto shlmenu_free;
+                mode = -1;
+                break;
+            } else if (idx == -2) {
+                /* create a new hilite */
+                if (mode)
+                    goto shlmenu_free;
+                mode = -2;
+                break;
             }
-            for (j = 0; j < 2 && (hltemp[i].behavior != BL_TH_NONE); ++j) {
-                char prompt[QBUFSZ];
-                /* j == 0 below, j == 1 above */
-                menu_item *pick2 = (menu_item *) 0;
-
-                Sprintf(prompt, "Display how when %s?", j ? above : below);
-                tmpwin = create_nhwindow(NHW_MENU);
-                start_menu(tmpwin);
-                for (k = -3; k < CLR_MAX; ++k) {
-                    /* if (k == -1) continue; */
-                    any = zeroany;
-                    any.a_int = (k >= 0) ? k + 1 : k;
-                    if (k > 0)
-                        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
-                                 c_obj_colors[k], MENU_UNSELECTED);
-                    else if (k == -1)
-                        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
-                                 "normal", MENU_UNSELECTED);
-                    else if (k == -2)
-                        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
-                                 "inverse", MENU_UNSELECTED);
-                    else if (k == -3)
-                        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
-                                 "bold", MENU_UNSELECTED);
-                }
-                end_menu(tmpwin, prompt);
-                if ((res = select_menu(tmpwin, PICK_ONE, &pick2)) > 0) {
-                    hltemp[i].coloridx[j] = (pick2->item.a_char > 0)
-                                                ? pick2->item.a_int - 1
-                                                : pick2->item.a_int;
-                    free((genericptr_t) pick2);
-                }
-                destroy_nhwindow(tmpwin);
-                if (res < 0)
-                    return FALSE;
+        }
+
+        if (mode == -1) {
+            /* delete selected hilites */
+            for (i = 0; i < res; i++) {
+                int idx = picks[i].item.a_int;
+                if (idx > 0)
+                    (void) status_hilite_remove(idx);
             }
+            reset_status_hilites();
+            acted = TRUE;
+        } else if (mode == -2) {
+            /* create a new hilite */
+            if (status_hilite_menu_add(fld))
+                acted = TRUE;
         }
+
+        free((genericptr_t) picks);
     }
-    buf[0] = '\0';
+
+shlmenu_free:
+
+    picks = (menu_item *) 0;
+    destroy_nhwindow(tmpwin);
+    return acted;
+}
+
+void
+status_hilites_viewall()
+{
+    winid datawin;
+    struct _status_hilite_line_str *hlstr = status_hilite_str;
+    char buf[BUFSZ];
+
+    datawin = create_nhwindow(NHW_TEXT);
+
+    while (hlstr) {
+        Sprintf(buf, "OPTIONS=hilite_status: %.*s",
+                (int)(BUFSZ - sizeof "OPTIONS=hilite_status: " - 1),
+                hlstr->str);
+        putstr(datawin, 0, buf);
+        hlstr = hlstr->next;
+    }
+
+    display_nhwindow(datawin, FALSE);
+    destroy_nhwindow(datawin);
+}
+
+boolean
+status_hilite_menu()
+{
+    winid tmpwin;
+    int i, res;
+    menu_item *picks = (menu_item *) 0;
+    anything any;
+    boolean redo;
+    int countall;
+
+shlmenu_redo:
+    redo = FALSE;
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+
+    status_hilite_linestr_gather();
+
+    countall = status_hilite_linestr_countfield(BL_FLUSH);
+
+    if (countall) {
+        any = zeroany;
+        any.a_int = -1;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 "View all hilites in config format", MENU_UNSELECTED);
+
+        any = zeroany;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+    }
+
     for (i = 0; i < MAXBLSTATS; i++) {
-        if (field_picks[i]) {
-            Sprintf(eos(buf), "%s/%s%s/", fieldids[i].fieldname,
-                    (hltemp[i].behavior == BL_TH_UPDOWN)
-                        ? "updown"
-                        : anything_to_s(thresholdbuf, &hltemp[i].threshold,
-                                        blstats[0][i].anytype),
-                    (hltemp[i].behavior == BL_TH_VAL_PERCENTAGE) ? "%" : "");
-            /* borrow thresholdbuf for use with these last two */
-            Sprintf(eos(buf), "%s/",
-                    clridx_to_s(thresholdbuf, hltemp[i].coloridx[0]));
-            Sprintf(eos(buf), "%s ",
-                    clridx_to_s(thresholdbuf, hltemp[i].coloridx[1]));
-        }
+        int count = status_hilite_linestr_countfield(i);
+        char buf[BUFSZ];
+
+        any = zeroany;
+        any.a_int = (i+1);
+        if (count)
+            Sprintf(buf, "%-18s (%i defined)",
+                    initblstats[i].fldname, count);
+        else
+            Sprintf(buf, "%-18s", initblstats[i].fldname);
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 buf, MENU_UNSELECTED);
+    }
+
+
+    end_menu(tmpwin, "Status hilites:");
+    if ((res = select_menu(tmpwin, PICK_ONE, &picks)) > 0) {
+        i = picks->item.a_int - 1;
+        if (i < 0)
+            status_hilites_viewall();
+        else
+            (void) status_hilite_menu_fld(i);
+        free((genericptr_t) picks);
+        redo = TRUE;
     }
-    return set_status_hilites(buf, FALSE);
+
+    picks = (menu_item *) 0;
+    destroy_nhwindow(tmpwin);
+    status_hilite_linestr_done();
+
+    if (redo)
+        goto shlmenu_redo;
+
+    return TRUE;
 }
-#endif /*STATUS_HILITES*/
-#endif /*STATUS_VIA_WINDOWPORT*/
+
+#endif /* STATUS_HILITES */
 
 /*botl.c*/
index 75dbbd6..afc6220 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 cmd.c   $NHDT-Date: 1446975462 2015/11/08 09:37:42 $  $NHDT-Branch: master $:$NHDT-Revision: 1.206 $ */
+/* NetHack 3.6 cmd.c   $NHDT-Date: 1523306904 2018/04/09 20:48:24 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.281 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -8,6 +9,7 @@
 /* JNetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
+#include "lev.h"
 #include "func_tab.h"
 
 #ifdef ALTMETA
@@ -112,22 +114,24 @@ extern int NDECL(dowield);            /**/
 extern int NDECL(dowieldquiver);      /**/
 extern int NDECL(dozap);              /**/
 extern int NDECL(doorganize);         /**/
-#endif                                /* DUMB */
+#endif /* DUMB */
 
 static int NDECL(dosuspend_core); /**/
 
 static int NDECL((*timed_occ_fn));
 
+STATIC_PTR int NDECL(doherecmdmenu);
+STATIC_PTR int NDECL(dotherecmdmenu);
 STATIC_PTR int NDECL(doprev_message);
 STATIC_PTR int NDECL(timed_occupation);
 STATIC_PTR int NDECL(doextcmd);
-STATIC_PTR int NDECL(domonability);
-STATIC_PTR int NDECL(dooverview_or_wiz_where);
 STATIC_PTR int NDECL(dotravel);
 STATIC_PTR int NDECL(doterrain);
 STATIC_PTR int NDECL(wiz_wish);
 STATIC_PTR int NDECL(wiz_identify);
+STATIC_PTR int NDECL(wiz_intrinsic);
 STATIC_PTR int NDECL(wiz_map);
+STATIC_PTR int NDECL(wiz_makemap);
 STATIC_PTR int NDECL(wiz_genesis);
 STATIC_PTR int NDECL(wiz_where);
 STATIC_PTR int NDECL(wiz_detect);
@@ -138,6 +142,7 @@ STATIC_PTR int NDECL(wiz_level_change);
 STATIC_PTR int NDECL(wiz_show_seenv);
 STATIC_PTR int NDECL(wiz_show_vision);
 STATIC_PTR int NDECL(wiz_smell);
+STATIC_PTR int NDECL(wiz_intrinsic);
 STATIC_PTR int NDECL(wiz_mon_polycontrol);
 STATIC_PTR int NDECL(wiz_show_wmodes);
 STATIC_DCL void NDECL(wiz_map_levltyp);
@@ -148,26 +153,25 @@ extern void FDECL(show_borlandc_stats, (winid));
 #ifdef DEBUG_MIGRATING_MONS
 STATIC_PTR int NDECL(wiz_migrate_mons);
 #endif
-STATIC_DCL int FDECL(size_monst, (struct monst *));
+STATIC_DCL int FDECL(size_monst, (struct monst *, BOOLEAN_P));
 STATIC_DCL int FDECL(size_obj, (struct obj *));
 STATIC_DCL void FDECL(count_obj, (struct obj *, long *, long *,
                                   BOOLEAN_P, BOOLEAN_P));
 STATIC_DCL void FDECL(obj_chain, (winid, const char *, struct obj *,
-                                  long *, long *));
+                                  BOOLEAN_P, long *, long *));
 STATIC_DCL void FDECL(mon_invent_chain, (winid, const char *, struct monst *,
                                          long *, long *));
 STATIC_DCL void FDECL(mon_chain, (winid, const char *, struct monst *,
-                                  long *, long *));
-STATIC_DCL void FDECL(contained, (winid, const char *, long *, long *));
+                                  BOOLEAN_P, long *, long *));
+STATIC_DCL void FDECL(contained_stats, (winid, const char *, long *, long *));
+STATIC_DCL void FDECL(misc_stats, (winid, long *, long *));
 STATIC_PTR int NDECL(wiz_show_stats);
 STATIC_DCL boolean FDECL(accept_menu_prefix, (int NDECL((*))));
 #ifdef PORT_DEBUG
 STATIC_DCL int NDECL(wiz_port_debug);
 #endif
 STATIC_PTR int NDECL(wiz_rumor_check);
-STATIC_DCL char FDECL(cmd_from_func, (int NDECL((*))));
 STATIC_PTR int NDECL(doattributes);
-STATIC_PTR int NDECL(doconduct); /**/
 
 STATIC_DCL void FDECL(enlght_line, (const char *, const char *, const char *,
                                     const char *));
@@ -185,8 +189,13 @@ STATIC_DCL void FDECL(attributes_enlightenment, (int, int));
 static const char *readchar_queue = "";
 static coord clicklook_cc;
 
+STATIC_DCL void FDECL(add_herecmd_menuitem, (winid, int NDECL((*)),
+                                             const char *));
+STATIC_DCL char FDECL(here_cmd_menu, (BOOLEAN_P));
+STATIC_DCL char FDECL(there_cmd_menu, (BOOLEAN_P, int, int));
 STATIC_DCL char *NDECL(parse);
-STATIC_DCL boolean FDECL(help_dir, (CHAR_P, const char *));
+STATIC_DCL void FDECL(show_direction_keys, (winid, CHAR_P, BOOLEAN_P));
+STATIC_DCL boolean FDECL(help_dir, (CHAR_P, int, const char *));
 
 STATIC_PTR int
 doprev_message(VOID_ARGS)
@@ -325,11 +334,20 @@ doextcmd(VOID_ARGS)
             return 0; /* quit */
 
         func = extcmdlist[idx].ef_funct;
+        if (!wizard && (extcmdlist[idx].flags & WIZMODECMD)) {
+            You("can't do that.");
+            return 0;
+        }
         if (iflags.menu_requested && !accept_menu_prefix(func)) {
-/*JP
-            pline("'m' prefix has no effect for this command.");
-*/
-            pline("'m'\90Ú\93ª\8e«\82Í\82±\82Ì\83R\83}\83\93\83h\82É\82Í\96³\8cø\81D");
+#if 0 /*JP*/
+            pline("'%s' prefix has no effect for the %s command.",
+                  visctrl(Cmd.spkeys[NHKF_REQMENU]),
+                  extcmdlist[idx].ef_txt);
+#else
+            pline("'%s'\90Ú\93ª\8e«\82Í%s\83R\83}\83\93\83h\82É\82Í\96³\8cø\81D",
+                  visctrl(Cmd.spkeys[NHKF_REQMENU]),
+                  extcmdlist[idx].ef_txt);
+#endif
             iflags.menu_requested = FALSE;
         }
         retval = (*func)();
@@ -345,6 +363,7 @@ doextlist(VOID_ARGS)
     register const struct ext_func_tab *efp;
     char buf[BUFSZ];
     winid datawin;
+    char ch = cmd_from_func(doextcmd);
 
     datawin = create_nhwindow(NHW_TEXT);
     putstr(datawin, 0, "");
@@ -353,27 +372,42 @@ doextlist(VOID_ARGS)
 */
     putstr(datawin, 0, "            \8ag\92£\83R\83}\83\93\83h\88ê\97\97");
     putstr(datawin, 0, "");
-/*JP
-    putstr(datawin, 0, "    Press '#', then type:");
-*/
-    putstr(datawin, 0, "    '#'\82ð\89\9f\82µ\82½\82 \82Æ\83^\83C\83v\82¹\82æ:");
-    putstr(datawin, 0, "");
+    if (ch) {
+#if 0 /*JP*/
+        Sprintf(buf, "    Press '%s', then type:",
+                visctrl(ch));
+#else
+        Sprintf(buf, "    '%s'\82ð\89\9f\82µ\82½\82 \82Æ\83^\83C\83v\82¹\82æ:",
+                visctrl(ch));
+#endif
+        putstr(datawin, 0, buf);
+        putstr(datawin, 0, "");
+    }
 
     for (efp = extcmdlist; efp->ef_txt; efp++) {
-        Sprintf(buf, "    %-15s - %s.", efp->ef_txt, efp->ef_desc);
+        if (!wizard && (efp->flags & WIZMODECMD))
+            continue;
+        Sprintf(buf, "   %-15s %c %s.",
+                efp->ef_txt,
+                (efp->flags & AUTOCOMPLETE) ? '*' : ' ',
+                efp->ef_desc);
         putstr(datawin, 0, buf);
     }
+    putstr(datawin, 0, "");
+    putstr(datawin, 0, "    Commands marked with a * will be autocompleted.");
     display_nhwindow(datawin, FALSE);
     destroy_nhwindow(datawin);
     return 0;
 }
 
 #ifdef TTY_GRAPHICS
-#define MAX_EXT_CMD 50 /* Change if we ever have > 50 ext cmds */
+#define MAX_EXT_CMD 200 /* Change if we ever have more ext cmds */
 
 /*
- * This is currently used only by the tty port and is
- * controlled via runtime option 'extmenu'.
+ * This is currently used only by the tty interface and is
+ * controlled via runtime option 'extmenu'.  (Most other interfaces
+ * already use a menu all the time for extended commands.)
+ *
  * ``# ?'' is counted towards the limit of the number of commands,
  * so we actually support MAX_EXT_CMD-1 "real" extended commands.
  *
@@ -390,9 +424,10 @@ extcmd_via_menu()
     char buf[BUFSZ];
     char cbuf[QBUFSZ], prompt[QBUFSZ], fmtstr[20];
     int i, n, nchoices, acount;
-    int ret, biggest;
+    int ret, len, biggest;
     int accelerator, prevaccelerator;
     int matchlevel = 0;
+    boolean wastoolong, one_per_line;
 
     ret = 0;
     cbuf[0] = '\0';
@@ -402,12 +437,13 @@ extcmd_via_menu()
         any = zeroany;
         /* populate choices */
         for (efp = extcmdlist; efp->ef_txt; efp++) {
+            if (!(efp->flags & AUTOCOMPLETE)
+                || (!wizard && (efp->flags & WIZMODECMD)))
+                continue;
             if (!matchlevel || !strncmp(efp->ef_txt, cbuf, matchlevel)) {
                 choices[i] = efp;
-                if ((int) strlen(efp->ef_desc) > biggest) {
-                    biggest = strlen(efp->ef_desc);
-                    Sprintf(fmtstr, "%%-%ds", biggest + 15);
-                }
+                if ((len = (int) strlen(efp->ef_desc)) > biggest)
+                    biggest = len;
                 if (++i > MAX_EXT_CMD) {
 #if defined(BETA)
                     impossible(
@@ -422,23 +458,33 @@ extcmd_via_menu()
         choices[i] = (struct ext_func_tab *) 0;
         nchoices = i;
         /* if we're down to one, we have our selection so get out of here */
-        if (nchoices == 1) {
-            for (i = 0; extcmdlist[i].ef_txt != (char *) 0; i++)
-                if (!strncmpi(extcmdlist[i].ef_txt, cbuf, matchlevel)) {
-                    ret = i;
-                    break;
-                }
+        if (nchoices  <= 1) {
+            ret = (nchoices == 1) ? (int) (choices[0] - extcmdlist) : -1;
             break;
         }
 
         /* otherwise... */
         win = create_nhwindow(NHW_MENU);
         start_menu(win);
+        Sprintf(fmtstr, "%%-%ds", biggest + 15);
+        prompt[0] = '\0';
+        wastoolong = FALSE; /* True => had to wrap due to line width
+                             * ('w' in wizard mode) */
+        /* -3: two line menu header, 1 line menu footer (for prompt) */
+        one_per_line = (nchoices < ROWNO - 3);
         accelerator = prevaccelerator = 0;
         acount = 0;
         for (i = 0; choices[i]; ++i) {
             accelerator = choices[i]->ef_txt[matchlevel];
-            if (accelerator != prevaccelerator || nchoices < (ROWNO - 3)) {
+            if (accelerator != prevaccelerator || one_per_line)
+                wastoolong = FALSE;
+            if (accelerator != prevaccelerator || one_per_line
+                || (acount >= 2
+                    /* +4: + sizeof " or " - sizeof "" */
+                    && (strlen(prompt) + 4 + strlen(choices[i]->ef_txt)
+                        /* -6: enough room for 1 space left margin
+                         *   + "%c - " menu selector + 1 space right margin */
+                        >= min(sizeof prompt, COLNO - 6)))) {
                 if (acount) {
                     /* flush extended cmds for that letter already in buf */
                     Sprintf(buf, fmtstr, prompt);
@@ -446,18 +492,27 @@ extcmd_via_menu()
                     add_menu(win, NO_GLYPH, &any, any.a_char, 0, ATR_NONE,
                              buf, FALSE);
                     acount = 0;
+                    if (!(accelerator != prevaccelerator || one_per_line))
+                        wastoolong = TRUE;
                 }
             }
             prevaccelerator = accelerator;
-            if (!acount || nchoices < (ROWNO - 3)) {
-                Sprintf(prompt, "%s [%s]", choices[i]->ef_txt,
-                        choices[i]->ef_desc);
+            if (!acount || one_per_line) {
+#if 0 /*JP:T*/
+                Sprintf(prompt, "%s%s [%s]", wastoolong ? "or " : "",
+                        choices[i]->ef_txt, choices[i]->ef_desc);
+#else
+                Sprintf(prompt, "%s%s [%s]", wastoolong ? "\82Ü\82½\82Í" : "",
+                        choices[i]->ef_txt, choices[i]->ef_desc);
+#endif
             } else if (acount == 1) {
-/*JP
-                Sprintf(prompt, "%s or %s", choices[i - 1]->ef_txt,
-*/
-                Sprintf(prompt, "%s \82Ü\82½\82Í %s", choices[i-1]->ef_txt,
-                        choices[i]->ef_txt);
+#if 0 /*JP:T*/
+                Sprintf(prompt, "%s%s or %s", wastoolong ? "or " : "",
+                        choices[i - 1]->ef_txt, choices[i]->ef_txt);
+#else
+                Sprintf(prompt, "%s%s\82Ü\82½\82Í%s", wastoolong ? "\82Ü\82½\82Í" : "",
+                        choices[i - 1]->ef_txt, choices[i]->ef_txt);
+#endif
             } else {
 /*JP
                 Strcat(prompt, " or ");
@@ -507,7 +562,7 @@ extcmd_via_menu()
 #endif /* TTY_GRAPHICS */
 
 /* #monster command - use special monster ability while polymorphed */
-STATIC_PTR int
+int
 domonability(VOID_ARGS)
 {
     if (can_breathe(youmonst.data))
@@ -618,16 +673,6 @@ enter_explore_mode(VOID_ARGS)
     return 0;
 }
 
-STATIC_PTR int
-dooverview_or_wiz_where(VOID_ARGS)
-{
-    if (wizard)
-        return wiz_where();
-    else
-        dooverview();
-    return 0;
-}
-
 /* ^W command - wish for something */
 STATIC_PTR int
 wiz_wish(VOID_ARGS) /* Unlimited wishes for debug mode by Paul Polderman */
@@ -666,6 +711,39 @@ wiz_identify(VOID_ARGS)
     return 0;
 }
 
+STATIC_PTR int
+wiz_makemap(VOID_ARGS)
+{
+    /* FIXME: doesn't handle riding */
+    if (wizard) {
+        struct monst *mtmp;
+
+        rm_mapseen(ledger_no(&u.uz));
+        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
+            if (mtmp->isshk)
+                setpaid(mtmp);
+        if (Punished) {
+            ballrelease(FALSE);
+            unplacebc();
+        }
+        check_special_room(TRUE);
+        dmonsfree();
+        savelev(-1, ledger_no(&u.uz), FREE_SAVE);
+        mklev();
+        vision_reset();
+        vision_full_recalc = 1;
+        cls();
+        (void) safe_teleds(TRUE);
+        if (Punished) {
+            unplacebc();
+            placebc();
+        }
+        docrt();
+        flush_screen(1);
+    }
+    return 0;
+}
+
 /* ^F command - reveal the level map and any traps on it */
 STATIC_PTR int
 wiz_map(VOID_ARGS)
@@ -770,7 +848,7 @@ wiz_mon_polycontrol(VOID_ARGS)
 STATIC_PTR int
 wiz_level_change(VOID_ARGS)
 {
-    char buf[BUFSZ];
+    char buf[BUFSZ] = DUMMY;
     int newlevel;
     int ret;
 
@@ -982,7 +1060,7 @@ wiz_map_levltyp(VOID_ARGS)
         for (x = 1; x < COLNO; x++) {
             terrain = levl[x][y].typ;
             /* assumes there aren't more than 10+26+26 terrain types */
-            row[x - 1] = (char) ((terrain == 0 && !may_dig(x, y))
+            row[x - 1] = (char) ((terrain == STONE && !may_dig(x, y))
                                     ? '*'
                                     : (terrain < 10)
                                        ? '0' + terrain
@@ -990,7 +1068,8 @@ wiz_map_levltyp(VOID_ARGS)
                                           ? 'a' + terrain - 10
                                           : 'A' + terrain - 36);
         }
-        if (levl[0][y].typ != 0 || may_dig(0, y))
+        x--;
+        if (levl[0][y].typ != STONE || may_dig(0, y))
             row[x++] = '!';
         row[x] = '\0';
         putstr(win, 0, row);
@@ -1205,6 +1284,123 @@ wiz_smell(VOID_ARGS)
     return 0;
 }
 
+/* #wizinstrinsic command to set some intrinsics for testing */
+STATIC_PTR int
+wiz_intrinsic(VOID_ARGS)
+{
+    if (wizard) {
+        extern const struct propname {
+            int prop_num;
+            const char *prop_name;
+        } propertynames[]; /* timeout.c */
+        static const char wizintrinsic[] = "#wizintrinsic";
+        static const char fmt[] = "You are%s %s.";
+        winid win;
+        anything any;
+        char buf[BUFSZ];
+        int i, j, n, p, amt, typ;
+        long oldtimeout, newtimeout;
+        const char *propname;
+        menu_item *pick_list = (menu_item *) 0;
+
+        any = zeroany;
+        win = create_nhwindow(NHW_MENU);
+        start_menu(win);
+        for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) {
+            p = propertynames[i].prop_num;
+            if (p == HALLUC_RES) {
+                /* Grayswandir vs hallucination; ought to be redone to
+                   use u.uprops[HALLUC].blocked instead of being treated
+                   as a separate property; letting in be manually toggled
+                   even only in wizard mode would be asking for trouble... */
+                continue;
+            }
+            if (p == FIRE_RES) {
+                any.a_int = 0;
+                add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "--", FALSE);
+            }
+            any.a_int = i + 1; /* +1: avoid 0 */
+            oldtimeout = u.uprops[p].intrinsic & TIMEOUT;
+            if (oldtimeout)
+                Sprintf(buf, "%-27s [%li]", propname, oldtimeout);
+            else
+                Sprintf(buf, "%s", propname);
+            add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
+        }
+        end_menu(win, "Which intrinsics?");
+        n = select_menu(win, PICK_ANY, &pick_list);
+        destroy_nhwindow(win);
+
+        amt = 30; /* TODO: prompt for duration */
+        for (j = 0; j < n; ++j) {
+            i = pick_list[j].item.a_int - 1; /* -1: reverse +1 above */
+            p = propertynames[i].prop_num;
+            oldtimeout = u.uprops[p].intrinsic & TIMEOUT;
+            newtimeout = oldtimeout + (long) amt;
+            switch (p) {
+            case SICK:
+            case SLIMED:
+            case STONED:
+                if (oldtimeout > 0L && newtimeout > oldtimeout)
+                    newtimeout = oldtimeout;
+                break;
+            }
+
+            switch (p) {
+            case BLINDED:
+                make_blinded(newtimeout, TRUE);
+                break;
+#if 0       /* make_confused() only gives feedback when confusion is
+             * ending so use the 'default' case for it instead */
+            case CONFUSION:
+                make_confused(newtimeout, TRUE);
+                break;
+#endif /*0*/
+            case DEAF:
+                make_deaf(newtimeout, TRUE);
+                break;
+            case HALLUC:
+                make_hallucinated(newtimeout, TRUE, 0L);
+                break;
+            case SICK:
+                typ = !rn2(2) ? SICK_VOMITABLE : SICK_NONVOMITABLE;
+                make_sick(newtimeout, wizintrinsic, TRUE, typ);
+                break;
+            case SLIMED:
+                Sprintf(buf, fmt,
+                        !Slimed ? "" : " still", "turning into slime");
+                make_slimed(newtimeout, buf);
+                break;
+            case STONED:
+                Sprintf(buf, fmt,
+                        !Stoned ? "" : " still", "turning into stone");
+                make_stoned(newtimeout, buf, KILLED_BY, wizintrinsic);
+                break;
+            case STUNNED:
+                make_stunned(newtimeout, TRUE);
+                break;
+            case VOMITING:
+                Sprintf(buf, fmt, !Vomiting ? "" : " still", "vomiting");
+                make_vomiting(newtimeout, FALSE);
+                pline1(buf);
+                break;
+            default:
+                pline("Timeout for %s %s %d.", propertynames[i].prop_name,
+                      oldtimeout ? "increased by" : "set to", amt);
+                incr_itimeout(&u.uprops[p].intrinsic, amt);
+                break;
+            }
+            context.botl = 1; /* probably not necessary... */
+        }
+        if (n >= 1)
+            free((genericptr_t) pick_list);
+        doredraw();
+    } else
+        pline("Unavailable command '%s'.",
+              visctrl((int) cmd_from_func(wiz_intrinsic)));
+    return 0;
+}
+
 /* #wizrumorcheck command - verify each rumor access */
 STATIC_PTR int
 wiz_rumor_check(VOID_ARGS)
@@ -1234,6 +1430,7 @@ doterrain(VOID_ARGS)
      *  a legend for the levl[][].typ codes dump
      */
     men = create_nhwindow(NHW_MENU);
+    start_menu(men);
     any = zeroany;
     any.a_int = 1;
     add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
@@ -1280,13 +1477,26 @@ doterrain(VOID_ARGS)
         free((genericptr_t) sel);
 
     switch (which) {
-    case 1: reveal_terrain(0, 0);   break; /* known map */
-    case 2: reveal_terrain(0, 1);   break; /* known map with traps */
-    case 3: reveal_terrain(0, 1|2); break; /* known map w/ traps & objs */
-    case 4: reveal_terrain(1, 0);   break; /* full map */
-    case 5: wiz_map_levltyp();      break; /* map internals */
-    case 6: wiz_levltyp_legend();   break; /* internal details */
-    default: break;
+    case 1: /* known map */
+        reveal_terrain(0, TER_MAP);
+        break;
+    case 2: /* known map with known traps */
+        reveal_terrain(0, TER_MAP | TER_TRP);
+        break;
+    case 3: /* known map with known traps and objects */
+        reveal_terrain(0, TER_MAP | TER_TRP | TER_OBJ);
+        break;
+    case 4: /* full map */
+        reveal_terrain(1, TER_MAP);
+        break;
+    case 5: /* map internals */
+        wiz_map_levltyp();
+        break;
+    case 6: /* internal details */
+        wiz_levltyp_legend();
+        break;
+    default:
+        break;
     }
     return 0; /* no time elapses */
 }
@@ -1584,7 +1794,10 @@ int final;
         Sprintf(buf, "%s%s%s\82Ì\8ep", !final ? "\8d¡\82Ì\82Æ\82±\82ë" : "", tmpbuf,
                 uasmon->mname);
 #endif
+/*JP
         you_are(buf, "");
+*/
+        you_are_ing(buf, "");
     }
 
     /* report role; omit gender if it's redundant (eg, "female priestess") */
@@ -1621,19 +1834,32 @@ int final;
                 tmpbuf, urace.adj, role_titl, rank_titl);
 #endif
     }
-    you_are(buf, "");
+/*JP
+        you_are(buf, "");
+*/
+        you_are_ing(buf, "");
 
-    /* report alignment (bypass you_are() in order to omit ending period) */
+    /* report alignment (bypass you_are() in order to omit ending period);
+       adverb is used to distinguish between temporary change (helm of opp.
+       alignment), permanent change (one-time conversion), and original */
 #if 0 /*JP*/
     Sprintf(buf, " %s%s%s, %son a mission for %s",
             You_, !final ? are : were,
             align_str(u.ualign.type),
             /* helm of opposite alignment (might hide conversion) */
-            (u.ualign.type != u.ualignbase[A_CURRENT]) ? "temporarily "
+            (u.ualign.type != u.ualignbase[A_CURRENT])
+               /* what's the past tense of "currently"? if we used "formerly"
+                  it would sound like a reference to the original alignment */
+               ? (!final ? "currently " : "temporarily ")
                /* permanent conversion */
-               : (u.ualign.type != u.ualignbase[A_ORIGINAL]) ? "now "
+               : (u.ualign.type != u.ualignbase[A_ORIGINAL])
+                  /* and what's the past tense of "now"? certainly not "then"
+                     in a context like this...; "belatedly" == weren't that
+                     way sooner (in other words, didn't start that way) */
+                  ? (!final ? "now " : "belatedly ")
                   /* atheist (ignored in very early game) */
-                  : (!u.uconduct.gnostic && moves > 1000L) ? "nominally "
+                  : (!u.uconduct.gnostic && moves > 1000L)
+                     ? "nominally "
                      /* lastly, normal case */
                      : "",
             u_gname());
@@ -1706,7 +1932,10 @@ int final;
         Sprintf(buf, "actually %s", align_str(u.ualignbase[A_CURRENT]));
 */
         Sprintf(buf, "\8eÀ\8dÛ\82É\82Í%s", align_str(u.ualignbase[A_CURRENT]));
+/*JP
         you_are(buf, "");
+*/
+        enl_msg(buf, "\82Ä\82¢\82é", "\82Ä\82¢\82½", "", "");
         difalgn &= ~1; /* suppress helm from "started out <foo>" message */
     }
     if (difgend || difalgn) { /* sex change or perm align change or both */
@@ -1725,12 +1954,19 @@ int final;
     }
 }
 
-/* characteristics: expanded version of bottom line strength, dexterity, &c */
+/* characteristics: expanded version of bottom line strength, dexterity, &c;
+   [3.6.1: now includes all status info (except things already shown in the
+   'background' section), primarily so that blind players can suppress the
+   status line(s) altogether and use ^X feedback on demand to view HP, &c] */
 STATIC_OVL void
 characteristics_enlightenment(mode, final)
 int mode;
 int final;
 {
+    char buf[BUFSZ];
+    int hp = Upolyd ? u.mh : u.uhp;
+    int hpmax = Upolyd ? u.mhmax : u.uhpmax;
+
     putstr(en_win, 0, ""); /* separator after background */
     putstr(en_win, 0,
 /*JP
@@ -1738,6 +1974,53 @@ int final;
 */
            final ? "\8dÅ\8fI\91®\90«\81F" : "\8c»\8dÝ\82Ì\91®\90«\81F");
 
+    if (hp < 0)
+        hp = 0;
+    Sprintf(buf, "%d hit points (max:%d)", hp, hpmax);
+    you_have(buf, "");
+
+    Sprintf(buf, "%d magic power (max:%d)", u.uen, u.uenmax);
+    you_have(buf, "");
+
+    Sprintf(buf, "%d", u.uac);
+    enl_msg("Your armor class ", "is ", "was ", buf, "");
+
+    if (Upolyd) {
+        switch (mons[u.umonnum].mlevel) {
+        case 0:
+            /* status line currently being explained shows "HD:0" */
+            Strcpy(buf, "0 hit dice (actually 1/2)");
+            break;
+        case 1:
+            Strcpy(buf, "1 hit die");
+            break;
+        default:
+            Sprintf(buf, "%d hit dice", mons[u.umonnum].mlevel);
+            break;
+        }
+    } else {
+        /* flags.showexp does not matter */
+        /* experience level is already shown in the Background section */
+        Sprintf(buf, "%-1ld experience point%s",
+                u.uexp, plur(u.uexp));
+    }
+    you_have(buf, "");
+
+    /* this is shown even if the 'time' option is off */
+    Sprintf(buf, "the dungeon %ld turn%s ago", moves, plur(moves));
+    /* same phrasing at end of game:  "entered" is unconditional */
+    enlght_line(You_, "entered ", buf, "");
+
+#ifdef SCORE_ON_BOTL
+    if (flags.showscore) {
+        /* describes what's shown on status line, which is an approximation;
+           only show it here if player has the 'showscore' option enabled */
+        Sprintf(buf, "%ld%s", botl_score(),
+                !final ? "" : " before end-of-game adjustments");
+        enl_msg("Your score ", "is ", "was ", buf, "");
+    }
+#endif
+
     /* bottom line order */
     one_characteristic(mode, final, A_STR); /* strength */
     one_characteristic(mode, final, A_DEX); /* dexterity */
@@ -1752,9 +2035,10 @@ STATIC_OVL void
 one_characteristic(mode, final, attrindx)
 int mode, final, attrindx;
 {
+    extern const char *const attrname[]; /* attrib.c */
     boolean hide_innate_value = FALSE, interesting_alimit;
     int acurrent, abase, apeak, alimit;
-    const char *attrname, *paren_pfx;
+    const char *paren_pfx;
     char subjbuf[BUFSZ], valubuf[BUFSZ], valstring[32];
 
     /* being polymorphed or wearing certain cursed items prevents
@@ -1772,46 +2056,24 @@ int mode, final, attrindx;
     }
     switch (attrindx) {
     case A_STR:
-/*JP
-        attrname = "strength";
-*/
-        attrname = "\8b­\82³";
         if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER && uarmg->cursed)
             hide_innate_value = TRUE;
         break;
     case A_DEX:
-/*JP
-        attrname = "dexterity";
-*/
-        attrname = "\91f\91\81\82³";
         break;
     case A_CON:
-/*JP
-        attrname = "constitution";
-*/
-        attrname = "\91Ï\8bv\97Í";
+        if (uwep && uwep->oartifact == ART_OGRESMASHER && uwep->cursed)
+            hide_innate_value = TRUE;
         break;
     case A_INT:
-/*JP
-        attrname = "intelligence";
-*/
-        attrname = "\92m\97Í";
         if (uarmh && uarmh->otyp == DUNCE_CAP && uarmh->cursed)
             hide_innate_value = TRUE;
         break;
     case A_WIS:
-/*JP
-        attrname = "wisdom";
-*/
-        attrname = "\8c«\82³";
         if (uarmh && uarmh->otyp == DUNCE_CAP && uarmh->cursed)
             hide_innate_value = TRUE;
         break;
     case A_CHA:
-/*JP
-        attrname = "charisma";
-*/
-        attrname = "\96£\97Í";
         break;
     default:
         return; /* impossible */
@@ -1823,9 +2085,9 @@ int mode, final, attrindx;
     acurrent = ACURR(attrindx);
     (void) attrval(attrindx, acurrent, valubuf); /* Sprintf(valubuf,"%d",) */
 /*JP
-    Sprintf(subjbuf, "Your %s ", attrname);
+    Sprintf(subjbuf, "Your %s ", attrname[attrindx]);
 */
-    Sprintf(subjbuf, "\82 \82È\82½\82Ì%s\82Í", attrname);
+    Sprintf(subjbuf, "\82 \82È\82½\82Ì%s\82Í", attrname[attrindx]);
 
     if (!hide_innate_value) {
         /* show abase, amax, and/or attrmax if acurr doesn't match abase
@@ -1926,11 +2188,17 @@ int final;
     Strcpy(youtoo, You_);
     /* not a traditional status but inherently obvious to player; more
        detail given below (attributes section) for magic enlightenment */
-    if (Upolyd)
-/*JP
-        you_are("transformed", "");
-*/
+    if (Upolyd) {
+#if 0 /*JP*/
+        Strcpy(buf, "transformed");
+        if (ugenocided())
+            Sprintf(eos(buf), " and %s %s inside",
+                    final ? "felt" : "feel", udeadinside());
+        you_are(buf, "");
+#else /*JP:TODO:\95Ï\89»+\8bs\8eE\83p\83^\81[\83\93*/
         you_are_ing("\95Ï\89»\82µ\82Ä", "");
+#endif
+    }
     /* not a trouble, but we want to display riding status before maybe
        reporting steed as trapped or hero stuck to cursed saddle */
     if (Riding) {
@@ -2100,11 +2368,7 @@ int final;
 */
             Strcpy(buf, "\94±\82ð\8eó\82¯\82Ä");
         }
-#if 0 /*JP*/
         you_are(buf, "");
-#else
-        you_are_ing(buf, "");
-#endif
     }
     if (u.utrap) {
         char predicament[BUFSZ];
@@ -2381,57 +2645,15 @@ int final;
         you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1], "");
     }
 
-    /* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
-    if (u.ualign.record >= 20)
-/*JP
-        you_are("piously aligned", "");
-*/
-      you_have("\8chåi\82È\90M\8bÂ\90S", "");
-    else if (u.ualign.record > 13)
 /*JP
-        you_are("devoutly aligned", "");
+    Sprintf(buf, "%s", piousness(TRUE, "aligned"));
 */
-      you_have("\90S\82©\82ç\82Ì\90M\8bÂ\90S", "");
-    else if (u.ualign.record > 8)
-/*JP
-        you_are("fervently aligned", "");
-*/
-      you_have("\94M\90S\82È\90M\8bÂ\90S", "");
-    else if (u.ualign.record > 3)
-/*JP
-        you_are("stridently aligned", "");
-*/
-      you_have("\82¨\82¨\82°\82³\82È\90M\8bÂ\90S", "");
-    else if (u.ualign.record == 3)
-/*JP
-        you_are("aligned", "");
-*/
-      you_have("\95\81\92Ê\82Ì\90M\8bÂ\90S", "");
-    else if (u.ualign.record > 0)
-/*JP
-        you_are("haltingly aligned", "");
-*/
-      you_have("çSçO\82µ\82È\82ª\82ç\82à\90M\8bÂ\90S", "");
-    else if (u.ualign.record == 0)
-/*JP
-        you_are("nominally aligned", "");
-*/
-      you_have("\8c`\82¾\82¯\82Ì\90M\8bÂ\90S", "");
-    else if (u.ualign.record >= -3)
-/*JP
-        you_have("strayed", "");
-*/
-      you_are_ing("\90M\8bÂ\82É\96À\82¢\82ð\82à\82Á\82Ä", "");
-    else if (u.ualign.record >= -8)
-/*JP
-        you_have("sinned", "");
-*/
-      you_are_ing("\8dß\82ð\95\89\82Á\82Ä", "");
+    Sprintf(buf, "%s", piousness(TRUE, "\90M\8bÂ\90S"));
+    if (u.ualign.record >= 0)
+        you_are(buf, "");
     else
-/*JP
-        you_have("transgressed", "");
-*/
-      you_are_ing("\90M\8bÂ\82©\82ç\88í\92E\82µ\82Ä", "");
+        you_have(buf, "");
+
     if (wizard) {
 #if 0 /*JP*/
         Sprintf(buf, " %d", u.ualign.record);
@@ -2592,7 +2814,7 @@ int final;
         you_have(buf, "");
 #endif
     }
-    if (Warn_of_mon && context.warntype.speciesidx) {
+    if (Warn_of_mon && context.warntype.speciesidx >= LOW_PM) {
 #if 0 /*JP*/
         Sprintf(buf, "aware of the presence of %s",
                 makeplural(mons[context.warntype.speciesidx].mname));
@@ -2904,11 +3126,7 @@ int final;
         Sprintf(buf, "%s\82É\95Ï\89»\82µ\82Ä", youmonst.data->mname);
         if (wizard)
             Sprintf(eos(buf), " (%d)", u.mtimedone);
-#if 0 /*JP*/
         you_are(buf, "");
-#else
-        you_are_ing(buf, "");
-#endif
     }
     if (lays_eggs(youmonst.data) && flags.female) /* Upolyd */
 /*JP
@@ -3060,22 +3278,25 @@ int final;
         }
     }
 
-    /* named fruit debugging (doesn't really belong here...) */
-    if (wizard) {
-        int fcount = 0;
+#ifdef DEBUG
+    /* named fruit debugging (doesn't really belong here...); to enable,
+       include 'fruit' in DEBUGFILES list (even though it isn't a file...) */
+    if (wizard && explicitdebug("fruit")) {
         struct fruit *f;
-        char buf2[BUFSZ];
 
+        reorder_fruit(TRUE); /* sort by fruit index, from low to high;
+                              * this modifies the ffruit chain, so could
+                              * possibly mask or even introduce a problem,
+                              * but it does useful sanity checking */
         for (f = ffruit; f; f = f->nextf) {
 /*JP
-            Sprintf(buf, "Fruit %d ", ++fcount);
+            Sprintf(buf, "Fruit #%d ", f->fid);
 */
-            Sprintf(buf, "fruit %d \82Í", ++fcount);
-            Sprintf(buf2, "%s (id %d)", f->fname, f->fid);
+            Sprintf(buf, "fruit $%d \82Í", f->fid);
 /*JP
-            enl_msg(buf, "is ", "was ", buf2, "");
+            enl_msg(buf, "is ", "was ", f->fname, "");
 */
-            enl_msg(buf, "\82¾", "\82¾\82Á\82½", buf2, "");
+            enl_msg(buf, "\82¾", "\82¾\82Á\82½", f->fname, "");
         }
 /*JP
         enl_msg("The current fruit ", "is ", "was ", pl_fruit, "");
@@ -3087,6 +3308,7 @@ int final;
 */
         enl_msg("made fruit flag \82Í", "\82¾", "\82¾\82Á\82½", buf, "");
     }
+#endif
 
     {
         const char *p;
@@ -3377,7 +3599,7 @@ int msgflag;          /* for variant message phrasing */
         /* mimic; hero is only able to mimic a strange object or gold
            or hallucinatory alternative to gold, so we skip the details
            for the hypothetical furniture and monster cases */
-#if 0 /*JP*//*\8cã\82ë\82É\89ñ\82·*/
+#if 0 /*JP*//*\8cã\82ë\82É\89ñ\82·*//* not used */
         bp = eos(strcpy(buf, "mimicking"));
 #endif
         if (youmonst.m_ap_type == M_AP_OBJECT) {
@@ -3451,11 +3673,7 @@ int msgflag;          /* for variant message phrasing */
     if (via_enlghtmt) {
         int final = msgflag; /* 'final' is used by you_are() macro */
 
-#if 0 /*JP*/
         you_are(buf, "");
-#else
-        enl_msg(buf, "\82Ä\82¢\82é", "\82Ä\82¢\82½", "", "");
-#endif
     } else {
         /* for dohide(), when player uses '#monster' command */
 #if 0 /*JP*/
@@ -3473,7 +3691,7 @@ int msgflag;          /* for variant message phrasing */
 /* KMH, #conduct
  * (shares enlightenment's tense handling)
  */
-STATIC_PTR int
+int
 doconduct(VOID_ARGS)
 {
     show_conduct(0);
@@ -3510,7 +3728,7 @@ int final;
         enl_msg(You_, "have gone", "went", " without food", "");
 */
         enl_msg("\82 \82È\82½\82Í\90H\8e\96\82ð\82µ", "\82Ä\82¢\82È\82¢", "\82È\82©\82Á\82½", "", "");
-    /* But beverages are okay */
+        /* but beverages are okay */
     else if (!u.uconduct.unvegan)
 /*JP
         you_have_X("followed a strict vegan diet");
@@ -3555,7 +3773,7 @@ int final;
 */
         you_have_never("\82 \82È\82½\82Í\93Ç\82Ý\8f\91\82«\82µ");
     } else if (wizard) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         Sprintf(buf, "read items or engraved %ld time%s", u.uconduct.literate,
                 plur(u.uconduct.literate));
         you_have_X(buf);
@@ -3572,7 +3790,7 @@ int final;
 */
         you_have_never("\82 \82È\82½\82Í\89ö\95¨\82ð\8bs\8eE\82µ");
     } else {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         Sprintf(buf, "genocided %d type%s of monster%s", ngenocided,
                 plur(ngenocided), plur(ngenocided));
         you_have_X(buf);
@@ -3588,12 +3806,12 @@ int final;
 */
         you_have_never("\82 \82È\82½\82Í\95¨\91Ì\82ð\95Ï\89»\82³\82¹");
     } else if (wizard) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         Sprintf(buf, "polymorphed %ld item%s", u.uconduct.polypiles,
                 plur(u.uconduct.polypiles));
         you_have_X(buf);
 #else
-        Sprintf(buf, "%ld\8cÂ\82Ì\93¹\8bï\82ð\95Ï\89»\82³\82¹", u.uconduct.polypiles);
+        Sprintf(buf, "%ld\8cÂ\82Ì\95¨\82ð\95Ï\89»\82³\82¹", u.uconduct.polypiles);
         you_have_X(buf);
 #endif
     }
@@ -3604,7 +3822,7 @@ int final;
 */
         you_have_never("\82 \82È\82½\82Í\95Ï\89»\82µ");
     } else if (wizard) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         Sprintf(buf, "changed form %ld time%s", u.uconduct.polyselfs,
                 plur(u.uconduct.polyselfs));
         you_have_X(buf);
@@ -3623,11 +3841,30 @@ int final;
 #if 0 /*JP*/
         Sprintf(buf, "used %ld wish%s", u.uconduct.wishes,
                 (u.uconduct.wishes > 1L) ? "es" : "");
-        you_have_X(buf);
 #else
         Sprintf(buf, "%ld\89ñ\8aè\82¢\8e\96\82ð\82µ", u.uconduct.wishes);
-        you_have_X(buf);
 #endif
+        if (u.uconduct.wisharti) {
+            /* if wisharti == wishes
+             *  1 wish (for an artifact)
+             *  2 wishes (both for artifacts)
+             *  N wishes (all for artifacts)
+             * else (N is at least 2 in order to get here; M < N)
+             *  N wishes (1 for an artifact)
+             *  N wishes (M for artifacts)
+             */
+            if (u.uconduct.wisharti == u.uconduct.wishes)
+                Sprintf(eos(buf), " (%s",
+                        (u.uconduct.wisharti > 2L) ? "all "
+                          : (u.uconduct.wisharti == 2L) ? "both " : "");
+            else
+                Sprintf(eos(buf), " (%ld ", u.uconduct.wisharti);
+
+            Sprintf(eos(buf), "for %s)",
+                    (u.uconduct.wisharti == 1L) ? "an artifact"
+                                                : "artifacts");
+        }
+        you_have_X(buf);
 
         if (!u.uconduct.wisharti)
 #if 0 /*JP*/
@@ -3644,422 +3881,641 @@ int final;
     en_win = WIN_ERR;
 }
 
+/* Macros for meta and ctrl modifiers:
+ *   M and C return the meta/ctrl code for the given character;
+ *     e.g., (C('c') is ctrl-c
+ */
 #ifndef M
 #ifndef NHSTDC
 #define M(c) (0x80 | (c))
 #else
-#define M(c) ((c) -128)
+#define M(c) ((c) - 128)
 #endif /* NHSTDC */
 #endif
+
 #ifndef C
 #define C(c) (0x1f & (c))
 #endif
 
-static const struct func_tab cmdlist[] = {
-    { C('d'), FALSE, dokick }, /* "D" is for door!...?  Msg is in dokick.c */
-    { C('e'), TRUE, wiz_detect },
-    { C('f'), TRUE, wiz_map },
-    { C('g'), TRUE, wiz_genesis },
-    { C('i'), TRUE, wiz_identify },
-    { C('l'), TRUE, doredraw },    /* if number_pad is set */
-    { C('n'), TRUE, donamelevel }, /* if number_pad is set */
-    { C('o'), TRUE, dooverview_or_wiz_where }, /* depends on wizard status */
-    { C('p'), TRUE, doprev_message },
-    { C('r'), TRUE, doredraw },
-    { C('t'), TRUE, dotele },
-    { C('v'), TRUE, wiz_level_tele },
-    { C('w'), TRUE, wiz_wish },
-    { C('x'), TRUE, doattributes },
-    { C('z'), TRUE, dosuspend_core },
-    { 'a', FALSE, doapply },
-    { 'A', FALSE, doddoremarm },
-    { M('a'), TRUE, doorganize },
-    { M('A'), TRUE, donamelevel }, /* #annotate */
-    /*  'b', 'B' : go sw */
-    { 'c', FALSE, doclose },
-    { 'C', TRUE, docallcmd },
-    { M('c'), TRUE, dotalk },
-    { M('C'), TRUE, doconduct }, /* #conduct */
-    { 'd', FALSE, dodrop },
-    { 'D', FALSE, doddrop },
-    { M('d'), FALSE, dodip },
-    { 'e', FALSE, doeat },
-    { 'E', FALSE, doengrave },
-    { M('e'), TRUE, enhance_weapon_skill },
-    { 'f', FALSE, dofire },
-    /*  'F' : fight (one time) */
-    { M('f'), FALSE, doforce },
-    /*  'g', 'G' : multiple go */
-    /*  'h', 'H' : go west */
-    { 'h', TRUE, dohelp }, /* if number_pad is set */
-    { 'i', TRUE, ddoinv },
-    { 'I', TRUE, dotypeinv }, /* Robert Viduya */
-    { M('i'), TRUE, doinvoke },
-    /*  'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
-    { 'j', FALSE, dojump }, /* if number_pad is on */
-    { M('j'), FALSE, dojump },
-    { 'k', FALSE, dokick }, /* if number_pad is on */
-    { 'l', FALSE, doloot }, /* if number_pad is on */
-    { M('l'), FALSE, doloot },
-    /*  'n' prefixes a count if number_pad is on */
-    { M('m'), TRUE, domonability },
-    { 'N', TRUE, docallcmd }, /* if number_pad is on */
-    { M('n'), TRUE, docallcmd },
-    { M('N'), TRUE, docallcmd },
-    { 'o', FALSE, doopen },
-    { 'O', TRUE, doset },
-    { M('o'), FALSE, dosacrifice },
-    { M('O'), TRUE, dooverview }, /* #overview */
-    { 'p', FALSE, dopay },
-    { 'P', FALSE, doputon },
-    { M('p'), TRUE, dopray },
-    { 'q', FALSE, dodrink },
-    { 'Q', FALSE, dowieldquiver },
-    { M('q'), TRUE, done2 },
-    { 'r', FALSE, doread },
-    { 'R', FALSE, doremring },
-    { M('r'), FALSE, dorub },
-    { M('R'), FALSE, doride }, /* #ride */
-/*JP
-    { 's', TRUE, dosearch, "searching" },
-*/
-    { 's', TRUE, dosearch, "\91{\82·" },
-    { 'S', TRUE, dosave },
-    { M('s'), FALSE, dosit },
-    { 't', FALSE, dothrow },
-    { 'T', FALSE, dotakeoff },
-    { M('t'), TRUE, doturn },
-    { M('T'), FALSE, dotip }, /* #tip */
-    /*  'u', 'U' : go ne */
-    { 'u', FALSE, dountrap }, /* if number_pad is on */
-    { M('u'), FALSE, dountrap },
-    { 'v', TRUE, doversion },
-    { 'V', TRUE, dohistory },
-    { M('v'), TRUE, doextversion },
-    { 'w', FALSE, dowield },
-    { 'W', FALSE, dowear },
-    { M('w'), FALSE, dowipe },
-    { 'x', FALSE, doswapweapon },
-    { 'X', FALSE, dotwoweapon },
-    /*  'y', 'Y' : go nw */
-    { 'z', FALSE, dozap },
-    { 'Z', TRUE, docast },
-    { '<', FALSE, doup },
-    { '>', FALSE, dodown },
-    { '/', TRUE, dowhatis },
-    { '&', TRUE, dowhatdoes },
-    { '?', TRUE, dohelp },
-    { M('?'), TRUE, doextlist },
-#ifdef SHELL
-    { '!', TRUE, dosh },
-#endif
-/*JP
-    { '.', TRUE, donull, "waiting" },
-*/
-    { '.', TRUE, donull, "\8bx\8ce\82·\82é" },
-/*JP
-    { ' ', TRUE, donull, "waiting" },
-*/
-    { ' ', TRUE, donull, "\8bx\8ce\82·\82é" },
-    { ',', FALSE, dopickup },
-    { ':', TRUE, dolook },
-    { ';', TRUE, doquickwhatis },
-    { '^', TRUE, doidtrap },
-    { '\\', TRUE, dodiscovered }, /* Robert Viduya */
-    { '`', TRUE, doclassdisco },
-    { '@', TRUE, dotogglepickup },
-    { M('2'), FALSE, dotwoweapon },
-    { WEAPON_SYM, TRUE, doprwep },
-    { ARMOR_SYM, TRUE, doprarm },
-    { RING_SYM, TRUE, doprring },
-    { AMULET_SYM, TRUE, dopramulet },
-    { TOOL_SYM, TRUE, doprtool },
-    { '*', TRUE, doprinuse }, /* inventory of all equipment in use */
-    { GOLD_SYM, TRUE, doprgold },
-    { SPBOOK_SYM, TRUE, dovspell }, /* Mike Stephenson */
-    { '#', TRUE, doextcmd },
-    { '_', TRUE, dotravel },
-    { 0, 0, 0, 0 }
-};
-
+/* ordered by command name */
 struct ext_func_tab extcmdlist[] = {
-/*JP
-    { "adjust", "adjust inventory letters", doorganize, TRUE },
-*/
-    { "adjust", "\8e\9d\82¿\95¨\88ê\97\97\82Ì\92²\90®", doorganize, TRUE },
-/*JP
-    { "annotate", "name current level", donamelevel, TRUE },
-*/
-    { "annotate", "\8c»\8dÝ\82Ì\8aK\82É\96¼\91O\82ð\82Â\82¯\82é", donamelevel, TRUE },
+    { '#', "#", "perform an extended command",
+            doextcmd, IFBURIED | GENERALCMD },
 #if 0 /*JP*/
-    { "chat", "talk to someone", dotalk, TRUE }, /* converse? */
+    { M('?'), "?", "list all extended commands",
 #else
-    { "chat", "\92N\82©\82Æ\98b\82·", dotalk, TRUE }, /* converse? */
+    { M('?'), "?", "\82±\82Ì\8ag\92£\83R\83}\83\93\83h\88ê\97\97\82ð\95\\8e¦\82·\82é",
 #endif
+            doextlist, IFBURIED | AUTOCOMPLETE | GENERALCMD },
 #if 0 /*JP*/
-    { "conduct", "list voluntary challenges you have maintained", doconduct,
-      TRUE },
+    { M('a'), "adjust", "adjust inventory letters",
 #else
-    { "conduct", "\82Ç\82¤\82¢\82¤\8ds\93®\82ð\82Æ\82Á\82½\82©\8c©\82é", doconduct, TRUE },
+    { M('a'), "adjust", "\8e\9d\82¿\95¨\88ê\97\97\82Ì\92²\90®",
 #endif
-/*JP
-    { "dip", "dip an object into something", dodip, FALSE },
-*/
-    { "dip", "\89½\82©\82É\95¨\82ð\90Z\82·", dodip, FALSE },
+            doorganize, IFBURIED | AUTOCOMPLETE },
 #if 0 /*JP*/
-    { "enhance", "advance or check weapon and spell skills",
-      enhance_weapon_skill, TRUE },
+    { M('A'), "annotate", "name current level",
 #else
-    { "enhance", "\95\90\8aí\8fn\97û\93x\82ð\8d\82\82ß\82é", enhance_weapon_skill, TRUE },
+    { M('A'), "annotate", "\8c»\8dÝ\82Ì\8aK\82É\96¼\91O\82ð\82Â\82¯\82é",
 #endif
-/*JP
-    { "exploremode", "enter explore mode", enter_explore_mode, TRUE },
-*/
-    { "exploremode", "\92T\8c\9f\83\82\81[\83h\82É\93ü\82é", enter_explore_mode, TRUE },
-/*JP
-    { "force", "force a lock", doforce, FALSE },
-*/
-    { "force", "\8c®\82ð\82±\82\82 \82¯\82é", doforce, FALSE },
-/*JP
-    { "invoke", "invoke an object's powers", doinvoke, TRUE },
-*/
-    { "invoke", "\95¨\82Ì\93Á\95Ê\82È\97Í\82ð\8eg\82¤", doinvoke, TRUE },
-/*JP
-    { "jump", "jump to a location", dojump, FALSE },
-*/
-    { "jump", "\91¼\82Ì\88Ê\92u\82É\94ò\82Ñ\82¤\82Â\82é", dojump, FALSE },
-/*JP
-    { "loot", "loot a box on the floor", doloot, FALSE },
-*/
-    { "loot", "\8f°\82Ì\8fã\82Ì\94 \82ð\8aJ\82¯\82é", doloot, TRUE },
-/*JP
-    { "monster", "use a monster's special ability", domonability, TRUE },
-*/
-    { "monster", "\89ö\95¨\82Ì\93Á\95Ê\94\\97Í\82ð\8eg\82¤", domonability, TRUE },
-/*JP
-    { "name", "name a monster or an object", docallcmd, TRUE },
-*/
-    { "name", "\83A\83C\83e\83\80\82â\95¨\82É\96¼\91O\82ð\82Â\82¯\82é", docallcmd, TRUE },
-/*JP
-    { "offer", "offer a sacrifice to the gods", dosacrifice, FALSE },
-*/
-    { "offer", "\90_\82É\8b\9f\95¨\82ð\95ù\82°\82é", dosacrifice, FALSE },
-/*JP
-    { "overview", "show an overview of the dungeon", dooverview, TRUE },
-*/
-    { "overview", "\96À\8b{\82Ì\8aT\97v\82ð\95\\8e¦\82·\82é", dooverview, TRUE },
-/*JP
-    { "pray", "pray to the gods for help", dopray, TRUE },
-*/
-    { "pray", "\90_\82É\8bF\82é", dopray, TRUE },
-/*JP
-    { "quit", "exit without saving current game", done2, TRUE },
-*/
-    { "quit", "\83Z\81[\83u\82µ\82È\82¢\82Å\8fI\97¹", done2, TRUE },
-/*JP
-    { "ride", "ride (or stop riding) a monster", doride, FALSE },
-*/
-    { "ride", "\89ö\95¨\82É\8fæ\82é(\82Ü\82½\82Í\8d~\82è\82é)", doride, FALSE },
-/*JP
-    { "rub", "rub a lamp or a stone", dorub, FALSE },
-*/
-    { "rub", "\83\89\83\93\83v\82ð\82±\82·\82é", dorub, FALSE },
-/*JP
-    { "sit", "sit down", dosit, FALSE },
-*/
-    { "sit", "\8dÀ\82é", dosit, FALSE },
-/*JP
-    { "terrain", "show map without obstructions", doterrain, TRUE },
-*/
-    { "terrain", "\8e×\96\82\82³\82ê\82¸\82É\92n\90}\82ð\8c©\82é", doterrain, TRUE },
-/*JP
-    { "tip", "empty a container", dotip, FALSE },
-*/
-    { "tip", "\93ü\82ê\95¨\82ð\8bó\82É\82·\82é", dotip, FALSE },
-/*JP
-    { "turn", "turn undead", doturn, TRUE },
-*/
-    { "turn", "\83A\83\93\83f\83b\83g\82ð\93y\82É\95Ô\82·", doturn, TRUE },
-/*JP
-    { "twoweapon", "toggle two-weapon combat", dotwoweapon, FALSE },
-*/
-    { "twoweapon", "\97¼\8eè\8e\9d\82¿\82Ì\90Ø\82è\91Ö\82¦", dotwoweapon, FALSE },
-/*JP
-    { "untrap", "untrap something", dountrap, FALSE },
-*/
-    { "untrap", "ã©\82ð\82Í\82¸\82·", dountrap, FALSE },
+            donamelevel, IFBURIED | AUTOCOMPLETE },
+    { 'a', "apply", "apply (use) a tool (pick-axe, key, lamp...)",
+            doapply },
+    { C('x'), "attributes", "show your attributes",
+            doattributes, IFBURIED },
+    { '@', "autopickup", "toggle the pickup option on/off",
+            dotogglepickup, IFBURIED },
+    { 'C', "call", "call (name) something", docallcmd, IFBURIED },
+    { 'Z', "cast", "zap (cast) a spell", docast, IFBURIED },
 #if 0 /*JP*/
-    { "version", "list compile time options for this version of NetHack",
-      doextversion, TRUE },
+    { M('c'), "chat", "talk to someone", dotalk, IFBURIED | AUTOCOMPLETE },
 #else
-    { "version", "\83R\83\93\83p\83C\83\8b\8e\9e\82Ì\83I\83v\83V\83\87\83\93\82ð\95\\8e¦\82·\82é", doextversion, TRUE },
+    { M('c'), "chat", "\92N\82©\82Æ\98b\82·", dotalk, IFBURIED | AUTOCOMPLETE },
 #endif
-/*JP
-    { "wipe", "wipe off your face", dowipe, FALSE },
-*/
-    { "wipe", "\8aç\82ð\90@\82¤", dowipe, FALSE },
-/*JP
-    { "?", "get this list of extended commands", doextlist, TRUE },
-*/
-    { "?", "\82±\82Ì\8ag\92£\83R\83}\83\93\83h\88ê\97\97\82ð\95\\8e¦\82·\82é", doextlist, TRUE },
-    /*
-     * There must be a blank entry here for every entry in the table
-     * below.
-     */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* levelchange */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* lightsources */
-#ifdef DEBUG_MIGRATING_MONS
-    { (char *) 0, (char *) 0, donull, TRUE }, /* migratemons */
+    { 'c', "close", "close a door", doclose },
+#if 0 /*JP*/
+    { M('C'), "conduct", "list voluntary challenges you have maintained",
+#else
+    { M('C'), "conduct", "\82Ç\82¤\82¢\82¤\8ds\93®\82ð\82Æ\82Á\82½\82©\8c©\82é",
 #endif
-    { (char *) 0, (char *) 0, donull, TRUE }, /* monpolycontrol */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* panic */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* polyself */
-#ifdef PORT_DEBUG
-    { (char *) 0, (char *) 0, donull, TRUE }, /* portdebug */
-#endif
-    { (char *) 0, (char *) 0, donull, TRUE }, /* seenv */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* stats */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* timeout */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* vanquished */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* vision */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* wizsmell */
-#ifdef DEBUG
-    { (char *) 0, (char *) 0, donull, TRUE }, /* wizdebug_traveldisplay */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* wizdebug_bury */
+            doconduct, IFBURIED | AUTOCOMPLETE },
+#if 0 /*JP*/
+    { M('d'), "dip", "dip an object into something", dodip, AUTOCOMPLETE },
+#else
+    { M('d'), "dip", "\89½\82©\82É\95¨\82ð\90Z\82·", dodip, AUTOCOMPLETE },
 #endif
-    { (char *) 0, (char *) 0, donull, TRUE }, /* wizrumorcheck */
-    { (char *) 0, (char *) 0, donull, TRUE }, /* wmode */
-    { (char *) 0, (char *) 0, donull, TRUE }  /* sentinel */
-};
-
-/* there must be a placeholder in the table above for every entry here */
-static const struct ext_func_tab debug_extcmdlist[] = {
-/*JP
-    { "levelchange", "change experience level", wiz_level_change, TRUE },
-*/
-    { "levelchange", "\8co\8c±\83\8c\83x\83\8b\82ð\95Ï\82¦\82é", wiz_level_change, TRUE},
-/*JP
-    { "lightsources", "show mobile light sources", wiz_light_sources, TRUE },
-*/
-    { "light sources", "\88Ú\93®\8cõ\8c¹\82ð\8c©\82é", wiz_light_sources, TRUE},
-#ifdef DEBUG_MIGRATING_MONS
-/*JP
-    { "migratemons", "migrate n random monsters", wiz_migrate_mons, TRUE },
-*/
-    { "migratemons", "\83\89\83\93\83_\83\80\82È\89ö\95¨\82ð\89½\91Ì\82©\88Ú\8fZ\82³\82¹\82é", wiz_migrate_mons, TRUE },
+    { '>', "down", "go down a staircase", dodown },
+    { 'd', "drop", "drop an item", dodrop },
+    { 'D', "droptype", "drop specific item types", doddrop },
+    { 'e', "eat", "eat something", doeat },
+    { 'E', "engrave", "engrave writing on the floor", doengrave },
+#if 0 /*JP*/
+    { M('e'), "enhance", "advance or check weapon and spell skills",
+#else
+    { M('e'), "enhance", "\95\90\8aí\8fn\97û\93x\82ð\8d\82\82ß\82é",
 #endif
-/*JP
-    { "monpolycontrol", "control monster polymorphs", wiz_mon_polycontrol,
-*/
-    { "monpoly_control", "\89ö\95¨\82Ö\82Ì\95Ï\89»\82ð\90§\8cä\82·\82é", wiz_mon_polycontrol,
-      TRUE },
-/*JP
-    { "panic", "test panic routine (fatal to game)", wiz_panic, TRUE },
-*/
-    { "panic", "\83p\83j\83b\83N\83\8b\81[\83`\83\93\82ð\83e\83X\83g\82·\82é(\92v\96½\93I)", wiz_panic, TRUE},
-/*JP
-    { "polyself", "polymorph self", wiz_polyself, TRUE },
-*/
-    { "polyself", "\95Ï\89»\82·\82é", wiz_polyself, TRUE},
+            enhance_weapon_skill, IFBURIED | AUTOCOMPLETE },
+#if 0 /*JP*/
+    { '\0', "exploremode", "enter explore (discovery) mode",
+#else
+    { '\0', "exploremode", "\92T\8c\9f(\94­\8c©)\83\82\81[\83h\82É\93ü\82é",
+#endif
+            enter_explore_mode, IFBURIED },
+    { 'f', "fire", "fire ammunition from quiver", dofire },
+#if 0 /*JP*/
+    { M('f'), "force", "force a lock", doforce, AUTOCOMPLETE },
+#else
+    { M('f'), "force", "\8c®\82ð\82±\82\82 \82¯\82é", doforce, AUTOCOMPLETE },
+#endif
+    { ';', "glance", "show what type of thing a map symbol corresponds to",
+            doquickwhatis, IFBURIED | GENERALCMD },
+    { '?', "help", "give a help message", dohelp, IFBURIED | GENERALCMD },
+    { '\0', "herecmdmenu", "show menu of commands you can do here",
+            doherecmdmenu, IFBURIED },
+    { 'V', "history", "show long version and game history",
+            dohistory, IFBURIED | GENERALCMD },
+    { 'i', "inventory", "show your inventory", ddoinv, IFBURIED },
+    { 'I', "inventtype", "inventory specific item types",
+            dotypeinv, IFBURIED },
+#if 0 /*JP*/
+    { M('i'), "invoke", "invoke an object's special powers",
+#else
+    { M('i'), "invoke", "\95¨\82Ì\93Á\95Ê\82È\97Í\82ð\8eg\82¤",
+#endif
+            doinvoke, IFBURIED | AUTOCOMPLETE },
+#if 0 /*JP*/
+    { M('j'), "jump", "jump to another location", dojump, AUTOCOMPLETE },
+#else
+    { M('j'), "jump", "\91¼\82Ì\88Ê\92u\82É\94ò\82Ñ\82¤\82Â\82é", dojump, AUTOCOMPLETE },
+#endif
+    { C('d'), "kick", "kick something", dokick },
+    { '\\', "known", "show what object types have been discovered",
+            dodiscovered, IFBURIED | GENERALCMD },
+    { '`', "knownclass", "show discovered types for one class of objects",
+            doclassdisco, IFBURIED | GENERALCMD },
+#if 0 /*JP*/
+    { '\0', "levelchange", "change experience level",
+#else
+    { '\0', "levelchange", "\8co\8c±\83\8c\83x\83\8b\82ð\95Ï\82¦\82é",
+#endif
+            wiz_level_change, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#if 0 /*JP*/
+    { '\0', "lightsources", "show mobile light sources",
+#else
+    { '\0', "lightsources", "\88Ú\93®\8cõ\8c¹\82ð\8c©\82é",
+#endif
+            wiz_light_sources, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { ':', "look", "look at what is here", dolook, IFBURIED },
+#if 0 /*JP*/
+    { M('l'), "loot", "loot a box on the floor", doloot, AUTOCOMPLETE },
+#else
+    { M('l'), "loot", "\8f°\82Ì\8fã\82Ì\94 \82ð\8aJ\82¯\82é", doloot, AUTOCOMPLETE },
+#endif
+#ifdef DEBUG_MIGRATING_MONS
+#if 0 /*JP*/
+    { '\0', "migratemons", "migrate N random monsters",
+#else
+    { '\0', "migratemons", "\83\89\83\93\83_\83\80\82È\89ö\95¨\82ð\89½\91Ì\82©\88Ú\8fZ\82³\82¹\82é",
+#endif
+            wiz_migrate_mons, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#endif
+#if 0 /*JP*/
+    { '\0', "monpolycontrol", "control monster polymorphs",
+#else
+    { '\0', "monpolycontrol", "\89ö\95¨\82Ö\82Ì\95Ï\89»\82ð\90§\8cä\82·\82é",
+#endif
+            wiz_mon_polycontrol, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#if 0 /*JP*/
+    { M('m'), "monster", "use monster's special ability",
+#else
+    { M('m'), "monster", "\89ö\95¨\82Ì\93Á\95Ê\94\\97Í\82ð\8eg\82¤",
+#endif
+            domonability, IFBURIED | AUTOCOMPLETE },
+#if 0 /*JP*/
+    { 'N', "name", "name a monster or an object",
+#else
+    { 'N', "name", "\83A\83C\83e\83\80\82â\95¨\82É\96¼\91O\82ð\82Â\82¯\82é",
+#endif
+            docallcmd, IFBURIED | AUTOCOMPLETE },
+#if 0 /*JP*/
+    { M('o'), "offer", "offer a sacrifice to the gods",
+#else
+    { M('o'), "offer", "\90_\82É\8b\9f\95¨\82ð\95ù\82°\82é",
+#endif
+            dosacrifice, AUTOCOMPLETE },
+    { 'o', "open", "open a door", doopen },
+    { 'O', "options", "show option settings, possibly change them",
+            doset, IFBURIED | GENERALCMD },
+#if 0 /*JP*/
+    { C('o'), "overview", "show a summary of the explored dungeon",
+#else
+    { C('o'), "overview", "\92T\8dõ\82µ\82½\96À\8b{\82Ì\8aT\97v\82ð\95\\8e¦\82·\82é",
+#endif
+            dooverview, IFBURIED | AUTOCOMPLETE },
+#if 0 /*JP*/
+    { '\0', "panic", "test panic routine (fatal to game)",
+#else
+    { '\0', "panic", "\83p\83j\83b\83N\83\8b\81[\83`\83\93\82ð\83e\83X\83g\82·\82é(\92v\96½\93I)",
+#endif
+            wiz_panic, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { 'p', "pay", "pay your shopping bill", dopay },
+    { ',', "pickup", "pick up things at the current location", dopickup },
+#if 0 /*JP*/
+    { '\0', "polyself", "polymorph self",
+#else
+    { '\0', "polyself", "\95Ï\89»\82·\82é",
+#endif
+            wiz_polyself, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
 #ifdef PORT_DEBUG
-/*JP
-    { "portdebug", "wizard port debug command", wiz_port_debug, TRUE },
-*/
-    { "portdebug", "\83E\83B\83U\81[\83h\83|\81[\83g\83f\83o\83b\83O\83R\83}\83\93\83h", wiz_port_debug, TRUE },
+#if 0 /*JP*/
+    { '\0', "portdebug", "wizard port debug command",
+#else
+    { '\0', "portdebug", "\83E\83B\83U\81[\83h\83|\81[\83g\83f\83o\83b\83O\83R\83}\83\93\83h",
+#endif
+            wiz_port_debug, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#endif
+#if 0 /*JP*/
+    { M('p'), "pray", "pray to the gods for help",
+#else
+    { M('p'), "pray", "\90_\82É\8bF\82é",
+#endif
+            dopray, IFBURIED | AUTOCOMPLETE },
+    { C('p'), "prevmsg", "view recent game messages",
+            doprev_message, IFBURIED | GENERALCMD },
+    { 'P', "puton", "put on an accessory (ring, amulet, etc)", doputon },
+    { 'q', "quaff", "quaff (drink) something", dodrink },
+#if 0 /*JP*/
+    { M('q'), "quit", "exit without saving current game",
+#else
+    { M('q'), "quit", "\83Z\81[\83u\82µ\82È\82¢\82Å\8fI\97¹",
+#endif
+            done2, IFBURIED | AUTOCOMPLETE | GENERALCMD },
+    { 'Q', "quiver", "select ammunition for quiver", dowieldquiver },
+    { 'r', "read", "read a scroll or spellbook", doread },
+    { C('r'), "redraw", "redraw screen", doredraw, IFBURIED | GENERALCMD },
+    { 'R', "remove", "remove an accessory (ring, amulet, etc)", doremring },
+#if 0 /*JP*/
+    { M('R'), "ride", "mount or dismount a saddled steed",
+#else
+    { M('R'), "ride", "\89ö\95¨\82É\8fæ\82é(\82Ü\82½\82Í\8d~\82è\82é)",
+#endif
+            doride, AUTOCOMPLETE },
+#if 0 /*JP*/
+    { M('r'), "rub", "rub a lamp or a stone", dorub, AUTOCOMPLETE },
+#else
+    { M('r'), "rub", "\83\89\83\93\83v\82ð\82±\82·\82é", dorub, AUTOCOMPLETE },
+#endif
+    { 'S', "save", "save the game and exit", dosave, IFBURIED | GENERALCMD },
+    { 's', "search", "search for traps and secret doors",
+            dosearch, IFBURIED, "searching" },
+    { '*', "seeall", "show all equipment in use", doprinuse, IFBURIED },
+    { AMULET_SYM, "seeamulet", "show the amulet currently worn",
+            dopramulet, IFBURIED },
+    { ARMOR_SYM, "seearmor", "show the armor currently worn",
+            doprarm, IFBURIED },
+    { GOLD_SYM, "seegold", "count your gold", doprgold, IFBURIED },
+#if 0 /*JP*/
+    { '\0', "seenv", "show seen vectors",
+#else
+    { '\0', "seenv", "\8e\8b\90ü\83x\83N\83g\83\8b\82ð\8c©\82é",
+#endif
+            wiz_show_seenv, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { RING_SYM, "seerings", "show the ring(s) currently worn",
+            doprring, IFBURIED },
+    { SPBOOK_SYM, "seespells", "list and reorder known spells",
+            dovspell, IFBURIED },
+    { TOOL_SYM, "seetools", "show the tools currently in use",
+            doprtool, IFBURIED },
+    { '^', "seetrap", "show the type of adjacent trap", doidtrap, IFBURIED },
+    { WEAPON_SYM, "seeweapon", "show the weapon currently wielded",
+            doprwep, IFBURIED },
+#ifdef SHELL
+    { '!', "shell", "do a shell escape", dosh, IFBURIED | GENERALCMD },
+#endif /* SHELL */
+#if 0 /*JP*/
+    { M('s'), "sit", "sit down", dosit, AUTOCOMPLETE },
+    { '\0', "stats", "show memory statistics",
+#else
+    { M('s'), "sit", "\8dÀ\82é", dosit, AUTOCOMPLETE },
+    { '\0', "stats", "\83\81\83\82\83\8a\8fó\91Ô\82ð\8c©\82é",
+#endif
+            wiz_show_stats, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#ifdef SUSPEND
+    { C('z'), "suspend", "suspend the game",
+            dosuspend_core, IFBURIED | GENERALCMD },
+#endif /* SUSPEND */
+    { 'x', "swap", "swap wielded and secondary weapons", doswapweapon },
+    { 'T', "takeoff", "take off one piece of armor", dotakeoff },
+    { 'A', "takeoffall", "remove all armor", doddoremarm },
+    { C('t'), "teleport", "teleport around the level", dotele, IFBURIED },
+#if 0 /*JP*/
+    { '\0', "terrain", "show map without obstructions",
+#else
+    { '\0', "terrain", "\8e×\96\82\82³\82ê\82¸\82É\92n\90}\82ð\8c©\82é",
+#endif
+            doterrain, IFBURIED | AUTOCOMPLETE },
+    { '\0', "therecmdmenu",
+            "menu of commands you can do from here to adjacent spot",
+            dotherecmdmenu },
+    { 't', "throw", "throw something", dothrow },
+#if 0 /*JP*/
+    { '\0', "timeout", "look at timeout queue and hero's timed intrinsics",
+#else
+    { '\0', "timeout", "\8e\9e\8aÔ\90Ø\82ê\83L\83\85\81[\82Æ\83v\83\8c\83C\83\84\81[\82Ì\8e\9e\8aÔ\8co\89ß\82ð\8c©\82é",
+#endif
+            wiz_timeout_queue, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#if 0 /*JP*/
+    { M('T'), "tip", "empty a container", dotip, AUTOCOMPLETE },
+#else
+    { M('T'), "tip", "\93ü\82ê\95¨\82ð\8bó\82É\82·\82é", dotip, AUTOCOMPLETE },
+#endif
+    { '_', "travel", "travel to a specific location on the map", dotravel },
+#if 0 /*JP*/
+    { M('t'), "turn", "turn undead away", doturn, IFBURIED | AUTOCOMPLETE },
+#else
+    { M('t'), "turn", "\83A\83\93\83f\83b\83g\82ð\93y\82É\95Ô\82·", doturn, IFBURIED | AUTOCOMPLETE },
+#endif
+#if 0 /*JP*/
+    { 'X', "twoweapon", "toggle two-weapon combat",
+#else
+    { 'X', "twoweapon", "\97¼\8eè\8e\9d\82¿\82Ì\90Ø\82è\91Ö\82¦",
+#endif
+            dotwoweapon, AUTOCOMPLETE },
+#if 0 /*JP*/
+    { M('u'), "untrap", "untrap something", dountrap, AUTOCOMPLETE },
+#else
+    { M('u'), "untrap", "ã©\82ð\82Í\82¸\82·", dountrap, AUTOCOMPLETE },
+#endif
+    { '<', "up", "go up a staircase", doup },
+#if 0 /*JP*/
+    { '\0', "vanquished", "list vanquished monsters",
+#else
+    { '\0', "vanquished", "\93|\82µ\82½\89ö\95¨\82Ì\88ê\97\97\82ð\8c©\82é",
+#endif
+            dovanquished, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { M('v'), "version",
+#if 0 /*JP*/
+            "list compile time options for this version of NetHack",
+#else
+            "\83R\83\93\83p\83C\83\8b\8e\9e\82Ì\83I\83v\83V\83\87\83\93\82ð\95\\8e¦\82·\82é",
+#endif
+            doextversion, IFBURIED | AUTOCOMPLETE | GENERALCMD },
+    { 'v', "versionshort", "show version", doversion, IFBURIED | GENERALCMD },
+#if 0 /*JP*/
+    { '\0', "vision", "show vision array",
+#else
+    { '\0', "vision", "\8e\8b\8aE\94z\97ñ\82ð\8c©\82é",
+#endif
+            wiz_show_vision, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { '.', "wait", "rest one move while doing nothing",
+            donull, IFBURIED, "waiting" },
+    { 'W', "wear", "wear a piece of armor", dowear },
+    { '&', "whatdoes", "tell what a command does", dowhatdoes, IFBURIED },
+    { '/', "whatis", "show what type of thing a symbol corresponds to",
+            dowhatis, IFBURIED | GENERALCMD },
+    { 'w', "wield", "wield (put in use) a weapon", dowield },
+#if 0 /*JP*/
+    { M('w'), "wipe", "wipe off your face", dowipe, AUTOCOMPLETE },
+#else
+    { M('w'), "wipe", "\8aç\82ð\90@\82¤", dowipe, AUTOCOMPLETE },
 #endif
-/*JP
-    { "seenv", "show seen vectors", wiz_show_seenv, TRUE },
-*/
-    { "seenv", "\8e\8b\90ü\83x\83N\83g\83\8b\82ð\8c©\82é", wiz_show_seenv, TRUE},
-/*JP
-    { "stats", "show memory statistics", wiz_show_stats, TRUE },
-*/
-    { "stats", "\83\81\83\82\83\8a\8fó\91Ô\82ð\8c©\82é", wiz_show_stats, TRUE},
-/*JP
-    { "timeout", "look at timeout queue", wiz_timeout_queue, TRUE },
-*/
-    { "timeout", "\8e\9e\8aÔ\90Ø\82ê\83L\83\85\81[\82ð\8c©\82é", wiz_timeout_queue, TRUE},
-/*JP
-    { "vanquished", "list vanquished monsters", dovanquished, TRUE },
-*/
-    { "vanquished", "\93|\82µ\82½\89ö\95¨\82Ì\88ê\97\97\82ð\8c©\82é", dovanquished, TRUE },
-/*JP
-    { "vision", "show vision array", wiz_show_vision, TRUE },
-*/
-    { "vision", "\8e\8b\8aE\94z\97ñ\82ð\8c©\82é", wiz_show_vision, TRUE},
-/*JP
-    { "wizsmell", "smell monster", wiz_smell, TRUE },
-*/
-    { "wizsmell", "\89ö\95¨\82Ì\93õ\82¢\82ð\9ak\82®", wiz_smell, TRUE },
 #ifdef DEBUG
-/*JP
-    { "wizdebug_traveldisplay", "wizard debug: toggle travel display",
-*/
-    { "wizdebug_traveldisplay", "\83E\83B\83U\81[\83h\83f\83o\83b\83O: \88Ú\93®\95\\8e¦\82ð\90Ø\82è\91Ö\82¦\82é",
-      wiz_debug_cmd_traveldisplay, TRUE },
-/*JP
-    { "wizdebug_bury", "wizard debug: bury objs under and around you",
-*/
-    { "wizdebug_bury", "\83E\83B\83U\81[\83h\82Å\83o\83b\83O: \95¨\82ð\82 \82È\82½\82Ì\8eü\82è\82É\96\84\82ß\82é",
-      wiz_debug_cmd_bury, TRUE },
+#if 0 /*JP*/
+    { '\0', "wizdebug_bury", "wizard debug: bury objs under and around you",
+#else
+    { '\0', "wizdebug_bury", "\83E\83B\83U\81[\83h\82Å\83o\83b\83O: \95¨\82ð\82 \82È\82½\82Ì\8eü\82è\82É\96\84\82ß\82é",
 #endif
-/*JP
-    { "wizrumorcheck", "verify rumor boundaries", wiz_rumor_check, TRUE },
-*/
-    { "wizrumorcheck", "\89\\82Ì\8b«\8aE\82ð\8c\9f\8fØ\82·\82é", wiz_rumor_check, TRUE },
-/*JP
-    { "wmode", "show wall modes", wiz_show_wmodes, TRUE },
-*/
-    { "wmode", "\95Ç\83\82\81[\83h\82ð\8c©\82é", wiz_show_wmodes, TRUE},
-    { (char *) 0, (char *) 0, donull, TRUE }
+            wiz_debug_cmd_bury, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#if 0 /*JP*/
+    { '\0', "wizdebug_traveldisplay", "wizard debug: toggle travel display",
+#else
+    { '\0', "wizdebug_traveldisplay", "\83E\83B\83U\81[\83h\83f\83o\83b\83O: \88Ú\93®\95\\8e¦\82ð\90Ø\82è\91Ö\82¦\82é",
+#endif
+          wiz_debug_cmd_traveldisplay, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#endif
+    { C('e'), "wizdetect", "reveal hidden things within a small radius",
+            wiz_detect, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { C('g'), "wizgenesis", "create a monster",
+            wiz_genesis, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { C('i'), "wizidentify", "identify all items in inventory",
+            wiz_identify, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { '\0', "wizintrinsic", "set an intrinsic",
+            wiz_intrinsic, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { C('v'), "wizlevelport", "teleport to another level",
+            wiz_level_tele, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { '\0', "wizmakemap", "recreate the current level",
+            wiz_makemap, IFBURIED | WIZMODECMD },
+    { C('f'), "wizmap", "map the level",
+            wiz_map, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#if 0 /*JP*/
+    { '\0', "wizrumorcheck", "verify rumor boundaries",
+#else
+    { '\0', "wizrumorcheck", "\89\\82Ì\8b«\8aE\82ð\8c\9f\8fØ\82·\82é",
+#endif
+            wiz_rumor_check, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#if 0 /*JP*/
+    { '\0', "wizsmell", "smell monster",
+#else
+    { '\0', "wizsmell", "\89ö\95¨\82Ì\93õ\82¢\82ð\9ak\82®",
+#endif
+            wiz_smell, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { '\0', "wizwhere", "show locations of special levels",
+            wiz_where, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { C('w'), "wizwish", "wish for something",
+            wiz_wish, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+#if 0 /*JP*/
+    { '\0', "wmode", "show wall modes",
+#else
+    { '\0', "wmode", "\95Ç\83\82\81[\83h\82ð\8c©\82é",
+#endif
+            wiz_show_wmodes, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
+    { 'z', "zap", "zap a wand", dozap },
+    { '\0', (char *) 0, (char *) 0, donull, 0, (char *) 0 } /* sentinel */
 };
 
-/*
- * Insert debug commands into the extended command list.  This function
- * assumes that the last entry will be the help entry.
- *
- * You must add entries in ext_func_tab every time you add one to the
- * debug_extcmdlist().
- */
+const char *
+key2extcmddesc(key)
+uchar key;
+{
+    if (Cmd.commands[key] && Cmd.commands[key]->ef_txt)
+        return Cmd.commands[key]->ef_desc;
+    return (char *) 0;
+}
+
+boolean
+bind_key(key, command)
+uchar key;
+const char *command;
+{
+    struct ext_func_tab *extcmd;
+
+    /* special case: "nothing" is reserved for unbinding */
+    if (!strcmp(command, "nothing")) {
+        Cmd.commands[key] = (struct ext_func_tab *) 0;
+        return TRUE;
+    }
+
+    for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) {
+        if (strcmp(command, extcmd->ef_txt))
+            continue;
+        Cmd.commands[key] = extcmd;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/* initialize all keyboard commands */
 void
-add_debug_extended_commands()
+commands_init()
 {
-    int i, j, k, n;
-
-    /* count the # of help entries */
-    for (n = 0; extcmdlist[n].ef_txt[0] != '?'; n++)
-        ;
-
-    for (i = 0; debug_extcmdlist[i].ef_txt; i++) {
-        /* need enough room for "?" entry plus terminator */
-        if (n + 2 >= SIZE(extcmdlist))
-            panic("Too many debugging commands!");
-        for (j = 0; j < n; j++)
-            if (strcmp(debug_extcmdlist[i].ef_txt, extcmdlist[j].ef_txt) < 0)
-                break;
+    struct ext_func_tab *extcmd;
+
+    for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++)
+        if (extcmd->key)
+            Cmd.commands[extcmd->key] = extcmd;
+
+    (void) bind_key(C('l'), "redraw"); /* if number_pad is set */
+    /*       'b', 'B' : go sw */
+    /*       'F' : fight (one time) */
+    /*       'g', 'G' : multiple go */
+    /*       'h', 'H' : go west */
+    (void) bind_key('h',    "help"); /* if number_pad is set */
+    (void) bind_key('j',    "jump"); /* if number_pad is on */
+    /*       'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' move commands */
+    (void) bind_key('k',    "kick"); /* if number_pad is on */
+    (void) bind_key('l',    "loot"); /* if number_pad is on */
+    (void) bind_key(C('n'), "annotate"); /* if number_pad is on */
+    (void) bind_key(M('n'), "name");
+    (void) bind_key(M('N'), "name");
+    (void) bind_key('u',    "untrap"); /* if number_pad is on */
+
+    /* alt keys: */
+    (void) bind_key(M('O'), "overview");
+    (void) bind_key(M('2'), "twoweapon");
+
+    /* wait_on_space */
+    (void) bind_key(' ',    "wait");
+}
+
+int
+dokeylist_putcmds(datawin, docount, cmdflags, exflags, keys_used)
+winid datawin;
+boolean docount;
+int cmdflags, exflags;
+boolean *keys_used; /* boolean keys_used[256] */
+{
+    int i;
+    char buf[BUFSZ];
+    char buf2[QBUFSZ];
+    int count = 0;
 
-        /* insert i'th debug entry into extcmdlist[j], pushing down  */
-        for (k = n; k >= j; --k)
-            extcmdlist[k + 1] = extcmdlist[k];
-        extcmdlist[j] = debug_extcmdlist[i];
-        n++; /* now an extra entry */
+    for (i = 0; i < 256; i++) {
+        const struct ext_func_tab *extcmd;
+        uchar key = (uchar) i;
+
+        if (keys_used[i])
+            continue;
+        if (key == ' ' && !flags.rest_on_space)
+            continue;
+        if ((extcmd = Cmd.commands[i]) != (struct ext_func_tab *) 0) {
+            if ((cmdflags && !(extcmd->flags & cmdflags))
+                || (exflags && (extcmd->flags & exflags)))
+                continue;
+            if (docount) {
+                count++;
+                continue;
+            }
+            Sprintf(buf, "%-8s %-12s %s", key2txt(key, buf2),
+                    extcmd->ef_txt,
+                    extcmd->ef_desc);
+            putstr(datawin, 0, buf);
+            keys_used[i] = TRUE;
+        }
     }
+    return count;
 }
 
-STATIC_OVL char
+/* list all keys and their bindings, like dat/hh but dynamic */
+void
+dokeylist(VOID_ARGS)
+{
+    char buf[BUFSZ], buf2[BUFSZ];
+    uchar key;
+    boolean keys_used[256] = {0};
+    winid datawin;
+    int i;
+    static const char
+        run_desc[] = "Prefix: run until something very interesting is seen",
+        forcefight_desc[] =
+                     "Prefix: force fight even if you don't see a monster";
+    static const struct {
+        int nhkf;
+        const char *desc;
+        boolean numpad;
+    } misc_keys[] = {
+        { NHKF_ESC, "escape from the current query/action", FALSE },
+        { NHKF_RUSH,
+          "Prefix: rush until something interesting is seen", FALSE },
+        { NHKF_RUN, run_desc, FALSE },
+        { NHKF_RUN2, run_desc, TRUE },
+        { NHKF_FIGHT, forcefight_desc, FALSE },
+        { NHKF_FIGHT2, forcefight_desc, TRUE } ,
+        { NHKF_NOPICKUP,
+          "Prefix: move without picking up objects/fighting", FALSE },
+        { NHKF_RUN_NOPICKUP,
+          "Prefix: run without picking up objects/fighting", FALSE },
+        { NHKF_DOINV, "view inventory", TRUE },
+        { NHKF_REQMENU, "Prefix: request a menu", FALSE },
+#ifdef REDO
+        { NHKF_DOAGAIN , "re-do: perform the previous command again", FALSE },
+#endif
+        { 0, (const char *) 0, FALSE }
+    };
+
+    datawin = create_nhwindow(NHW_TEXT);
+    putstr(datawin, 0, "");
+    putstr(datawin, 0, "            Full Current Key Bindings List");
+
+    /* directional keys */
+    putstr(datawin, 0, "");
+    putstr(datawin, 0, "Directional keys:");
+    show_direction_keys(datawin, '.', FALSE); /* '.'==self in direction grid */
+
+    keys_used[(uchar) Cmd.move_NW] = keys_used[(uchar) Cmd.move_N]
+        = keys_used[(uchar) Cmd.move_NE] = keys_used[(uchar) Cmd.move_W]
+        = keys_used[(uchar) Cmd.move_E] = keys_used[(uchar) Cmd.move_SW]
+        = keys_used[(uchar) Cmd.move_S] = keys_used[(uchar) Cmd.move_SE]
+        = TRUE;
+
+    if (!iflags.num_pad) {
+        keys_used[(uchar) highc(Cmd.move_NW)]
+            = keys_used[(uchar) highc(Cmd.move_N)]
+            = keys_used[(uchar) highc(Cmd.move_NE)]
+            = keys_used[(uchar) highc(Cmd.move_W)]
+            = keys_used[(uchar) highc(Cmd.move_E)]
+            = keys_used[(uchar) highc(Cmd.move_SW)]
+            = keys_used[(uchar) highc(Cmd.move_S)]
+            = keys_used[(uchar) highc(Cmd.move_SE)] = TRUE;
+        keys_used[(uchar) C(Cmd.move_NW)]
+            = keys_used[(uchar) C(Cmd.move_N)]
+            = keys_used[(uchar) C(Cmd.move_NE)]
+            = keys_used[(uchar) C(Cmd.move_W)]
+            = keys_used[(uchar) C(Cmd.move_E)]
+            = keys_used[(uchar) C(Cmd.move_SW)]
+            = keys_used[(uchar) C(Cmd.move_S)]
+            = keys_used[(uchar) C(Cmd.move_SE)] = TRUE;
+        putstr(datawin, 0, "");
+        putstr(datawin, 0,
+          "Shift-<direction> will move in specified direction until you hit");
+        putstr(datawin, 0, "        a wall or run into something.");
+        putstr(datawin, 0,
+          "Ctrl-<direction> will run in specified direction until something");
+        putstr(datawin, 0, "        very interesting is seen.");
+    }
+
+    putstr(datawin, 0, "");
+    putstr(datawin, 0, "Miscellaneous keys:");
+    for (i = 0; misc_keys[i].desc; i++) {
+        key = Cmd.spkeys[misc_keys[i].nhkf];
+        if (key && ((misc_keys[i].numpad && iflags.num_pad)
+                    || !misc_keys[i].numpad)) {
+            keys_used[(uchar) key] = TRUE;
+            Sprintf(buf, "%-8s %s", key2txt(key, buf2), misc_keys[i].desc);
+            putstr(datawin, 0, buf);
+        }
+    }
+#ifndef NO_SIGNAL
+    putstr(datawin, 0, "^c       break out of NetHack (SIGINT)");
+    keys_used[(uchar) C('c')] = TRUE;
+#endif
+
+    putstr(datawin, 0, "");
+    show_menu_controls(datawin, TRUE);
+
+    if (dokeylist_putcmds(datawin, TRUE, GENERALCMD, WIZMODECMD, keys_used)) {
+        putstr(datawin, 0, "");
+        putstr(datawin, 0, "General commands:");
+        (void) dokeylist_putcmds(datawin, FALSE, GENERALCMD, WIZMODECMD,
+                                 keys_used);
+    }
+
+    if (dokeylist_putcmds(datawin, TRUE, 0, WIZMODECMD, keys_used)) {
+        putstr(datawin, 0, "");
+        putstr(datawin, 0, "Game commands:");
+        (void) dokeylist_putcmds(datawin, FALSE, 0, WIZMODECMD, keys_used);
+    }
+
+    if (wizard
+        && dokeylist_putcmds(datawin, TRUE, WIZMODECMD, 0, keys_used)) {
+        putstr(datawin, 0, "");
+        putstr(datawin, 0, "Wizard-mode commands:");
+        (void) dokeylist_putcmds(datawin, FALSE, WIZMODECMD, 0, keys_used);
+    }
+
+    display_nhwindow(datawin, FALSE);
+    destroy_nhwindow(datawin);
+}
+
+char
 cmd_from_func(fn)
 int NDECL((*fn));
 {
     int i;
-    for (i = 0; i < SIZE(cmdlist); ++i)
-        if (cmdlist[i].f_funct == fn)
-            return cmdlist[i].f_char;
-    return 0;
+
+    for (i = 0; i < 256; ++i)
+        if (Cmd.commands[i] && Cmd.commands[i]->ef_funct == fn)
+            return (char) i;
+    return '\0';
 }
 
-static const char template[] = "%-18s %4ld  %6ld";
-static const char count_str[] = "                   count  bytes";
-static const char separator[] = "------------------ -----  ------";
+/*
+ * wizard mode sanity_check code
+ */
+
+static const char template[] = "%-27s  %4ld  %6ld";
+static const char stats_hdr[] = "                             count  bytes";
+static const char stats_sep[] = "---------------------------  ----- -------";
 
 STATIC_OVL int
 size_obj(otmp)
@@ -4107,21 +4563,25 @@ boolean recurse;
 }
 
 STATIC_OVL void
-obj_chain(win, src, chain, total_count, total_size)
+obj_chain(win, src, chain, force, total_count, total_size)
 winid win;
 const char *src;
 struct obj *chain;
+boolean force;
 long *total_count;
 long *total_size;
 {
     char buf[BUFSZ];
-    long count = 0, size = 0;
+    long count = 0L, size = 0L;
 
     count_obj(chain, &count, &size, TRUE, FALSE);
-    *total_count += count;
-    *total_size += size;
-    Sprintf(buf, template, src, count, size);
-    putstr(win, 0, buf);
+
+    if (count || size || force) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, src, count, size);
+        putstr(win, 0, buf);
+    }
 }
 
 STATIC_OVL void
@@ -4138,14 +4598,17 @@ long *total_size;
 
     for (mon = chain; mon; mon = mon->nmon)
         count_obj(mon->minvent, &count, &size, TRUE, FALSE);
-    *total_count += count;
-    *total_size += size;
-    Sprintf(buf, template, src, count, size);
-    putstr(win, 0, buf);
+
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, src, count, size);
+        putstr(win, 0, buf);
+    }
 }
 
 STATIC_OVL void
-contained(win, src, total_count, total_size)
+contained_stats(win, src, total_count, total_size)
 winid win;
 const char *src;
 long *total_count;
@@ -4166,58 +4629,173 @@ long *total_size;
     for (mon = migrating_mons; mon; mon = mon->nmon)
         count_obj(mon->minvent, &count, &size, FALSE, TRUE);
 
-    *total_count += count;
-    *total_size += size;
-
-    Sprintf(buf, template, src, count, size);
-    putstr(win, 0, buf);
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, src, count, size);
+        putstr(win, 0, buf);
+    }
 }
 
 STATIC_OVL int
-size_monst(mtmp)
+size_monst(mtmp, incl_wsegs)
 struct monst *mtmp;
+boolean incl_wsegs;
 {
-    int sz = (int) sizeof(struct monst);
+    int sz = (int) sizeof (struct monst);
+
+    if (mtmp->wormno && incl_wsegs)
+        sz += size_wseg(mtmp);
 
     if (mtmp->mextra) {
-        sz += (int) sizeof(struct mextra);
+        sz += (int) sizeof (struct mextra);
         if (MNAME(mtmp))
             sz += (int) strlen(MNAME(mtmp)) + 1;
         if (EGD(mtmp))
-            sz += (int) sizeof(struct egd);
+            sz += (int) sizeof (struct egd);
         if (EPRI(mtmp))
-            sz += (int) sizeof(struct epri);
+            sz += (int) sizeof (struct epri);
         if (ESHK(mtmp))
-            sz += (int) sizeof(struct eshk);
+            sz += (int) sizeof (struct eshk);
         if (EMIN(mtmp))
-            sz += (int) sizeof(struct emin);
+            sz += (int) sizeof (struct emin);
         if (EDOG(mtmp))
-            sz += (int) sizeof(struct edog);
+            sz += (int) sizeof (struct edog);
         /* mextra->mcorpsenm doesn't point to more memory */
     }
     return sz;
 }
 
 STATIC_OVL void
-mon_chain(win, src, chain, total_count, total_size)
+mon_chain(win, src, chain, force, total_count, total_size)
 winid win;
 const char *src;
 struct monst *chain;
+boolean force;
 long *total_count;
 long *total_size;
 {
     char buf[BUFSZ];
     long count, size;
     struct monst *mon;
+    /* mon->wormno means something different for migrating_mons and mydogs */
+    boolean incl_wsegs = !strcmpi(src, "fmon");
 
-    for (count = size = 0, mon = chain; mon; mon = mon->nmon) {
+    count = size = 0L;
+    for (mon = chain; mon; mon = mon->nmon) {
         count++;
-        size += size_monst(mon);
+        size += size_monst(mon, incl_wsegs);
+    }
+    if (count || size || force) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, src, count, size);
+        putstr(win, 0, buf);
+    }
+}
+
+STATIC_OVL void
+misc_stats(win, total_count, total_size)
+winid win;
+long *total_count;
+long *total_size;
+{
+    char buf[BUFSZ], hdrbuf[QBUFSZ];
+    long count, size;
+    int idx;
+    struct trap *tt;
+    struct damage *sd; /* shop damage */
+    struct cemetery *bi; /* bones info */
+
+    /* traps and engravings are output unconditionally;
+     * others only if nonzero
+     */
+    count = size = 0L;
+    for (tt = ftrap; tt; tt = tt->ntrap) {
+        ++count;
+        size += (long) sizeof *tt;
     }
     *total_count += count;
     *total_size += size;
-    Sprintf(buf, template, src, count, size);
+    Sprintf(hdrbuf, "traps, size %ld", (long) sizeof (struct trap));
+    Sprintf(buf, template, hdrbuf, count, size);
     putstr(win, 0, buf);
+
+    count = size = 0L;
+    engr_stats("engravings, size %ld+text", hdrbuf, &count, &size);
+    *total_count += count;
+    *total_size += size;
+    Sprintf(buf, template, hdrbuf, count, size);
+    putstr(win, 0, buf);
+
+    count = size = 0L;
+    light_stats("light sources, size %ld", hdrbuf, &count, &size);
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
+
+    count = size = 0L;
+    timer_stats("timers, size %ld", hdrbuf, &count, &size);
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
+
+    count = size = 0L;
+    for (sd = level.damagelist; sd; sd = sd->next) {
+        ++count;
+        size += (long) sizeof *sd;
+    }
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(hdrbuf, "shop damage, size %ld",
+                (long) sizeof (struct damage));
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
+
+    count = size = 0L;
+    region_stats("regions, size %ld+%ld*rect+N", hdrbuf, &count, &size);
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
+
+    count = size = 0L;
+    for (bi = level.bonesinfo; bi; bi = bi->next) {
+        ++count;
+        size += (long) sizeof *bi;
+    }
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Sprintf(hdrbuf, "bones history, size %ld",
+                (long) sizeof (struct cemetery));
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
+
+    count = size = 0L;
+    for (idx = 0; idx < NUM_OBJECTS; ++idx)
+        if (objects[idx].oc_uname) {
+            ++count;
+            size += (long) (strlen(objects[idx].oc_uname) + 1);
+        }
+    if (count || size) {
+        *total_count += count;
+        *total_size += size;
+        Strcpy(hdrbuf, "object type names, text");
+        Sprintf(buf, template, hdrbuf, count, size);
+        putstr(win, 0, buf);
+    }
 }
 
 /*
@@ -4228,45 +4806,73 @@ wiz_show_stats()
 {
     char buf[BUFSZ];
     winid win;
-    long total_obj_size = 0, total_obj_count = 0;
-    long total_mon_size = 0, total_mon_count = 0;
+    long total_obj_size, total_obj_count,
+         total_mon_size, total_mon_count,
+         total_ovr_size, total_ovr_count,
+         total_misc_size, total_misc_count;
 
     win = create_nhwindow(NHW_TEXT);
     putstr(win, 0, "Current memory statistics:");
-    putstr(win, 0, "");
-    Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj));
+
+    total_obj_count = total_obj_size = 0L;
+    putstr(win, 0, stats_hdr);
+    Sprintf(buf, "  Objects, base size %ld", (long) sizeof (struct obj));
     putstr(win, 0, buf);
-    putstr(win, 0, "");
-    putstr(win, 0, count_str);
-
-    obj_chain(win, "invent", invent, &total_obj_count, &total_obj_size);
-    obj_chain(win, "fobj", fobj, &total_obj_count, &total_obj_size);
-    obj_chain(win, "buried", level.buriedobjlist, &total_obj_count,
-              &total_obj_size);
-    obj_chain(win, "migrating obj", migrating_objs, &total_obj_count,
-              &total_obj_size);
+    obj_chain(win, "invent", invent, TRUE, &total_obj_count, &total_obj_size);
+    obj_chain(win, "fobj", fobj, TRUE, &total_obj_count, &total_obj_size);
+    obj_chain(win, "buried", level.buriedobjlist, FALSE,
+              &total_obj_count, &total_obj_size);
+    obj_chain(win, "migrating obj", migrating_objs, FALSE,
+              &total_obj_count, &total_obj_size);
+    obj_chain(win, "billobjs", billobjs, FALSE,
+              &total_obj_count, &total_obj_size);
     mon_invent_chain(win, "minvent", fmon, &total_obj_count, &total_obj_size);
     mon_invent_chain(win, "migrating minvent", migrating_mons,
                      &total_obj_count, &total_obj_size);
-
-    contained(win, "contained", &total_obj_count, &total_obj_size);
-
-    putstr(win, 0, separator);
-    Sprintf(buf, template, "Total", total_obj_count, total_obj_size);
+    contained_stats(win, "contained", &total_obj_count, &total_obj_size);
+    putstr(win, 0, stats_sep);
+    Sprintf(buf, template, "  Obj total", total_obj_count, total_obj_size);
     putstr(win, 0, buf);
 
+    total_mon_count = total_mon_size = 0L;
     putstr(win, 0, "");
-    putstr(win, 0, "");
-    Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst));
+    Sprintf(buf, "  Monsters, base size %ld", (long) sizeof (struct monst));
+    putstr(win, 0, buf);
+    mon_chain(win, "fmon", fmon, TRUE, &total_mon_count, &total_mon_size);
+    mon_chain(win, "migrating", migrating_mons, FALSE,
+              &total_mon_count, &total_mon_size);
+    /* 'mydogs' is only valid during level change or end of game disclosure,
+       but conceivably we've been called from within debugger at such time */
+    if (mydogs) /* monsters accompanying hero */
+        mon_chain(win, "mydogs", mydogs, FALSE,
+                  &total_mon_count, &total_mon_size);
+    putstr(win, 0, stats_sep);
+    Sprintf(buf, template, "  Mon total", total_mon_count, total_mon_size);
     putstr(win, 0, buf);
+
+    total_ovr_count = total_ovr_size = 0L;
     putstr(win, 0, "");
+    putstr(win, 0, "  Overview");
+    overview_stats(win, template, &total_ovr_count, &total_ovr_size);
+    putstr(win, 0, stats_sep);
+    Sprintf(buf, template, "  Over total", total_ovr_count, total_ovr_size);
+    putstr(win, 0, buf);
 
-    mon_chain(win, "fmon", fmon, &total_mon_count, &total_mon_size);
-    mon_chain(win, "migrating", migrating_mons, &total_mon_count,
-              &total_mon_size);
+    total_misc_count = total_misc_size = 0L;
+    putstr(win, 0, "");
+    putstr(win, 0, "  Miscellaneous");
+    misc_stats(win, &total_misc_count, &total_misc_size);
+    putstr(win, 0, stats_sep);
+    Sprintf(buf, template, "  Misc total", total_misc_count, total_misc_size);
+    putstr(win, 0, buf);
 
-    putstr(win, 0, separator);
-    Sprintf(buf, template, "Total", total_mon_count, total_mon_size);
+    putstr(win, 0, "");
+    putstr(win, 0, stats_sep);
+    Sprintf(buf, template, "  Grand total",
+            (total_obj_count + total_mon_count
+             + total_ovr_count + total_misc_count),
+            (total_obj_size + total_mon_size
+             + total_ovr_size + total_misc_size));
     putstr(win, 0, buf);
 
 #if defined(__BORLANDC__) && !defined(_WIN32)
@@ -4292,7 +4898,7 @@ static int
 wiz_migrate_mons()
 {
     int mcount = 0;
-    char inbuf[BUFSZ];
+    char inbuf[BUFSZ] = DUMMY;
     struct permonst *ptr;
     struct monst *mtmp;
     d_level tolevel;
@@ -4319,8 +4925,201 @@ wiz_migrate_mons()
 }
 #endif
 
-#define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c))
-#define unmeta(c) (0x7f & (c))
+#define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c))
+#define unmeta(c) (0x7f & (c))
+
+struct {
+    int nhkf;
+    char key;
+    const char *name;
+} const spkeys_binds[] = {
+    { NHKF_ESC,              '\033', (char *) 0 }, /* no binding */
+    { NHKF_DOAGAIN,          DOAGAIN, "repeat" },
+    { NHKF_REQMENU,          'm', "reqmenu" },
+    { NHKF_RUN,              'G', "run" },
+    { NHKF_RUN2,             '5', "run.numpad" },
+    { NHKF_RUSH,             'g', "rush" },
+    { NHKF_FIGHT,            'F', "fight" },
+    { NHKF_FIGHT2,           '-', "fight.numpad" },
+    { NHKF_NOPICKUP,         'm', "nopickup" },
+    { NHKF_RUN_NOPICKUP,     'M', "run.nopickup" },
+    { NHKF_DOINV,            '0', "doinv" },
+    { NHKF_TRAVEL,           CMD_TRAVEL, (char *) 0 }, /* no binding */
+    { NHKF_CLICKLOOK,        CMD_CLICKLOOK, (char *) 0 }, /* no binding */
+    { NHKF_REDRAW,           C('r'), "redraw" },
+    { NHKF_REDRAW2,          C('l'), "redraw.numpad" },
+    { NHKF_GETDIR_SELF,      '.', "getdir.self" },
+    { NHKF_GETDIR_SELF2,     's', "getdir.self2" },
+    { NHKF_GETDIR_HELP,      '?', "getdir.help" },
+    { NHKF_COUNT,            'n', "count" },
+    { NHKF_GETPOS_SELF,      '@', "getpos.self" },
+    { NHKF_GETPOS_PICK,      '.', "getpos.pick" },
+    { NHKF_GETPOS_PICK_Q,    ',', "getpos.pick.quick" },
+    { NHKF_GETPOS_PICK_O,    ';', "getpos.pick.once" },
+    { NHKF_GETPOS_PICK_V,    ':', "getpos.pick.verbose" },
+    { NHKF_GETPOS_SHOWVALID, '$', "getpos.valid" },
+    { NHKF_GETPOS_AUTODESC,  '#', "getpos.autodescribe" },
+    { NHKF_GETPOS_MON_NEXT,  'm', "getpos.mon.next" },
+    { NHKF_GETPOS_MON_PREV,  'M', "getpos.mon.prev" },
+    { NHKF_GETPOS_OBJ_NEXT,  'o', "getpos.obj.next" },
+    { NHKF_GETPOS_OBJ_PREV,  'O', "getpos.obj.prev" },
+    { NHKF_GETPOS_DOOR_NEXT, 'd', "getpos.door.next" },
+    { NHKF_GETPOS_DOOR_PREV, 'D', "getpos.door.prev" },
+    { NHKF_GETPOS_UNEX_NEXT, 'x', "getpos.unexplored.next" },
+    { NHKF_GETPOS_UNEX_PREV, 'X', "getpos.unexplored.prev" },
+    { NHKF_GETPOS_VALID_NEXT, 'z', "getpos.valid.next" },
+    { NHKF_GETPOS_VALID_PREV, 'Z', "getpos.valid.prev" },
+    { NHKF_GETPOS_INTERESTING_NEXT, 'a', "getpos.all.next" },
+    { NHKF_GETPOS_INTERESTING_PREV, 'A', "getpos.all.prev" },
+    { NHKF_GETPOS_HELP,      '?', "getpos.help" },
+    { NHKF_GETPOS_LIMITVIEW, '"', "getpos.filter" },
+    { NHKF_GETPOS_MOVESKIP,  '*', "getpos.moveskip" },
+    { NHKF_GETPOS_MENU,      '!', "getpos.menu" }
+};
+
+boolean
+bind_specialkey(key, command)
+uchar key;
+const char *command;
+{
+    int i;
+    for (i = 0; i < SIZE(spkeys_binds); i++) {
+        if (!spkeys_binds[i].name || strcmp(command, spkeys_binds[i].name))
+            continue;
+        Cmd.spkeys[spkeys_binds[i].nhkf] = key;
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/* returns a one-byte character from the text (it may massacre the txt
+ * buffer) */
+char
+txt2key(txt)
+char *txt;
+{
+    txt = trimspaces(txt);
+    if (!*txt)
+        return '\0';
+
+    /* simple character */
+    if (!txt[1])
+        return txt[0];
+
+    /* a few special entries */
+    if (!strcmp(txt, "<enter>"))
+        return '\n';
+    if (!strcmp(txt, "<space>"))
+        return ' ';
+    if (!strcmp(txt, "<esc>"))
+        return '\033';
+
+    /* control and meta keys */
+    switch (*txt) {
+    case 'm': /* can be mx, Mx, m-x, M-x */
+    case 'M':
+        txt++;
+        if (*txt == '-' && txt[1])
+            txt++;
+        if (txt[1])
+            return '\0';
+        return M(*txt);
+    case 'c': /* can be cx, Cx, ^x, c-x, C-x, ^-x */
+    case 'C':
+    case '^':
+        txt++;
+        if (*txt == '-' && txt[1])
+            txt++;
+        if (txt[1])
+            return '\0';
+        return C(*txt);
+    }
+
+    /* ascii codes: must be three-digit decimal */
+    if (*txt >= '0' && *txt <= '9') {
+        uchar key = 0;
+        int i;
+
+        for (i = 0; i < 3; i++) {
+            if (txt[i] < '0' || txt[i] > '9')
+                return '\0';
+            key = 10 * key + txt[i] - '0';
+        }
+        return key;
+    }
+
+    return '\0';
+}
+
+/* returns the text for a one-byte encoding;
+ * must be shorter than a tab for proper formatting */
+char *
+key2txt(c, txt)
+uchar c;
+char *txt; /* sufficiently long buffer */
+{
+    /* should probably switch to "SPC", "ESC", "RET"
+       since nethack's documentation uses ESC for <escape> */
+    if (c == ' ')
+        Sprintf(txt, "<space>");
+    else if (c == '\033')
+        Sprintf(txt, "<esc>");
+    else if (c == '\n')
+        Sprintf(txt, "<enter>");
+    else if (c == '\177')
+        Sprintf(txt, "<del>"); /* "<delete>" won't fit */
+    else
+        Strcpy(txt, visctrl((char) c));
+    return txt;
+}
+
+
+void
+parseautocomplete(autocomplete, condition)
+char *autocomplete;
+boolean condition;
+{
+    struct ext_func_tab *efp;
+    register char *autoc;
+
+    /* break off first autocomplete from the rest; parse the rest */
+    if ((autoc = index(autocomplete, ',')) != 0
+        || (autoc = index(autocomplete, ':')) != 0) {
+        *autoc++ = '\0';
+        parseautocomplete(autoc, condition);
+    }
+
+    /* strip leading and trailing white space */
+    autocomplete = trimspaces(autocomplete);
+
+    if (!*autocomplete)
+        return;
+
+    /* take off negation */
+    if (*autocomplete == '!') {
+        /* unlike most options, a leading "no" might actually be a part of
+         * the extended command.  Thus you have to use ! */
+        autocomplete++;
+        autocomplete = trimspaces(autocomplete);
+        condition = !condition;
+    }
+
+    /* find and modify the extended command */
+    for (efp = extcmdlist; efp->ef_txt; efp++) {
+        if (!strcmp(autocomplete, efp->ef_txt)) {
+            if (condition)
+                efp->flags |= AUTOCOMPLETE;
+            else
+                efp->flags &= ~AUTOCOMPLETE;
+            return;
+        }
+    }
+
+    /* not a real extended command */
+    raw_printf("Bad autocomplete: invalid extended command '%s'.",
+               autocomplete);
+    wait_synch();
+}
 
 /* called at startup and after number_pad is twiddled */
 void
@@ -4334,26 +5133,35 @@ boolean initial;
     static const int ylist[] = {
         'y', 'Y', C('y'), M('y'), M('Y'), M(C('y'))
     };
-    const struct func_tab *cmdtmp;
+    static struct ext_func_tab *back_dir_cmd[8];
+    const struct ext_func_tab *cmdtmp;
     boolean flagtemp;
     int c, i, updated = 0;
+    static boolean backed_dir_cmd = FALSE;
 
     if (initial) {
         updated = 1;
-        for (i = 0; i < SIZE(cmdlist); i++) {
-            c = cmdlist[i].f_char & 0xff;
-            Cmd.commands[c] = &cmdlist[i];
-        }
         Cmd.num_pad = FALSE;
         Cmd.pcHack_compat = Cmd.phone_layout = Cmd.swap_yz = FALSE;
+        for (i = 0; i < SIZE(spkeys_binds); i++)
+            Cmd.spkeys[spkeys_binds[i].nhkf] = spkeys_binds[i].key;
+        commands_init();
     } else {
+
+        if (backed_dir_cmd) {
+            for (i = 0; i < 8; i++) {
+                Cmd.commands[(uchar) Cmd.dirchars[i]] = back_dir_cmd[i];
+            }
+        }
+
         /* basic num_pad */
         flagtemp = iflags.num_pad;
         if (flagtemp != Cmd.num_pad) {
             Cmd.num_pad = flagtemp;
             ++updated;
         }
-        /* swap_yz mode (only applicable for !num_pad) */
+        /* swap_yz mode (only applicable for !num_pad); intended for
+           QWERTZ keyboard used in Central Europe, particularly Germany */
         flagtemp = (iflags.num_pad_mode & 1) ? !Cmd.num_pad : FALSE;
         if (flagtemp != Cmd.swap_yz) {
             Cmd.swap_yz = flagtemp;
@@ -4387,12 +5195,12 @@ boolean initial;
             ++updated;
             /* phone_layout has been toggled */
             for (i = 0; i < 3; i++) {
-                c = '1' + i;                           /* 1,2,3 <-> 7,8,9 */
+                c = '1' + i;             /* 1,2,3 <-> 7,8,9 */
                 cmdtmp = Cmd.commands[c];              /* tmp = [1] */
                 Cmd.commands[c] = Cmd.commands[c + 6]; /* [1] = [7] */
                 Cmd.commands[c + 6] = cmdtmp;          /* [7] = tmp */
-                c = (M('1') & 0xff) + i;  /* M-1,M-2,M-3 <-> M-7,M-8,M-9 */
-                cmdtmp = Cmd.commands[c]; /* tmp = [M-1] */
+                c = (M('1') & 0xff) + i; /* M-1,M-2,M-3 <-> M-7,M-8,M-9 */
+                cmdtmp = Cmd.commands[c];              /* tmp = [M-1] */
                 Cmd.commands[c] = Cmd.commands[c + 6]; /* [M-1] = [M-7] */
                 Cmd.commands[c + 6] = cmdtmp;          /* [M-7] = tmp */
             }
@@ -4414,22 +5222,60 @@ boolean initial;
     Cmd.move_SE = Cmd.dirchars[5];
     Cmd.move_S = Cmd.dirchars[6];
     Cmd.move_SW = Cmd.dirchars[7];
+
+    if (!initial) {
+        for (i = 0; i < 8; i++) {
+            back_dir_cmd[i] =
+                (struct ext_func_tab *) Cmd.commands[(uchar) Cmd.dirchars[i]];
+            Cmd.commands[(uchar) Cmd.dirchars[i]] = (struct ext_func_tab *) 0;
+        }
+        backed_dir_cmd = TRUE;
+        for (i = 0; i < 8; i++)
+            (void) bind_key(Cmd.dirchars[i], "nothing");
+    }
 }
 
+/* non-movement commands which accept 'm' prefix to request menu operation */
 STATIC_OVL boolean
 accept_menu_prefix(cmd_func)
 int NDECL((*cmd_func));
 {
     if (cmd_func == dopickup || cmd_func == dotip
+        /* eat, #offer, and apply tinning-kit all use floorfood() to pick
+           an item on floor or in invent; 'm' skips picking from floor
+           (ie, inventory only) rather than request use of menu operation */
+        || cmd_func == doeat || cmd_func == dosacrifice || cmd_func == doapply
+        /* 'm' for removing saddle from adjacent monster without checking
+           for containers at <u.ux,u.uy> */
+        || cmd_func == doloot
+        /* travel: pop up a menu of interesting targets in view */
+        || cmd_func == dotravel
+        /* wizard mode ^V */
+        || cmd_func == wiz_level_tele
+        /* 'm' prefix allowed for some extended commands */
         || cmd_func == doextcmd || cmd_func == doextlist)
         return TRUE;
     return FALSE;
 }
 
+int
+ch2spkeys(c, start, end)
+char c;
+int start,end;
+{
+    int i;
+
+    for (i = start; i <= end; i++)
+        if (Cmd.spkeys[i] == c)
+            return i;
+    return NHKF_ESC;
+}
+
 void
 rhack(cmd)
 register char *cmd;
 {
+    int spkey;
     boolean do_walk, do_rush, prefix_seen, bad_command,
         firsttime = (cmd == 0);
 
@@ -4442,7 +5288,7 @@ register char *cmd;
         context.nopick = 0;
         cmd = parse();
     }
-    if (*cmd == '\033') {
+    if (*cmd == Cmd.spkeys[NHKF_ESC]) {
         context.move = FALSE;
         return;
     }
@@ -4463,40 +5309,44 @@ register char *cmd;
     /* handle most movement commands */
     do_walk = do_rush = prefix_seen = FALSE;
     context.travel = context.travel1 = 0;
-    switch (*cmd) {
-    case 'g':
+    spkey = ch2spkeys(*cmd, NHKF_RUN, NHKF_CLICKLOOK);
+
+    switch (spkey) {
+    case NHKF_RUSH:
         if (movecmd(cmd[1])) {
             context.run = 2;
             do_rush = TRUE;
         } else
             prefix_seen = TRUE;
         break;
-    case '5':
+    case NHKF_RUN2:
         if (!Cmd.num_pad)
-            break; /* else FALLTHRU */
-    case 'G':
+            break;
+        /*FALLTHRU*/
+    case NHKF_RUN:
         if (movecmd(lowc(cmd[1]))) {
             context.run = 3;
             do_rush = TRUE;
         } else
             prefix_seen = TRUE;
         break;
-    case '-':
+    case NHKF_FIGHT2:
         if (!Cmd.num_pad)
-            break; /* else FALLTHRU */
+            break;
+        /*FALLTHRU*/
     /* Effects of movement commands and invisible monsters:
      * m: always move onto space (even if 'I' remembered)
      * F: always attack space (even if 'I' not remembered)
      * normal movement: attack if 'I', move otherwise.
      */
-    case 'F':
+    case NHKF_FIGHT:
         if (movecmd(cmd[1])) {
             context.forcefight = 1;
             do_walk = TRUE;
         } else
             prefix_seen = TRUE;
         break;
-    case 'm':
+    case NHKF_NOPICKUP:
         if (movecmd(cmd[1]) || u.dz) {
             context.run = 0;
             context.nopick = 1;
@@ -4507,7 +5357,7 @@ register char *cmd;
         } else
             prefix_seen = TRUE;
         break;
-    case 'M':
+    case NHKF_RUN_NOPICKUP:
         if (movecmd(lowc(cmd[1]))) {
             context.run = 1;
             context.nopick = 1;
@@ -4515,20 +5365,20 @@ register char *cmd;
         } else
             prefix_seen = TRUE;
         break;
-    case '0':
+    case NHKF_DOINV:
         if (!Cmd.num_pad)
             break;
         (void) ddoinv(); /* a convenience borrowed from the PC */
         context.move = FALSE;
         multi = 0;
         return;
-    case CMD_CLICKLOOK:
+    case NHKF_CLICKLOOK:
         if (iflags.clicklook) {
             context.move = FALSE;
             do_look(2, &clicklook_cc);
         }
         return;
-    case CMD_TRAVEL:
+    case NHKF_TRAVEL:
         if (flags.travelcmd) {
             context.travel = 1;
             context.travel1 = 1;
@@ -4554,10 +5404,10 @@ register char *cmd;
 
     /* some special prefix handling */
     /* overload 'm' prefix to mean "request a menu" */
-    if (prefix_seen && cmd[0] == 'm') {
+    if (prefix_seen && cmd[0] == Cmd.spkeys[NHKF_REQMENU]) {
         /* (for func_tab cast, see below) */
-        const struct func_tab *ft = Cmd.commands[cmd[1] & 0xff];
-        int NDECL((*func)) = ft ? ((struct func_tab *) ft)->f_funct : 0;
+        const struct ext_func_tab *ft = Cmd.commands[cmd[1] & 0xff];
+        int NDECL((*func)) = ft ? ((struct ext_func_tab *) ft)->ef_funct : 0;
 
         if (func && accept_menu_prefix(func)) {
             iflags.menu_requested = TRUE;
@@ -4594,27 +5444,24 @@ register char *cmd;
         context.mv = TRUE;
         domove();
         return;
-    } else if (prefix_seen && cmd[1] == '\033') { /* <prefix><escape> */
+    } else if (prefix_seen && cmd[1] == Cmd.spkeys[NHKF_ESC]) {
+        /* <prefix><escape> */
         /* don't report "unknown command" for change of heart... */
         bad_command = FALSE;
     } else if (*cmd == ' ' && !flags.rest_on_space) {
         bad_command = TRUE; /* skip cmdlist[] loop */
 
-        /* handle all other commands */
+    /* handle all other commands */
     } else {
-        register const struct func_tab *tlist;
+        register const struct ext_func_tab *tlist;
         int res, NDECL((*func));
 
-#if 0
-        /* obsolete - scan through the cmdlist array looking for *cmd */
-        for (tlist = cmdlist; tlist->f_char; tlist++) {
-            if ((*cmd & 0xff) != (tlist->f_char & 0xff))
-                continue;
-#else
         /* current - use *cmd to directly index cmdlist array */
         if ((tlist = Cmd.commands[*cmd & 0xff]) != 0) {
-#endif
-            if (u.uburied && !tlist->can_if_buried) {
+            if (!wizard && (tlist->flags & WIZMODECMD)) {
+                You_cant("do that!");
+                res = 0;
+            } else if (u.uburied && !(tlist->flags & IFBURIED)) {
 /*JP
                 You_cant("do that while you are buried!");
 */
@@ -4623,7 +5470,7 @@ register char *cmd;
             } else {
                 /* we discard 'const' because some compilers seem to have
                    trouble with the pointer passed to set_occupation() */
-                func = ((struct func_tab *) tlist)->f_funct;
+                func = ((struct ext_func_tab *) tlist)->ef_funct;
                 if (tlist->f_text && !occupation && multi)
                     set_occupation(func, tlist->f_text, multi);
                 res = (*func)(); /* perform the command */
@@ -4639,28 +5486,17 @@ register char *cmd;
     }
 
     if (bad_command) {
-        char expcmd[10];
-        register char c, *cp = expcmd;
-
-        while ((c = *cmd++) != '\0'
-               && (int) (cp - expcmd) < (int) (sizeof expcmd - 3)) {
-            if (c >= 040 && c < 0177) {
-                *cp++ = c;
-            } else if (c & 0200) {
-                *cp++ = 'M';
-                *cp++ = '-';
-                *cp++ = c & ~0200;
-            } else {
-                *cp++ = '^';
-                *cp++ = c ^ 0100;
-            }
-        }
-        *cp = '\0';
-        if (!prefix_seen || !iflags.cmdassist
+        char expcmd[20]; /* we expect 'cmd' to point to 1 or 2 chars */
+        char c, c1 = cmd[1];
+
+        expcmd[0] = '\0';
+        while ((c = *cmd++) != '\0')
+            Strcat(expcmd, visctrl(c)); /* add 1..4 chars plus terminator */
+
 /*JP
-            || !help_dir(0, "Invalid direction key!"))
+        if (!prefix_seen || !help_dir(c1, spkey, "Invalid direction key!"))
 */
-            || !help_dir(0, "\96³\8cø\82È\95û\8cü\8ew\92è\82Å\82·\81I"))
+        if (!prefix_seen || !help_dir(c1, spkey, "\96³\8cø\82È\95û\8cü\8ew\92è\82Å\82·\81I"))
 /*JP
             Norep("Unknown command '%s'.", expcmd);
 */
@@ -4732,7 +5568,21 @@ boolean
 redraw_cmd(c)
 char c;
 {
-    return (boolean) (c == C('r') || (Cmd.num_pad && c == C('l')));
+    return (boolean) (c == Cmd.spkeys[NHKF_REDRAW]
+                      || (Cmd.num_pad && c == Cmd.spkeys[NHKF_REDRAW2]));
+}
+
+boolean
+prefix_cmd(c)
+char c;
+{
+    return (c == Cmd.spkeys[NHKF_RUSH]
+            || c == Cmd.spkeys[NHKF_RUN]
+            || c == Cmd.spkeys[NHKF_NOPICKUP]
+            || c == Cmd.spkeys[NHKF_RUN_NOPICKUP]
+            || c == Cmd.spkeys[NHKF_FIGHT]
+            || (Cmd.num_pad && (c == Cmd.spkeys[NHKF_RUN2]
+                                || c == Cmd.spkeys[NHKF_FIGHT2])));
 }
 
 /*
@@ -4794,17 +5644,18 @@ retry:
     }
     savech(dirsym);
 
-    if (dirsym == '.' || dirsym == 's') {
+    if (dirsym == Cmd.spkeys[NHKF_GETDIR_SELF]
+        || dirsym == Cmd.spkeys[NHKF_GETDIR_SELF2]) {
         u.dx = u.dy = u.dz = 0;
     } else if (!(is_mov = movecmd(dirsym)) && !u.dz) {
         boolean did_help = FALSE, help_requested;
 
         if (!index(quitchars, dirsym)) {
-            help_requested = (dirsym == '?');
+            help_requested = (dirsym == Cmd.spkeys[NHKF_GETDIR_HELP]);
             if (help_requested || iflags.cmdassist) {
-                did_help =
-                    help_dir((s && *s == '^') ? dirsym : 0,
-                             help_requested ? (const char *) 0
+                did_help = help_dir((s && *s == '^') ? dirsym : '\0',
+                                    NHKF_ESC,
+                                    help_requested ? (const char *) 0
 /*JP
                                             : "Invalid direction key!");
 */
@@ -4831,71 +5682,183 @@ retry:
     return 1;
 }
 
+STATIC_OVL void
+show_direction_keys(win, centerchar, nodiag)
+winid win; /* should specify a window which is using a fixed-width font... */
+char centerchar; /* '.' or '@' or ' ' */
+boolean nodiag;
+{
+    char buf[BUFSZ];
+
+    if (!centerchar)
+        centerchar = ' ';
+
+    if (nodiag) {
+        Sprintf(buf, "             %c   ", Cmd.move_N);
+        putstr(win, 0, buf);
+        putstr(win, 0, "             |   ");
+        Sprintf(buf, "          %c- %c -%c",
+                Cmd.move_W, centerchar, Cmd.move_E);
+        putstr(win, 0, buf);
+        putstr(win, 0, "             |   ");
+        Sprintf(buf, "             %c   ", Cmd.move_S);
+        putstr(win, 0, buf);
+    } else {
+        Sprintf(buf, "          %c  %c  %c",
+                Cmd.move_NW, Cmd.move_N, Cmd.move_NE);
+        putstr(win, 0, buf);
+        putstr(win, 0, "           \\ | / ");
+        Sprintf(buf, "          %c- %c -%c",
+                Cmd.move_W, centerchar, Cmd.move_E);
+        putstr(win, 0, buf);
+        putstr(win, 0, "           / | \\ ");
+        Sprintf(buf, "          %c  %c  %c",
+                Cmd.move_SW, Cmd.move_S, Cmd.move_SE);
+        putstr(win, 0, buf);
+    };
+}
+
+/* explain choices if player has asked for getdir() help or has given
+   an invalid direction after a prefix key ('F', 'g', 'm', &c), which
+   might be bogus but could be up, down, or self when not applicable */
 STATIC_OVL boolean
-help_dir(sym, msg)
+help_dir(sym, spkey, msg)
 char sym;
+int spkey; /* NHKF_ code for prefix key, if one was used, or for ESC */
 const char *msg;
 {
+    static const char wiz_only_list[] = "EFGIVW";
     char ctrl;
     winid win;
-    static const char wiz_only_list[] = "EFGIOVW";
     char buf[BUFSZ], buf2[BUFSZ], *explain;
+    const char *dothat, *how;
+    boolean prefixhandling, viawindow;
+
+    /* NHKF_ESC indicates that player asked for help at getdir prompt */
+    viawindow = (spkey == NHKF_ESC || iflags.cmdassist);
+    prefixhandling = (spkey != NHKF_ESC);
+    /*
+     * Handling for prefix keys that don't want special directions.
+     * Delivered via pline if 'cmdassist' is off, or instead of the
+     * general message if it's on.
+     */
+    dothat = "do that";
+    how = " at"; /* for "<action> at yourself"; not used for up/down */
+    switch (spkey) {
+    case NHKF_NOPICKUP:
+        dothat = "move";
+        break;
+    case NHKF_RUSH:
+        dothat = "rush";
+        break;
+    case NHKF_RUN2:
+        if (!Cmd.num_pad)
+            break;
+        /*FALLTHRU*/
+    case NHKF_RUN:
+    case NHKF_RUN_NOPICKUP:
+        dothat = "run";
+        break;
+    case NHKF_FIGHT2:
+        if (!Cmd.num_pad)
+            break;
+        /*FALLTHRU*/
+    case NHKF_FIGHT:
+        dothat = "fight";
+        how = ""; /* avoid "fight at yourself" */
+        break;
+    default:
+        prefixhandling = FALSE;
+        break;
+    }
+
+    buf[0] = '\0';
+    /* for movement prefix followed by '.' or (numpad && 's') to mean 'self';
+       note: '-' for hands (inventory form of 'self') is not handled here */
+    if (prefixhandling
+        && (sym == Cmd.spkeys[NHKF_GETDIR_SELF]
+            || (Cmd.num_pad && sym == Cmd.spkeys[NHKF_GETDIR_SELF2]))) {
+        Sprintf(buf, "You can't %s%s yourself.", dothat, how);
+    /* for movement prefix followed by up or down */
+    } else if (prefixhandling && (sym == '<' || sym == '>')) {
+        Sprintf(buf, "You can't %s %s.", dothat,
+                /* was "upwards" and "downwards", but they're considered
+                   to be variants of canonical "upward" and "downward" */
+                (sym == '<') ? "upward" : "downward");
+    }
+
+    /* if '!cmdassist', display via pline() and we're done (note: asking
+       for help at getdir() prompt forces cmdassist for this operation) */
+    if (!viawindow) {
+        if (prefixhandling) {
+            if (!*buf)
+                Sprintf(buf, "Invalid direction for '%s' prefix.",
+                        visctrl(Cmd.spkeys[spkey]));
+            pline("%s", buf);
+            return TRUE;
+        }
+        /* when 'cmdassist' is off and caller doesn't insist, do nothing */
+        return FALSE;
+    }
 
     win = create_nhwindow(NHW_TEXT);
     if (!win)
         return FALSE;
-    if (msg) {
+
+    if (*buf) {
+        /* show bad-prefix message instead of general invalid-direction one */
+        putstr(win, 0, buf);
+        putstr(win, 0, "");
+    } else if (msg) {
         Sprintf(buf, "cmdassist: %s", msg);
         putstr(win, 0, buf);
         putstr(win, 0, "");
     }
-    if (letter(sym)) {
-        sym = highc(sym);
-        ctrl = (sym - 'A') + 1;
-        if ((explain = dowhatdoes_core(ctrl, buf2))
+
+    if (!prefixhandling && (letter(sym) || sym == '[')) {
+        /* '[': old 'cmdhelp' showed ESC as ^[ */
+        sym = highc(sym); /* @A-Z[ (note: letter() accepts '@') */
+        ctrl = (sym - 'A') + 1; /* 0-27 (note: 28-31 aren't applicable) */
+        if ((explain = dowhatdoes_core(ctrl, buf2)) != 0
             && (!index(wiz_only_list, sym) || wizard)) {
             Sprintf(buf, "Are you trying to use ^%c%s?", sym,
-                    index(wiz_only_list, sym)
-                        ? ""
+                    index(wiz_only_list, sym) ? ""
                         : " as specified in the Guidebook");
             putstr(win, 0, buf);
             putstr(win, 0, "");
             putstr(win, 0, explain);
             putstr(win, 0, "");
-            putstr(win, 0, "To use that command, you press");
-            Sprintf(buf, "the <Ctrl> key, and the <%c> key at the same time.",
-                    sym);
+            putstr(win, 0,
+                  "To use that command, hold down the <Ctrl> key as a shift");
+            Sprintf(buf, "and press the <%c> key.", sym);
             putstr(win, 0, buf);
             putstr(win, 0, "");
         }
     }
-    if (NODIAG(u.umonnum)) {
-        putstr(win, 0, "Valid direction keys in your current form are:");
-        Sprintf(buf, "             %c   ", Cmd.move_N);
-        putstr(win, 0, buf);
-        putstr(win, 0, "             |   ");
-        Sprintf(buf, "          %c- . -%c", Cmd.move_W, Cmd.move_E);
-        putstr(win, 0, buf);
-        putstr(win, 0, "             |   ");
-        Sprintf(buf, "             %c   ", Cmd.move_S);
-        putstr(win, 0, buf);
-    } else {
-        putstr(win, 0, "Valid direction keys are:");
-        Sprintf(buf, "          %c  %c  %c", Cmd.move_NW, Cmd.move_N,
-                Cmd.move_NE);
-        putstr(win, 0, buf);
-        putstr(win, 0, "           \\ | / ");
-        Sprintf(buf, "          %c- . -%c", Cmd.move_W, Cmd.move_E);
-        putstr(win, 0, buf);
-        putstr(win, 0, "           / | \\ ");
-        Sprintf(buf, "          %c  %c  %c", Cmd.move_SW, Cmd.move_S,
-                Cmd.move_SE);
-        putstr(win, 0, buf);
-    };
-    putstr(win, 0, "");
-    putstr(win, 0, "          <  up");
-    putstr(win, 0, "          >  down");
-    putstr(win, 0, "          .  direct at yourself");
+
+    Sprintf(buf, "Valid direction keys%s%s%s are:",
+            prefixhandling ? " to " : "", prefixhandling ? dothat : "",
+            NODIAG(u.umonnum) ? " in your current form" : "");
+    putstr(win, 0, buf);
+    show_direction_keys(win, !prefixhandling ? '.' : ' ', NODIAG(u.umonnum));
+
+    if (!prefixhandling || spkey == NHKF_NOPICKUP) {
+        /* NOPICKUP: unlike the other prefix keys, 'm' allows up/down for
+           stair traversal; we won't get here when "m<" or "m>" has been
+           given but we include up and down for 'm'+invalid_direction;
+           self is excluded as a viable direction for every prefix */
+        putstr(win, 0, "");
+        putstr(win, 0, "          <  up");
+        putstr(win, 0, "          >  down");
+        if (!prefixhandling) {
+            int selfi = Cmd.num_pad ? NHKF_GETDIR_SELF2 : NHKF_GETDIR_SELF;
+
+            Sprintf(buf,   "       %4s  direct at yourself",
+                    visctrl(Cmd.spkeys[selfi]));
+            putstr(win, 0, buf);
+        }
+    }
+
     if (msg) {
         /* non-null msg means that this wasn't an explicit user request */
         putstr(win, 0, "");
@@ -4942,6 +5905,251 @@ register int x, y;
     return x >= 1 && x <= COLNO - 1 && y >= 0 && y <= ROWNO - 1;
 }
 
+/* #herecmdmenu command */
+STATIC_PTR int
+doherecmdmenu(VOID_ARGS)
+{
+    char ch = here_cmd_menu(TRUE);
+
+    return ch ? 1 : 0;
+}
+
+/* #therecmdmenu command, a way to test there_cmd_menu without mouse */
+STATIC_PTR int
+dotherecmdmenu(VOID_ARGS)
+{
+    char ch;
+
+    if (!getdir((const char *) 0) || !isok(u.ux + u.dx, u.uy + u.dy))
+        return 0;
+
+    if (u.dx || u.dy)
+        ch = there_cmd_menu(TRUE, u.ux + u.dx, u.uy + u.dy);
+    else
+        ch = here_cmd_menu(TRUE);
+
+    return ch ? 1 : 0;
+}
+
+STATIC_OVL void
+add_herecmd_menuitem(win, func, text)
+winid win;
+int NDECL((*func));
+const char *text;
+{
+    char ch;
+    anything any;
+
+    if ((ch = cmd_from_func(func)) != '\0') {
+        any = zeroany;
+        any.a_nfunc = func;
+        add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, text, MENU_UNSELECTED);
+    }
+}
+
+STATIC_OVL char
+there_cmd_menu(doit, x, y)
+boolean doit;
+int x, y;
+{
+    winid win;
+    char ch;
+    char buf[BUFSZ];
+    schar typ = levl[x][y].typ;
+    int npick, K = 0;
+    menu_item *picks = (menu_item *) 0;
+    struct trap *ttmp;
+    struct monst *mtmp;
+
+    win = create_nhwindow(NHW_MENU);
+    start_menu(win);
+
+    if (IS_DOOR(typ)) {
+        boolean key_or_pick, card;
+        int dm = levl[x][y].doormask;
+
+        if ((dm & (D_CLOSED | D_LOCKED))) {
+            add_herecmd_menuitem(win, doopen, "Open the door"), ++K;
+            /* unfortunately there's no lknown flag for doors to
+               remember the locked/unlocked state */
+            key_or_pick = (carrying(SKELETON_KEY) || carrying(LOCK_PICK));
+            card = (carrying(CREDIT_CARD) != 0);
+            if (key_or_pick || card) {
+                Sprintf(buf, "%sunlock the door",
+                        key_or_pick ? "lock or " : "");
+                add_herecmd_menuitem(win, doapply, upstart(buf)), ++K;
+            }
+            /* unfortunately there's no tknown flag for doors (or chests)
+               to remember whether a trap had been found */
+            add_herecmd_menuitem(win, dountrap,
+                                 "Search the door for a trap"), ++K;
+            /* [what about #force?] */
+            add_herecmd_menuitem(win, dokick, "Kick the door"), ++K;
+        } else if ((dm & D_ISOPEN)) {
+            add_herecmd_menuitem(win, doclose, "Close the door"), ++K;
+        }
+    }
+
+    if (typ <= SCORR)
+        add_herecmd_menuitem(win, dosearch, "Search for secret doors"), ++K;
+
+    if ((ttmp = t_at(x, y)) != 0 && ttmp->tseen) {
+        add_herecmd_menuitem(win, doidtrap, "Examine trap"), ++K;
+        if (ttmp->ttyp != VIBRATING_SQUARE)
+            add_herecmd_menuitem(win, dountrap, "Attempt to disarm trap"), ++K;
+    }
+
+    mtmp = m_at(x, y);
+    if (mtmp && !canspotmon(mtmp))
+        mtmp = 0;
+    if (mtmp && which_armor(mtmp, W_SADDLE)) {
+        char *mnam = x_monnam(mtmp, ARTICLE_THE, (char *) 0,
+                              SUPPRESS_SADDLE, FALSE);
+
+        if (!u.usteed) {
+            Sprintf(buf, "Ride %s", mnam);
+            add_herecmd_menuitem(win, doride, buf), ++K;
+        }
+        Sprintf(buf, "Remove saddle from %s", mnam);
+        add_herecmd_menuitem(win, doloot, buf), ++K;
+    }
+    if (mtmp && can_saddle(mtmp) && !which_armor(mtmp, W_SADDLE)
+        && carrying(SADDLE)) {
+        Sprintf(buf, "Put saddle on %s", mon_nam(mtmp)), ++K;
+        add_herecmd_menuitem(win, doapply, buf);
+    }
+#if 0
+    if (mtmp || glyph_is_invisible(glyph_at(x, y))) {
+        /* "Attack %s", mtmp ? mon_nam(mtmp) : "unseen creature" */
+    } else {
+        /* "Move %s", direction */
+    }
+#endif
+
+    if (K) {
+        end_menu(win, "What do you want to do?");
+        npick = select_menu(win, PICK_ONE, &picks);
+    } else {
+        pline("No applicable actions.");
+        npick = 0;
+    }
+    destroy_nhwindow(win);
+    ch = '\0';
+    if (npick > 0) {
+        int NDECL((*func)) = picks->item.a_nfunc;
+        free((genericptr_t) picks);
+
+        if (doit) {
+            int ret = (*func)();
+
+            ch = (char) ret;
+        } else {
+            ch = cmd_from_func(func);
+        }
+    }
+    return ch;
+}
+
+STATIC_OVL char
+here_cmd_menu(doit)
+boolean doit;
+{
+    winid win;
+    char ch;
+    char buf[BUFSZ];
+    schar typ = levl[u.ux][u.uy].typ;
+    int npick;
+    menu_item *picks = (menu_item *) 0;
+
+    win = create_nhwindow(NHW_MENU);
+    start_menu(win);
+
+    if (IS_FOUNTAIN(typ) || IS_SINK(typ)) {
+        Sprintf(buf, "Drink from the %s",
+                defsyms[IS_FOUNTAIN(typ) ? S_fountain : S_sink].explanation);
+        add_herecmd_menuitem(win, dodrink, buf);
+    }
+    if (IS_FOUNTAIN(typ))
+        add_herecmd_menuitem(win, dodip,
+                             "Dip something into the fountain");
+    if (IS_THRONE(typ))
+        add_herecmd_menuitem(win, dosit,
+                             "Sit on the throne");
+
+    if ((u.ux == xupstair && u.uy == yupstair)
+        || (u.ux == sstairs.sx && u.uy == sstairs.sy && sstairs.up)
+        || (u.ux == xupladder && u.uy == yupladder)) {
+        Sprintf(buf, "Go up the %s",
+                (u.ux == xupladder && u.uy == yupladder)
+                ? "ladder" : "stairs");
+        add_herecmd_menuitem(win, doup, buf);
+    }
+    if ((u.ux == xdnstair && u.uy == ydnstair)
+        || (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)
+        || (u.ux == xdnladder && u.uy == ydnladder)) {
+        Sprintf(buf, "Go down the %s",
+                (u.ux == xupladder && u.uy == yupladder)
+                ? "ladder" : "stairs");
+        add_herecmd_menuitem(win, dodown, buf);
+    }
+    if (u.usteed) { /* another movement choice */
+        Sprintf(buf, "Dismount %s",
+                x_monnam(u.usteed, ARTICLE_THE, (char *) 0,
+                         SUPPRESS_SADDLE, FALSE));
+        add_herecmd_menuitem(win, doride, buf);
+    }
+
+#if 0
+    if (Upolyd) { /* before objects */
+        Sprintf(buf, "Use %s special ability",
+                s_suffix(mons[u.umonnum].mname));
+        add_herecmd_menuitem(win, domonability, buf);
+    }
+#endif
+
+    if (OBJ_AT(u.ux, u.uy)) {
+        struct obj *otmp = level.objects[u.ux][u.uy];
+
+        Sprintf(buf, "Pick up %s", otmp->nexthere ? "items" : doname(otmp));
+        add_herecmd_menuitem(win, dopickup, buf);
+
+        if (Is_container(otmp)) {
+            Sprintf(buf, "Loot %s", doname(otmp));
+            add_herecmd_menuitem(win, doloot, buf);
+        }
+        if (otmp->oclass == FOOD_CLASS) {
+            Sprintf(buf, "Eat %s", doname(otmp));
+            add_herecmd_menuitem(win, doeat, buf);
+        }
+    }
+
+    if (invent)
+        add_herecmd_menuitem(win, dodrop, "Drop items");
+
+    add_herecmd_menuitem(win, donull, "Rest one turn");
+    add_herecmd_menuitem(win, dosearch, "Search around you");
+    add_herecmd_menuitem(win, dolook, "Look at what is here");
+
+    end_menu(win, "What do you want to do?");
+    npick = select_menu(win, PICK_ONE, &picks);
+    destroy_nhwindow(win);
+    ch = '\0';
+    if (npick > 0) {
+        int NDECL((*func)) = picks->item.a_nfunc;
+        free((genericptr_t) picks);
+
+        if (doit) {
+            int ret = (*func)();
+
+            ch = (char) ret;
+        } else {
+            ch = cmd_from_func(func);
+        }
+    }
+    return ch;
+}
+
+
 static NEARDATA int last_multi;
 
 /*
@@ -4958,7 +6166,7 @@ int x, y, mod;
     if (iflags.clicklook && mod == CLICK_2) {
         clicklook_cc.x = x;
         clicklook_cc.y = y;
-        cmd[0] = CMD_CLICKLOOK;
+        cmd[0] = Cmd.spkeys[NHKF_CLICKLOOK];
         return cmd;
     }
 
@@ -4971,35 +6179,43 @@ int x, y, mod;
         } else {
             u.tx = u.ux + x;
             u.ty = u.uy + y;
-            cmd[0] = CMD_TRAVEL;
+            cmd[0] = Cmd.spkeys[NHKF_TRAVEL];
             return cmd;
         }
 
         if (x == 0 && y == 0) {
+            if (iflags.herecmd_menu) {
+                cmd[0] = here_cmd_menu(FALSE);
+                return cmd;
+            }
+
             /* here */
             if (IS_FOUNTAIN(levl[u.ux][u.uy].typ)
                 || IS_SINK(levl[u.ux][u.uy].typ)) {
-                cmd[0] = mod == CLICK_1 ? 'q' : M('d');
+                cmd[0] = cmd_from_func(mod == CLICK_1 ? dodrink : dodip);
                 return cmd;
             } else if (IS_THRONE(levl[u.ux][u.uy].typ)) {
-                cmd[0] = M('s');
+                cmd[0] = cmd_from_func(dosit);
                 return cmd;
             } else if ((u.ux == xupstair && u.uy == yupstair)
                        || (u.ux == sstairs.sx && u.uy == sstairs.sy
                            && sstairs.up)
                        || (u.ux == xupladder && u.uy == yupladder)) {
-                return "<";
+                cmd[0] = cmd_from_func(doup);
+                return cmd;
             } else if ((u.ux == xdnstair && u.uy == ydnstair)
                        || (u.ux == sstairs.sx && u.uy == sstairs.sy
                            && !sstairs.up)
                        || (u.ux == xdnladder && u.uy == ydnladder)) {
-                return ">";
+                cmd[0] = cmd_from_func(dodown);
+                return cmd;
             } else if (OBJ_AT(u.ux, u.uy)) {
-                cmd[0] =
-                    Is_container(level.objects[u.ux][u.uy]) ? M('l') : ',';
+                cmd[0] = cmd_from_func(Is_container(level.objects[u.ux][u.uy])
+                                       ? doloot : dopickup);
                 return cmd;
             } else {
-                return "."; /* just rest */
+                cmd[0] = cmd_from_func(donull); /* just rest */
+                return cmd;
             }
         }
 
@@ -5011,20 +6227,27 @@ int x, y, mod;
             && !test_move(u.ux, u.uy, x, y, TEST_MOVE)) {
             cmd[1] = Cmd.dirchars[dir];
             cmd[2] = '\0';
+            if (iflags.herecmd_menu) {
+                cmd[0] = there_cmd_menu(FALSE, u.ux + x, u.uy + y);
+                if (cmd[0] == '\0')
+                    cmd[1] = '\0';
+                return cmd;
+            }
+
             if (IS_DOOR(levl[u.ux + x][u.uy + y].typ)) {
                 /* slight assistance to the player: choose kick/open for them
                  */
                 if (levl[u.ux + x][u.uy + y].doormask & D_LOCKED) {
-                    cmd[0] = C('d');
+                    cmd[0] = cmd_from_func(dokick);
                     return cmd;
                 }
                 if (levl[u.ux + x][u.uy + y].doormask & D_CLOSED) {
-                    cmd[0] = 'o';
+                    cmd[0] = cmd_from_func(doopen);
                     return cmd;
                 }
             }
             if (levl[u.ux + x][u.uy + y].typ <= SCORR) {
-                cmd[0] = 's';
+                cmd[0] = cmd_from_func(dosearch);
                 cmd[1] = 0;
                 return cmd;
             }
@@ -5042,9 +6265,11 @@ int x, y, mod;
         else
             x = sgn(x), y = sgn(y);
 
-        if (x == 0 && y == 0) /* map click on player to "rest" command */
-            return ".";
-
+        if (x == 0 && y == 0) {
+            /* map click on player to "rest" command */
+            cmd[0] = cmd_from_func(donull);
+            return cmd;
+        }
         dir = xytod(x, y);
     }
 
@@ -5061,6 +6286,76 @@ int x, y, mod;
     return cmd;
 }
 
+char
+get_count(allowchars, inkey, maxcount, count, historical)
+char *allowchars;
+char inkey;
+long maxcount;
+long *count;
+boolean historical; /* whether to include in message history: True => yes */
+{
+    char qbuf[QBUFSZ];
+    int key;
+    long cnt = 0L;
+    boolean backspaced = FALSE;
+    /* this should be done in port code so that we have erase_char
+       and kill_char available; we can at least fake erase_char */
+#define STANDBY_erase_char '\177'
+
+    for (;;) {
+        if (inkey) {
+            key = inkey;
+            inkey = '\0';
+        } else
+            key = readchar();
+
+        if (digit(key)) {
+            cnt = 10L * cnt + (long) (key - '0');
+            if (cnt < 0)
+                cnt = 0;
+            else if (maxcount > 0 && cnt > maxcount)
+                cnt = maxcount;
+        } else if (cnt && (key == '\b' || key == STANDBY_erase_char)) {
+            cnt = cnt / 10;
+            backspaced = TRUE;
+        } else if (key == Cmd.spkeys[NHKF_ESC]) {
+            break;
+        } else if (!allowchars || index(allowchars, key)) {
+            *count = cnt;
+            break;
+        }
+
+        if (cnt > 9 || backspaced) {
+            clear_nhwindow(WIN_MESSAGE);
+            if (backspaced && !cnt) {
+/*JP
+                Sprintf(qbuf, "Count: ");
+*/
+                Sprintf(qbuf, "\90\94: ");
+            } else {
+/*JP
+                Sprintf(qbuf, "Count: %ld", cnt);
+*/
+                Sprintf(qbuf, "\90\94: %ld", cnt);
+                backspaced = FALSE;
+            }
+            /* bypassing pline() keeps intermediate prompt out of
+               DUMPLOG message history */
+            putstr(WIN_MESSAGE, 0, qbuf);
+            mark_synch();
+        }
+    }
+
+    if (historical) {
+        Sprintf(qbuf, "Count: %ld ", *count);
+        (void) key2txt((uchar) key, eos(qbuf));
+        putmsghistory(qbuf, FALSE);
+    }
+
+    return key;
+}
+
+
 STATIC_OVL char *
 parse()
 {
@@ -5072,6 +6367,7 @@ parse()
     register int foo;
     boolean prezero = FALSE;
 
+    iflags.in_parse = TRUE;
     multi = 0;
     context.move = 1;
     flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
@@ -5079,36 +6375,20 @@ parse()
 #ifdef ALTMETA
     alt_esc = iflags.altmeta; /* readchar() hack */
 #endif
-    if (!Cmd.num_pad || (foo = readchar()) == 'n')
-        for (;;) {
-            foo = readchar();
-            if (foo >= '0' && foo <= '9') {
-                multi = 10 * multi + foo - '0';
-                if (multi < 0 || multi >= LARGEST_INT)
-                    multi = LARGEST_INT;
-                if (multi > 9) {
-                    clear_nhwindow(WIN_MESSAGE);
-/*JP
-                    Sprintf(in_line, "Count: %d", multi);
-*/
-                    Sprintf(in_line, "\90\94: %d", multi);
-                    pline1(in_line);
-                    mark_synch();
-                }
-                last_multi = multi;
-                if (!multi && foo == '0')
-                    prezero = TRUE;
-            } else
-                break; /* not a digit */
-        }
+    if (!Cmd.num_pad || (foo = readchar()) == Cmd.spkeys[NHKF_COUNT]) {
+        long tmpmulti = multi;
+
+        foo = get_count((char *) 0, '\0', LARGEST_INT, &tmpmulti, FALSE);
+        last_multi = multi = tmpmulti;
+    }
 #ifdef ALTMETA
     alt_esc = FALSE; /* readchar() reset */
 #endif
 
-    if (foo == '\033') { /* esc cancels count (TH) */
+    if (foo == Cmd.spkeys[NHKF_ESC]) { /* esc cancels count (TH) */
         clear_nhwindow(WIN_MESSAGE);
         multi = last_multi = 0;
-    } else if (foo == DOAGAIN || in_doagain) {
+    } else if (foo == Cmd.spkeys[NHKF_DOAGAIN] || in_doagain) {
         multi = last_multi;
     } else {
         last_multi = multi;
@@ -5130,13 +6410,13 @@ parse()
            from the number pad. Now do not map them until here. */
         switch (foo) {
         case '5':
-            foo = 'g';
+            foo = Cmd.spkeys[NHKF_RUSH];
             break;
         case M('5'):
-            foo = 'G';
+            foo = Cmd.spkeys[NHKF_RUN];
             break;
         case M('0'):
-            foo = 'I';
+            foo = Cmd.spkeys[NHKF_DOINV];
             break;
         default:
             break; /* as is */
@@ -5145,8 +6425,7 @@ parse()
 
     in_line[0] = foo;
     in_line[1] = '\0';
-    if (foo == 'g' || foo == 'G' || foo == 'm' || foo == 'M' || foo == 'F'
-        || (Cmd.num_pad && (foo == '5' || foo == '-'))) {
+    if (prefix_cmd(foo)) {
         foo = readchar();
         savech((char) foo);
         in_line[1] = foo;
@@ -5154,7 +6433,9 @@ parse()
     }
     clear_nhwindow(WIN_MESSAGE);
     if (prezero)
-        in_line[0] = '\033';
+        in_line[0] = Cmd.spkeys[NHKF_ESC];
+
+    iflags.in_parse = FALSE;
     return in_line;
 }
 
@@ -5204,7 +6485,7 @@ end_of_input()
     if (iflags.window_inited)
         exit_nhwindows((char *) 0);
     clearlocks();
-    terminate(EXIT_SUCCESS);
+    nh_terminate(EXIT_SUCCESS);
     /*NOTREACHED*/ /* not necessarily true for vms... */
     return;
 }
@@ -5249,7 +6530,7 @@ readchar()
             sym = '\033';
         else if (sym != '\033')
             sym |= 0200; /* force 8th bit on */
-#endif                   /*ALTMETA*/
+#endif /*ALTMETA*/
     } else if (sym == 0) {
         /* click event */
         readchar_queue = click_to_cmd(x, y, mod);
@@ -5275,6 +6556,17 @@ dotravel(VOID_ARGS)
         cc.x = u.ux;
         cc.y = u.uy;
     }
+    iflags.getloc_travelmode = TRUE;
+    if (iflags.menu_requested) {
+        int gf = iflags.getloc_filter;
+        iflags.getloc_filter = GFILTER_VIEW;
+        if (!getpos_menu(&cc, GLOC_INTERESTING)) {
+            iflags.getloc_filter = gf;
+            iflags.getloc_travelmode = FALSE;
+            return 0;
+        }
+        iflags.getloc_filter = gf;
+    } else {
 /*JP
     pline("Where do you want to travel to?");
 */
@@ -5283,12 +6575,15 @@ dotravel(VOID_ARGS)
     if (getpos(&cc, TRUE, "the desired destination") < 0) {
 */
     if (getpos(&cc, TRUE, "\88Ú\93®\90æ") < 0) {
-        /* user pressed ESC */
-        return 0;
+            /* user pressed ESC */
+            iflags.getloc_travelmode = FALSE;
+            return 0;
+        }
     }
+    iflags.getloc_travelmode = FALSE;
     iflags.travelcc.x = u.tx = cc.x;
     iflags.travelcc.y = u.ty = cc.y;
-    cmd[0] = CMD_TRAVEL;
+    cmd[0] = Cmd.spkeys[NHKF_TRAVEL];
     readchar_queue = cmd;
     return 0;
 }
@@ -5314,12 +6609,13 @@ wiz_port_debug()
         { "show keystroke handler information (tty only)",
           win32con_handler_info },
 #endif
-        { (char *) 0, (void NDECL((*) )) 0 } /* array terminator */
+        { (char *) 0, (void NDECL((*))) 0 } /* array terminator */
     };
 
     num_menu_selections = SIZE(menu_selections) - 1;
     if (num_menu_selections > 0) {
         menu_item *pick_list;
+
         win = create_nhwindow(NHW_MENU);
         start_menu(win);
         for (k = 0; k < num_menu_selections; ++k) {
@@ -5352,19 +6648,36 @@ yn_function(query, resp, def)
 const char *query, *resp;
 char def;
 {
-    char qbuf[QBUFSZ];
+    char res, qbuf[QBUFSZ];
+#ifdef DUMPLOG
+    extern unsigned saved_pline_index; /* pline.c */
+    unsigned idx = saved_pline_index;
+    /* buffer to hold query+space+formatted_single_char_response */
+    char dumplog_buf[QBUFSZ + 1 + 15]; /* [QBUFSZ+1+7] should suffice */
+#endif
 
     iflags.last_msg = PLNMSG_UNKNOWN; /* most recent pline is clobbered */
 
     /* maximum acceptable length is QBUFSZ-1 */
-    if (strlen(query) < QBUFSZ)
-        return (*windowprocs.win_yn_function)(query, resp, def);
-
-    /* caller shouldn't have passed anything this long */
-    paniclog("Query truncated: ", query);
-    (void) strncpy(qbuf, query, QBUFSZ - 1 - 3);
-    Strcpy(&qbuf[QBUFSZ - 1 - 3], "...");
-    return (*windowprocs.win_yn_function)(qbuf, resp, def);
+    if (strlen(query) >= QBUFSZ) {
+        /* caller shouldn't have passed anything this long */
+        paniclog("Query truncated: ", query);
+        (void) strncpy(qbuf, query, QBUFSZ - 1 - 3);
+        Strcpy(&qbuf[QBUFSZ - 1 - 3], "...");
+        query = qbuf;
+    }
+    res = (*windowprocs.win_yn_function)(query, resp, def);
+#ifdef DUMPLOG
+    if (idx == saved_pline_index) {
+        /* when idx is still the same as saved_pline_index, the interface
+           didn't put the prompt into saved_plines[]; we put a simplified
+           version in there now (without response choices or default) */
+        Sprintf(dumplog_buf, "%s ", query);
+        (void) key2txt((uchar) res, eos(dumplog_buf));
+        dumplogmsg(dumplog_buf);
+    }
+#endif
+    return res;
 }
 
 /* for paranoid_confirm:quit,die,attack prompting */
@@ -5379,7 +6692,7 @@ const char *prompt;
        to give the go-ahead for this query; default is "no" unless the
        ParanoidConfirm flag is set in which case there's no default */
     if (be_paranoid) {
-        char qbuf[QBUFSZ], ans[BUFSZ];
+        char qbuf[QBUFSZ], ans[BUFSZ] = DUMMY;
         const char *promptprefix = "", *responsetype = ParanoidConfirm
                                                            ? "(yes|no)"
                                                            : "(yes) [no]";
index 8bc8b2e..b1a115d 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 dbridge.c       $NHDT-Date: 1449269914 2015/12/04 22:58:34 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.35 $ */
+/* NetHack 3.6 dbridge.c       $NHDT-Date: 1503355815 2017/08/21 22:50:15 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.39 $ */
 /*      Copyright (c) 1989 by Jean-Christophe Collet              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -120,16 +120,12 @@ int mask;
     switch (mask & DB_UNDER) {
     case DB_ICE:
         return ICE;
-        break;
     case DB_LAVA:
         return LAVAPOOL;
-        break;
     case DB_MOAT:
         return MOAT;
-        break;
     default:
         return STONE;
-        break;
     }
 }
 
@@ -239,7 +235,6 @@ int *x, *y;
  *     dir is the direction.
  *     flag must be put to TRUE if we want the drawbridge to be opened.
  */
-
 boolean
 create_drawbridge(x, y, dir, flag)
 int x, y, dir;
@@ -387,7 +382,6 @@ struct entity *etmp;
  * Generates capitalized entity name, makes 2nd -> 3rd person conversion on
  * verb, where necessary.
  */
-
 STATIC_OVL const char *
 E_phrase(etmp, verb)
 struct entity *etmp;
@@ -414,7 +408,6 @@ const char *verb;
 /*
  * Simple-minded "can it be here?" routine
  */
-
 STATIC_OVL boolean
 e_survives_at(etmp, x, y)
 struct entity *etmp;
@@ -440,9 +433,9 @@ int x, y;
 }
 
 STATIC_OVL void
-e_died(etmp, dest, how)
+e_died(etmp, xkill_flags, how)
 struct entity *etmp;
-int dest, how;
+int xkill_flags, how;
 {
     if (is_u(etmp)) {
         if (how == DROWNING) {
@@ -487,13 +480,14 @@ int dest, how;
 
         killer.name[0] = 0;
 /* fake "digested to death" damage-type suppresses corpse */
-#define mk_message(dest) ((dest & 1) ? "" : (char *) 0)
-#define mk_corpse(dest) ((dest & 2) ? AD_DGST : AD_PHYS)
+#define mk_message(dest) (((dest & XKILL_NOMSG) != 0) ? (char *) 0 : "")
+#define mk_corpse(dest) (((dest & XKILL_NOCORPSE) != 0) ? AD_DGST : AD_PHYS)
         /* if monsters are moving, one of them caused the destruction */
         if (context.mon_moving)
-            monkilled(etmp->emon, mk_message(dest), mk_corpse(dest));
+            monkilled(etmp->emon,
+                      mk_message(xkill_flags), mk_corpse(xkill_flags));
         else /* you caused it */
-            xkilled(etmp->emon, dest);
+            xkilled(etmp->emon, xkill_flags);
         etmp->edata = (struct permonst *) 0;
 
         /* dead long worm handling */
@@ -510,7 +504,6 @@ int dest, how;
 /*
  * These are never directly affected by a bridge or portcullis.
  */
-
 STATIC_OVL boolean
 automiss(etmp)
 struct entity *etmp;
@@ -522,7 +515,6 @@ struct entity *etmp;
 /*
  * Does falling drawbridge or portcullis miss etmp?
  */
-
 STATIC_OVL boolean
 e_missed(etmp, chunks)
 struct entity *etmp;
@@ -560,7 +552,6 @@ boolean chunks;
 /*
  * Can etmp jump from death?
  */
-
 STATIC_OVL boolean
 e_jumps(etmp)
 struct entity *etmp;
@@ -637,12 +628,19 @@ struct entity *etmp;
         }
     } else {
         if (crm->typ == DRAWBRIDGE_DOWN) {
+            if (is_u(etmp)) {
+                killer.format = NO_KILLER_PREFIX;
+                Strcpy(killer.name,
+                       "crushed to death underneath a drawbridge");
+            }
 /*JP
             pline("%s crushed underneath the drawbridge.",
 */
             pline("%s\82Í\92µ\82Ë\8b´\82Ì\89º\95~\82É\82È\82Á\82½\81D",
                   E_phrase(etmp, "are"));             /* no jump */
-            e_died(etmp, e_inview ? 3 : 2, CRUSHING); /* no corpse */
+            e_died(etmp,
+                   XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
+                   CRUSHING); /* no corpse */
             return;       /* Note: Beyond this point, we know we're  */
         }                 /* not at an opened drawbridge, since all  */
         must_jump = TRUE; /* *missable* creatures survive on the     */
@@ -664,7 +662,10 @@ struct entity *etmp;
                     You_hear("a crushing sound.");
 */
                     You_hear("\89½\82©\82ª\92×\82ê\82é\89¹\82ð\95·\82¢\82½\81D");
-                e_died(etmp, e_inview ? 3 : 2, CRUSHING);
+                e_died(etmp,
+                       XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG
+                                                  : XKILL_NOMSG),
+                       CRUSHING);
                 /* no corpse */
                 return;
             }
@@ -676,11 +677,10 @@ struct entity *etmp;
 
     /*
      * Here's where we try to do relocation.  Assumes that etmp is not
-     * arriving
-     * at the portcullis square while the drawbridge is falling, since this
-     * square
-     * would be inaccessible (i.e. etmp started on drawbridge square) or
-     * unnecessary (i.e. etmp started here) in such a situation.
+     * arriving at the portcullis square while the drawbridge is
+     * falling, since this square would be inaccessible (i.e. etmp
+     * started on drawbridge square) or unnecessary (i.e. etmp started
+     * here) in such a situation.
      */
     debugpline0("Doing relocation.");
     newx = oldx;
@@ -691,12 +691,10 @@ struct entity *etmp;
     debugpline0("Checking new square for occupancy.");
     if (relocates && (e_at(newx, newy))) {
         /*
-         * Standoff problem:  one or both entities must die, and/or both
-         * switch
-         * places.  Avoid infinite recursion by checking first whether the
-         * other
-         * entity is staying put.  Clean up if we happen to move/die in
-         * recursion.
+         * Standoff problem: one or both entities must die, and/or
+         * both switch places.  Avoid infinite recursion by checking
+         * first whether the other entity is staying put.  Clean up if
+         * we happen to move/die in recursion.
          */
         struct entity *other;
 
@@ -775,7 +773,7 @@ struct entity *etmp;
             Strcpy(killer.name, "closing drawbridge");
 */
             Strcpy(killer.name, "\95Â\82\82Ä\82¢\82­\92µ\82Ë\8b´\82É\8b·\82Ü\82ê\82Ä");
-            e_died(etmp, 0, CRUSHING); /* no message */
+            e_died(etmp, XKILL_NOMSG, CRUSHING);
             return;
         }
         debugpline1("%s in here", E_phrase(etmp, "survive"));
@@ -804,7 +802,7 @@ struct entity *etmp;
                 boolean lava = is_lava(etmp->ex, etmp->ey);
 
                 if (Hallucination)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                     pline("%s the %s and disappears.",
                           E_phrase(etmp, "drink"), lava ? "lava" : "moat");
 #else
@@ -812,12 +810,12 @@ struct entity *etmp;
                           E_phrase(etmp, "drink"), lava ? "\97n\8aâ" : "\96x");
 #endif
                 else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                     pline("%s into the %s.", E_phrase(etmp, "fall"),
-                          lava ? "lava" : "moat");
+                          lava ? hliquid("lava") : "moat");
 #else
                     pline("%s\82Í%s\82Ì\92\86\82É\97\8e\82¿\82½\81D", E_phrase(etmp, "fall"),
-                          lava ? "\97n\8aâ" : "\96x");
+                          lava ? hliquid("\97n\8aâ") : "\96x");
 #endif
             }
 #if 0 /*JP:T*/
@@ -827,19 +825,21 @@ struct entity *etmp;
         killer.format = KILLED_BY;
         Strcpy(killer.name, "\92µ\82Ë\8b´\82©\82ç\97\8e\82¿\82Ä");
 #endif
-        e_died(etmp, e_inview ? 3 : 2, /* CRUSHING is arbitrary */
-               (is_pool(etmp->ex, etmp->ey))
-                   ? DROWNING
-                   : (is_lava(etmp->ex, etmp->ey)) ? BURNING
-                                                   : CRUSHING); /*no corpse*/
+        e_died(etmp, /* CRUSHING is arbitrary */
+               XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
+               is_pool(etmp->ex, etmp->ey) ? DROWNING
+                 : is_lava(etmp->ex, etmp->ey) ? BURNING
+                   : CRUSHING); /*no corpse*/
         return;
     }
 }
 
+/* clear stale reason for death before returning */
+#define nokiller() (killer.name[0] = '\0', killer.format = 0)
+
 /*
  * Close the drawbridge located at x,y
  */
-
 void
 close_drawbridge(x, y)
 int x, y;
@@ -906,12 +906,12 @@ int x, y;
     newsym(x, y);
     newsym(x2, y2);
     block_point(x2, y2); /* vision */
+    nokiller();
 }
 
 /*
  * Open the drawbridge located at x,y
  */
-
 void
 open_drawbridge(x, y)
 int x, y;
@@ -960,12 +960,12 @@ int x, y;
     unblock_point(x2, y2); /* vision */
     if (Is_stronghold(&u.uz))
         u.uevent.uopened_dbridge = TRUE;
+    nokiller();
 }
 
 /*
  * Let's destroy the drawbridge located at x,y
  */
-
 void
 destroy_drawbridge(x, y)
 int x, y;
@@ -988,14 +988,15 @@ int x, y;
         || (lev1->drawbridgemask & DB_UNDER) == DB_LAVA) {
         struct obj *otmp2;
         boolean lava = (lev1->drawbridgemask & DB_UNDER) == DB_LAVA;
+
         if (lev1->typ == DRAWBRIDGE_UP) {
             if (cansee(x2, y2))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 pline_The("portcullis of the drawbridge falls into the %s!",
-                          lava ? "lava" : "moat");
+                          lava ? hliquid("lava") : "moat");
 #else
                 pline("\92µ\82Ë\8b´\82Ì\97\8e\82µ\8ai\8eq\82ª%s\82É\97\8e\82¿\82½\81I",
-                          lava ? "\97n\8aâ" : "\96x");
+                          lava ? hliquid("\97n\8aâ") : "\96x");
 #endif
             else if (!Deaf)
 /*JP
@@ -1004,12 +1005,12 @@ int x, y;
                 You_hear("\91å\82«\82È\83o\83b\83V\83\83\81[\83\93\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81I");
         } else {
             if (cansee(x, y))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 pline_The("drawbridge collapses into the %s!",
-                          lava ? "lava" : "moat");
+                          lava ? hliquid("lava") : "moat");
 #else
                 pline("\92µ\82Ë\8b´\82Í%s\82É\82­\82¸\82ê\97\8e\82¿\82½\81I",
-                          lava ? "\97n\8aâ" : "\96x");
+                          lava ? hliquid("\97n\8aâ") : "\96x");
 #endif
             else if (!Deaf)
 /*JP
@@ -1081,7 +1082,9 @@ int x, y;
             Strcpy(killer.name, "exploding drawbridge");
 */
             Strcpy(killer.name, "\92µ\82Ë\8b´\82Ì\94\9a\94­\82Å");
-            e_died(etmp2, e_inview ? 3 : 2, CRUSHING); /*no corpse*/
+            e_died(etmp2,
+                   XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
+                   CRUSHING); /*no corpse*/
         } /* nothing which is vulnerable can survive this */
     }
     set_entity(x, y, etmp1);
@@ -1123,11 +1126,14 @@ int x, y;
             Strcpy(killer.name, "collapsing drawbridge");
 */
             Strcpy(killer.name, "\83o\83\89\83o\83\89\82É\82È\82Á\82½\92µ\82Ë\8b´\82Å");
-            e_died(etmp1, e_inview ? 3 : 2, CRUSHING); /*no corpse*/
+            e_died(etmp1,
+                   XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
+                   CRUSHING); /*no corpse*/
             if (levl[etmp1->ex][etmp1->ey].typ == MOAT)
                 do_entity(etmp1);
         }
     }
+    nokiller();
 }
 
 /*dbridge.c*/
index 84d9437..314a2ae 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 decl.c  $NHDT-Date: 1446975463 2015/11/08 09:37:43 $  $NHDT-Branch: master $:$NHDT-Revision: 1.62 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2009. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
@@ -194,8 +195,9 @@ NEARDATA struct obj *migrating_objs = (struct obj *) 0;
 /* objects not yet paid for */
 NEARDATA struct obj *billobjs = (struct obj *) 0;
 
-/* used to zero all elements of a struct obj */
+/* used to zero all elements of a struct obj and a struct monst */
 NEARDATA struct obj zeroobj = DUMMY;
+NEARDATA struct monst zeromonst = DUMMY;
 /* used to zero out union any; initializer deliberately omitted */
 NEARDATA anything zeroany;
 
@@ -311,9 +313,7 @@ NEARDATA char **viz_array = 0; /* used in cansee() and couldsee() macros */
 
 /* Global windowing data, defined here for multi-window-system support */
 NEARDATA winid WIN_MESSAGE = WIN_ERR;
-#ifndef STATUS_VIA_WINDOWPORT
 NEARDATA winid WIN_STATUS = WIN_ERR;
-#endif
 NEARDATA winid WIN_MAP = WIN_ERR, WIN_INVEN = WIN_ERR;
 char toplines[TBUFSZ];
 /* Windowing stuff that's really tty oriented, but present for all ports */
@@ -380,7 +380,7 @@ NEARDATA struct savefile_info sfrestinfo, sfsaveinfo = {
 struct plinemsg_type *plinemsg_types = (struct plinemsg_type *) 0;
 
 #ifdef PANICTRACE
-char *ARGV0;
+const char *ARGV0;
 #endif
 
 /* support for lint.h */
index 73e4ef6..97365de 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 detect.c        $NHDT-Date: 1446369464 2015/11/01 09:17:44 $  $NHDT-Branch: master $:$NHDT-Revision: 1.61 $ */
+/* NetHack 3.6 detect.c        $NHDT-Date: 1522891623 2018/04/05 01:27:03 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.81 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
 
 extern boolean known; /* from read.c */
 
+STATIC_DCL boolean NDECL(unconstrain_map);
+STATIC_DCL void NDECL(reconstrain_map);
+STATIC_DCL void FDECL(browse_map, (int, const char *));
+STATIC_DCL void FDECL(map_monst, (struct monst *, BOOLEAN_P));
 STATIC_DCL void FDECL(do_dknown_of, (struct obj *));
 STATIC_DCL boolean FDECL(check_map_spot, (int, int, CHAR_P, unsigned));
 STATIC_DCL boolean FDECL(clear_stale_map, (CHAR_P, unsigned));
@@ -25,9 +30,136 @@ STATIC_DCL int FDECL(detect_obj_traps, (struct obj *, BOOLEAN_P, int));
 STATIC_DCL void FDECL(show_map_spot, (int, int));
 STATIC_PTR void FDECL(findone, (int, int, genericptr_t));
 STATIC_PTR void FDECL(openone, (int, int, genericptr_t));
+STATIC_DCL int FDECL(mfind0, (struct monst *, BOOLEAN_P));
+STATIC_DCL int FDECL(reveal_terrain_getglyph, (int, int, int,
+                                               unsigned, int, int));
 
-/* Recursively search obj for an object in class oclass and return 1st found
- */
+/* bring hero out from underwater or underground or being engulfed;
+   return True iff any change occurred */
+STATIC_OVL boolean
+unconstrain_map()
+{
+    boolean res = u.uinwater || u.uburied || u.uswallow;
+
+    /* bring Underwater, buried, or swallowed hero to normal map */
+    iflags.save_uinwater = u.uinwater, u.uinwater = 0;
+    iflags.save_uburied  = u.uburied,  u.uburied  = 0;
+    iflags.save_uswallow = u.uswallow, u.uswallow = 0;
+
+    return res;
+}
+
+/* put hero back underwater or underground or engulfed */
+STATIC_OVL void
+reconstrain_map()
+{
+    u.uinwater = iflags.save_uinwater, iflags.save_uinwater = 0;
+    u.uburied  = iflags.save_uburied,  iflags.save_uburied  = 0;
+    u.uswallow = iflags.save_uswallow, iflags.save_uswallow = 0;
+}
+
+/* use getpos()'s 'autodescribe' to view whatever is currently shown on map */
+STATIC_DCL void
+browse_map(ter_typ, ter_explain)
+int ter_typ;
+const char *ter_explain;
+{
+    coord dummy_pos; /* don't care whether player actually picks a spot */
+    boolean save_autodescribe;
+
+    dummy_pos.x = u.ux, dummy_pos.y = u.uy; /* starting spot for getpos() */
+    save_autodescribe = iflags.autodescribe;
+    iflags.autodescribe = TRUE;
+    iflags.terrainmode = ter_typ;
+    getpos(&dummy_pos, FALSE, ter_explain);
+    iflags.terrainmode = 0;
+    iflags.autodescribe = save_autodescribe;
+}
+
+/* extracted from monster_detection() so can be shared by do_vicinity_map() */
+STATIC_DCL void
+map_monst(mtmp, showtail)
+struct monst *mtmp;
+boolean showtail;
+{
+    if (def_monsyms[(int) mtmp->data->mlet].sym == ' ')
+        show_glyph(mtmp->mx, mtmp->my, detected_mon_to_glyph(mtmp));
+    else
+        show_glyph(mtmp->mx, mtmp->my,
+                   mtmp->mtame ? pet_to_glyph(mtmp) : mon_to_glyph(mtmp));
+
+    if (showtail && mtmp->data == &mons[PM_LONG_WORM])
+        detect_wsegs(mtmp, 0);
+}
+
+/* this is checking whether a trap symbol represents a trapped chest,
+   not whether a trapped chest is actually present */
+boolean
+trapped_chest_at(ttyp, x, y)
+int ttyp;
+int x, y;
+{
+    struct monst *mtmp;
+    struct obj *otmp;
+
+    if (!glyph_is_trap(glyph_at(x, y)))
+        return FALSE;
+    if (ttyp != BEAR_TRAP || (Hallucination && rn2(20)))
+        return FALSE;
+
+    /*
+     * TODO?  We should check containers recursively like the trap
+     * detecting routine does.  Chests and large boxes do not nest in
+     * themselves or each other, but could be contained inside statues.
+     *
+     * For farlook, we should also check for buried containers, but
+     * for '^' command to examine adjacent trap glyph, we shouldn't.
+     */
+
+    /* on map, presence of any trappable container will do */
+    if (sobj_at(CHEST, x, y) || sobj_at(LARGE_BOX, x, y))
+        return TRUE;
+    /* in inventory, we need to find one which is actually trapped */
+    if (x == u.ux && y == u.uy) {
+        for (otmp = invent; otmp; otmp = otmp->nobj)
+            if (Is_box(otmp) && otmp->otrapped)
+                return TRUE;
+        if (u.usteed) { /* steed isn't on map so won't be found by m_at() */
+            for (otmp = u.usteed->minvent; otmp; otmp = otmp->nobj)
+                if (Is_box(otmp) && otmp->otrapped)
+                    return TRUE;
+        }
+    }
+    if ((mtmp = m_at(x, y)) != 0)
+        for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
+            if (Is_box(otmp) && otmp->otrapped)
+                return TRUE;
+    return FALSE;
+}
+
+/* this is checking whether a trap symbol represents a trapped door,
+   not whether the door here is actually trapped */
+boolean
+trapped_door_at(ttyp, x, y)
+int ttyp;
+int x, y;
+{
+    struct rm *lev;
+
+    if (!glyph_is_trap(glyph_at(x, y)))
+        return FALSE;
+    if (ttyp != BEAR_TRAP || (Hallucination && rn2(20)))
+        return FALSE;
+    lev = &levl[x][y];
+    if (!IS_DOOR(lev->typ))
+        return FALSE;
+    if ((lev->doormask & (D_NODOOR | D_BROKEN | D_ISOPEN)) != 0
+         && trapped_chest_at(ttyp, x, y))
+        return FALSE;
+    return TRUE;
+}
+
+/* recursively search obj for an object in class oclass, return 1st found */
 struct obj *
 o_in(obj, oclass)
 struct obj *obj;
@@ -43,7 +175,7 @@ char oclass;
         for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
             if (otmp->oclass == oclass)
                 return otmp;
-            else if (Has_contents(otmp) && (temp = o_in(otmp, oclass)))
+            else if (Has_contents(otmp) && (temp = o_in(otmp, oclass)) != 0)
                 return temp;
     }
     return (struct obj *) 0;
@@ -68,7 +200,7 @@ unsigned material;
             if (objects[otmp->otyp].oc_material == material)
                 return otmp;
             else if (Has_contents(otmp)
-                     && (temp = o_material(otmp, material)))
+                     && (temp = o_material(otmp, material)) != 0)
                 return temp;
     }
     return (struct obj *) 0;
@@ -170,28 +302,36 @@ register struct obj *sobj;
 {
     register struct obj *obj;
     register struct monst *mtmp;
-    struct obj *temp;
-    boolean stale;
+    struct obj gold, *temp = 0;
+    boolean stale, ugold = FALSE, steedgold = FALSE;
+    int ter_typ = TER_DETECT | TER_OBJ;
 
-    known = stale =
-        clear_stale_map(COIN_CLASS, (unsigned) (sobj->blessed ? GOLD : 0));
+    known = stale = clear_stale_map(COIN_CLASS,
+                                    (unsigned) (sobj->blessed ? GOLD : 0));
 
     /* look for gold carried by monsters (might be in a container) */
     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
         if (DEADMONSTER(mtmp))
             continue; /* probably not needed in this case but... */
         if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
-            known = TRUE;
-            goto outgoldmap; /* skip further searching */
-        } else
+            if (mtmp == u.usteed) {
+                steedgold = TRUE;
+            } else {
+                known = TRUE;
+                goto outgoldmap; /* skip further searching */
+            }
+        } else {
             for (obj = mtmp->minvent; obj; obj = obj->nobj)
-                if (sobj->blessed && o_material(obj, GOLD)) {
-                    known = TRUE;
-                    goto outgoldmap;
-                } else if (o_in(obj, COIN_CLASS)) {
-                    known = TRUE;
-                    goto outgoldmap; /* skip further searching */
+                if ((sobj->blessed && o_material(obj, GOLD))
+                    || o_in(obj, COIN_CLASS)) {
+                    if (mtmp == u.usteed) {
+                        steedgold = TRUE;
+                    } else {
+                        known = TRUE;
+                        goto outgoldmap; /* skip further searching */
+                    }
                 }
+        }
     }
 
     /* look for gold objects */
@@ -212,22 +352,31 @@ register struct obj *sobj;
            adjust message if you have gold in your inventory */
         if (sobj) {
             char buf[BUFSZ];
-            if (youmonst.data == &mons[PM_GOLD_GOLEM]) {
+
+            if (youmonst.data == &mons[PM_GOLD_GOLEM])
 /*JP
                 Sprintf(buf, "You feel like a million %s!", currency(2L));
 */
                 Strcpy(buf, "\82 \82È\82½\82Í\8bà\8e\9d\82¿\82É\82È\82Á\82½\82æ\82¤\82É\8a´\82\82½\81I");
-            } else if (hidden_gold() || money_cnt(invent))
+            else if (money_cnt(invent) || hidden_gold())
                 Strcpy(buf,
 /*JP
                    "You feel worried about your future financial situation.");
 */
                    "\82 \82È\82½\82Í\8f«\97\88\82Ì\8co\8dÏ\8fó\8bµ\82ª\90S\94z\82É\82È\82Á\82½\81D");
+            else if (steedgold)
+                Sprintf(buf, "You feel interested in %s financial situation.",
+                        s_suffix(x_monnam(u.usteed,
+                                          u.usteed->mtame ? ARTICLE_YOUR
+                                                          : ARTICLE_THE,
+                                          (char *) 0,
+                                          SUPPRESS_SADDLE, FALSE)));
             else
 /*JP
                 Strcpy(buf, "You feel materially poor.");
 */
                 Strcpy(buf, "\82 \82È\82½\82Í\82Ð\82à\82\82³\82ð\8a´\82\82½\81D");
+
             strange_feeling(sobj, buf);
         }
         return 1;
@@ -244,56 +393,67 @@ register struct obj *sobj;
 outgoldmap:
     cls();
 
-    iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
-    u.uinwater = u.uburied = 0;
+    (void) unconstrain_map();
     /* Discover gold locations. */
     for (obj = fobj; obj; obj = obj->nobj) {
-        if (sobj->blessed && (temp = o_material(obj, GOLD))) {
+        if (sobj->blessed && (temp = o_material(obj, GOLD)) != 0) {
             if (temp != obj) {
                 temp->ox = obj->ox;
                 temp->oy = obj->oy;
             }
             map_object(temp, 1);
-        } else if ((temp = o_in(obj, COIN_CLASS))) {
+        } else if ((temp = o_in(obj, COIN_CLASS)) != 0) {
             if (temp != obj) {
                 temp->ox = obj->ox;
                 temp->oy = obj->oy;
             }
             map_object(temp, 1);
         }
+        if (temp && temp->ox == u.ux && temp->oy == u.uy)
+            ugold = TRUE;
     }
     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
         if (DEADMONSTER(mtmp))
             continue; /* probably overkill here */
+        temp = 0;
         if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
-            struct obj gold;
             gold = zeroobj; /* ensure oextra is cleared too */
             gold.otyp = GOLD_PIECE;
+            gold.quan = (long) rnd(10); /* usually more than 1 */
             gold.ox = mtmp->mx;
             gold.oy = mtmp->my;
             map_object(&gold, 1);
-        } else
+            temp = &gold;
+        } else {
             for (obj = mtmp->minvent; obj; obj = obj->nobj)
-                if (sobj->blessed && (temp = o_material(obj, GOLD))) {
+                if (sobj->blessed && (temp = o_material(obj, GOLD)) != 0) {
                     temp->ox = mtmp->mx;
                     temp->oy = mtmp->my;
                     map_object(temp, 1);
                     break;
-                } else if ((temp = o_in(obj, COIN_CLASS))) {
+                } else if ((temp = o_in(obj, COIN_CLASS)) != 0) {
                     temp->ox = mtmp->mx;
                     temp->oy = mtmp->my;
                     map_object(temp, 1);
                     break;
                 }
+        }
+        if (temp && temp->ox == u.ux && temp->oy == u.uy)
+            ugold = TRUE;
+    }
+    if (!ugold) {
+        newsym(u.ux, u.uy);
+        ter_typ |= TER_MON; /* so autodescribe will recognize hero */
     }
-    newsym(u.ux, u.uy);
-    u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
 /*JP
     You_feel("very greedy, and sense gold!");
 */
     You("\82Ç\82ñ\97~\82É\82È\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81C\82»\82µ\82Ä\8bà\89Ý\82Ì\88Ê\92u\82ð\8a´\92m\82µ\82½\81I");
     exercise(A_WIS, TRUE);
-    display_nhwindow(WIN_MAP, TRUE);
+
+    browse_map(ter_typ, "gold");
+
+    reconstrain_map();
     docrt();
     if (Underwater)
         under_water(2);
@@ -319,6 +479,8 @@ register struct obj *sobj;
     const char *what = confused ? "\83n\83\89\83w\83\8a" : "\90H\82×\95¨";
 
     stale = clear_stale_map(oclass, 0);
+    if (u.usteed) /* some situations leave steed with stale coordinates */
+        u.usteed->mx = u.ux, u.usteed->my = u.uy;
 
     for (obj = fobj; obj; obj = obj->nobj)
         if (o_in(obj, oclass)) {
@@ -327,12 +489,14 @@ register struct obj *sobj;
             else
                 ct++;
         }
-    for (mtmp = fmon; mtmp && !ct; mtmp = mtmp->nmon) {
-        /* no DEADMONSTER(mtmp) check needed since dmons never have inventory
-         */
+    for (mtmp = fmon; mtmp && (!ct || !ctu); mtmp = mtmp->nmon) {
+        /* no DEADMONSTER(mtmp) check needed -- dmons never have inventory */
         for (obj = mtmp->minvent; obj; obj = obj->nobj)
             if (o_in(obj, oclass)) {
-                ct++;
+                if (mtmp->mx == u.ux && mtmp->my == u.uy)
+                    ctu++; /* steed or an engulfer with inventory */
+                else
+                    ct++;
                 break;
             }
     }
@@ -355,7 +519,8 @@ register struct obj *sobj;
             }
         } else if (sobj) {
             char buf[BUFSZ];
-#if 0 /*JP*/
+
+#if 0 /*JP:T*/
             Sprintf(buf, "Your %s twitches%s.", body_part(NOSE),
                     (sobj->blessed && !u.uedibility)
                         ? " then starts to tingle"
@@ -393,10 +558,11 @@ register struct obj *sobj;
         }
     } else {
         struct obj *temp;
+        int ter_typ = TER_DETECT | TER_OBJ;
+
         known = TRUE;
         cls();
-        iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
-        u.uinwater = u.uburied = 0;
+        (void) unconstrain_map();
         for (obj = fobj; obj; obj = obj->nobj)
             if ((temp = o_in(obj, oclass)) != 0) {
                 if (temp != obj) {
@@ -406,8 +572,7 @@ register struct obj *sobj;
                 map_object(temp, 1);
             }
         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
-            /* no DEADMONSTER(mtmp) check needed since dmons never have
-             * inventory */
+            /* no DEADMONSTER() check needed -- dmons never have inventory */
             for (obj = mtmp->minvent; obj; obj = obj->nobj)
                 if ((temp = o_in(obj, oclass)) != 0) {
                     temp->ox = mtmp->mx;
@@ -415,8 +580,10 @@ register struct obj *sobj;
                     map_object(temp, 1);
                     break; /* skip rest of this monster's inventory */
                 }
-        newsym(u.ux, u.uy);
-        u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
+        if (!ctu) {
+            newsym(u.ux, u.uy);
+            ter_typ |= TER_MON; /* for autodescribe of self */
+        }
         if (sobj) {
             if (sobj->blessed) {
 #if 0 /*JP*/
@@ -437,8 +604,11 @@ register struct obj *sobj;
             You("sense %s.", what);
 */
             You("%s\82ð\8a´\92m\82µ\82½\81D", what);
-        display_nhwindow(WIN_MAP, TRUE);
         exercise(A_WIS, TRUE);
+
+        browse_map(ter_typ, "food");
+
+        reconstrain_map();
         docrt();
         if (Underwater)
             under_water(2);
@@ -468,7 +638,7 @@ int class;            /* an object class, 0 for all */
     int ct = 0, ctu = 0;
     register struct obj *obj, *otmp = (struct obj *) 0;
     register struct monst *mtmp;
-    int sym, boulder = 0;
+    int sym, boulder = 0, ter_typ = TER_DETECT | TER_OBJ;
 
     if (class < 0 || class >= MAXOCLASSES) {
         impossible("object_detect:  illegal class %d", class);
@@ -524,6 +694,9 @@ int class;            /* an object class, 0 for all */
             do_dknown_of(obj);
     }
 
+    if (u.usteed)
+        u.usteed->mx = u.ux, u.usteed->my = u.uy;
+
     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
         if (DEADMONSTER(mtmp))
             continue;
@@ -561,13 +734,12 @@ int class;            /* an object class, 0 for all */
 
     cls();
 
-    iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
-    u.uinwater = u.uburied = 0;
+    (void) unconstrain_map();
     /*
      *  Map all buried objects first.
      */
     for (obj = level.buriedobjlist; obj; obj = obj->nobj)
-        if (!class || (otmp = o_in(obj, class))) {
+        if (!class || (otmp = o_in(obj, class)) != 0) {
             if (class) {
                 if (otmp != obj) {
                     otmp->ox = obj->ox;
@@ -588,8 +760,8 @@ int class;            /* an object class, 0 for all */
     for (x = 1; x < COLNO; x++)
         for (y = 0; y < ROWNO; y++)
             for (obj = level.objects[x][y]; obj; obj = obj->nexthere)
-                if ((!class && !boulder) || (otmp = o_in(obj, class))
-                    || (otmp = o_in(obj, boulder))) {
+                if ((!class && !boulder) || (otmp = o_in(obj, class)) != 0
+                    || (otmp = o_in(obj, boulder)) != 0) {
                     if (class || boulder) {
                         if (otmp != obj) {
                             otmp->ox = obj->ox;
@@ -606,8 +778,8 @@ int class;            /* an object class, 0 for all */
         if (DEADMONSTER(mtmp))
             continue;
         for (obj = mtmp->minvent; obj; obj = obj->nobj)
-            if ((!class && !boulder) || (otmp = o_in(obj, class))
-                || (otmp = o_in(obj, boulder))) {
+            if ((!class && !boulder) || (otmp = o_in(obj, class)) != 0
+                || (otmp = o_in(obj, boulder)) != 0) {
                 if (!class && !boulder)
                     otmp = obj;
                 otmp->ox = mtmp->mx; /* at monster location */
@@ -620,8 +792,9 @@ int class;            /* an object class, 0 for all */
             && (!class || class == objects[mtmp->mappearance].oc_class)) {
             struct obj temp;
 
-            temp.oextra = (struct oextra *) 0;
+            temp = zeroobj;
             temp.otyp = mtmp->mappearance; /* needed for obj_to_glyph() */
+            temp.quan = 1L;
             temp.ox = mtmp->mx;
             temp.oy = mtmp->my;
             temp.corpsenm = PM_TENGU; /* if mimicing a corpse */
@@ -629,27 +802,31 @@ int class;            /* an object class, 0 for all */
         } else if (findgold(mtmp->minvent)
                    && (!class || class == COIN_CLASS)) {
             struct obj gold;
+
             gold = zeroobj; /* ensure oextra is cleared too */
             gold.otyp = GOLD_PIECE;
+            gold.quan = (long) rnd(10); /* usually more than 1 */
             gold.ox = mtmp->mx;
             gold.oy = mtmp->my;
             map_object(&gold, 1);
         }
     }
-
-    newsym(u.ux, u.uy);
-    u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
+    if (!glyph_is_object(glyph_at(u.ux, u.uy))) {
+        newsym(u.ux, u.uy);
+        ter_typ |= TER_MON;
+    }
 /*JP
     You("detect the %s of %s.", ct ? "presence" : "absence", stuff);
 */
     You("%s%s\81D", stuff, ct ? "\82ð\94­\8c©\82µ\82½" : "\82Í\89½\82à\82È\82¢\82±\82Æ\82ª\82í\82©\82Á\82½" );
-    display_nhwindow(WIN_MAP, TRUE);
-    /*
-     * What are we going to do when the hero does an object detect while blind
-     * and the detected object covers a known pool?
-     */
-    docrt(); /* this will correctly reset vision */
 
+    if (!ct)
+        display_nhwindow(WIN_MAP, TRUE);
+    else
+        browse_map(ter_typ, "object");
+
+    reconstrain_map();
+    docrt(); /* this will correctly reset vision */
     if (Underwater)
         under_water(2);
     if (u.uburied)
@@ -695,26 +872,19 @@ int mclass;                /* monster class, 0 for all */
                                       : "\82 \82È\82½\82Í\8b°\95|\82Å\82¼\82­\82Á\82Æ\82µ\82½\81D");
         return 1;
     } else {
-        boolean woken = FALSE;
+        boolean unconstrained, woken = FALSE;
+        unsigned swallowed = u.uswallow; /* before unconstrain_map() */
 
         cls();
+        unconstrained = unconstrain_map();
         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
             if (DEADMONSTER(mtmp))
                 continue;
             if (!mclass || mtmp->data->mlet == mclass
                 || (mtmp->data == &mons[PM_LONG_WORM]
                     && mclass == S_WORM_TAIL))
-                if (mtmp->mx > 0) {
-                    if (mclass && def_monsyms[mclass].sym == ' ')
-                        show_glyph(mtmp->mx, mtmp->my,
-                                   detected_mon_to_glyph(mtmp));
-                    else
-                        show_glyph(mtmp->mx, mtmp->my,
-                                   mtmp->mtame ? pet_to_glyph(mtmp) : mon_to_glyph(mtmp));
-                    /* don't be stingy - display entire worm */
-                    if (mtmp->data == &mons[PM_LONG_WORM])
-                        detect_wsegs(mtmp, 0);
-                }
+                map_monst(mtmp, TRUE);
+
             if (otmp && otmp->cursed
                 && (mtmp->msleeping || !mtmp->mcanmove)) {
                 mtmp->msleeping = mtmp->mfrozen = 0;
@@ -722,7 +892,8 @@ int mclass;                /* monster class, 0 for all */
                 woken = TRUE;
             }
         }
-        display_self();
+        if (!swallowed)
+            display_self();
 /*JP
         You("sense the presence of monsters.");
 */
@@ -732,8 +903,20 @@ int mclass;                /* monster class, 0 for all */
             pline("Monsters sense the presence of you.");
 */
             pline("\89ö\95¨\82Í\82 \82È\82½\82Ì\91\8dÝ\82ð\9ak\82¬\82Â\82¯\82½\81D");
-        display_nhwindow(WIN_MAP, TRUE);
-        docrt();
+
+        if ((otmp && otmp->blessed) && !unconstrained) {
+            /* persistent detection--just show updated map */
+            display_nhwindow(WIN_MAP, TRUE);
+        } else {
+            /* one-shot detection--allow player to move cursor around and
+               get autodescribe feedback */
+            EDetect_monsters |= I_SPECIAL;
+            browse_map(TER_DETECT | TER_MON, "monster of interest");
+            EDetect_monsters &= ~I_SPECIAL;
+        }
+
+        reconstrain_map();
+        docrt(); /* redraw the screen to remove unseen monsters from map */
         if (Underwater)
             under_water(2);
         if (u.uburied)
@@ -751,7 +934,7 @@ int src_cursed;
     if (Hallucination || src_cursed) {
         struct obj obj; /* fake object */
 
-        obj.oextra = (struct oextra *) 0;
+        obj = zeroobj;
         if (trap) {
             obj.ox = trap->tx;
             obj.oy = trap->ty;
@@ -759,14 +942,18 @@ int src_cursed;
             obj.ox = x;
             obj.oy = y;
         }
-        obj.otyp = (src_cursed) ? GOLD_PIECE : random_object();
+        obj.otyp = !Hallucination ? GOLD_PIECE : random_object();
+        obj.quan = (long) ((obj.otyp == GOLD_PIECE) ? rnd(10)
+                           : objects[obj.otyp].oc_merge ? rnd(2) : 1);
         obj.corpsenm = random_monster(); /* if otyp == CORPSE */
         map_object(&obj, 1);
     } else if (trap) {
         map_trap(trap, 1);
         trap->tseen = 1;
-    } else {
+    } else { /* trapped door or trapped chest */
         struct trap temp_trap; /* fake trap */
+
+        (void) memset((genericptr_t) &temp_trap, 0, sizeof temp_trap);
         temp_trap.tx = x;
         temp_trap.ty = y;
         temp_trap.ttyp = BEAR_TRAP; /* some kind of trap */
@@ -791,6 +978,11 @@ int how; /* 1 for misleading map feedback */
     xchar x, y;
     int result = OTRAP_NONE;
 
+    /*
+     * TODO?  Display locations of unarmed land mine and beartrap objects.
+     * If so, should they be displayed as objects or as traps?
+     */
+
     for (otmp = objlist; otmp; otmp = otmp->nobj) {
         if (Is_box(otmp) && otmp->otrapped
             && get_obj_location(otmp, &x, &y, BURIED_TOO | CONTAINED_TOO)) {
@@ -811,16 +1003,18 @@ int how; /* 1 for misleading map feedback */
  */
 int
 trap_detect(sobj)
-register struct obj *sobj;
-/* sobj is null if crystal ball, *scroll if gold detection scroll */
+struct obj *sobj; /* null if crystal ball, *scroll if gold detection scroll */
 {
     register struct trap *ttmp;
     struct monst *mon;
-    int door, glyph, tr;
+    int door, glyph, tr, ter_typ = TER_DETECT | TER_TRP;
     int cursed_src = sobj && sobj->cursed;
     boolean found = FALSE;
     coord cc;
 
+    if (u.usteed)
+        u.usteed->mx = u.ux, u.usteed->my = u.uy;
+
     /* floor/ceiling traps */
     for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
         if (ttmp->tx != u.ux || ttmp->ty != u.uy)
@@ -835,8 +1029,7 @@ register struct obj *sobj;
         else
             found = TRUE;
     }
-    if ((tr = detect_obj_traps(level.buriedobjlist, FALSE, 0))
-        != OTRAP_NONE) {
+    if ((tr = detect_obj_traps(level.buriedobjlist, FALSE, 0)) != OTRAP_NONE) {
         if (tr & OTRAP_THERE)
             goto outtrapmap;
         else
@@ -880,12 +1073,11 @@ register struct obj *sobj;
 */
     Your("%s\82Í\82Þ\82¸\82Þ\82¸\82µ\82½\81D", makeplural(body_part(TOE)));
     return 0;
+
 outtrapmap:
     cls();
 
-    iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
-    u.uinwater = u.uburied = 0;
-
+    (void) unconstrain_map();
     /* show chest traps first, so that subsequent floor trap display
        will override if both types are present at the same location */
     (void) detect_obj_traps(fobj, TRUE, cursed_src);
@@ -908,17 +1100,19 @@ outtrapmap:
 
     /* redisplay hero unless sense_trap() revealed something at <ux,uy> */
     glyph = glyph_at(u.ux, u.uy);
-    if (!(glyph_is_trap(glyph) || glyph_is_object(glyph)))
+    if (!(glyph_is_trap(glyph) || glyph_is_object(glyph))) {
         newsym(u.ux, u.uy);
-    u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
-
+        ter_typ |= TER_MON; /* for autodescribe at <u.ux,u.uy> */
+    }
 /*JP
     You_feel("%s.", cursed_src ? "very greedy" : "entrapped");
 */
     You("%s\8bC\8e\9d\82É\82È\82Á\82½\81D", cursed_src ? "\82Æ\82Ä\82à\82Ç\82ñ\97~\82È" : "\82¾\82Ü\82³\82ê\82Ä\82¢\82é\82æ\82¤\82È");
-    /* wait for user to respond, then reset map display to normal */
-    display_nhwindow(WIN_MAP, TRUE);
-    docrt();
+
+    browse_map(ter_typ, "trap of interest");
+
+    reconstrain_map();
+    docrt(); /* redraw the screen to remove unseen traps from the map */
     if (Underwater)
         under_water(2);
     if (u.uburied)
@@ -1194,13 +1388,13 @@ struct obj **optr;
 */
     multi_reason = "\90\85\8f»\8b\85\82ð\94`\82«\8d\9e\82ñ\82Å\82¢\82é\8e\9e\82É";
     nomovemsg = "";
-    if (obj->spe <= 0)
+    if (obj->spe <= 0) {
 /*JP
         pline_The("vision is unclear.");
 */
         pline("\89f\91\9c\82Í\95s\91N\96¾\82¾\82Á\82½\81D");
-    else {
-        int class;
+    else {
+        int class, i;
         int ret = 0;
 
         makeknown(CRYSTAL_BALL);
@@ -1223,16 +1417,15 @@ struct obj **optr;
             case '^':
                 ret = trap_detect((struct obj *) 0);
                 break;
-            default: {
-                int i = rn2(SIZE(level_detects));
-#if 0 /*JP*/
+            default:
+                i = rn2(SIZE(level_detects));
+#if 0 /*JP:T*/
                 You_see("%s, %s.", level_detects[i].what,
                         level_distance(level_detects[i].where));
 #else
                 You_see("%s\82ð%s\8c©\82½\81D", level_detects[i].what,
                         level_distance(level_detects[i].where));
 #endif
-            }
                 ret = 0;
                 break;
             }
@@ -1302,39 +1495,71 @@ void
 do_mapping()
 {
     register int zx, zy;
+    boolean unconstrained;
 
-    iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
-    u.uinwater = u.uburied = 0;
+    unconstrained = unconstrain_map();
     for (zx = 1; zx < COLNO; zx++)
         for (zy = 0; zy < ROWNO; zy++)
             show_map_spot(zx, zy);
-    u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
-    if (!level.flags.hero_memory || Underwater) {
+
+    if (!level.flags.hero_memory || unconstrained) {
         flush_screen(1);                 /* flush temp screen */
-        display_nhwindow(WIN_MAP, TRUE); /* wait */
+        /* browse_map() instead of display_nhwindow(WIN_MAP, TRUE) */
+        browse_map(TER_DETECT | TER_MAP | TER_TRP | TER_OBJ,
+                   "anything of interest");
         docrt();
     }
+    reconstrain_map();
     exercise(A_WIS, TRUE);
 }
 
+/* clairvoyance */
 void
-do_vicinity_map()
+do_vicinity_map(sobj)
+struct obj *sobj; /* scroll--actually fake spellbook--object */
 {
     register int zx, zy;
-    int lo_y = (u.uy - 5 < 0 ? 0 : u.uy - 5),
-        hi_y = (u.uy + 6 > ROWNO ? ROWNO : u.uy + 6),
-        lo_x = (u.ux - 9 < 1 ? 1 : u.ux - 9), /* avoid column 0 */
-        hi_x = (u.ux + 10 > COLNO ? COLNO : u.ux + 10);
-
-    for (zx = lo_x; zx < hi_x; zx++)
-        for (zy = lo_y; zy < hi_y; zy++)
+    struct monst *mtmp;
+    boolean unconstrained, refresh = FALSE, mdetected = FALSE,
+            extended = (sobj && sobj->blessed);
+    int lo_y = ((u.uy - 5 < 0) ? 0 : u.uy - 5),
+        hi_y = ((u.uy + 6 >= ROWNO) ? ROWNO - 1 : u.uy + 6),
+        lo_x = ((u.ux - 9 < 1) ? 1 : u.ux - 9), /* avoid column 0 */
+        hi_x = ((u.ux + 10 >= COLNO) ? COLNO - 1 : u.ux + 10),
+        ter_typ = TER_DETECT | TER_MAP | TER_TRP | TER_OBJ;
+
+    unconstrained = unconstrain_map();
+    for (zx = lo_x; zx <= hi_x; zx++)
+        for (zy = lo_y; zy <= hi_y; zy++) {
             show_map_spot(zx, zy);
 
-    if (!level.flags.hero_memory || Underwater) {
+            if (extended && (mtmp = m_at(zx, zy)) != 0
+                && mtmp->mx == zx && mtmp->my == zy) { /* skip worm tails */
+                int oldglyph = glyph_at(zx, zy);
+
+                map_monst(mtmp, FALSE);
+                if (glyph_at(zx, zy) != oldglyph)
+                    mdetected = TRUE;
+            }
+        }
+
+    if (!level.flags.hero_memory || unconstrained || mdetected) {
         flush_screen(1);                 /* flush temp screen */
-        display_nhwindow(WIN_MAP, TRUE); /* wait */
-        docrt();
+        /* the getpos() prompt from browse_map() is only shown when
+           flags.verbose is set, but make this unconditional so that
+           not-verbose users become aware of the prompting situation */
+        You("sense your surroundings.");
+        if (extended || glyph_is_monster(glyph_at(u.ux, u.uy)))
+            ter_typ |= TER_MON;
+        if (extended)
+            EDetect_monsters |= I_SPECIAL;
+        browse_map(ter_typ, "anything of interest");
+        EDetect_monsters &= ~I_SPECIAL;
+        refresh = TRUE;
     }
+    reconstrain_map();
+    if (refresh)
+        docrt();
 }
 
 /* convert a secret door into a normal door */
@@ -1394,9 +1619,7 @@ genericptr_t num;
         }
         if (!canspotmon(mtmp) && !glyph_is_invisible(levl[zx][zy].glyph))
             map_invisible(zx, zy);
-    } else if (glyph_is_invisible(levl[zx][zy].glyph)) {
-        unmap_object(zx, zy);
-        newsym(zx, zy);
+    } else if (unmap_invisible(zx, zy)) {
         (*(int *) num)++;
     }
 }
@@ -1549,15 +1772,70 @@ struct trap *trap;
     }
 }
 
+STATIC_OVL int
+mfind0(mtmp, via_warning)
+struct monst *mtmp;
+boolean via_warning;
+{
+    xchar x = mtmp->mx,
+          y = mtmp->my;
+
+    if (via_warning && !warning_of(mtmp))
+        return -1;
+
+    if (mtmp->m_ap_type) {
+        seemimic(mtmp);
+    find:
+        exercise(A_WIS, TRUE);
+        if (!canspotmon(mtmp)) {
+            if (glyph_is_invisible(levl[x][y].glyph)) {
+                /* Found invisible monster in a square which already has
+                 * an 'I' in it.  Logically, this should still take time
+                 * and lead to a return 1, but if we did that the player
+                 * would keep finding the same monster every turn.
+                 */
+                return -1;
+            } else {
+/*JP
+                                    You_feel("an unseen monster!");
+*/
+                                    You("\8c©\82¦\82È\82¢\89ö\95¨\82Ì\8bC\94z\82ð\8a´\82\82½\81I");
+                map_invisible(x, y);
+            }
+        } else if (!sensemon(mtmp))
+#if 0 /*JP:T*/
+                You("find %s.",
+                    mtmp->mtame ? y_monnam(mtmp) : a_monnam(mtmp));
+#else
+                You("%s\82ð\8c©\82Â\82¯\82½\81D",
+                    mtmp->mtame ? y_monnam(mtmp) : a_monnam(mtmp));
+#endif
+        return 1;
+    }
+    if (!canspotmon(mtmp)) {
+        if (mtmp->mundetected
+            && (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL))
+            if (via_warning) {
+                Your("warning senses cause you to take a second %s.",
+                     Blind ? "to check nearby" : "look close by");
+                display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
+            }
+        mtmp->mundetected = 0;
+        newsym(x, y);
+        goto find;
+    }
+    return 0;
+}
+
 int
 dosearch0(aflag)
 register int aflag; /* intrinsic autosearch vs explicit searching */
 {
 #ifdef GCC_BUG
-    /* some versions of gcc seriously muck up nested loops. if you get strange
-       crashes while searching in a version compiled with gcc, try putting
-       #define GCC_BUG in *conf.h (or adding -DGCC_BUG to CFLAGS in the
-       makefile).
+    /* Some old versions of gcc seriously muck up nested loops.  If you get
+     * strange crashes while searching in a version compiled with gcc, try
+     * putting #define GCC_BUG in *conf.h (or adding -DGCC_BUG to CFLAGS in
+     * the makefile).
      */
     volatile xchar x, y;
 #else
@@ -1607,7 +1885,7 @@ register int aflag; /* intrinsic autosearch vs explicit searching */
                     unblock_point(x, y); /* vision */
                     exercise(A_WIS, TRUE);
                     nomul(0);
-                    feel_location(x, y); /* make sure it shows up */
+                    feel_newsym(x, y); /* make sure it shows up */
 /*JP
                     You("find a hidden passage.");
 */
@@ -1615,54 +1893,19 @@ register int aflag; /* intrinsic autosearch vs explicit searching */
                 } else {
                     /* Be careful not to find anything in an SCORR or SDOOR */
                     if ((mtmp = m_at(x, y)) != 0 && !aflag) {
-                        if (mtmp->m_ap_type) {
-                            seemimic(mtmp);
-                        find:
-                            exercise(A_WIS, TRUE);
-                            if (!canspotmon(mtmp)) {
-                                if (glyph_is_invisible(levl[x][y].glyph)) {
-                                    /* found invisible monster in a square
-                                     * which already has an 'I' in it.
-                                     * Logically, this should still take
-                                     * time and lead to a return(1), but
-                                     * if we did that the player would keep
-                                     * finding the same monster every turn.
-                                     */
-                                    continue;
-                                } else {
-/*JP
-                                    You_feel("an unseen monster!");
-*/
-                                    You("\8c©\82¦\82È\82¢\89ö\95¨\82Ì\8bC\94z\82ð\8a´\82\82½\81I");
-                                    map_invisible(x, y);
-                                }
-                            } else if (!sensemon(mtmp))
-/*JP
-                                You("find %s.", mtmp->mtame
-*/
-                                You("%s\82ð\8c©\82Â\82¯\82½\81D", mtmp->mtame
-                                                   ? y_monnam(mtmp)
-                                                   : a_monnam(mtmp));
-                            return 1;
-                        }
-                        if (!canspotmon(mtmp)) {
-                            if (mtmp->mundetected
-                                && (is_hider(mtmp->data)
-                                    || mtmp->data->mlet == S_EEL))
-                                mtmp->mundetected = 0;
-                            newsym(x, y);
-                            goto find;
-                        }
+                        int mfres = mfind0(mtmp, 0);
+
+                        if (mfres == -1)
+                            continue;
+                        else if (mfres > 0)
+                            return mfres;
                     }
 
                     /* see if an invisible monster has moved--if Blind,
                      * feel_location() already did it
                      */
-                    if (!aflag && !mtmp && !Blind
-                        && glyph_is_invisible(levl[x][y].glyph)) {
-                        unmap_object(x, y);
-                        newsym(x, y);
-                    }
+                    if (!aflag && !mtmp && !Blind)
+                        (void) unmap_invisible(x, y);
 
                     if ((trap = t_at(x, y)) && !trap->tseen && !rnl(8)) {
                         nomul(0);
@@ -1687,6 +1930,22 @@ dosearch()
     return dosearch0(0);
 }
 
+void
+warnreveal()
+{
+    int x, y;
+    struct monst *mtmp;
+
+    for (x = u.ux - 1; x <= u.ux + 1; x++)
+        for (y = u.uy - 1; y <= u.uy + 1; y++) {
+            if (!isok(x, y) || (x == u.ux && y == u.uy))
+                continue;
+            if ((mtmp = m_at(x, y)) != 0
+                && warning_of(mtmp) && mtmp->mundetected)
+                (void) mfind0(mtmp, 1); /* via_warning */
+        }
+}
+
 /* Pre-map the sokoban levels */
 void
 sokoban_detect()
@@ -1715,6 +1974,141 @@ sokoban_detect()
     }
 }
 
+STATIC_DCL int
+reveal_terrain_getglyph(x, y, full, swallowed, default_glyph, which_subset)
+int x, y, full;
+unsigned swallowed;
+int default_glyph, which_subset;
+{
+    int glyph, levl_glyph;
+    uchar seenv;
+    boolean keep_traps = (which_subset & TER_TRP) !=0,
+            keep_objs = (which_subset & TER_OBJ) != 0,
+            keep_mons = (which_subset & TER_MON) != 0;
+    struct monst *mtmp;
+    struct trap *t;
+
+    /* for 'full', show the actual terrain for the entire level,
+       otherwise what the hero remembers for seen locations with
+       monsters, objects, and/or traps removed as caller dictates */
+    seenv = (full || level.flags.hero_memory)
+              ? levl[x][y].seenv : cansee(x, y) ? SVALL : 0;
+    if (full) {
+        levl[x][y].seenv = SVALL;
+        glyph = back_to_glyph(x, y);
+        levl[x][y].seenv = seenv;
+    } else {
+        levl_glyph = level.flags.hero_memory
+              ? levl[x][y].glyph
+              : seenv ? back_to_glyph(x, y): default_glyph;
+        /* glyph_at() returns the displayed glyph, which might
+           be a monster.  levl[][].glyph contains the remembered
+           glyph, which will never be a monster (unless it is
+           the invisible monster glyph, which is handled like
+           an object, replacing any object or trap at its spot) */
+        glyph = !swallowed ? glyph_at(x, y) : levl_glyph;
+        if (keep_mons && x == u.ux && y == u.uy && swallowed)
+            glyph = mon_to_glyph(u.ustuck);
+        else if (((glyph_is_monster(glyph)
+                   || glyph_is_warning(glyph)) && !keep_mons)
+                 || glyph_is_swallow(glyph))
+            glyph = levl_glyph;
+        if (((glyph_is_object(glyph) && !keep_objs)
+             || glyph_is_invisible(glyph))
+            && keep_traps && !covers_traps(x, y)) {
+            if ((t = t_at(x, y)) != 0 && t->tseen)
+                glyph = trap_to_glyph(t);
+        }
+        if ((glyph_is_object(glyph) && !keep_objs)
+            || (glyph_is_trap(glyph) && !keep_traps)
+            || glyph_is_invisible(glyph)) {
+            if (!seenv) {
+                glyph = default_glyph;
+            } else if (lastseentyp[x][y] == levl[x][y].typ) {
+                glyph = back_to_glyph(x, y);
+            } else {
+                /* look for a mimic here posing as furniture;
+                   if we don't find one, we'll have to fake it */
+                if ((mtmp = m_at(x, y)) != 0
+                    && mtmp->m_ap_type == M_AP_FURNITURE) {
+                    glyph = cmap_to_glyph(mtmp->mappearance);
+                } else {
+                    /* we have a topology type but we want a screen
+                       symbol in order to derive a glyph; some screen
+                       symbols need the flags field of levl[][] in
+                       addition to the type (to disambiguate STAIRS to
+                       S_upstair or S_dnstair, for example; current
+                       flags might not be intended for remembered type,
+                       but we've got no other choice) */
+                    schar save_typ = levl[x][y].typ;
+
+                    levl[x][y].typ = lastseentyp[x][y];
+                    glyph = back_to_glyph(x, y);
+                    levl[x][y].typ = save_typ;
+                }
+            }
+        }
+    }
+    if (glyph == cmap_to_glyph(S_darkroom))
+        glyph = cmap_to_glyph(S_room); /* FIXME: dirty hack */
+    return glyph;
+}
+
+#ifdef DUMPLOG
+void
+dump_map()
+{
+    int x, y, glyph, skippedrows, lastnonblank;
+    int subset = TER_MAP | TER_TRP | TER_OBJ | TER_MON;
+    int default_glyph = cmap_to_glyph(level.flags.arboreal ? S_tree : S_stone);
+    char buf[BUFSZ];
+    boolean blankrow, toprow;
+
+    /*
+     * Squeeze out excess vertial space when dumping the map.
+     * If there are any blank map rows at the top, suppress them
+     * (our caller has already printed a separator).  If there is
+     * more than one blank map row at the bottom, keep just one.
+     * Any blank rows within the middle of the map are kept.
+     * Note: putstr() with winid==0 is for dumplog.
+     */
+    skippedrows = 0;
+    toprow = TRUE;
+    for (y = 0; y < ROWNO; y++) {
+        blankrow = TRUE; /* assume blank until we discover otherwise */
+        lastnonblank = -1; /* buf[] index rather than map's x */
+        for (x = 1; x < COLNO; x++) {
+            int ch, color;
+            unsigned special;
+
+            glyph = reveal_terrain_getglyph(x, y, FALSE, u.uswallow,
+                                            default_glyph, subset);
+            (void) mapglyph(glyph, &ch, &color, &special, x, y);
+            buf[x - 1] = ch;
+            if (ch != ' ') {
+                blankrow = FALSE;
+                lastnonblank = x - 1;
+            }
+        }
+        if (!blankrow) {
+            buf[lastnonblank + 1] = '\0';
+            if (toprow) {
+                skippedrows = 0;
+                toprow = FALSE;
+            }
+            for (x = 0; x < skippedrows; x++)
+                putstr(0, 0, "");
+            putstr(0, 0, buf); /* map row #y */
+            skippedrows = 0;
+        } else {
+            ++skippedrows;
+        }
+    }
+    if (skippedrows)
+        putstr(0, 0, "");
+}
+#endif /* DUMPLOG */
+
 /* idea from crawl; show known portion of map without any monsters,
    objects, or traps occluding the view of the underlying terrain */
 void
@@ -1728,94 +2122,27 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */
 */
         You("\8d¬\97\90\82µ\82Ä\82¢\82é\82Ì\82Å\82»\82ê\82Í\82Å\82«\82È\82¢\81D");
     } else {
-        int x, y, glyph, levl_glyph, default_glyph;
-        uchar seenv;
-        unsigned save_swallowed;
-        struct monst *mtmp;
-        struct trap *t;
+        int x, y, glyph, default_glyph;
         char buf[BUFSZ];
-        boolean keep_traps = (which_subset & 1) !=0,
-                keep_objs = (which_subset & 2) != 0,
-                keep_mons = (which_subset & 4) != 0; /* actually always 0 */
-
-        save_swallowed = u.uswallow;
-        iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
-        u.uinwater = u.uburied = 0;
-        u.uswallow = 0;
+        /* there is a TER_MAP bit too; we always show map regardless of it */
+        boolean keep_traps = (which_subset & TER_TRP) !=0,
+                keep_objs = (which_subset & TER_OBJ) != 0,
+                keep_mons = (which_subset & TER_MON) != 0; /* not used */
+        unsigned swallowed = u.uswallow; /* before unconstrain_map() */
+
+        if (unconstrain_map())
+            docrt();
         default_glyph = cmap_to_glyph(level.flags.arboreal ? S_tree : S_stone);
-        /* for 'full', show the actual terrain for the entire level,
-           otherwise what the hero remembers for seen locations with
-           monsters, objects, and/or traps removed as caller dictates */
+
         for (x = 1; x < COLNO; x++)
             for (y = 0; y < ROWNO; y++) {
-                seenv = (full || level.flags.hero_memory)
-                           ? levl[x][y].seenv : cansee(x, y) ? SVALL : 0;
-                if (full) {
-                    levl[x][y].seenv = SVALL;
-                    glyph = back_to_glyph(x, y);
-                    levl[x][y].seenv = seenv;
-                } else {
-                    levl_glyph = level.flags.hero_memory
-                                    ? levl[x][y].glyph
-                                    : seenv
-                                       ? back_to_glyph(x, y)
-                                       : default_glyph;
-                    /* glyph_at() returns the displayed glyph, which might
-                       be a monster.  levl[][].glyph contains the remembered
-                       glyph, which will never be a monster (unless it is
-                       the invisible monster glyph, which is handled like
-                       an object, replacing any object or trap at its spot) */
-                    glyph = !save_swallowed ? glyph_at(x, y) : levl_glyph;
-                    if (keep_mons && x == u.ux && y == u.uy && save_swallowed)
-                        glyph = mon_to_glyph(u.ustuck);
-                    else if (((glyph_is_monster(glyph)
-                               || glyph_is_warning(glyph)) && !keep_mons)
-                             || glyph_is_swallow(glyph))
-                        glyph = levl_glyph;
-                    if (((glyph_is_object(glyph) && !keep_objs)
-                         || glyph_is_invisible(glyph))
-                        && keep_traps && !covers_traps(x, y)) {
-                        if ((t = t_at(x, y)) != 0 && t->tseen)
-                            glyph = trap_to_glyph(t);
-                    }
-                    if ((glyph_is_object(glyph) && !keep_objs)
-                        || (glyph_is_trap(glyph) && !keep_traps)
-                        || glyph_is_invisible(glyph)) {
-                        if (!seenv) {
-                            glyph = default_glyph;
-                        } else if (lastseentyp[x][y] == levl[x][y].typ) {
-                            glyph = back_to_glyph(x, y);
-                        } else {
-                            /* look for a mimic here posing as furniture;
-                               if we don't find one, we'll have to fake it */
-                            if ((mtmp = m_at(x, y)) != 0
-                                && mtmp->m_ap_type == M_AP_FURNITURE) {
-                                glyph = cmap_to_glyph(mtmp->mappearance);
-                            } else {
-                                /* we have a topology type but we want a
-                                   screen symbol in order to derive a glyph;
-                                   some screen symbols need the flags field
-                                   of levl[][] in addition to the type
-                                   (to disambiguate STAIRS to S_upstair or
-                                   S_dnstair, for example; current flags
-                                   might not be intended for remembered
-                                   type, but we've got no other choice) */
-                                schar save_typ = levl[x][y].typ;
-
-                                levl[x][y].typ = lastseentyp[x][y];
-                                glyph = back_to_glyph(x, y);
-                                levl[x][y].typ = save_typ;
-                            }
-                        }
-                    }
-                }
+                glyph = reveal_terrain_getglyph(x,y, full, swallowed,
+                                                default_glyph, which_subset);
                 show_glyph(x, y, glyph);
             }
 
-        /* [TODO: highlight hero's location somehow] */
-        u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
-        if (save_swallowed)
-            u.uswallow = 1;
+        /* hero's location is not highlighted, but getpos() starts with
+           cursor there, and after moving it anywhere '@' moves it back */
         flush_screen(1);
         if (full) {
 /*JP
@@ -1854,7 +2181,13 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */
         pline("Showing %s only...", buf);
 */
         pline("%s\82¾\82¯\82ð\8c©\82é\81D\81D\81D", buf);
-        display_nhwindow(WIN_MAP, TRUE); /* give "--More--" prompt */
+
+        /* allow player to move cursor around and get autodescribe feedback
+           based on what is visible now rather than what is on 'real' map */
+        which_subset |= TER_MAP; /* guarantee non-zero */
+        browse_map(which_subset, "anything of interest");
+
+        reconstrain_map();
         docrt(); /* redraw the screen, restoring regular map */
         if (Underwater)
             under_water(2);
index 074bbac..32510ab 100644 (file)
--- a/src/dig.c
+++ b/src/dig.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 dig.c   $NHDT-Date: 1449269915 2015/12/04 22:58:35 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.103 $ */
+/* NetHack 3.6 dig.c   $NHDT-Date: 1517913682 2018/02/06 10:41:22 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.108 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -21,12 +22,14 @@ STATIC_DCL int FDECL(adj_pit_checks, (coord *, char *));
 STATIC_DCL void FDECL(pit_flow, (struct trap *, SCHAR_P));
 
 /* Indices returned by dig_typ() */
-#define DIGTYP_UNDIGGABLE 0
-#define DIGTYP_ROCK 1
-#define DIGTYP_STATUE 2
-#define DIGTYP_BOULDER 3
-#define DIGTYP_DOOR 4
-#define DIGTYP_TREE 5
+enum dig_types {
+    DIGTYP_UNDIGGABLE = 0,
+    DIGTYP_ROCK,
+    DIGTYP_STATUE,
+    DIGTYP_BOULDER,
+    DIGTYP_DOOR,
+    DIGTYP_TREE
+};
 
 STATIC_OVL boolean
 rm_waslit()
@@ -241,9 +244,9 @@ int x, y;
     } else if (Is_waterlevel(&u.uz)) {
         if (verbose)
 /*JP
-            pline_The("water splashes and subsides.");
+            pline_The("%s splashes and subsides.", hliquid("water"));
 */
-            pline("\90\85\82ª\83s\83V\83\83\83b\82Æ\92µ\82Ë\82½\81D");
+            pline_The("%s\82ª\83s\83V\83\83\83b\82Æ\92µ\82Ë\82½\81D", hliquid("\90\85"));
         return FALSE;
     } else if ((IS_ROCK(levl[x][y].typ) && levl[x][y].typ != SDOOR
                 && (levl[x][y].wall_info & W_NONDIGGABLE) != 0)
@@ -497,7 +500,7 @@ dig(VOID_ARGS)
             }
         } else if (IS_WALL(lev->typ)) {
             if (shopedge) {
-                add_damage(dpx, dpy, 10L * ACURRSTR);
+                add_damage(dpx, dpy, SHOP_WALL_DMG);
 /*JP
                 dmgtxt = "damage";
 */
@@ -529,7 +532,7 @@ dig(VOID_ARGS)
 */
             digtxt = "\94à\82ð\92Ê\82è\94²\82¯\82½\81D";
             if (shopedge) {
-                add_damage(dpx, dpy, 400L);
+                add_damage(dpx, dpy, SHOP_DOOR_COST);
 /*JP
                 dmgtxt = "break";
 */
@@ -884,8 +887,8 @@ int ttyp;
                     }
                     if (mtmp->isshk)
                         make_angry_shk(mtmp, 0, 0);
-                    migrate_to_level(mtmp, ledger_no(&tolevel), MIGR_RANDOM,
-                                     (coord *) 0);
+                    migrate_to_level(mtmp, ledger_no(&tolevel),
+                                     MIGR_RANDOM, (coord *) 0);
                 }
             }
         }
@@ -912,9 +915,9 @@ const char *fillmsg;
 
     if (fillmsg)
 /*JP
-        pline(fillmsg, typ == LAVAPOOL ? "lava" : "water");
+        pline(fillmsg, hliquid(typ == LAVAPOOL ? "lava" : "water"));
 */
-        pline(fillmsg, typ == LAVAPOOL ? "\97n\8aâ" : "\90\85");
+        pline(fillmsg, hliquid(typ == LAVAPOOL ? "\97n\8aâ" : "\90\85"));
     if (u_spot && !(Levitation || Flying)) {
         if (typ == LAVAPOOL)
             (void) lava_effects();
@@ -964,10 +967,10 @@ coord *cc;
     } else if (is_pool_or_lava(dig_x, dig_y)) {
 #if 0 /*JP:T*/
         pline_The("%s sloshes furiously for a moment, then subsides.",
-                  is_lava(dig_x, dig_y) ? "lava" : "water");
+                  hliquid(is_lava(dig_x, dig_y) ? "lava" : "water"));
 #else
         pline("%s\82Í\8c\83\82µ\82­\94g\82¤\82Á\82½\81D",
-                  is_lava(dig_x, dig_y) ? "\97n\8aâ" : "\90\85");
+                  hliquid(is_lava(dig_x, dig_y) ? "\97n\8aâ" : "\90\85"));
 #endif
         wake_nearby(); /* splashing */
 
@@ -1050,7 +1053,7 @@ coord *cc;
 #endif
         return TRUE;
 
-        /* the following two are here for the wand of digging */
+    /* the following two are here for the wand of digging */
     } else if (IS_THRONE(lev->typ)) {
 /*JP
         pline_The("throne is too hard to break apart.");
@@ -1145,9 +1148,8 @@ coord *cc;
         You("unearth a corpse.");
 */
         You("\8e\80\91Ì\82ð\8c@\82è\8bN\82µ\82½\81D");
-        if (!!(otmp = mk_tt_object(CORPSE, dig_x, dig_y)))
+        if ((otmp = mk_tt_object(CORPSE, dig_x, dig_y)) != 0)
             otmp->age -= 100; /* this is an *OLD* corpse */
-        ;
         break;
     case 2:
         if (!Blind)
@@ -1362,19 +1364,20 @@ struct obj *obj;
 */
                 pline("\83K\83c\83\93\81I");
                 wake_nearby();
-            } else if (IS_TREE(lev->typ))
+            } else if (IS_TREE(lev->typ)) {
 /*JP
                 You("need an axe to cut down a tree.");
 */
                 You("\96Ø\82ð\90Ø\82é\82É\82Í\95\80\82ª\95K\97v\82¾\81D");
-            else if (IS_ROCK(lev->typ))
+            } else if (IS_ROCK(lev->typ)) {
 /*JP
                 You("need a pick to dig rock.");
 */
                 You("\8c@\82é\82É\82Í\82Â\82é\82Í\82µ\82ª\95K\97v\82¾\81D");
-            else if (!ispick && (sobj_at(STATUE, rx, ry)
-                                 || sobj_at(BOULDER, rx, ry))) {
+            else if (!ispick && (sobj_at(STATUE, rx, ry)
+                                   || sobj_at(BOULDER, rx, ry))) {
                 boolean vibrate = !rn2(3);
+
 #if 0 /*JP:T*/
                 pline("Sparks fly as you whack the %s.%s",
                       sobj_at(STATUE, rx, ry) ? "statue" : "boulder",
@@ -1395,6 +1398,7 @@ struct obj *obj;
                        && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
                        && !conjoined_pits(trap, trap_with_u, FALSE)) {
                 int idx;
+
                 for (idx = 0; idx < 8; idx++) {
                     if (xdir[idx] == u.dx && ydir[idx] == u.dy)
                         break;
@@ -1402,6 +1406,7 @@ struct obj *obj;
                 /* idx is valid if < 8 */
                 if (idx < 8) {
                     int adjidx = (idx + 4) % 8;
+
                     trap_with_u->conjoined |= (1 << idx);
                     trap->conjoined |= (1 << adjidx);
 /*JP
@@ -1417,11 +1422,12 @@ struct obj *obj;
 #else
                 You("%s\82ð\90U\82è\89ñ\82µ\82½\82ª\81C\94j\95Ð\82Ì\8ds\82«\8fê\8f\8a\82ª\82È\82¢\81D", xname(obj));
 #endif
-            } else
+            } else {
 /*JP
                 You("swing %s through thin air.", yobjnam(obj, (char *) 0));
 */
                 You("\8bó\92\86\82Å%s\82ð\90U\82è\89ñ\82µ\82½\81D", xname(obj));
+            }
         } else {
 #if 0 /*JP*/
             static const char *const d_action[6] = { "swinging", "digging",
@@ -1447,13 +1453,15 @@ struct obj *obj;
                 "\96Ø\82ð\90Ø\82é"
               };
 #endif
+
             did_dig_msg = FALSE;
             context.digging.quiet = FALSE;
             if (context.digging.pos.x != rx || context.digging.pos.y != ry
                 || !on_level(&context.digging.level, &u.uz)
                 || context.digging.down) {
                 if (flags.autodig && dig_target == DIGTYP_ROCK
-                    && !context.digging.down && context.digging.pos.x == u.ux
+                    && !context.digging.down
+                    && context.digging.pos.x == u.ux
                     && context.digging.pos.y == u.uy
                     && (moves <= context.digging.lastdigtime + 2
                         && moves >= context.digging.lastdigtime)) {
@@ -1653,8 +1661,9 @@ register struct monst *mtmp;
         newsym(mtmp->mx, mtmp->my);
         draft_message(FALSE); /* "You feel a draft." */
         return FALSE;
-    } else if (!IS_ROCK(here->typ) && !IS_TREE(here->typ)) /* no dig */
+    } else if (!IS_ROCK(here->typ) && !IS_TREE(here->typ)) /* no dig */
         return FALSE;
+    }
 
     /* Only rock, trees, and walls fall through to this point. */
     if ((here->wall_info & W_NONDIGGABLE) != 0) {
@@ -1792,7 +1801,7 @@ zap_dig()
                 You("pierce %s %s wall!", s_suffix(mon_nam(mtmp)),
                     mbodypart(mtmp, STOMACH));
 #else
-                You("%s\82Ì%s\82Ì\95Ç\82É\8c\8a\82ð\8aJ\82¯\82½\81I", s_suffix(mon_nam(mtmp)),
+                You("%s\82Ì%s\82Ì\95Ç\82É\8c\8a\82ð\8aJ\82¯\82½\81I", mon_nam(mtmp),
                     mbodypart(mtmp, STOMACH));
 #endif
             mtmp->mhp = 1; /* almost dead */
@@ -1906,7 +1915,7 @@ zap_dig()
             }
         } else if (closed_door(zx, zy) || room->typ == SDOOR) {
             if (*in_rooms(zx, zy, SHOPBASE)) {
-                add_damage(zx, zy, 400L);
+                add_damage(zx, zy, SHOP_DOOR_COST);
                 shopdoor = TRUE;
             }
             if (room->typ == SDOOR)
@@ -1926,7 +1935,7 @@ zap_dig()
             if (IS_WALL(room->typ)) {
                 if (!(room->wall_info & W_NONDIGGABLE)) {
                     if (*in_rooms(zx, zy, SHOPBASE)) {
-                        add_damage(zx, zy, 200L);
+                        add_damage(zx, zy, SHOP_WALL_COST);
                         shopwall = TRUE;
                     }
                     room->typ = ROOM;
@@ -1963,7 +1972,7 @@ zap_dig()
                 break;
             if (IS_WALL(room->typ) || room->typ == SDOOR) {
                 if (*in_rooms(zx, zy, SHOPBASE)) {
-                    add_damage(zx, zy, 200L);
+                    add_damage(zx, zy, SHOP_WALL_COST);
                     shopwall = TRUE;
                 }
                 watch_dig((struct monst *) 0, zx, zy, TRUE);
@@ -2189,36 +2198,47 @@ struct obj *
 buried_ball(cc)
 coord *cc;
 {
-    xchar check_x, check_y;
-    struct obj *otmp, *otmp2;
+    int odist, bdist = COLNO;
+    struct obj *otmp, *ball = 0;
+
+    /* FIXME:
+     *  This is just approximate; if multiple buried balls meet the
+     *  criterium (within 2 steps of tethered hero's present location)
+     *  it will find an arbitrary one rather than the one which used
+     *  to be uball.  Once 3.6.{0,1} save file compatibility is broken,
+     *  we should add context.buriedball_oid and then we can find the
+     *  actual former uball, which might be extra heavy or christened
+     *  or not the one buried directly underneath the target spot.
+     *
+     *  [Why does this search within a radius of two when trapmove()
+     *  only lets hero get one step away from the buried ball?]
+     */
 
-    if (u.utraptype == TT_BURIEDBALL)
-        for (otmp = level.buriedobjlist; otmp; otmp = otmp2) {
-            otmp2 = otmp->nobj;
+    if (u.utrap && u.utraptype == TT_BURIEDBALL)
+        for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) {
             if (otmp->otyp != HEAVY_IRON_BALL)
                 continue;
-            /* try the exact location first */
+            /* if found at the target spot, we're done */
             if (otmp->ox == cc->x && otmp->oy == cc->y)
                 return otmp;
-            /* Now try the vicinity */
-            /*
-             * (x-2,y-2)       (x+2,y-2)
-             *           (x,y)
-             * (x-2,y+2)       (x+2,y+2)
+            /* find nearest within allowable vicinity: +/-2
+             *  4 5 8
+             *  1 2 5
+             *  0 1 4
              */
-            for (check_x = cc->x - 2; check_x <= cc->x + 2; ++check_x)
-                for (check_y = cc->y - 2; check_y <= cc->y + 2; ++check_y) {
-                    if (check_x == cc->x && check_y == cc->y)
-                        continue;
-                    if (isok(check_x, check_y)
-                        && (otmp->ox == check_x && otmp->oy == check_y)) {
-                        cc->x = check_x;
-                        cc->y = check_y;
-                        return otmp;
-                    }
-                }
+            odist = dist2(otmp->ox, otmp->oy, cc->x, cc->y);
+            if (odist <= 8 && (!ball || odist < bdist)) {
+                /* remember nearest buried ball but keep checking others */
+                ball = otmp;
+                bdist = odist;
+            }
         }
-    return (struct obj *) 0;
+    if (ball) {
+        /* found, but not at < cc->x, cc->y > */
+        cc->x = ball->ox;
+        cc->y = ball->oy;
+    }
+    return ball;
 }
 
 void
@@ -2226,6 +2246,7 @@ buried_ball_to_punishment()
 {
     coord cc;
     struct obj *ball;
+
     cc.x = u.ux;
     cc.y = u.uy;
     ball = buried_ball(&cc);
@@ -2249,6 +2270,7 @@ buried_ball_to_freedom()
 {
     coord cc;
     struct obj *ball;
+
     cc.x = u.ux;
     cc.y = u.uy;
     ball = buried_ball(&cc);
@@ -2347,16 +2369,33 @@ bury_objs(x, y)
 int x, y;
 {
     struct obj *otmp, *otmp2;
+    struct monst *shkp;
+    long loss = 0L;
+    boolean costly;
+
+    costly = ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE)))
+              && costly_spot(x, y));
 
     if (level.objects[x][y] != (struct obj *) 0) {
         debugpline2("bury_objs: at <%d,%d>", x, y);
     }
-    for (otmp = level.objects[x][y]; otmp; otmp = otmp2)
+    for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
+        if (costly) {
+            loss += stolen_value(otmp, x, y, (boolean) shkp->mpeaceful, TRUE);
+            if (otmp->oclass != COIN_CLASS)
+                otmp->no_charge = 1;
+        }
         otmp2 = bury_an_obj(otmp, (boolean *) 0);
+    }
 
     /* don't expect any engravings here, but just in case */
     del_engr_at(x, y);
     newsym(x, y);
+
+    if (costly && loss) {
+        You("owe %s %ld %s for burying merchandise.", mon_nam(shkp), loss,
+            currency(loss));
+    }
 }
 
 /* move objects from buriedobjlist to fobj/nexthere lists */
@@ -2374,7 +2413,8 @@ int x, y;
     for (otmp = level.buriedobjlist; otmp; otmp = otmp2) {
         otmp2 = otmp->nobj;
         if (otmp->ox == x && otmp->oy == y) {
-            if (bball && otmp == bball && u.utraptype == TT_BURIEDBALL) {
+            if (bball && otmp == bball
+                && u.utrap && u.utraptype == TT_BURIEDBALL) {
                 buried_ball_to_punishment();
             } else {
                 obj_extract_self(otmp);
@@ -2498,7 +2538,7 @@ struct monst *mtmp;
     }
 
     mtmp->mburied = TRUE;
-    wakeup(mtmp);       /* at least give it a chance :-) */
+    wakeup(mtmp, FALSE);       /* at least give it a chance :-) */
     newsym(mtmp->mx, mtmp->my);
 }
 
index e75f74d..5c98c8a 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 display.c       $NHDT-Date: 1446808439 2015/11/06 11:13:59 $  $NHDT-Branch: master $:$NHDT-Revision: 1.77 $ */
+/* NetHack 3.6 display.c       $NHDT-Date: 1524780381 2018/04/26 22:06:21 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.90 $ */
 /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */
 /* and Dave Cohrs, 1990.                                          */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -277,6 +277,19 @@ register xchar x, y;
     }
 }
 
+boolean
+unmap_invisible(x, y)
+int x, y;
+{
+    if (isok(x,y) && glyph_is_invisible(levl[x][y].glyph)) {
+        unmap_object(x, y);
+        newsym(x, y);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+
 /*
  * unmap_object()
  *
@@ -378,6 +391,7 @@ xchar worm_tail;            /* mon is actually a worm tail */
         default:
             impossible("display_monster:  bad m_ap_type value [ = %d ]",
                        (int) mon->m_ap_type);
+            /*FALLTHRU*/
         case M_AP_NOTHING:
             show_glyph(x, y, mon_to_glyph(mon));
             break;
@@ -424,24 +438,29 @@ xchar worm_tail;            /* mon is actually a worm tail */
         }
     }
 
-    /* If the mimic is unsuccessfully mimicing something, display the monster
+    /* If the mimic is unsuccessfully mimicing something, display the monster.
      */
     if (!mon_mimic || sensed) {
         int num;
 
         /* [ALI] Only use detected glyphs when monster wouldn't be
          * visible by any other means.
+         *
+         * There are no glyphs for "detected pets" so we have to
+         * decide whether to display such things as detected or as tame.
+         * If both are being highlighted in the same way, it doesn't
+         * matter, but if not, showing them as pets is preferrable.
          */
-        if (sightflags == DETECTED && !mon->mtame) {
-            if (worm_tail)
-                num = detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL));
-            else
-                num = detected_mon_to_glyph(mon);
-        } else if (mon->mtame && !Hallucination) {
+        if (mon->mtame && !Hallucination) {
             if (worm_tail)
                 num = petnum_to_glyph(PM_LONG_WORM_TAIL);
             else
                 num = pet_to_glyph(mon);
+        } else if (sightflags == DETECTED) {
+            if (worm_tail)
+                num = detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL));
+            else
+                num = detected_mon_to_glyph(mon);
         } else {
             if (worm_tail)
                 num = monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL));
@@ -466,16 +485,10 @@ display_warning(mon)
 register struct monst *mon;
 {
     int x = mon->mx, y = mon->my;
-    int wl = (int) (mon->m_lev / 4);
     int glyph;
 
     if (mon_warning(mon)) {
-        if (wl > WARNCOUNT - 1)
-            wl = WARNCOUNT - 1;
-        /* 3.4.1: this really ought to be rn2(WARNCOUNT), but value "0"
-           isn't handled correctly by the what_is routine so avoid it */
-        if (Hallucination)
-            wl = rn1(WARNCOUNT - 1, 1);
+        int wl = Hallucination ? rn1(WARNCOUNT - 1, 1) : warning_of(mon);
         glyph = warning_to_glyph(wl);
     } else if (MATCH_WARN_OF_MON(mon)) {
         glyph = mon_to_glyph(mon);
@@ -483,9 +496,28 @@ register struct monst *mon;
         impossible("display_warning did not match warning type?");
         return;
     }
+    /* warning glyph is drawn on the monster layer; unseen
+       monster glyph is drawn on the object/trap/floor layer;
+       if we see a 'warning' move onto 'remembered, unseen' we
+       need to explicitly remove that in order for it to not
+       reappear when the warned-of monster moves off that spot */
+    if (glyph_is_invisible(levl[x][y].glyph))
+        unmap_object(x, y);
     show_glyph(x, y, glyph);
 }
 
+int
+warning_of(mon)
+struct monst *mon;
+{
+    int wl = 0, tmp = 0;
+    if (mon_warning(mon)) {
+        tmp = (int) (mon->m_lev / 4);    /* match display.h */
+        wl = (tmp > WARNCOUNT - 1) ? WARNCOUNT - 1 : tmp;
+    }
+    return wl;
+}
+
 
 /*
  * feel_newsym()
@@ -524,8 +556,7 @@ xchar x, y;
     if (!isok(x, y))
         return;
     lev = &(levl[x][y]);
-    /* If the hero's memory of an invisible monster is accurate, we want to
-     * keep
+    /* If hero's memory of an invisible monster is accurate, we want to keep
      * him from detecting the same monster over and over again on each turn.
      * We must return (so we don't erase the monster).  (We must also, in the
      * search function, be sure to skip over previously detected 'I's.)
@@ -533,8 +564,10 @@ xchar x, y;
     if (glyph_is_invisible(lev->glyph) && m_at(x, y))
         return;
 
-    /* The hero can't feel non pool locations while under water. */
-    if (Underwater && !Is_waterlevel(&u.uz) && !is_pool(x, y))
+    /* The hero can't feel non pool locations while under water
+       except for lava and ice. */
+    if (Underwater && !Is_waterlevel(&u.uz)
+        && !is_pool_or_lava(x, y) && !is_ice(x, y))
         return;
 
     /* Set the seen vector as if the hero had seen it.
@@ -566,6 +599,8 @@ xchar x, y;
         } else if (IS_DOOR(lev->typ)) {
             map_background(x, y, 1);
         } else if (IS_ROOM(lev->typ) || IS_POOL(lev->typ)) {
+            boolean do_room_glyph;
+
             /*
              * An open room or water location.  Normally we wouldn't touch
              * this, but we have to get rid of remembered boulder symbols.
@@ -591,20 +626,18 @@ xchar x, y;
              * We could also just display what is currently on the top of the
              * object stack (if anything).
              */
-            if (lev->glyph == objnum_to_glyph(BOULDER)) {
-                if (lev->typ != ROOM && lev->seenv) {
+            do_room_glyph = FALSE;
+            if (lev->glyph == objnum_to_glyph(BOULDER)
+                || glyph_is_invisible(lev->glyph)) {
+                if (lev->typ != ROOM && lev->seenv)
                     map_background(x, y, 1);
-                } else {
-                    lev->glyph = (flags.dark_room && iflags.use_color
-                                  && !Is_rogue_level(&u.uz))
-                                     ? cmap_to_glyph(S_darkroom)
-                                     : (lev->waslit ? cmap_to_glyph(S_room)
-                                                    : cmap_to_glyph(S_stone));
-                    show_glyph(x, y, lev->glyph);
-                }
-            } else if ((lev->glyph >= cmap_to_glyph(S_stone)
-                        && lev->glyph < cmap_to_glyph(S_darkroom))
-                       || glyph_is_invisible(levl[x][y].glyph)) {
+                else
+                    do_room_glyph = TRUE;
+            } else if (lev->glyph >= cmap_to_glyph(S_stone)
+                       && lev->glyph < cmap_to_glyph(S_darkroom)) {
+                do_room_glyph = TRUE;
+            }
+            if (do_room_glyph) {
                 lev->glyph = (flags.dark_room && iflags.use_color
                               && !Is_rogue_level(&u.uz))
                                  ? cmap_to_glyph(S_darkroom)
@@ -659,7 +692,7 @@ xchar x, y;
             show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr));
     }
     /* draw monster on top if we can sense it */
-    if ((x != u.ux || y != u.uy) && (mon = m_at(x, y)) && sensemon(mon))
+    if ((x != u.ux || y != u.uy) && (mon = m_at(x, y)) != 0 && sensemon(mon))
         display_monster(x, y, mon,
                         (tp_sensemon(mon) || MATCH_WARN_OF_MON(mon))
                             ? PHYSICALLY_SEEN
@@ -695,18 +728,9 @@ register int x, y;
         return;
     }
     if (Underwater && !Is_waterlevel(&u.uz)) {
-        /* don't do anything unless (x,y) is an adjacent underwater position
-         */
-        int dx, dy;
-        if (!is_pool(x, y))
-            return;
-        dx = x - u.ux;
-        if (dx < 0)
-            dx = -dx;
-        dy = y - u.uy;
-        if (dy < 0)
-            dy = -dy;
-        if (dx > 1 || dy > 1)
+        /* when underwater, don't do anything unless <x,y> is an
+           adjacent water or lava or ice position */
+        if (!(is_pool_or_lava(x, y) || is_ice(x, y)) || distu(x, y) > 2)
             return;
     }
 
@@ -1011,9 +1035,10 @@ int first;
     static xchar lastx, lasty; /* last swallowed position */
     int swallower, left_ok, rght_ok;
 
-    if (first)
+    if (first) {
         cls();
-    else {
+        bot();
+    } else {
         register int x, y;
 
         /* Clear old location */
@@ -1097,9 +1122,13 @@ int mode;
                     show_glyph(x, y, cmap_to_glyph(S_stone));
     }
 
+    /*
+     * TODO?  Should this honor Xray radius rather than force radius 1?
+     */
+
     for (x = u.ux - 1; x <= u.ux + 1; x++)
         for (y = u.uy - 1; y <= u.uy + 1; y++)
-            if (isok(x, y) && is_pool(x, y)) {
+            if (isok(x, y) && (is_pool_or_lava(x, y) || is_ice(x, y))) {
                 if (Blind && !(x == u.ux && y == u.uy))
                     show_glyph(x, y, cmap_to_glyph(S_stone));
                 else
@@ -1201,8 +1230,7 @@ set_mimic_blocking()
     for (mon = fmon; mon; mon = mon->nmon) {
         if (DEADMONSTER(mon))
             continue;
-        if (mon->minvis && (is_door_mappear(mon)
-                            || is_obj_mappear(mon,BOULDER))) {
+        if (mon->minvis && is_lightblocker_mappear(mon)) {
             if (See_invisible)
                 block_point(mon->mx, mon->my);
             else
@@ -1319,6 +1347,21 @@ static gbuf_entry gbuf[ROWNO][COLNO];
 static char gbuf_start[ROWNO];
 static char gbuf_stop[ROWNO];
 
+/* FIXME: This is a dirty hack, because newsym() doesn't distinguish
+ * between object piles and single objects, it doesn't mark the location
+ * for update. */
+void
+newsym_force(x, y)
+register int x, y;
+{
+    newsym(x,y);
+    gbuf[y][x].new = 1;
+    if (gbuf_start[y] > x)
+        gbuf_start[y] = x;
+    if (gbuf_stop[y] < x)
+        gbuf_stop[y] = x;
+}
+
 /*
  * Store the glyph in the 3rd screen for later flushing.
  */
@@ -1728,7 +1771,8 @@ xchar x, y;
     int idx, bkglyph = NO_GLYPH;
     struct rm *lev = &levl[x][y];
 
-    if (iflags.use_background_glyph) {
+    if (iflags.use_background_glyph && lev->seenv != 0
+            && gbuf[y][x].glyph != cmap_to_glyph(S_stone)) {
         switch (lev->typ) {
         case SCORR:
         case STONE:
@@ -1749,9 +1793,16 @@ xchar x, y;
         case CLOUD:
            idx = S_cloud;
            break;
+        case POOL:
+        case MOAT:
+           idx = S_pool;
+           break;
         case WATER:
            idx = S_water;
            break;
+        case LAVAPOOL:
+           idx = S_lava;
+           break;
         default:
            idx = S_room;
            break;
index 7f9737e..00c98a3 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 do.c    $NHDT-Date: 1446975464 2015/11/08 09:37:44 $  $NHDT-Branch: master $:$NHDT-Revision: 1.149 $ */
+/* NetHack 3.6 do.c    $NHDT-Date: 1472809073 2016/09/02 09:37:53 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.158 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) */
@@ -39,7 +40,8 @@ dodrop()
     result = drop(getobj(&drop_types[i], "drop"));
     if (*u.ushops)
         sellobj_state(SELL_NORMAL);
-    reset_occupations();
+    if (result)
+        reset_occupations();
 
     return result;
 }
@@ -131,10 +133,13 @@ boolean pushing;
                 You("\82¢\82Â\82Ì\82Ü\82É\82©\8a£\82¢\82½\8fê\8f\8a\82É\82¢\82½\81I");
             } else if (lava && distu(rx, ry) <= 2) {
                 int dmg;
-/*JP
-                You("are hit by molten lava%c", Fire_resistance ? '.' : '!');
-*/
-                You("\82Ç\82ë\82Ç\82ë\82Ì\97n\8aâ\82Å\83_\83\81\81[\83W\82ð\8eó\82¯\82½%s", Fire_resistance ? "\81D" : "\81I");
+#if 0 /*JP:T*/
+                You("are hit by molten %s%c",
+                    hliquid("lava"), Fire_resistance ? '.' : '!');
+#else
+                You("\82Ç\82ë\82Ç\82ë\82Ì%s\82Å\83_\83\81\81[\83W\82ð\8eó\82¯\82½%s",
+                    hliquid("\97n\8aâ"), Fire_resistance ? "\81D" : "\81I");
+#endif
                 burn_away_slime();
                 dmg = d((Fire_resistance ? 1 : 3), 6);
 #if 0 /*JP:T*/
@@ -204,7 +209,10 @@ const char *verb;
 #endif
             if (mtmp) {
                 if (!passes_walls(mtmp->data) && !throws_rocks(mtmp->data)) {
-                    if (hmon(mtmp, obj, TRUE) && !is_whirly(mtmp->data))
+                    int dieroll = rnd(20);
+
+                    if (hmon(mtmp, obj, HMON_THROWN, dieroll)
+                        && !is_whirly(mtmp->data))
                         return FALSE; /* still alive */
                 }
                 mtmp->mtrapped = 0;
@@ -254,7 +262,7 @@ const char *verb;
         newsym(x, y);
         return TRUE;
     } else if (is_lava(x, y)) {
-        return fire_damage(obj, FALSE, x, y);
+        return lava_damage(obj, x, y);
     } else if (is_pool(x, y)) {
         /* Reasonably bulky objects (arbitrary) splash when dropped.
          * If you're floating above the water even small things make
@@ -295,15 +303,13 @@ const char *verb;
 #endif
     } else if (obj->globby) {
         /* Globby things like puddings might stick together */
-        while (obj
-               && (otmp = obj_nexto_xy(obj->otyp, x, y, obj->o_id))
-                      != (struct obj *) 0) {
+        while (obj && (otmp = obj_nexto_xy(obj, x, y, TRUE)) != 0) {
             pudding_merge_message(obj, otmp);
             /* intentionally not getting the melded object; obj_meld may set
              * obj to null. */
             (void) obj_meld(&obj, &otmp);
         }
-        return (boolean) (obj == NULL);
+        return (boolean) !obj;
     }
     return FALSE;
 }
@@ -359,6 +365,8 @@ register struct obj *obj;
 STATIC_DCL void
 polymorph_sink()
 {
+    uchar sym = S_sink;
+
     if (levl[u.ux][u.uy].typ != SINK)
         return;
 
@@ -367,30 +375,36 @@ polymorph_sink()
     switch (rn2(4)) {
     default:
     case 0:
+        sym = S_fountain;
         levl[u.ux][u.uy].typ = FOUNTAIN;
         level.flags.nfountains++;
         break;
     case 1:
+        sym = S_throne;
         levl[u.ux][u.uy].typ = THRONE;
         break;
     case 2:
+        sym = S_altar;
         levl[u.ux][u.uy].typ = ALTAR;
         levl[u.ux][u.uy].altarmask = Align2amask(rn2((int) A_LAWFUL + 2) - 1);
         break;
     case 3:
+        sym = S_room;
         levl[u.ux][u.uy].typ = ROOM;
         make_grave(u.ux, u.uy, (char *) 0);
+        if (levl[u.ux][u.uy].typ == GRAVE)
+            sym = S_grave;
         break;
     }
-#if 0 /*JP*/
-    pline_The("sink transforms into %s!", (levl[u.ux][u.uy].typ == THRONE)
-                                              ? "a throne"
-                                              : an(surface(u.ux, u.uy)));
-#else
-    pline_The("\97¬\82µ\91ä\82Í%s\82É\95Ï\89»\82µ\82½\81I", (levl[u.ux][u.uy].typ == THRONE)
-                                              ? "\8bÊ\8dÀ"
-                                              : an(surface(u.ux, u.uy)));
-#endif
+    /* give message even if blind; we know we're not levitating,
+       so can feel the outcome even if we can't directly see it */
+    if (levl[u.ux][u.uy].typ != ROOM)
+/*JP
+        pline_The("sink transforms into %s!", an(defsyms[sym].explanation));
+*/
+        pline_The("\97¬\82µ\91ä\82Í%s\82É\95Ï\89»\82µ\82½\81I", defsyms[sym].explanation);
+    else
+        pline_The("sink vanishes.");
     newsym(u.ux, u.uy);
 }
 
@@ -492,44 +506,50 @@ register struct obj *obj;
         break;
     case RIN_SUSTAIN_ABILITY: /* KMH */
 /*JP
-        pline_The("water flow seems fixed.");
+        pline_The("%s flow seems fixed.", hliquid("water"));
 */
-        pline("\90\85\82Ì\97¬\82ê\82ª\88ê\92è\82É\82È\82Á\82½\82æ\82¤\82¾\81D");
+        pline("%s\82Ì\97¬\82ê\82ª\88ê\92è\82É\82È\82Á\82½\82æ\82¤\82¾\81D", hliquid("\90\85"));
         break;
     case RIN_GAIN_STRENGTH:
-#if 0 /*JP*/
-        pline_The("water flow seems %ser now.",
+#if 0 /*JP:T*/
+        pline_The("%s flow seems %ser now.",
+                  hliquid("water"),
                   (obj->spe < 0) ? "weak" : "strong");
 #else
-        pline("\90\85\82Ì\97¬\82ê\82ª%s\82È\82Á\82½\82æ\82¤\82¾\81D",
-              (obj->spe<0) ? "\8eã\82­" : "\8b­\82­");
+        pline("%s\82Ì\97¬\82ê\82ª%s\82­\82È\82Á\82½\82æ\82¤\82¾\81D",
+                  hliquid("\90\85"),
+                  (obj->spe < 0) ? "\8eã" : "\8b­");
 #endif
         break;
     case RIN_GAIN_CONSTITUTION:
-#if 0 /*JP*/
-        pline_The("water flow seems %ser now.",
+#if 0 /*JP:T*/
+        pline_The("%s flow seems %ser now.",
+                  hliquid("water"),
                   (obj->spe < 0) ? "less" : "great");
 #else
-        pline("\97¬\82ê\82é\90\85\82Ì\97Ê\82ª%s\82È\82Á\82½\82æ\82¤\82¾\81D",
-              (obj->spe < 0) ? "\8f­\82È\82­" : "\91½\82­");
+        pline("\97¬\82ê\82é%s\82Ì\97Ê\82ª%s\82­\82È\82Á\82½\82æ\82¤\82¾\81D",
+                  hliquid("\90\85"),
+                  (obj->spe < 0) ? "\8f­\82È" : "\91½");
 #endif
         break;
     case RIN_INCREASE_ACCURACY: /* KMH */
-#if 0 /*JP*/
-        pline_The("water flow %s the drain.",
+#if 0 /*JP:T*/
+        pline_The("%s flow %s the drain.",
+                  hliquid("water"),
                   (obj->spe < 0) ? "misses" : "hits");
 #else
-        pline_The("\90\85\82ª\94r\90\85\8cû%s\82æ\82¤\82É\82È\82Á\82½\81D",
+        pline("%s\82ª\94r\90\85\8cû%s\82æ\82¤\82É\82È\82Á\82½\81D",
+                  hliquid("\90\85"),
                   (obj->spe < 0) ? "\82©\82ç\94½\82ê\82é" : "\82ß\82ª\82¯\82Ä\97¬\82ê\82é");
 #endif
         break;
     case RIN_INCREASE_DAMAGE:
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         pline_The("water's force seems %ser now.",
                   (obj->spe < 0) ? "small" : "great");
 #else
-        pline_The("\90\85\82Ì\90¨\82¢\82ª%s\82È\82Á\82½\82æ\82¤\82¾\81D",
-                  (obj->spe < 0) ? "\8eã\82­" : "\8b­\82­");
+        pline("\90\85\82Ì\90¨\82¢\82ª%s\82­\82È\82Á\82½\82æ\82¤\82¾\81D",
+                  (obj->spe < 0) ? "\8eã" : "\8b­");
 #endif
         break;
     case RIN_HUNGER:
@@ -558,11 +578,27 @@ register struct obj *obj;
 */
         pline("\90\94\95C\82Ì\83n\83G\82ª\83u\83\93\83u\83\93\97¬\82µ\91ä\82Ì\89ñ\82è\82ð\94ò\82Ñ\82Ü\82í\82Á\82½\81D");
         break;
+    case RIN_TELEPORTATION:
+        nosink = teleport_sink();
+        /* give message even if blind; we know we're not levitating,
+           so can feel the outcome even if we can't directly see it */
+/*JP
+            pline_The("sink %svanishes.", nosink ? "" : "momentarily ");
+*/
+            pline_The("\97¬\82µ\91ä\82Í%s\8fÁ\82¦\82½\81D", nosink ? "" : "\88ê\8fu");
+        ideed = FALSE;
+        break;
+    case RIN_POLYMORPH:
+        polymorph_sink();
+        nosink = TRUE;
+        /* for S_room case, same message as for teleportation is given */
+        ideed = (levl[u.ux][u.uy].typ != ROOM);
+        break;
     default:
         ideed = FALSE;
         break;
     }
-    if (!Blind && !ideed && obj->otyp != RIN_HUNGER) {
+    if (!Blind && !ideed) {
         ideed = TRUE;
         switch (obj->otyp) { /* effects that need eyes */
         case RIN_ADORNMENT:
@@ -605,16 +641,20 @@ register struct obj *obj;
             pline("\88ê\8fu\81C\97¬\82µ\91ä\82ª\8f°\82É\97n\82¯\82±\82ñ\82¾\82æ\82¤\82É\8c©\82¦\82½\81D");
             break;
         case RIN_FIRE_RESISTANCE:
-/*JP
-            pline_The("hot water faucet flashes brightly for a moment.");
-*/
+#if 0 /*JP*/
+            pline_The("hot %s faucet flashes brightly for a moment.",
+                      hliquid("water"));
+#else /*\82Æ\82è\82 \82¦\82¸hliquid()\82Í\8eg\82í\82È\82¢\8c`\82É*/
             pline("\88ê\8fu\81C\94M\93\92\82Ì\8eÖ\8cû\82ª\96¾\82é\82­\8bP\82¢\82½\81D");
+#endif
             break;
         case RIN_COLD_RESISTANCE:
-/*JP
-            pline_The("cold water faucet flashes brightly for a moment.");
-*/
+#if 0 /*JP*/
+            pline_The("cold %s faucet flashes brightly for a moment.",
+                      hliquid("water"));
+#else /*\82Æ\82è\82 \82¦\82¸hliquid()\82Í\8eg\82í\82È\82¢\8c`\82É*/
             pline("\88ê\8fu\81C\97â\90\85\82Ì\8eÖ\8cû\82ª\96¾\82é\82­\8bP\82¢\82½\81D");
+#endif
             break;
         case RIN_PROTECTION_FROM_SHAPE_CHAN:
 /*JP
@@ -623,27 +663,19 @@ register struct obj *obj;
             pline("\97¬\82µ\91ä\82Í\90ò\82Æ\82Í\82Ü\82Á\82½\82­\88á\82¤\82à\82Ì\82Ì\82æ\82¤\82É\8c©\82¦\82½\81D");
             break;
         case RIN_PROTECTION:
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             pline_The("sink glows %s for a moment.",
                       hcolor((obj->spe < 0) ? NH_BLACK : NH_SILVER));
 #else
             pline("\97¬\82µ\91ä\82Í\88ê\8fu%s\8bP\82¢\82½\81D",
-                  jconj_adj(hcolor((obj->spe<0) ? NH_BLACK : NH_SILVER)));
+                      jconj_adj(hcolor((obj->spe < 0) ? NH_BLACK : NH_SILVER)));
 #endif
             break;
         case RIN_WARNING:
-#if 0 /*JP*/
-            pline_The("sink glows %s for a moment.", hcolor(NH_WHITE));
-#else
-            pline("\97¬\82µ\91ä\82Í\88ê\8fu%s\8bP\82¢\82½\81D", jconj_adj(hcolor(NH_WHITE)));
-#endif
-            break;
-        case RIN_TELEPORTATION:
-            nosink = teleport_sink();
 /*JP
-            pline_The("sink %svanishes.", nosink ? "" : "momentarily ");
+            pline_The("sink glows %s for a moment.", hcolor(NH_WHITE));
 */
-            pline_The("\97¬\82µ\91ä\82Í%s\8fÁ\82¦\82½\81D", nosink ? "" : "\88ê\8fu");
+            pline("\97¬\82µ\91ä\82Í\88ê\8fu%s\8bP\82¢\82½\81D", jconj_adj(hcolor(NH_WHITE)));
             break;
         case RIN_TELEPORT_CONTROL:
 /*JP: "beam aboard" \82Í\83X\83^\81[\83g\83\8c\83b\83N\82Ì\81u\93]\91\97\81v*/
@@ -652,10 +684,6 @@ register struct obj *obj;
 */
             pline("\97¬\82µ\91ä\82Í\82Ç\82±\82©\82É\93]\91\97\82³\82ê\82æ\82¤\82Æ\82µ\82Ä\82¢\82é\82æ\82¤\82É\8c©\82¦\82½\81D");
             break;
-        case RIN_POLYMORPH:
-            polymorph_sink();
-            nosink = TRUE;
-            break;
         case RIN_POLYMORPH_CONTROL:
             pline_The(
 /*JP
@@ -663,6 +691,8 @@ register struct obj *obj;
 */
                 "\97¬\82µ\91ä\82Í\88ê\8fu\8bK\91¥\90³\82µ\82­\95¬\8fo\82·\82é\8aÔ\8c\87\90ò\82Ì\82æ\82¤\82É\8c©\82¦\82½\81D");
             break;
+        default:
+            break;
         }
     }
     if (ideed)
@@ -680,6 +710,12 @@ register struct obj *obj;
         pline("\97¬\82µ\91ä\82ª\8bt\97¬\82µ\82Ä\81C%s\82ª\96ß\82Á\82Ä\82«\82½\81D", doname(obj));
         obj->in_use = FALSE;
         dropx(obj);
+    } else if (!rn2(5)) {
+        freeinv(obj);
+        obj->in_use = FALSE;
+        obj->ox = u.ux;
+        obj->oy = u.uy;
+        add_to_buried(obj);
     } else
         useup(obj);
 }
@@ -775,7 +811,7 @@ register struct obj *obj;
             You("drop %s into %s %s.", doname(obj), buf,
                 mbodypart(u.ustuck, STOMACH));
 #else
-            You("%s\82ð%s\82Ì%s\82É\92u\82¢\82½\81D", doname(obj), buf,
+            You("%s\82ð%s%s\82É\92u\82¢\82½\81D", doname(obj), buf,
                 mbodypart(u.ustuck, STOMACH));
 #endif
         }
@@ -955,6 +991,10 @@ doddrop()
 {
     int result = 0;
 
+    if (!invent) {
+        You("have nothing to drop.");
+        return 0;
+    }
     add_valid_menu_class(0); /* clear any classes already there */
     if (*u.ushops)
         sellobj_state(SELL_DELIBERATE);
@@ -963,7 +1003,8 @@ doddrop()
         result = menu_drop(result);
     if (*u.ushops)
         sellobj_state(SELL_NORMAL);
-    reset_occupations();
+    if (result)
+        reset_occupations();
 
     return result;
 }
@@ -1004,6 +1045,7 @@ int retry;
         free((genericptr_t) pick_list);
     } else if (flags.menu_style == MENU_COMBINATION) {
         unsigned ggoresults = 0;
+
         all_categories = FALSE;
         /* Gather valid classes via traditional NetHack method */
         i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
@@ -1038,12 +1080,15 @@ int retry;
         bypass_objlist(invent, FALSE);
     } else {
         /* should coordinate with perm invent, maybe not show worn items */
-/*JP
-        n = query_objlist("What would you like to drop?", invent,
-*/
-        n = query_objlist("\82Ç\82ê\82ð\92u\82«\82Ü\82·\82©\81H", invent,
-                          USE_INVLET | INVORDER_SORT, &pick_list, PICK_ANY,
+#if 0 /*JP*/
+        n = query_objlist("What would you like to drop?", &invent,
+                          (USE_INVLET | INVORDER_SORT), &pick_list, PICK_ANY,
+                          all_categories ? allow_all : allow_category);
+#else
+        n = query_objlist("\82Ç\82ê\82ð\92u\82«\82Ü\82·\82©\81H", &invent,
+                          (USE_INVLET | INVORDER_SORT), &pick_list, PICK_ANY,
                           all_categories ? allow_all : allow_category);
+#endif
         if (n > 0) {
             /*
              * picklist[] contains a set of pointers into inventory, but
@@ -1148,12 +1193,18 @@ dodown()
                 ladder_down =
                     (glyph_to_cmap(levl[u.ux][u.uy].glyph) == S_dnladder);
         }
-#if 0 /*JP*/
-        floating_above(stairs_down ? "stairs" : ladder_down
+        if (Is_airlevel(&u.uz))
+            You("are floating in the %s.", surface(u.ux, u.uy));
+        else if (Is_waterlevel(&u.uz))
+            You("are floating in %s.",
+                is_pool(u.ux, u.uy) ? "the water" : "a bubble of air");
+        else
+#if 0 /*JP:T*/
+            floating_above(stairs_down ? "stairs" : ladder_down
                                                     ? "ladder"
                                                     : surface(u.ux, u.uy));
 #else
-        floating_above(stairs_down ? "\8aK\92i" : ladder_down
+            floating_above(stairs_down ? "\8aK\92i" : ladder_down
                                                     ? "\82Í\82µ\82²"
                                                     : surface(u.ux, u.uy));
 #endif
@@ -1395,11 +1446,12 @@ boolean at_stairs, falling, portal;
 {
     int fd, l_idx;
     xchar new_ledger;
-    boolean cant_go_back, up = (depth(newlevel) < depth(&u.uz)),
-                          newdungeon = (u.uz.dnum != newlevel->dnum),
-                          was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz),
-                          familiar = FALSE;
-    boolean new = FALSE; /* made a new level? */
+    boolean cant_go_back, great_effort,
+            up = (depth(newlevel) < depth(&u.uz)),
+            newdungeon = (u.uz.dnum != newlevel->dnum),
+            was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz),
+            familiar = FALSE,
+            new = FALSE; /* made a new level? */
     struct monst *mtmp;
     char whynot[BUFSZ];
     char *annotation;
@@ -1534,6 +1586,7 @@ boolean at_stairs, falling, portal;
 #ifdef USE_TILES
     substitute_tiles(newlevel);
 #endif
+    check_gold_symbol();
     /* record this level transition as a potential seen branch unless using
      * some non-standard means of transportation (level teleport).
      */
@@ -1606,16 +1659,18 @@ boolean at_stairs, falling, portal;
                 u_on_dnstairs();
             /* you climb up the {stairs|ladder};
                fly up the stairs; fly up along the ladder */
+            great_effort = (Punished && !Levitation);
+            if (flags.verbose || great_effort)
 #if 0 /*JP*/
-            pline("%s %s up%s the %s.",
-                  (Punished && !Levitation) ? "With great effort you" : "You",
-                  Flying ? "fly" : "climb",
-                  (Flying && at_ladder) ? " along" : "",
-                  at_ladder ? "ladder" : "stairs");
-#else
-            pline("%s%s\82ð\8fã\82Á\82½\81D",
-                  (Punished && !Levitation) ? "\82â\82Á\82Æ\82±\82³" : "",
-                  at_ladder ? "\82Í\82µ\82²" : "\8aK\92i");
+                pline("%s %s up%s the %s.",
+                      great_effort ? "With great effort, you" : "You",
+                      Levitation ? "float" : Flying ? "fly" : "climb",
+                      (Flying && at_ladder) ? " along" : "",
+                      at_ladder ? "ladder" : "stairs");
+#else /* \94ò\82ñ\82¾\82è\82µ\82Ä\82¢\82Ä\82à\81u\8fã\82Á\82½\81v */
+                pline("%s%s\82ð\8fã\82Á\82½\81D",
+                      great_effort ? "\82â\82Á\82Æ\82±\82³" : "",
+                      at_ladder ? "\82Í\82µ\82²" : "\8aK\92i");
 #endif
         } else { /* down */
             if (at_ladder)
@@ -1628,15 +1683,15 @@ boolean at_stairs, falling, portal;
                 ; /* stayed on same level? (no transit effects) */
             } else if (Flying) {
                 if (flags.verbose)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                     You("fly down %s.",
                         at_ladder ? "along the ladder" : "the stairs");
 #else
                     You("%s\94ò\82ñ\82Å\8d~\82è\82½\81D",
                         at_ladder ? "\82Í\82µ\82²\82É\89\88\82Á\82Ä" : "\8aK\92i\82ð");
 #endif
-            } else if (near_capacity() > UNENCUMBERED || Punished
-                       || Fumbling) {
+            } else if (near_capacity() > UNENCUMBERED
+                       || Punished || Fumbling) {
 /*JP
                 You("fall down the %s.", at_ladder ? "ladder" : "stairs");
 */
@@ -1896,7 +1951,7 @@ boolean at_stairs, falling, portal;
     save_currentstate();
 #endif
 
-    if ((annotation = get_annotation(&u.uz)))
+    if ((annotation = get_annotation(&u.uz)) != 0)
 /*JP
         You("remember this level as %s.", annotation);
 */
@@ -1905,7 +1960,14 @@ boolean at_stairs, falling, portal;
     /* assume this will always return TRUE when changing level */
     (void) in_out_region(u.ux, u.uy);
     (void) pickup(1);
-    context.polearm.hitmon = NULL;
+
+    /* discard context which applied to previous level */
+    maybe_reset_pick(); /* for door or for box not accompanying hero */
+    reset_trapset(); /* even if to-be-armed trap obj is accompanying hero */
+    iflags.travelcc.x = iflags.travelcc.y = -1; /* travel destination cache */
+    context.polearm.hitmon = (struct monst *) 0; /* polearm target */
+    /* digging context is level-aware and can actually be resumed if
+       hero returns to the previous level without any intervening dig */
 }
 
 STATIC_OVL void
index fbb0ded..dc4e79a 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 do_name.c       $NHDT-Date: 1446808440 2015/11/06 11:14:00 $  $NHDT-Branch: master $:$NHDT-Revision: 1.77 $ */
+/* NetHack 3.6 do_name.c       $NHDT-Date: 1519420054 2018/02/23 21:07:34 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.128 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 
 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 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));
 STATIC_DCL void NDECL(do_mname);
+STATIC_DCL boolean FDECL(alreadynamed, (struct monst *, char *, char *));
 STATIC_DCL void FDECL(do_oname, (struct obj *));
+STATIC_PTR char *FDECL(docall_xname, (struct obj *));
 STATIC_DCL void NDECL(namefloorobj);
 STATIC_DCL char *FDECL(bogusmon, (char *,char *));
 
@@ -34,13 +42,51 @@ nextmbuf()
 /* function for getpos() to highlight desired map locations.
  * parameter value 0 = initialize, 1 = highlight, 2 = done
  */
-void FDECL((*getpos_hilitefunc), (int)) = (void FDECL((*), (int))) 0;
+static void FDECL((*getpos_hilitefunc), (int)) = (void FDECL((*), (int))) 0;
+static boolean FDECL((*getpos_getvalid), (int, int)) =
+                                           (boolean FDECL((*), (int, int))) 0;
 
 void
-getpos_sethilite(f)
-void FDECL((*f), (int));
+getpos_sethilite(gp_hilitef, gp_getvalidf)
+void FDECL((*gp_hilitef), (int));
+boolean FDECL((*gp_getvalidf), (int, int));
 {
-    getpos_hilitefunc = f;
+    getpos_hilitefunc = gp_hilitef;
+    getpos_getvalid = gp_getvalidf;
+}
+
+const char *const gloc_descr[NUM_GLOCS][4] = {
+    { "any monsters", "monster", "next monster", "monsters" },
+    { "any items", "item", "next object", "objects" },
+    { "any doors", "door", "next door or doorway", "doors or doorways" },
+    { "any unexplored areas", "unexplored area", "unexplored location",
+      "unexplored locations" },
+    { "anything interesting", "interesting thing", "anything interesting",
+      "anything interesting" }
+};
+
+const char *const gloc_filtertxt[NUM_GFILTER] = {
+    "",
+    " in view",
+    " in this area"
+};
+
+void
+getpos_help_keyxhelp(tmpwin, k1, k2, gloc)
+winid tmpwin;
+const char *k1;
+const char *k2;
+int gloc;
+{
+    char sbuf[BUFSZ];
+
+    Sprintf(sbuf, "Use '%s' or '%s' to %s%s%s.",
+            k1, k2,
+            iflags.getloc_usemenu ? "get a menu of "
+                                  : "move the cursor to ",
+            gloc_descr[gloc][2 + iflags.getloc_usemenu],
+            gloc_filtertxt[iflags.getloc_filter]);
+    putstr(tmpwin, 0, sbuf);
 }
 
 /* the response for '?' help request in getpos() */
@@ -52,46 +98,157 @@ const char *goal;
     char sbuf[BUFSZ];
     boolean doing_what_is;
     winid tmpwin = create_nhwindow(NHW_MENU);
+#if 0 /*JP*/
+    const char *const fastmovemode[2] = { "8 units at a time",
+                                          "skipping same glyphs" };
+#else
+    const char *const fastmovemode[2] = { "\88ê\93x\82É8\95à",
+                                          "\93¯\82\92n\8c`\82ð\94ò\82Î\82µ\82Ä" };
+#endif
 
+    Sprintf(sbuf,
 #if 0 /*JP*/
-    Sprintf(sbuf, "Use [%c%c%c%c] to move the cursor to %s.", /* hjkl */
+            "Use '%c', '%c', '%c', '%c' to move the cursor to %s.", /* hjkl */
 #else
-    Sprintf(sbuf, "[%c%c%c%c]\82Å%s\82Ö\88Ú\93®\82Å\82«\82é\81D",
+            "[%c%c%c%c]\82Å%s\82Ö\88Ú\93®\82Å\82«\82é\81D",
 #endif
             Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E, goal);
     putstr(tmpwin, 0, sbuf);
+#if 0 /*JP*/
+    Sprintf(sbuf,
+            "Use 'H', 'J', 'K', 'L' to fast-move the cursor, %s.",
+            fastmovemode[iflags.getloc_moveskip]);
+#else
+    Sprintf(sbuf,
+            "'H', 'J', 'K', 'L' \82Å%s\88Ú\93®\82Å\82«\82é\81D",
+            fastmovemode[iflags.getloc_moveskip]);
+#endif
+    putstr(tmpwin, 0, sbuf);
 /*JP
-    putstr(tmpwin, 0, "Use [HJKL] to move the cursor 8 units at a time.");
-*/
-    putstr(tmpwin, 0, "[HJKL]\82Å\88ê\93x\82É8\95à\88Ú\93®\82Å\82«\82é\81D");
-/*JP
-    putstr(tmpwin, 0, "Or enter a background symbol (ex. <).");
-*/
-    putstr(tmpwin, 0, "\94w\8ci\82Ì\83V\83\93\83{\83\8b\82ð\93ü\97Í\82·\82é\82Æ\82»\82Ì\88Ê\92u\82É\88Ú\93®\82·\82é(\97á\81F<)\81D");
-/*JP
-    putstr(tmpwin, 0, "Use @ to move the cursor on yourself.");
-*/
-    putstr(tmpwin, 0, "@\82Å\8e©\95ª\8e©\90g\82Ì\88Ê\92u\82É\88Ú\93®\82·\82é\81D");
-    if (getpos_hilitefunc != NULL)
-/*JP
-        putstr(tmpwin, 0, "Use $ to display valid locations.");
-*/
-        putstr(tmpwin, 0, "$\82Å\89Â\94\\82È\88Ê\92u\82ð\95\\8e¦\82·\82é\81D");
-/*JP
-    putstr(tmpwin, 0, "Use # to toggle automatic description.");
+    putstr(tmpwin, 0, "Or enter a background symbol (ex. '<').");
 */
-    putstr(tmpwin, 0, "#\82Å\90à\96¾\82Ì\8e©\93®\95\\8e¦\82ð\90Ø\82è\91Ö\82¦\82é\81D");
-    /* disgusting hack; the alternate selection characters work for any
-       getpos call, but they only matter for dowhatis (and doquickwhatis) */
-    doing_what_is = (goal == what_is_an_unknown_object);
-#if 0 /*JP:T*/
-    Sprintf(sbuf, "Type a .%s when you are at the right place.",
-            doing_what_is ? " or , or ; or :" : "");
+    putstr(tmpwin, 0, "\94w\8ci\82Ì\83V\83\93\83{\83\8b\82ð\93ü\97Í\82·\82é\82Æ\82»\82Ì\88Ê\92u\82É\88Ú\93®\82·\82é(\97á\81F'<')\81D");
+#if 0 /*JP*/
+    Sprintf(sbuf, "Use '%s' to move the cursor on yourself.",
+           visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
 #else
-    Sprintf(sbuf, "[.]%s\82Å\8c\88\92è\81D",
-            doing_what_is ? "[,][;][:]" : "");
+    Sprintf(sbuf, "'%s'\82Å\8e©\95ª\8e©\90g\82Ì\88Ê\92u\82É\88Ú\93®\82·\82é\81D",
+           visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
 #endif
     putstr(tmpwin, 0, sbuf);
+    if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) {
+        getpos_help_keyxhelp(tmpwin,
+                             visctrl(Cmd.spkeys[NHKF_GETPOS_MON_NEXT]),
+                             visctrl(Cmd.spkeys[NHKF_GETPOS_MON_PREV]),
+                             GLOC_MONS);
+    }
+    if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
+        getpos_help_keyxhelp(tmpwin,
+                             visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_NEXT]),
+                             visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_PREV]),
+                             GLOC_OBJS);
+    }
+    if (!iflags.terrainmode || (iflags.terrainmode & TER_MAP) != 0) {
+        /* these are primarily useful when choosing a travel
+           destination for the '_' command */
+        getpos_help_keyxhelp(tmpwin,
+                             visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_NEXT]),
+                             visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_PREV]),
+                             GLOC_DOOR);
+        getpos_help_keyxhelp(tmpwin,
+                             visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_NEXT]),
+                             visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_PREV]),
+                             GLOC_EXPLORE);
+        getpos_help_keyxhelp(tmpwin,
+                             visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_NEXT]),
+                             visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_PREV]),
+                             GLOC_INTERESTING);
+    }
+    Sprintf(sbuf, "Use '%s' to change fast-move mode to %s.",
+            visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]),
+            fastmovemode[!iflags.getloc_moveskip]);
+    putstr(tmpwin, 0, sbuf);
+    if (!iflags.terrainmode || (iflags.terrainmode & TER_DETECT) == 0) {
+        Sprintf(sbuf, "Use '%s' to toggle menu listing for possible targets.",
+                visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
+        putstr(tmpwin, 0, sbuf);
+        Sprintf(sbuf,
+                "Use '%s' to change the mode of limiting possible targets.",
+                visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
+        putstr(tmpwin, 0, sbuf);
+    }
+    if (!iflags.terrainmode) {
+        char kbuf[BUFSZ];
+
+        if (getpos_getvalid) {
+            Sprintf(sbuf, "Use '%s' or '%s' to move to valid locations.",
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]),
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV]));
+            putstr(tmpwin, 0, sbuf);
+        }
+        if (getpos_hilitefunc) {
+#if 0 /*JP:T*/
+            Sprintf(sbuf, "Use '%s' to display valid locations.",
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
+#else
+            Sprintf(sbuf, "'%s'\82Å\89Â\94\\82È\88Ê\92u\82ð\95\\8e¦\82·\82é\81D",
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
+#endif
+            putstr(tmpwin, 0, sbuf);
+        }
+#if 0 /*JP:T*/
+        Sprintf(sbuf, "Use '%s' to toggle automatic description.",
+                visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
+#else
+        Sprintf(sbuf, "'%s'\82Å\90à\96¾\82Ì\8e©\93®\95\\8e¦\82ð\90Ø\82è\91Ö\82¦\82é\81D",
+                visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
+#endif
+        putstr(tmpwin, 0, sbuf);
+        if (iflags.cmdassist) { /* assisting the '/' command, I suppose... */
+            Sprintf(sbuf,
+                    (iflags.getpos_coords == GPCOORDS_NONE)
+         ? "(Set 'whatis_coord' option to include coordinates with '%s' text.)"
+         : "(Reset 'whatis_coord' option to omit coordinates from '%s' text.)",
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
+        }
+        /* disgusting hack; the alternate selection characters work for any
+           getpos call, but only matter for dowhatis (and doquickwhatis) */
+       doing_what_is = (goal == what_is_an_unknown_object);
+        if (doing_what_is) {
+            Sprintf(kbuf, "'%s' or '%s' or '%s' or '%s'",
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]),
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]),
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
+        } else {
+            Sprintf(kbuf, "'%s'", visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
+        }
+#if 0 /*JP:T*/
+        Sprintf(sbuf, "Type a %s when you are at the right place.", kbuf);
+#else
+        Sprintf(sbuf, "[.]%s\82Å\8c\88\92è\81D", kbuf);
+#endif
+        putstr(tmpwin, 0, sbuf);
+        if (doing_what_is) {
+            Sprintf(sbuf,
+       "  '%s' describe current spot, show 'more info', move to another spot.",
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
+            putstr(tmpwin, 0, sbuf);
+            Sprintf(sbuf,
+                    "  '%s' describe current spot,%s move to another spot;",
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
+                    flags.help ? " prompt if 'more info'," : "");
+            putstr(tmpwin, 0, sbuf);
+            Sprintf(sbuf,
+                    "  '%s' describe current spot, move to another spot;",
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]));
+            putstr(tmpwin, 0, sbuf);
+            Sprintf(sbuf,
+                    "  '%s' describe current spot, stop looking at things;",
+                    visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]));
+            putstr(tmpwin, 0, sbuf);
+        }
+    }
     if (!force)
 /*JP
         putstr(tmpwin, 0, "Type Space or Escape when you're done.");
@@ -102,21 +259,459 @@ const char *goal;
     destroy_nhwindow(tmpwin);
 }
 
+STATIC_OVL int
+cmp_coord_distu(a, b)
+const void *a;
+const void *b;
+{
+    const coord *c1 = a;
+    const coord *c2 = b;
+    int dx, dy, dist_1, dist_2;
+
+    dx = u.ux - c1->x;
+    dy = u.uy - c1->y;
+    dist_1 = max(abs(dx), abs(dy));
+    dx = u.ux - c2->x;
+    dy = u.uy - c2->y;
+    dist_2 = max(abs(dx), abs(dy));
+
+    if (dist_1 == dist_2)
+        return (c1->y != c2->y) ? (c1->y - c2->y) : (c1->x - c2->x);
+
+    return dist_1 - dist_2;
+}
+
+#define IS_UNEXPLORED_LOC(x,y) \
+    (isok((x), (y))                                     \
+     && glyph_is_cmap(levl[(x)][(y)].glyph)             \
+     && glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone  \
+     && !levl[(x)][(y)].seenv)
+
+static struct opvar *gloc_filter_map = (struct opvar *) 0;
+
+#define GLOC_SAME_AREA(x,y)                                     \
+    (isok((x), (y))                                             \
+     && (selection_getpoint((x),(y), gloc_filter_map)))
+
+static int gloc_filter_floodfill_match_glyph;
+
+int
+gloc_filter_classify_glyph(glyph)
+int glyph;
+{
+    int c;
+
+    if (!glyph_is_cmap(glyph))
+        return 0;
+
+    c = glyph_to_cmap(glyph);
+
+    if (is_cmap_room(c) || is_cmap_furniture(c))
+        return 1;
+    else if (is_cmap_wall(c) || c == S_tree)
+        return 2;
+    else if (is_cmap_corr(c))
+        return 3;
+    else if (is_cmap_water(c))
+        return 4;
+    else if (is_cmap_lava(c))
+        return 5;
+    return 0;
+}
+
+STATIC_OVL int
+gloc_filter_floodfill_matcharea(x,y)
+int x,y;
+{
+    int glyph = back_to_glyph(x, y);
+
+    if (!levl[x][y].seenv)
+        return FALSE;
+
+    if (glyph == gloc_filter_floodfill_match_glyph)
+        return TRUE;
+
+    if (gloc_filter_classify_glyph(glyph)
+        == gloc_filter_classify_glyph(gloc_filter_floodfill_match_glyph))
+        return TRUE;
+
+    return FALSE;
+}
+
+void
+gloc_filter_floodfill(x, y)
+int x, y;
+{
+    gloc_filter_floodfill_match_glyph = back_to_glyph(x, y);
+
+    set_selection_floodfillchk(gloc_filter_floodfill_matcharea);
+    selection_floodfill(gloc_filter_map, x, y, FALSE);
+}
+
+void
+gloc_filter_init()
+{
+    if (iflags.getloc_filter == GFILTER_AREA) {
+        if (!gloc_filter_map) {
+            gloc_filter_map = selection_opvar(NULL);
+        }
+        /* special case: if we're in a doorway, try to figure out which
+           direction we're moving, and use that side of the doorway */
+        if (IS_DOOR(levl[u.ux][u.uy].typ)) {
+            if (u.dx || u.dy) {
+                gloc_filter_floodfill(u.ux + u.dx, u.uy + u.dy);
+            } else {
+                /* TODO: maybe add both sides of the doorway? */
+            }
+        } else {
+            gloc_filter_floodfill(u.ux, u.uy);
+        }
+
+
+    }
+}
+
+void
+gloc_filter_done()
+{
+    if (gloc_filter_map) {
+        opvar_free_x(gloc_filter_map);
+        gloc_filter_map = NULL;
+    }
+}
+
+STATIC_OVL boolean
+gather_locs_interesting(x, y, gloc)
+int x, y, gloc;
+{
+    /* TODO: if glyph is a pile glyph, convert to ordinary one
+     *       in order to keep tail/boulder/rock check simple.
+     */
+    int glyph = glyph_at(x, y);
+
+    if (iflags.getloc_filter == GFILTER_VIEW && !cansee(x, y))
+        return FALSE;
+    if (iflags.getloc_filter == GFILTER_AREA && !GLOC_SAME_AREA(x, y)
+        && !GLOC_SAME_AREA(x - 1, y) && !GLOC_SAME_AREA(x, y - 1)
+        && !GLOC_SAME_AREA(x + 1, y) && !GLOC_SAME_AREA(x, y + 1))
+        return FALSE;
+
+    switch (gloc) {
+    default:
+    case GLOC_MONS:
+        /* unlike '/M', this skips monsters revealed by
+           warning glyphs and remembered unseen ones */
+        return (glyph_is_monster(glyph)
+                && glyph != monnum_to_glyph(PM_LONG_WORM_TAIL));
+    case GLOC_OBJS:
+        return (glyph_is_object(glyph)
+                && glyph != objnum_to_glyph(BOULDER)
+                && glyph != objnum_to_glyph(ROCK));
+    case GLOC_DOOR:
+        return (glyph_is_cmap(glyph)
+                && (is_cmap_door(glyph_to_cmap(glyph))
+                    || is_cmap_drawbridge(glyph_to_cmap(glyph))
+                    || glyph_to_cmap(glyph) == S_ndoor));
+    case GLOC_EXPLORE:
+        return (glyph_is_cmap(glyph)
+                && (is_cmap_door(glyph_to_cmap(glyph))
+                    || is_cmap_drawbridge(glyph_to_cmap(glyph))
+                    || glyph_to_cmap(glyph) == S_ndoor
+                    || glyph_to_cmap(glyph) == S_room
+                    || glyph_to_cmap(glyph) == S_darkroom
+                    || glyph_to_cmap(glyph) == S_corr
+                    || glyph_to_cmap(glyph) == S_litcorr)
+                && (IS_UNEXPLORED_LOC(x + 1, y)
+                    || IS_UNEXPLORED_LOC(x - 1, y)
+                    || IS_UNEXPLORED_LOC(x, y + 1)
+                    || IS_UNEXPLORED_LOC(x, y - 1)));
+    case GLOC_INTERESTING:
+        return gather_locs_interesting(x,y, GLOC_DOOR)
+            || !(glyph_is_cmap(glyph)
+                 && (is_cmap_wall(glyph_to_cmap(glyph))
+                     || glyph_to_cmap(glyph) == S_tree
+                     || glyph_to_cmap(glyph) == S_bars
+                     || glyph_to_cmap(glyph) == S_ice
+                     || glyph_to_cmap(glyph) == S_air
+                     || glyph_to_cmap(glyph) == S_cloud
+                     || glyph_to_cmap(glyph) == S_lava
+                     || glyph_to_cmap(glyph) == S_water
+                     || glyph_to_cmap(glyph) == S_pool
+                     || glyph_to_cmap(glyph) == S_ndoor
+                     || glyph_to_cmap(glyph) == S_room
+                     || glyph_to_cmap(glyph) == S_darkroom
+                     || glyph_to_cmap(glyph) == S_corr
+                     || glyph_to_cmap(glyph) == S_litcorr));
+    case GLOC_VALID:
+        return (getpos_getvalid && getpos_getvalid(x,y));
+    }
+    /*NOTREACHED*/
+    return FALSE;
+}
+
+/* gather locations for monsters or objects shown on the map */
+STATIC_OVL void
+gather_locs(arr_p, cnt_p, gloc)
+coord **arr_p;
+int *cnt_p;
+int gloc;
+{
+    int x, y, pass, idx;
+
+    /*
+     * We always include the hero's location even if there is no monster
+     * (invisible hero without see invisible) or object (usual case)
+     * displayed there.  That way, the count will always be at least 1,
+     * and player has a visual indicator (cursor returns to hero's spot)
+     * highlighting when successive 'm's or 'o's have cycled all the way
+     * through all monsters or objects.
+     *
+     * Hero's spot will always sort to array[0] because it will always
+     * be the shortest distance (namely, 0 units) away from <u.ux,u.uy>.
+     */
+
+    gloc_filter_init();
+
+    *cnt_p = idx = 0;
+    for (pass = 0; pass < 2; pass++) {
+        for (x = 1; x < COLNO; x++)
+            for (y = 0; y < ROWNO; y++) {
+                if ((x == u.ux && y == u.uy)
+                    || gather_locs_interesting(x, y, gloc)) {
+                    if (!pass) {
+                        ++*cnt_p;
+                    } else {
+                        (*arr_p)[idx].x = x;
+                        (*arr_p)[idx].y = y;
+                        ++idx;
+                    }
+                }
+            }
+
+        if (!pass) /* end of first pass */
+            *arr_p = (coord *) alloc(*cnt_p * sizeof (coord));
+        else /* end of second pass */
+            qsort(*arr_p, *cnt_p, sizeof (coord), cmp_coord_distu);
+    } /* pass */
+
+    gloc_filter_done();
+}
+
+char *
+dxdy_to_dist_descr(dx, dy, fulldir)
+int dx, dy;
+boolean fulldir;
+{
+    static char buf[30];
+    int dst;
+
+    if (!dx && !dy) {
+        Sprintf(buf, "here");
+    } else if ((dst = xytod(dx, dy)) != -1) {
+        /* explicit direction; 'one step' is implicit */
+        Sprintf(buf, "%s", directionname(dst));
+    } else {
+        const char *dirnames[4][2] = {
+            { "n", "north" },
+            { "s", "south" },
+            { "w", "west" },
+            { "e", "east" } };
+        buf[0] = '\0';
+        /* 9999: protect buf[] against overflow caused by invalid values */
+        if (dy) {
+            if (abs(dy) > 9999)
+                dy = sgn(dy) * 9999;
+            Sprintf(eos(buf), "%d%s%s", abs(dy), dirnames[(dy > 0)][fulldir],
+                    dx ? "," : "");
+        }
+        if (dx) {
+            if (abs(dx) > 9999)
+                dx = sgn(dx) * 9999;
+            Sprintf(eos(buf), "%d%s", abs(dx),
+                    dirnames[2 + (dx > 0)][fulldir]);
+        }
+    }
+    return buf;
+}
+
+/* coordinate formatting for 'whatis_coord' option */
+char *
+coord_desc(x, y, outbuf, cmode)
+int x, y;
+char *outbuf, cmode;
+{
+    static char screen_fmt[16]; /* [12] suffices: "[%02d,%02d]" */
+    int dx, dy;
+
+    outbuf[0] = '\0';
+    switch (cmode) {
+    default:
+        break;
+    case GPCOORDS_COMFULL:
+    case GPCOORDS_COMPASS:
+        /* "east", "3s", "2n,4w" */
+        dx = x - u.ux;
+        dy = y - u.uy;
+        Sprintf(outbuf, "(%s)",
+                dxdy_to_dist_descr(dx, dy, cmode == GPCOORDS_COMFULL));
+        break;
+    case GPCOORDS_MAP: /* x,y */
+        /* upper left corner of map is <1,0>;
+           with default COLNO,ROWNO lower right corner is <79,20> */
+        Sprintf(outbuf, "<%d,%d>", x, y);
+        break;
+    case GPCOORDS_SCREEN: /* y+2,x */
+        /* for normal map sizes, force a fixed-width formatting so that
+           /m, /M, /o, and /O output lines up cleanly; map sizes bigger
+           than Nx999 or 999xM will still work, but not line up like normal
+           when displayed in a column setting */
+        if (!*screen_fmt)
+            Sprintf(screen_fmt, "[%%%sd,%%%sd]",
+                    (ROWNO - 1 + 2 < 100) ? "02" :  "03",
+                    (COLNO - 1 < 100) ? "02" : "03");
+        /* map line 0 is screen row 2;
+           map column 0 isn't used, map column 1 is screen column 1 */
+        Sprintf(outbuf, screen_fmt, y + 2, x);
+        break;
+    }
+    return outbuf;
+}
+
+STATIC_OVL void
+auto_describe(cx, cy)
+int cx, cy;
+{
+    coord cc;
+    int sym = 0;
+    char tmpbuf[BUFSZ];
+    const char *firstmatch = "unknown";
+
+    cc.x = cx;
+    cc.y = cy;
+    if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) {
+        (void) coord_desc(cx, cy, tmpbuf, iflags.getpos_coords);
+        custompline(SUPPRESS_HISTORY,
+                    "%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
+                    (iflags.autodescribe
+                     && getpos_getvalid && !getpos_getvalid(cx, cy))
+                      ? " (illegal)" : "",
+                    (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy))
+                      ? " (no travel path)" : "");
+        curs(WIN_MAP, cx, cy);
+        flush_screen(0);
+    }
+}
+
+boolean
+getpos_menu(ccp, gloc)
+coord *ccp;
+int gloc;
+{
+    coord *garr = DUMMY;
+    int gcount = 0;
+    winid tmpwin;
+    anything any;
+    int i, pick_cnt;
+    menu_item *picks = (menu_item *) 0;
+    char tmpbuf[BUFSZ];
+
+    gather_locs(&garr, &gcount, gloc);
+
+    if (gcount < 2) { /* gcount always includes the hero */
+        free((genericptr_t) garr);
+        You("cannot %s %s.",
+            iflags.getloc_filter == GFILTER_VIEW ? "see" : "detect",
+            gloc_descr[gloc][0]);
+        return FALSE;
+    }
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+    any = zeroany;
+
+    /* gather_locs returns array[0] == you. skip it. */
+    for (i = 1; i < gcount; i++) {
+        char fullbuf[BUFSZ];
+        coord tmpcc;
+        const char *firstmatch = "unknown";
+        int sym = 0;
+        any.a_int = i + 1;
+        tmpcc.x = garr[i].x;
+        tmpcc.y = garr[i].y;
+        if (do_screen_description(tmpcc, TRUE, sym, tmpbuf, &firstmatch)) {
+            (void) coord_desc(garr[i].x, garr[i].y, tmpbuf,
+                              iflags.getpos_coords);
+            Sprintf(fullbuf, "%s%s%s", firstmatch,
+                    (*tmpbuf ? " " : ""), tmpbuf);
+            add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, fullbuf,
+                     MENU_UNSELECTED);
+        }
+    }
+
+    Sprintf(tmpbuf, "Pick a target %s%s%s",
+            gloc_descr[gloc][1],
+            gloc_filtertxt[iflags.getloc_filter],
+            iflags.getloc_travelmode ? " for travel" : "");
+    end_menu(tmpwin, tmpbuf);
+    pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
+    destroy_nhwindow(tmpwin);
+    if (pick_cnt > 0) {
+        ccp->x = garr[picks->item.a_int - 1].x;
+        ccp->y = garr[picks->item.a_int - 1].y;
+        free((genericptr_t) picks);
+    }
+    free((genericptr_t) garr);
+    return (pick_cnt > 0);
+}
+
 int
 getpos(ccp, force, goal)
 coord *ccp;
 boolean force;
 const char *goal;
 {
+    const char *cp;
+    struct {
+        int nhkf, ret;
+    } const pick_chars_def[] = {
+        { NHKF_GETPOS_PICK, LOOK_TRADITIONAL },
+        { NHKF_GETPOS_PICK_Q, LOOK_QUICK },
+        { NHKF_GETPOS_PICK_O, LOOK_ONCE },
+        { NHKF_GETPOS_PICK_V, LOOK_VERBOSE }
+    };
+    const int mMoOdDxX_def[] = {
+        NHKF_GETPOS_MON_NEXT,
+        NHKF_GETPOS_MON_PREV,
+        NHKF_GETPOS_OBJ_NEXT,
+        NHKF_GETPOS_OBJ_PREV,
+        NHKF_GETPOS_DOOR_NEXT,
+        NHKF_GETPOS_DOOR_PREV,
+        NHKF_GETPOS_UNEX_NEXT,
+        NHKF_GETPOS_UNEX_PREV,
+        NHKF_GETPOS_INTERESTING_NEXT,
+        NHKF_GETPOS_INTERESTING_PREV,
+        NHKF_GETPOS_VALID_NEXT,
+        NHKF_GETPOS_VALID_PREV
+    };
+    char pick_chars[6];
+    char mMoOdDxX[13];
     int result = 0;
     int cx, cy, i, c;
     int sidx, tx, ty;
     boolean msg_given = TRUE; /* clear message window by default */
-    boolean auto_msg = FALSE;
     boolean show_goal_msg = FALSE;
-    static const char pick_chars[] = ".,;:";
-    const char *cp;
     boolean hilite_state = FALSE;
+    coord *garr[NUM_GLOCS] = DUMMY;
+    int gcount[NUM_GLOCS] = DUMMY;
+    int gidx[NUM_GLOCS] = DUMMY;
+
+    for (i = 0; i < SIZE(pick_chars_def); i++)
+        pick_chars[i] = Cmd.spkeys[pick_chars_def[i].nhkf];
+    pick_chars[SIZE(pick_chars_def)] = '\0';
+
+    for (i = 0; i < SIZE(mMoOdDxX_def); i++)
+        mMoOdDxX[i] = Cmd.spkeys[mMoOdDxX_def[i]];
+    mMoOdDxX[SIZE(mMoOdDxX_def)] = '\0';
 
     if (!goal)
 /*JP
@@ -124,10 +719,13 @@ const char *goal;
 */
         goal = "\96Ú\93I\92n";
     if (flags.verbose) {
-/*JP
-        pline("(For instructions type a ?)");
-*/
-        pline("(?\82Å\83w\83\8b\83v)");
+#if 0 /*JP*/
+        pline("(For instructions type a '%s')",
+              visctrl(Cmd.spkeys[NHKF_GETPOS_HELP]));
+#else
+        pline("('%s'\82Å\83w\83\8b\83v)",
+              visctrl(Cmd.spkeys[NHKF_GETPOS_HELP]));
+#endif
         msg_given = TRUE;
     }
     cx = ccp->x;
@@ -149,19 +747,8 @@ const char *goal;
             curs(WIN_MAP, cx, cy);
             flush_screen(0);
             show_goal_msg = FALSE;
-        } else if (auto_msg && !msg_given && !hilite_state) {
-            coord cc;
-            int sym = 0;
-            char tmpbuf[BUFSZ];
-            const char *firstmatch = NULL;
-
-            cc.x = cx;
-            cc.y = cy;
-            if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) {
-                pline1(firstmatch);
-                curs(WIN_MAP, cx, cy);
-                flush_screen(0);
-            }
+        } else if (iflags.autodescribe && !msg_given && !hilite_state) {
+            auto_describe(cx, cy);
         }
 
         c = nh_poskey(&tx, &ty, &sidx);
@@ -173,10 +760,10 @@ const char *goal;
             flush_screen(0);
         }
 
-        if (auto_msg)
+        if (iflags.autodescribe)
             msg_given = FALSE;
 
-        if (c == '\033') {
+        if (c == Cmd.spkeys[NHKF_ESC]) {
             cx = cy = -10;
             msg_given = TRUE; /* force clear */
             result = -1;
@@ -192,7 +779,7 @@ const char *goal;
         }
         if ((cp = index(pick_chars, c)) != 0) {
             /* '.' => 0, ',' => 1, ';' => 2, ':' => 3 */
-            result = (int) (cp - pick_chars);
+            result = pick_chars_def[(int) (cp - pick_chars)].ret;
             break;
         }
         for (i = 0; i < 8; i++) {
@@ -205,8 +792,24 @@ const char *goal;
             } else if (Cmd.alphadirchars[i] == lowc((char) c)
                        || (Cmd.num_pad && Cmd.dirchars[i] == (c & 0177))) {
                 /* a shifted movement letter or Meta-digit */
-                dx = 8 * xdir[i];
-                dy = 8 * ydir[i];
+                if (iflags.getloc_moveskip) {
+                    /* skip same glyphs */
+                    int glyph = glyph_at(cx, cy);
+
+                    dx = xdir[i];
+                    dy = ydir[i];
+                    while (isok(cx + dx, cy + dy)
+                           && glyph == glyph_at(cx + dx, cy + dy)
+                           && isok(cx + dx + xdir[i], cy + dy + ydir[i])
+                           && glyph == glyph_at(cx + dx + xdir[i],
+                                                cy + dy + ydir[i])) {
+                        dx += xdir[i];
+                        dy += ydir[i];
+                    }
+                } else {
+                    dx = 8 * xdir[i];
+                    dy = 8 * ydir[i];
+                }
             } else
                 continue;
 
@@ -230,48 +833,116 @@ const char *goal;
             goto nxtc;
         }
 
-        if (c == '?' || redraw_cmd(c)) {
-            if (c == '?')
+        if (c == Cmd.spkeys[NHKF_GETPOS_HELP] || redraw_cmd(c)) {
+            if (c == Cmd.spkeys[NHKF_GETPOS_HELP])
                 getpos_help(force, goal);
-            else         /* ^R */
+            else /* ^R */
                 docrt(); /* redraw */
             /* update message window to reflect that we're still targetting */
             show_goal_msg = TRUE;
             msg_given = TRUE;
-        } else if ((c == '$') && (getpos_hilitefunc != NULL)) {
+        } else if (c == Cmd.spkeys[NHKF_GETPOS_SHOWVALID]
+                   && getpos_hilitefunc) {
             if (!hilite_state) {
                 (*getpos_hilitefunc)(0);
                 (*getpos_hilitefunc)(1);
                 hilite_state = TRUE;
             }
             goto nxtc;
-        } else if (c == '#') {
-            auto_msg = !auto_msg;
-#if 0 /*JP*/
+        } else if (c == Cmd.spkeys[NHKF_GETPOS_AUTODESC]) {
+            iflags.autodescribe = !iflags.autodescribe;
+#if 0 /*JP:T*/
             pline("Automatic description %sis %s.",
                   flags.verbose ? "of features under cursor " : "",
-                  auto_msg ? "on" : "off");
+                  iflags.autodescribe ? "on" : "off");
 #else
             pline("%s\90à\96¾\8e©\93®\95\\8e¦\81F%s",
                   flags.verbose ? "\83J\81[\83\\83\8b\82Ì\89º\82É\82 \82é\82à\82Ì\82Ì" : "",
-                  auto_msg ? "\83I\83\93" : "\83I\83t");
+                  iflags.autodescribe ? "\83I\83\93" : "\83I\83t");
 #endif
-            if (!auto_msg)
+            if (!iflags.autodescribe)
                 show_goal_msg = TRUE;
             msg_given = TRUE;
             goto nxtc;
-        } else if (c == '@') {
+        } else if (c == Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]) {
+            const char *const view_filters[NUM_GFILTER] = {
+                "Not limiting targets",
+                "Limiting targets to in sight",
+                "Limiting targets to in same area"
+            };
+            iflags.getloc_filter = (iflags.getloc_filter + 1) % NUM_GFILTER;
+            for (i = 0; i < NUM_GLOCS; i++) {
+                if (garr[i]) {
+                    free((genericptr_t) garr[i]);
+                    garr[i] = NULL;
+                }
+                gidx[i] = gcount[i] = 0;
+            }
+            pline("%s.", view_filters[iflags.getloc_filter]);
+            msg_given = TRUE;
+            goto nxtc;
+        } else if (c == Cmd.spkeys[NHKF_GETPOS_MENU]) {
+            iflags.getloc_usemenu = !iflags.getloc_usemenu;
+            pline("%s a menu to show possible targets.",
+                  iflags.getloc_usemenu ? "Using" : "Not using");
+            msg_given = TRUE;
+            goto nxtc;
+        } else if (c == Cmd.spkeys[NHKF_GETPOS_SELF]) {
+            /* reset 'm&M', 'o&O', &c; otherwise, there's no way for player
+               to achieve that except by manually cycling through all spots */
+            for (i = 0; i < NUM_GLOCS; i++)
+                gidx[i] = 0;
             cx = u.ux;
             cy = u.uy;
             goto nxtc;
+        } else if (c == Cmd.spkeys[NHKF_GETPOS_MOVESKIP]) {
+            iflags.getloc_moveskip = !iflags.getloc_moveskip;
+            pline("%skipping over similar terrain when fastmoving the cursor.",
+                  iflags.getloc_moveskip ? "S" : "Not s");
+        } else if ((cp = index(mMoOdDxX, c)) != 0) { /* 'm|M', 'o|O', &c */
+            /* nearest or farthest monster or object or door or unexplored */
+            int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */
+                gloc = gtmp >> 1;             /* 0..3 */
+
+            if (iflags.getloc_usemenu) {
+                coord tmpcrd;
+                if (getpos_menu(&tmpcrd, gloc)) {
+                    cx = tmpcrd.x;
+                    cy = tmpcrd.y;
+                }
+                goto nxtc;
+            }
+
+            if (!garr[gloc]) {
+                gather_locs(&garr[gloc], &gcount[gloc], gloc);
+                gidx[gloc] = 0; /* garr[][0] is hero's spot */
+            }
+            if (!(gtmp & 1)) {  /* c=='m' || c=='o' || c=='d' || c=='x') */
+                gidx[gloc] = (gidx[gloc] + 1) % gcount[gloc];
+            } else {            /* c=='M' || c=='O' || c=='D' || c=='X') */
+                if (--gidx[gloc] < 0)
+                    gidx[gloc] = gcount[gloc] - 1;
+            }
+            cx = garr[gloc][gidx[gloc]].x;
+            cy = garr[gloc][gidx[gloc]].y;
+            goto nxtc;
         } else {
             if (!index(quitchars, c)) {
                 char matching[MAXPCHARS];
                 int pass, lo_x, lo_y, hi_x, hi_y, k = 0;
+
                 (void) memset((genericptr_t) matching, 0, sizeof matching);
-                for (sidx = 1; sidx < MAXPCHARS; sidx++)
+                for (sidx = 1; sidx < MAXPCHARS; sidx++) { /* [0] left as 0 */
+                    if (IS_DOOR(sidx) || IS_WALL(sidx)
+                        || sidx == SDOOR || sidx == SCORR
+                        || glyph_to_cmap(k) == S_room
+                        || glyph_to_cmap(k) == S_darkroom
+                        || glyph_to_cmap(k) == S_corr
+                        || glyph_to_cmap(k) == S_litcorr)
+                        continue;
                     if (c == defsyms[sidx].sym || c == (int) showsyms[sidx])
                         matching[sidx] = (char) ++k;
+                }
                 if (k) {
                     for (pass = 0; pass <= 1; pass++) {
                         /* pass 0: just past current pos to lower right;
@@ -282,34 +953,39 @@ const char *goal;
                             lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1;
                             hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1;
                             for (tx = lo_x; tx <= hi_x; tx++) {
-                                /* look at dungeon feature, not at
-                                 * user-visible glyph */
-                                k = back_to_glyph(tx, ty);
-                                /* uninteresting background glyph */
+                                /* first, look at what is currently visible
+                                   (might be monster) */
+                                k = glyph_at(tx, ty);
                                 if (glyph_is_cmap(k)
-                                    && (IS_DOOR(levl[tx][ty].typ)
-                                        || glyph_to_cmap(k) == S_room
-                                        || glyph_to_cmap(k) == S_darkroom
-                                        || glyph_to_cmap(k) == S_corr
-                                        || glyph_to_cmap(k) == S_litcorr)) {
-                                    /* what hero remembers to be at tx,ty */
-                                    k = glyph_at(tx, ty);
+                                    && matching[glyph_to_cmap(k)])
+                                    goto foundc;
+                                /* next, try glyph that's remembered here
+                                   (might be trap or object) */
+                                if (level.flags.hero_memory
+                                    /* !terrainmode: don't move to remembered
+                                       trap or object if not currently shown */
+                                    && !iflags.terrainmode) {
+                                    k = levl[tx][ty].glyph;
+                                    if (glyph_is_cmap(k)
+                                        && matching[glyph_to_cmap(k)])
+                                        goto foundc;
                                 }
-                                if (glyph_is_cmap(k)
-                                    && matching[glyph_to_cmap(k)]
-                                    && levl[tx][ty].seenv
-                                    && (!IS_WALL(levl[tx][ty].typ))
-                                    && (levl[tx][ty].typ != SDOOR)
-                                    && glyph_to_cmap(k) != S_room
-                                    && glyph_to_cmap(k) != S_corr
-                                    && glyph_to_cmap(k) != S_litcorr) {
-                                    cx = tx, cy = ty;
-                                    if (msg_given) {
-                                        clear_nhwindow(WIN_MESSAGE);
-                                        msg_given = FALSE;
-                                    }
-                                    goto nxtc;
+                                /* last, try actual terrain here (shouldn't
+                                   we be using lastseentyp[][] instead?) */
+                                if (levl[tx][ty].seenv) {
+                                    k = back_to_glyph(tx, ty);
+                                    if (glyph_is_cmap(k)
+                                        && matching[glyph_to_cmap(k)])
+                                        goto foundc;
+                                }
+                                continue;
+                            foundc:
+                                cx = tx, cy = ty;
+                                if (msg_given) {
+                                    clear_nhwindow(WIN_MESSAGE);
+                                    msg_given = FALSE;
                                 }
+                                goto nxtc;
                             } /* column */
                         }     /* row */
                     }         /* pass */
@@ -327,14 +1003,16 @@ const char *goal;
                         Strcpy(note, "aborted");
 */
                         Strcpy(note, "\92\86\92f\82µ\82½");
-                    else
+                    else /* hjkl */
 #if 0 /*JP*/
-                        Sprintf(note, "use %c%c%c%c or .", /* hjkl */
+                        Sprintf(note, "use '%c', '%c', '%c', '%c' or '%s'",
+                                Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E,
+                                visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
 #else
-                        Sprintf(note, "%c%c%c%c\82Å\88Ú\93®\81C.\82Å\8fI\97¹", /* hjkl */
+                        Sprintf(note, "%c%c%c%c\82Å\88Ú\93®\81C%s\82Å\8fI\97¹",
+                                Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E,
+                                visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
 #endif
-                                Cmd.move_W, Cmd.move_S, Cmd.move_N,
-                                Cmd.move_E);
 /*JP
                     pline("Unknown direction: '%s' (%s).", visctrl((char) c),
 */
@@ -370,7 +1048,11 @@ const char *goal;
         clear_nhwindow(WIN_MESSAGE);
     ccp->x = cx;
     ccp->y = cy;
-    getpos_hilitefunc = NULL;
+    for (i = 0; i < NUM_GLOCS; i++)
+        if (garr[i])
+            free((genericptr_t) garr[i]);
+    getpos_hilitefunc = (void FDECL((*), (int))) 0;
+    getpos_getvalid = (boolean FDECL((*), (int, int))) 0;
     return result;
 }
 
@@ -477,15 +1159,45 @@ const char *name;
     return mtmp;
 }
 
+/* check whether user-supplied name matches or nearly matches an unnameable
+   monster's name; if so, give an alternate reject message for do_mname() */
+STATIC_OVL boolean
+alreadynamed(mtmp, monnambuf, usrbuf)
+struct monst *mtmp;
+char *monnambuf, *usrbuf;
+{
+    char pronounbuf[10], *p;
+
+    if (fuzzymatch(usrbuf, monnambuf, " -_", TRUE)
+        /* catch trying to name "the Oracle" as "Oracle" */
+        || (!strncmpi(monnambuf, "the ", 4)
+            && fuzzymatch(usrbuf, monnambuf + 4, " -_", TRUE))
+        /* catch trying to name "invisible Orcus" as "Orcus" */
+        || ((p = strstri(monnambuf, "invisible ")) != 0
+            && fuzzymatch(usrbuf, p + 10, " -_", TRUE))
+        /* catch trying to name "the {priest,Angel} of Crom" as "Crom" */
+        || ((p = strstri(monnambuf, " of ")) != 0
+            && fuzzymatch(usrbuf, p + 4, " -_", TRUE))) {
+        pline("%s is already called %s.",
+              upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf);
+        return TRUE;
+    } else if (mtmp->data == &mons[PM_JUIBLEX]
+               && strstri(monnambuf, "Juiblex")
+               && !strcmpi(usrbuf, "Jubilex")) {
+        pline("%s doesn't like being called %s.", upstart(monnambuf), usrbuf);
+        return TRUE;
+    }
+    return FALSE;
+}
+
 /* allow player to assign a name to some chosen monster */
 STATIC_OVL void
 do_mname()
 {
-    char buf[BUFSZ], monnambuf[BUFSZ];
+    char buf[BUFSZ] = DUMMY, monnambuf[BUFSZ], qbuf[QBUFSZ];
     coord cc;
-    register int cx, cy;
-    register struct monst *mtmp;
-    char qbuf[QBUFSZ];
+    int cx, cy;
+    struct monst *mtmp = 0;
 
     if (Hallucination) {
 /*JP
@@ -505,9 +1217,9 @@ do_mname()
     cy = cc.y;
 
     if (cx == u.ux && cy == u.uy) {
-        if (u.usteed && canspotmon(u.usteed))
+        if (u.usteed && canspotmon(u.usteed)) {
             mtmp = u.usteed;
-        else {
+        else {
 /*JP
             pline("This %s creature is called %s and cannot be renamed.",
 */
@@ -542,41 +1254,50 @@ do_mname()
     /* 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
-       name formatting routines which ignore any user-supplied name */
-    if (mtmp->data->geno & G_UNIQ)
+    /* Unique monsters have their own specific names or titles.
+     * Shopkeepers, temple priests and other minions use alternate
+     * name formatting routines which ignore any user-supplied name.
+     *
+     * Don't say the name is being rejected if it happens to match
+     * the existing name.
+     */
+    if ((mtmp->data->geno & G_UNIQ) && !mtmp->ispriest) {
+        if (!alreadynamed(mtmp, monnambuf, buf))
 /*JP
         pline("%s doesn't like being called names!", upstart(monnambuf));
 */
         pline("%s\82Í\82 \82¾\96¼\82Å\8cÄ\82Î\82ê\82é\82Ì\82ª\8c\99\82¢\82È\82æ\82¤\82¾\81I", Monnam(mtmp));
-    else if (mtmp->isshk
-             && !(Deaf || mtmp->msleeping || !mtmp->mcanmove
-                  || mtmp->data->msound <= MS_ANIMAL))
+    } else if (mtmp->isshk
+               && !(Deaf || mtmp->msleeping || !mtmp->mcanmove
+                    || mtmp->data->msound <= MS_ANIMAL)) {
+        if (!alreadynamed(mtmp, monnambuf, buf))
 /*JP
         verbalize("I'm %s, not %s.", shkname(mtmp), buf);
 */
         verbalize("\8e\84\82Í%s\82¾\81C%s\82Å\82Í\82È\82¢\81D", shkname(mtmp), buf);
-    else if (mtmp->ispriest || mtmp->isminion || mtmp->isshk)
+    } else if (mtmp->ispriest || mtmp->isminion || mtmp->isshk) {
+        if (!alreadynamed(mtmp, monnambuf, buf))
 /*JP
         pline("%s will not accept the name %s.", upstart(monnambuf), buf);
 */
         pline("%s\82Í%s\82Æ\82¢\82¤\96¼\91O\82ð\8eó\82¯\82¢\82ê\82È\82©\82Á\82½\81D", monnambuf, buf);
-    else
+    else
         (void) christen_monst(mtmp, buf);
 }
 
+STATIC_VAR int via_naming = 0;
+
 /*
- * This routine changes the address of obj. Be careful not to call it
- * when there might be pointers around in unknown places. For now: only
- * when obj is in the inventory.
+ * This routine used to change the address of 'obj' so be unsafe if not
+ * used with extreme care.  Applying a name to an object no longer
+ * allocates a replacement object, so that old risk is gone.
  */
 STATIC_OVL
 void
 do_oname(obj)
 register struct obj *obj;
 {
-    char *bufp, buf[BUFSZ], bufcpy[BUFSZ], qbuf[QBUFSZ];
+    char *bufp, buf[BUFSZ] = DUMMY, bufcpy[BUFSZ], qbuf[QBUFSZ];
     const char *aname;
     short objtyp;
 #if 1 /*JP*/
@@ -605,6 +1326,16 @@ register struct obj *obj;
     /* strip leading and trailing spaces; unnames item if all spaces */
     (void) mungspaces(buf);
 
+    /*
+     * We don't violate illiteracy conduct here, although it is
+     * arguable that we should for anything other than "X".  Doing so
+     * would make attaching player's notes to hero's inventory have an
+     * in-game effect, which may or may not be the correct thing to do.
+     *
+     * We do violate illiteracy in oname() if player creates Sting or
+     * Orcrist, clearly being literate (no pun intended...).
+     */
+
     /* relax restrictions over proper capitalization for artifacts */
     if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp)
 #if 0 /*JP*/
@@ -612,7 +1343,7 @@ register struct obj *obj;
 #else
         {
             is_japanese = is_kanji(*buf);
-            Strcpy(buf, aname);
+        Strcpy(buf, aname);
         }
 #endif
 
@@ -649,8 +1380,13 @@ register struct obj *obj;
         You("engrave: \"%s\".", buf);
 */
         You("\8d\8f\82ñ\82¾: \81u%s\81v\81D",buf);
+        /* violate illiteracy conduct since hero attempted to write
+           a valid artifact name */
+        u.uconduct.literate++;
     }
+    ++via_naming; /* This ought to be an argument rather than a static... */
     obj = oname(obj, buf);
+    --via_naming; /* ...but oname() is used in a lot of places, so defer. */
 }
 
 struct obj *
@@ -697,6 +1433,10 @@ const char *name;
         /* if obj is owned by a shop, increase your bill */
         if (obj->unpaid)
             alter_cost(obj, 0L);
+        if (via_naming) {
+            /* violate illiteracy conduct since successfully wrote arti-name */
+            u.uconduct.literate++;
+        }
     }
     if (carried(obj))
         update_inventory();
@@ -832,32 +1572,64 @@ docallcmd()
     return 0;
 }
 
+/* for use by safe_qbuf() */
+STATIC_PTR char *
+docall_xname(obj)
+struct obj *obj;
+{
+    struct obj otemp;
+
+    otemp = *obj;
+    otemp.oextra = (struct oextra *) 0;
+    otemp.quan = 1L;
+    /* in case water is already known, convert "[un]holy water" to "water" */
+    otemp.blessed = otemp.cursed = 0;
+    /* remove attributes that are doname() caliber but get formatted
+       by xname(); most of these fixups aren't really needed because the
+       relevant type of object isn't callable so won't reach this far */
+    if (otemp.oclass == WEAPON_CLASS)
+        otemp.opoisoned = 0; /* not poisoned */
+    else if (otemp.oclass == POTION_CLASS)
+        otemp.odiluted = 0; /* not diluted */
+    else if (otemp.otyp == TOWEL || otemp.otyp == STATUE)
+        otemp.spe = 0; /* not wet or historic */
+    else if (otemp.otyp == TIN)
+        otemp.known = 0; /* suppress tin type (homemade, &c) and mon type */
+    else if (otemp.otyp == FIGURINE)
+        otemp.corpsenm = NON_PM; /* suppress mon type */
+    else if (otemp.otyp == HEAVY_IRON_BALL)
+        otemp.owt = objects[HEAVY_IRON_BALL].oc_weight; /* not "very heavy" */
+    else if (otemp.oclass == FOOD_CLASS && otemp.globby)
+        otemp.owt = 120; /* 6*20, neither a small glob nor a large one */
+
+    return an(xname(&otemp));
+}
+
 void
 docall(obj)
-register struct obj *obj;
+struct obj *obj;
 {
-    char buf[BUFSZ], qbuf[QBUFSZ];
-    struct obj otemp;
-    register char **str1;
+    char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
+    char **str1;
 
     if (!obj->dknown)
         return; /* probably blind */
-    otemp = *obj;
-    otemp.quan = 1L;
-    otemp.oextra = (struct oextra *) 0;
 
-    if (objects[otemp.otyp].oc_class == POTION_CLASS && otemp.fromsink)
+    if (obj->oclass == POTION_CLASS && obj->fromsink)
         /* kludge, meaning it's sink water */
 /*JP
         Sprintf(qbuf, "Call a stream of %s fluid:",
 */
         Sprintf(qbuf, "%s\89t\91Ì:",
-                OBJ_DESCR(objects[otemp.otyp]));
+                OBJ_DESCR(objects[obj->otyp]));
     else
-/*JP
-        Sprintf(qbuf, "Call %s:", an(xname(&otemp)));
-*/
-        Sprintf(qbuf, "%s\82É\89½\82Æ\96¼\91O\82ð\82Â\82¯\82é\81H", an(xname(&otemp)));
+#if 0 /*JP*/
+        (void) safe_qbuf(qbuf, "Call ", ":", obj,
+                         docall_xname, simpleonames, "thing");
+#else
+        (void) safe_qbuf(qbuf, "", "\82É\89½\82Æ\96¼\91O\82ð\95t\82¯\82é\81H", obj,
+                         docall_xname, simpleonames, "\82±\82ê");
+#endif
     getlin(qbuf, buf);
     if (!*buf || *buf == '\033')
         return;
@@ -1012,6 +1784,8 @@ rndghostname()
  * a_monnam:    a newt          it      an invisible orc        Fido
  * m_monnam:    newt            xan     orc                     Fido
  * y_monnam:    your newt     your xan  your invisible orc      Fido
+ * noname_monnam(mon,article):
+ *              article newt    art xan art invisible orc       art dog
  */
 
 /* Bug: if the monster is a priest or shopkeeper, not every one of these
@@ -1032,13 +1806,14 @@ const char *adjective;
 int suppress;
 /* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE.
  * EXACT_NAME: combination of all the above
+ * SUPPRESS_NAME: omit monster's assigned name (unless uniq w/ pname).
  */
 boolean called;
 {
     char *buf = nextmbuf();
     struct permonst *mdat = mtmp->data;
     const char *pm_name = mdat->mname;
-    boolean do_hallu, do_invis, do_it, do_saddle;
+    boolean do_hallu, do_invis, do_it, do_saddle, do_name;
 #if 0 /*JP*/
     boolean name_at_start, has_adjectives;
     char *bp;
@@ -1055,6 +1830,7 @@ boolean called;
             && !program_state.gameover && mtmp != u.usteed
             && !(u.uswallow && mtmp == u.ustuck) && !(suppress & SUPPRESS_IT);
     do_saddle = !(suppress & SUPPRESS_SADDLE);
+    do_name = !(suppress & SUPPRESS_NAME) || type_is_pname(mdat);
 
     buf[0] = '\0';
 
@@ -1170,7 +1946,7 @@ boolean called;
 #if 0 /*JP*/
         name_at_start = bogon_is_pname(rnamecode);
 #endif
-    } else if (has_mname(mtmp)) {
+    } else if (do_name && has_mname(mtmp)) {
         char *name = MNAME(mtmp);
 
         if (mdat == &mons[PM_GHOST]) {
@@ -1291,7 +2067,7 @@ struct monst *mtmp;
 {
     return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
                     (has_mname(mtmp)) ? (SUPPRESS_SADDLE | SUPPRESS_IT)
-                                       : SUPPRESS_IT,
+                                      : SUPPRESS_IT,
                     FALSE);
 }
 
@@ -1315,7 +2091,17 @@ struct monst *mtmp;
     return  bp;
 }
 
-/* monster's own name */
+/* return "a dog" rather than "Fido", honoring hallucination and visibility */
+char *
+noname_monnam(mtmp, article)
+struct monst *mtmp;
+int article;
+{
+    return x_monnam(mtmp, article, (char *) 0, SUPPRESS_NAME, FALSE);
+}
+
+/* monster's own name -- overrides hallucination and [in]visibility
+   so shouldn't be used in ordinary messages (mainly for disclosure) */
 char *
 m_monnam(mtmp)
 struct monst *mtmp;
@@ -1513,6 +2299,24 @@ rndcolor()
                                            : c_obj_colors[k];
 }
 
+static NEARDATA const char *const hliquids[] = {
+    "yoghurt", "oobleck", "clotted blood", "diluted water", "purified water",
+    "instant coffee", "tea", "herbal infusion", "liquid rainbow",
+    "creamy foam", "mulled wine", "bouillon", "nectar", "grog", "flubber",
+    "ketchup", "slow light", "oil", "vinaigrette", "liquid crystal", "honey",
+    "caramel sauce", "ink", "aqueous humour", "milk substitute", "fruit juice",
+    "glowing lava", "gastric acid", "mineral water", "cough syrup", "quicksilver",
+    "sweet vitriol", "grey goo", "pink slime",
+};
+
+const char *
+hliquid(liquidpref)
+const char *liquidpref;
+{
+    return (Hallucination || !liquidpref) ? hliquids[rn2(SIZE(hliquids))]
+                                         : liquidpref;
+}
+
 /* Aliases for road-runner nemesis
  */
 static const char *const coynames[] = {
@@ -1535,7 +2339,7 @@ char *buf;
         Sprintf(buf, "%s - %s",
                 x_monnam(mtmp, ARTICLE_NONE, (char *) 0, 0, TRUE),
                 mtmp->mcan ? coynames[SIZE(coynames) - 1]
-                           : coynames[rn2(SIZE(coynames) - 1)]);
+                           : coynames[mtmp->m_id % (SIZE(coynames) - 1)]);
     }
     return buf;
 }
@@ -1548,7 +2352,7 @@ static const char *const sir_Terry_novels[] = {
     "Lords and Ladies", "Men at Arms", "Soul Music", "Interesting Times",
     "Maskerade", "Feet of Clay", "Hogfather", "Jingo", "The Last Continent",
     "Carpe Jugulum", "The Fifth Elephant", "The Truth", "Thief of Time",
-    "The Last Hero", "The Amazing Maurice and his Educated Rodents",
+    "The Last Hero", "The Amazing Maurice and His Educated Rodents",
     "Night Watch", "The Wee Free Men", "Monstrous Regiment",
     "A Hat Full of Sky", "Going Postal", "Thud!", "Wintersmith",
     "Making Money", "Unseen Academicals", "I Shall Wear Midnight", "Snuff",
index 8c76f0a..5eb875f 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 do_wear.c       $NHDT-Date: 1446975698 2015/11/08 09:41:38 $  $NHDT-Branch: master $:$NHDT-Revision: 1.87 $ */
+/* NetHack 3.6 do_wear.c       $NHDT-Date: 1514072526 2017/12/23 23:42:06 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.100 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -37,7 +38,7 @@ STATIC_DCL void FDECL(on_msg, (struct obj *));
 STATIC_DCL void FDECL(toggle_stealth, (struct obj *, long, BOOLEAN_P));
 STATIC_DCL void FDECL(toggle_displacement, (struct obj *, long, BOOLEAN_P));
 STATIC_PTR int NDECL(Armor_on);
-STATIC_PTR int NDECL(Boots_on);
+/* int NDECL(Boots_on); -- moved to extern.h */
 STATIC_PTR int NDECL(Cloak_on);
 STATIC_PTR int NDECL(Helmet_on);
 STATIC_PTR int NDECL(Gloves_on);
@@ -198,7 +199,6 @@ boolean on;
  * [Blindf_on() is an exception and calls setworn() itself.]
  */
 
-STATIC_PTR
 int
 Boots_on(VOID_ARGS)
 {
@@ -855,11 +855,12 @@ Amulet_on()
     case AMULET_OF_STRANGULATION:
         if (can_be_strangled(&youmonst)) {
             makeknown(AMULET_OF_STRANGULATION);
+            Strangled = 6L;
+            context.botl = TRUE;
 /*JP
             pline("It constricts your throat!");
 */
             pline("\96\82\8f\9c\82¯\82Í\82 \82È\82½\82Ì\8dA\82ð\8di\82ß\82Â\82¯\82½\81I");
-            Strangled = 6L;
         }
         break;
     case AMULET_OF_RESTFUL_SLEEP: {
@@ -900,10 +901,13 @@ Amulet_off()
             setworn((struct obj *) 0, W_AMUL);
             if (!breathless(youmonst.data) && !amphibious(youmonst.data)
                 && !Swimming) {
-/*JP
-                You("suddenly inhale an unhealthy amount of water!");
-*/
-                You("\93Ë\91R\81C\91å\97Ê\82Ì\90\85\82ð\88ù\82Ý\8d\9e\82ñ\82¾\81I");
+#if 0 /*JP*/
+                You("suddenly inhale an unhealthy amount of %s!",
+                    hliquid("water"));
+#else
+                You("\93Ë\91R\81C\91å\97Ê\82Ì%s\82ð\88ù\82Ý\8d\9e\82ñ\82¾\81I",
+                    hliquid("\90\85"));
+#endif
                 (void) drown();
             }
             return;
@@ -911,6 +915,8 @@ Amulet_off()
         break;
     case AMULET_OF_STRANGULATION:
         if (Strangled) {
+            Strangled = 0L;
+            context.botl = TRUE;
             if (Breathless)
 /*JP
                 Your("%s is no longer constricted!", body_part(NECK));
@@ -921,7 +927,6 @@ Amulet_off()
                 You("can breathe more easily!");
 */
                 You("\8ay\82É\8cÄ\8bz\82Å\82«\82é\82æ\82¤\82É\82È\82Á\82½\81I");
-            Strangled = 0L;
         }
         break;
     case AMULET_OF_RESTFUL_SLEEP:
@@ -1364,37 +1369,30 @@ struct obj *obj; /* if null, do all worn items; otherwise just obj itself */
 }
 
 /* check whether the target object is currently being put on (or taken off--
-   also checks for doffing) */
+   also checks for doffing--[why?]) */
 boolean
 donning(otmp)
 struct obj *otmp;
 {
-    /* long what = (occupation == take_off) ? context.takeoff.what : 0L; */
-    long what = context.takeoff.what; /* if nonzero, occupation is implied */
     boolean result = FALSE;
 
-    /* 'W' and 'T' set afternmv, 'A' sets context.takeoff.what */
-    if (otmp == uarm)
-        result = (afternmv == Armor_on || afternmv == Armor_off
-                  || what == WORN_ARMOR);
+    /* 'W' (or 'P' used for armor) sets afternmv */
+    if (doffing(otmp))
+        result = TRUE;
+    else if (otmp == uarm)
+        result = (afternmv == Armor_on);
     else if (otmp == uarmu)
-        result = (afternmv == Shirt_on || afternmv == Shirt_off
-                  || what == WORN_SHIRT);
+        result = (afternmv == Shirt_on);
     else if (otmp == uarmc)
-        result = (afternmv == Cloak_on || afternmv == Cloak_off
-                  || what == WORN_CLOAK);
+        result = (afternmv == Cloak_on);
     else if (otmp == uarmf)
-        result = (afternmv == Boots_on || afternmv == Boots_off
-                  || what == WORN_BOOTS);
+        result = (afternmv == Boots_on);
     else if (otmp == uarmh)
-        result = (afternmv == Helmet_on || afternmv == Helmet_off
-                  || what == WORN_HELMET);
+        result = (afternmv == Helmet_on);
     else if (otmp == uarmg)
-        result = (afternmv == Gloves_on || afternmv == Gloves_off
-                  || what == WORN_GLOVES);
+        result = (afternmv == Gloves_on);
     else if (otmp == uarms)
-        result = (afternmv == Shield_on || afternmv == Shield_off
-                  || what == WORN_SHIELD);
+        result = (afternmv == Shield_on);
 
     return result;
 }
@@ -1408,7 +1406,7 @@ struct obj *otmp;
     long what = context.takeoff.what;
     boolean result = FALSE;
 
-    /* 'T' (also 'W') sets afternmv, 'A' sets context.takeoff.what */
+    /* 'T' (or 'R' used for armor) sets afternmv, 'A' sets takeoff.what */
     if (otmp == uarm)
         result = (afternmv == Armor_off || what == WORN_ARMOR);
     else if (otmp == uarmu)
@@ -1423,10 +1421,48 @@ struct obj *otmp;
         result = (afternmv == Gloves_off || what == WORN_GLOVES);
     else if (otmp == uarms)
         result = (afternmv == Shield_off || what == WORN_SHIELD);
+    /* these 1-turn items don't need 'afternmv' checks */
+    else if (otmp == uamul)
+        result = (what == WORN_AMUL);
+    else if (otmp == uleft)
+        result = (what == LEFT_RING);
+    else if (otmp == uright)
+        result = (what == RIGHT_RING);
+    else if (otmp == ublindf)
+        result = (what == WORN_BLINDF);
+    else if (otmp == uwep)
+        result = (what == W_WEP);
+    else if (otmp == uswapwep)
+        result = (what == W_SWAPWEP);
+    else if (otmp == uquiver)
+        result = (what == W_QUIVER);
 
     return result;
 }
 
+/* despite their names, cancel_don() and cancel_doff() both apply to both
+   donning and doffing... */
+void
+cancel_doff(obj, slotmask)
+struct obj *obj;
+long slotmask;
+{
+    /* Called by setworn() for old item in specified slot or by setnotworn()
+     * for specified item.  We don't want to call cancel_don() if we got
+     * here via <X>_off() -> setworn((struct obj *)0) -> cancel_doff()
+     * because that would stop the 'A' command from continuing with next
+     * selected item.  So do_takeoff() sets a flag in takeoff.mask for us.
+     * [For taking off an individual item with 'T'/'R'/'w-', it doesn't
+     * matter whether cancel_don() gets called here--the item has already
+     * been removed by now.]
+     */
+    if (!(context.takeoff.mask & I_SPECIAL) && donning(obj))
+        cancel_don(); /* applies to doffing too */
+    context.takeoff.mask &= ~slotmask;
+}
+
+/* despite their names, cancel_don() and cancel_doff() both apply to both
+   donning and doffing... */
 void
 cancel_don()
 {
@@ -1437,7 +1473,7 @@ cancel_don()
     context.takeoff.cancelled_don =
         (afternmv == Boots_on || afternmv == Helmet_on
          || afternmv == Gloves_on || afternmv == Armor_on);
-    afternmv = 0;
+    afternmv = (int NDECL((*))) 0;
     nomovemsg = (char *) 0;
     multi = 0;
     context.takeoff.delay = 0;
@@ -1463,11 +1499,11 @@ struct obj *stolenobj; /* no message if stolenobj is already being doffing */
 
     /* donning() returns True when doffing too; doffing() is more specific */
     putting_on = !doffing(otmp);
-    /* cancel_don() looks at afternmv; it also serves as cancel_doff() */
+    /* cancel_don() looks at afternmv; it can also cancel doffing */
     cancel_don();
     /* don't want <armor>_on() or <armor>_off() being called
        by unmul() since the on or off action isn't completing */
-    afternmv = 0;
+    afternmv = (int NDECL((*))) 0;
     if (putting_on || otmp != stolenobj) {
 #if 0 /*JP*/
         Sprintf(buf, "You stop %s %s.",
@@ -1546,6 +1582,10 @@ STATIC_OVL int
 armor_or_accessory_off(obj)
 struct obj *obj;
 {
+#if 1 /*JP*/
+    const char *j;
+    const char *m;
+#endif
     if (!(obj->owornmask & (W_ARMOR | W_ACCESSORY))) {
 /*JP
         You("are not wearing that.");
@@ -1553,6 +1593,32 @@ struct obj *obj;
         You("\82»\82ê\82ð\90g\82É\82Â\82¯\82Ä\82¢\82È\82¢\81D");
         return 0;
     }
+    if (obj == uskin
+        || ((obj == uarm) && uarmc)
+        || ((obj == uarmu) && (uarmc || uarm))) {
+        char why[QBUFSZ], what[QBUFSZ];
+
+        why[0] = what[0] = '\0';
+        if (obj != uskin) {
+            if (uarmc)
+                Strcat(what, cloak_simple_name(uarmc));
+            if ((obj == uarmu) && uarm) {
+                if (uarmc)
+                    Strcat(what, " and ");
+                Strcat(what, suit_simple_name(uarm));
+            }
+            Sprintf(why, " without taking off your %s first", what);
+        } else {
+            Strcpy(why, "; it's embedded");
+        }
+#if 0 /*JP*/
+        You_cant("take that off%s.", why);
+#else
+        m = joffmsg(obj, &j);
+        You("\82»\82ê%s%s\82±\82Æ\82Í\82Å\82«\82È\82¢\81D", j, m);
+#endif
+        return 0;
+    }
 
     reset_remarm(); /* clear context.takeoff.mask and context.takeoff.what */
     (void) select_off(obj);
@@ -1620,30 +1686,6 @@ dotakeoff()
         otmp = getobj(clothes, "take off");
     if (!otmp)
         return 0;
-    if (otmp == uskin
-        || ((otmp == uarm) && uarmc)
-        || ((otmp == uarmu) && (uarmc || uarm))) {
-        char why[BUFSZ], what[BUFSZ];
-
-        why[0] = what[0] = '\0';
-        if (otmp != uskin) {
-            if (uarmc)
-                Strcat(what, cloak_simple_name(uarmc));
-            if ((otmp == uarmu) && uarm) {
-                if (uarmc)
-                    Strcat(what, " and ");
-                Strcat(what, suit_simple_name(uarm));
-            }
-            Sprintf(why, " without taking off your %s first", what);
-        }
-#if 0 /*JP*/
-        You_cant("take that off%s.", why);
-#else
-        m = joffmsg(otmp, &j);
-        You("\82»\82ê%s%s\82±\82Æ\82Í\82Å\82«\82È\82¢\81D", j, m);
-#endif
-        return 0;
-    }
 
     return armor_or_accessory_off(otmp);
 }
@@ -1675,6 +1717,10 @@ int
 cursed(otmp)
 register struct obj *otmp;
 {
+    if (!otmp) {
+        impossible("cursed without otmp");
+        return 0;
+    }
     /* Curses, like chickens, come home to roost. */
     if ((otmp == uwep) ? welded(otmp) : (int) otmp->cursed) {
 #if 0 /*JP*/
@@ -1823,6 +1869,14 @@ boolean noisy;
     const char *j;
 #endif
 
+    /* this is the same check as for 'W' (dowear), but different message,
+       in case we get here via 'P' (doputon) */
+    if (verysmall(youmonst.data) || nohands(youmonst.data)) {
+        if (noisy)
+            You("can't wear any armor in your current form.");
+        return 0;
+    }
+
     which = is_cloak(otmp)
                 ? c_cloak
                 : is_shirt(otmp)
@@ -2323,7 +2377,7 @@ dowear()
 
     /* cantweararm() checks for suits of armor, not what we want here;
        verysmall() or nohands() checks for shields, gloves, etc... */
-    if ((verysmall(youmonst.data) || nohands(youmonst.data))) {
+    if (verysmall(youmonst.data) || nohands(youmonst.data)) {
 /*JP
         pline("Don't even bother.");
 */
@@ -2757,6 +2811,7 @@ do_takeoff()
     struct obj *otmp = (struct obj *) 0;
     struct takeoff_info *doff = &context.takeoff;
 
+    context.takeoff.mask |= I_SPECIAL; /* set flag for cancel_doff() */
     if (doff->what == W_WEP) {
         if (!cursed(uwep)) {
             setuwep((struct obj *) 0);
@@ -2825,6 +2880,7 @@ do_takeoff()
     } else {
         impossible("do_takeoff: taking off %lx", doff->what);
     }
+    context.takeoff.mask &= ~I_SPECIAL; /* clear cancel_doff() flag */
 
     return otmp;
 }
@@ -2842,10 +2898,9 @@ take_off(VOID_ARGS)
         if (doff->delay > 0) {
             doff->delay--;
             return 1; /* still busy */
-        } else {
-            if ((otmp = do_takeoff()))
-                off_msg(otmp);
         }
+        if ((otmp = do_takeoff()) != 0)
+            off_msg(otmp);
         doff->mask &= ~doff->what;
         doff->what = 0L;
     }
@@ -2903,7 +2958,9 @@ take_off(VOID_ARGS)
     } else if (doff->what == RIGHT_RING) {
         doff->delay = 1;
     } else if (doff->what == WORN_BLINDF) {
-        doff->delay = 2;
+        /* [this used to be 2, but 'R' (and 'T') only require 1 turn to
+           remove a blindfold, so 'A' shouldn't have been requiring 2] */
+        doff->delay = 1;
     } else {
         impossible("take_off: taking off %lx", doff->what);
         return 0; /* force done */
@@ -2997,8 +3054,9 @@ int retry;
         n = query_category("What type of things do you want to take off?",
 */
         n = query_category("\82Ç\82Ì\83^\83C\83v\82Ì\95¨\82Ì\91\95\94õ\82ð\89ð\82«\82Ü\82·\82©\81H",
-                           invent, WORN_TYPES | ALL_TYPES, &pick_list,
-                           PICK_ANY);
+                           invent, (WORN_TYPES | ALL_TYPES
+                                    | UNPAID_TYPES | BUCX_TYPES),
+                           &pick_list, PICK_ANY);
         if (!n)
             return 0;
         for (i = 0; i < n; i++) {
@@ -3009,18 +3067,29 @@ int retry;
         }
         free((genericptr_t) pick_list);
     } else if (flags.menu_style == MENU_COMBINATION) {
-        all_worn_categories = FALSE;
-        if (ggetobj("take off", select_off, 0, TRUE, (unsigned *) 0) == -2)
-            all_worn_categories = TRUE;
+        unsigned ggofeedback = 0;
+
+        i = ggetobj("take off", select_off, 0, TRUE, &ggofeedback);
+        if (ggofeedback & ALL_FINISHED)
+            return 0;
+        all_worn_categories = (i == -2);
     }
+    if (menu_class_present('u')
+        || menu_class_present('B') || menu_class_present('U')
+        || menu_class_present('C') || menu_class_present('X'))
+        all_worn_categories = FALSE;
 
-/*JP
-    n = query_objlist("What do you want to take off?", invent,
-*/
-    n = query_objlist("\82Ç\82Ì\91\95\94õ\82ð\89ð\82«\82Ü\82·\82©\81H", invent,
-                      SIGNAL_NOMENU | USE_INVLET | INVORDER_SORT, &pick_list,
-                      PICK_ANY,
+#if 0 /*JP:T*/
+    n = query_objlist("What do you want to take off?", &invent,
+                      (SIGNAL_NOMENU | USE_INVLET | INVORDER_SORT),
+                      &pick_list, PICK_ANY,
                       all_worn_categories ? is_worn : is_worn_by_type);
+#else
+    n = query_objlist("\82Ç\82Ì\91\95\94õ\82ð\89ð\82«\82Ü\82·\82©\81H", &invent,
+                      (SIGNAL_NOMENU | USE_INVLET | INVORDER_SORT),
+                      &pick_list, PICK_ANY,
+                      all_worn_categories ? is_worn : is_worn_by_type);
+#endif
     if (n > 0) {
         for (i = 0; i < n; i++)
             (void) select_off(pick_list[i].item.a_obj);
index 49250d9..9433c1f 100644 (file)
--- a/src/dog.c
+++ b/src/dog.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 dog.c   $NHDT-Date: 1446808440 2015/11/06 11:14:00 $  $NHDT-Branch: master $:$NHDT-Revision: 1.52 $ */
+/* NetHack 3.6 dog.c   $NHDT-Date: 1502753406 2017/08/14 23:30:06 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.60 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -46,7 +47,7 @@ register struct monst *mtmp;
     mtmp->meating = 0;
     EDOG(mtmp)->droptime = 0;
     EDOG(mtmp)->dropdist = 10000;
-    EDOG(mtmp)->apport = 10;
+    EDOG(mtmp)->apport = ACURR(A_CHA);
     EDOG(mtmp)->whistletime = 0;
     EDOG(mtmp)->hungrytime = 1000 + monstermoves;
     EDOG(mtmp)->ogoal.x = -1; /* force error if used before set */
@@ -220,13 +221,8 @@ makedog()
     context.startingpet_mid = mtmp->m_id;
     /* Horses already wear a saddle */
     if (pettype == PM_PONY && !!(otmp = mksobj(SADDLE, TRUE, FALSE))) {
-        if (mpickobj(mtmp, otmp))
-            panic("merged saddle?");
-        mtmp->misc_worn_check |= W_SADDLE;
         otmp->dknown = otmp->bknown = otmp->rknown = 1;
-        otmp->owornmask = W_SADDLE;
-        otmp->leashmon = mtmp->m_id;
-        update_mon_intrinsics(mtmp, otmp, TRUE, TRUE);
+        put_saddle_on_mon(otmp, mtmp);
     }
 
     if (!petname_used++ && *petname)
@@ -358,8 +354,7 @@ boolean with_you;
     xyflags = mtmp->mtrack[0].y;
     xlocale = mtmp->mtrack[1].x;
     ylocale = mtmp->mtrack[1].y;
-    mtmp->mtrack[0].x = mtmp->mtrack[0].y = 0;
-    mtmp->mtrack[1].x = mtmp->mtrack[1].y = 0;
+    memset(mtmp->mtrack, 0, sizeof(mtmp->mtrack));
 
     if (mtmp == u.usteed)
         return; /* don't place steed on the map */
@@ -469,9 +464,10 @@ boolean with_you;
 
     mtmp->mx = 0; /*(already is 0)*/
     mtmp->my = xyflags;
-    if (xlocale)
-        (void) mnearto(mtmp, xlocale, ylocale, FALSE);
-    else {
+    if (xlocale) {
+        if (!mnearto(mtmp, xlocale, ylocale, FALSE))
+            goto fail_mon_placement;
+    } else {
         if (!rloc(mtmp, TRUE)) {
             /*
              * Failed to place migrating monster,
@@ -479,6 +475,7 @@ boolean with_you;
              * Dump the monster's cargo and leave the monster dead.
              */
             struct obj *obj;
+fail_mon_placement:
             while ((obj = mtmp->minvent) != 0) {
                 obj_extract_self(obj);
                 obj_no_longer_held(obj);
@@ -791,7 +788,8 @@ struct monst *mon;
 register struct obj *obj;
 {
     struct permonst *mptr = mon->data, *fptr = 0;
-    boolean carni = carnivorous(mptr), herbi = herbivorous(mptr), starving;
+    boolean carni = carnivorous(mptr), herbi = herbivorous(mptr),
+            starving, mblind;
 
     if (is_quest_artifact(obj) || obj_resists(obj, 0, 95))
         return obj->cursed ? TABU : APPORT;
@@ -810,8 +808,10 @@ register struct obj *obj;
             return obj->cursed ? UNDEF : APPORT;
 
         /* a starving pet will eat almost anything */
-        starving =
-            (mon->mtame && !mon->isminion && EDOG(mon)->mhpmax_penalty);
+        starving = (mon->mtame && !mon->isminion
+                    && EDOG(mon)->mhpmax_penalty);
+        /* even carnivores will eat carrots if they're temporarily blind */
+        mblind = (!mon->mcansee && haseyes(mon->data));
 
         /* ghouls prefer old corpses and unhatchable eggs, yum!
            they'll eat fresh non-veggy corpses and hatchable eggs
@@ -868,11 +868,12 @@ register struct obj *obj;
         case TIN:
             return metallivorous(mptr) ? ACCFOOD : MANFOOD;
         case APPLE:
-        case CARROT:
             return herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
+        case CARROT:
+            return (herbi || mblind) ? DOGFOOD : starving ? ACCFOOD : MANFOOD;
         case BANANA:
-            return (mptr->mlet == S_YETI)
-                      ? DOGFOOD
+            return (mptr->mlet == S_YETI && herbi)
+                      ? DOGFOOD /* for monkey and ape (tameable), sasquatch */
                       : (herbi || starving)
                          ? ACCFOOD
                          : MANFOOD;
index 3add048..18593a4 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 dogmove.c       $NHDT-Date: 1446604109 2015/11/04 02:28:29 $  $NHDT-Branch: master $:$NHDT-Revision: 1.56 $ */
+/* NetHack 3.6 dogmove.c       $NHDT-Date: 1502753407 2017/08/14 23:30:07 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.63 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -16,6 +17,10 @@ extern boolean notonhead;
 STATIC_DCL boolean FDECL(dog_hunger, (struct monst *, struct edog *));
 STATIC_DCL int FDECL(dog_invent, (struct monst *, struct edog *, int));
 STATIC_DCL int FDECL(dog_goal, (struct monst *, struct edog *, int, int, int));
+STATIC_DCL struct monst *FDECL(find_targ, (struct monst *, int, int, int));
+STATIC_OVL int FDECL(find_friends, (struct monst *, struct monst *, int));
+STATIC_DCL struct monst *FDECL(best_target, (struct monst *));
+STATIC_DCL long FDECL(score_targ, (struct monst *, struct monst *));
 STATIC_DCL boolean FDECL(can_reach_location, (struct monst *, XCHAR_P,
                                               XCHAR_P, XCHAR_P, XCHAR_P));
 STATIC_DCL boolean FDECL(could_reach_item, (struct monst *, XCHAR_P, XCHAR_P));
@@ -210,7 +215,7 @@ int x, y; /* dog's starting location, might be different from current */
 boolean devour;
 {
     register struct edog *edog = EDOG(mtmp);
-    boolean poly, grow, heal, slimer, deadmimic;
+    boolean poly, grow, heal, eyes, slimer, deadmimic;
     int nutrit;
     long oprice;
     char objnambuf[BUFSZ];
@@ -227,6 +232,7 @@ boolean devour;
     poly = polyfodder(obj);
     grow = mlevelgain(obj);
     heal = mhealup(obj);
+    eyes = (obj->otyp == CARROT);
 
     if (devour) {
         if (mtmp->meating > 1)
@@ -298,8 +304,8 @@ boolean devour;
         Strcpy(objnambuf, xname(obj));
         iflags.suppress_price--;
     }
-    /* It's a reward if it's DOGFOOD and the player dropped/threw it. */
-    /* We know the player had it if invlet is set -dlc */
+    /* It's a reward if it's DOGFOOD and the player dropped/threw it.
+       We know the player had it if invlet is set. -dlc */
     if (dogfood(mtmp, obj) == DOGFOOD && obj->invlet)
 #ifdef LINT
         edog->apport = 0;
@@ -367,6 +373,8 @@ boolean devour;
     }
     if (heal)
         mtmp->mhp = mtmp->mhpmax;
+    if ((eyes || heal) && !mtmp->mcansee)
+        mcureblindness(mtmp, canseemon(mtmp));
     if (deadmimic)
         quickmimic(mtmp);
     return 1;
@@ -375,8 +383,8 @@ boolean devour;
 /* hunger effects -- returns TRUE on starvation */
 STATIC_OVL boolean
 dog_hunger(mtmp, edog)
-register struct monst *mtmp;
-register struct edog *edog;
+struct monst *mtmp;
+struct edog *edog;
 {
     if (monstermoves > edog->hungrytime + 500) {
         if (!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) {
@@ -450,9 +458,10 @@ int udist;
     omx = mtmp->mx;
     omy = mtmp->my;
 
-    /* if we are carrying something then we drop it (perhaps near @) */
-    /* Note: if apport == 1 then our behaviour is independent of udist */
-    /* Use udist+1 so steed won't cause divide by zero */
+    /* If we are carrying something then we drop it (perhaps near @).
+     * Note: if apport == 1 then our behaviour is independent of udist.
+     * Use udist+1 so steed won't cause divide by zero.
+     */
     if (droppables(mtmp)) {
         if (!rn2(udist + 1) || !rn2(edog->apport))
             if (rn2(10) < edog->apport) {
@@ -463,7 +472,8 @@ int udist;
                 edog->droptime = monstermoves;
             }
     } else {
-        if ((obj = level.objects[omx][omy]) && !index(nofetch, obj->oclass)
+        if ((obj = level.objects[omx][omy]) != 0
+            && !index(nofetch, obj->oclass)
 #ifdef MAIL
             && obj->otyp != SCR_MAIL
 #endif
@@ -509,7 +519,7 @@ int udist;
     return 0;
 }
 
-/* set dog's goal -- gtyp, gx, gy
+/* set dog's goal -- gtyp, gx, gy;
    returns -1/0/1 (dog's desire to approach player) or -2 (abort move) */
 STATIC_OVL int
 dog_goal(mtmp, edog, after, udist, whappr)
@@ -606,16 +616,12 @@ int after, udist, whappr;
                 appr = 1;
         }
         /* if you have dog food it'll follow you more closely */
-        if (appr == 0) {
-            obj = invent;
-            while (obj) {
+        if (appr == 0)
+            for (obj = invent; obj; obj = obj->nobj)
                 if (dogfood(mtmp, obj) == DOGFOOD) {
                     appr = 1;
                     break;
                 }
-                obj = obj->nobj;
-            }
-        }
     } else
         appr = 1; /* gtyp != UNDEF */
     if (mtmp->mconf)
@@ -634,7 +640,7 @@ int after, udist, whappr;
         } else {
             /* assume master hasn't moved far, and reuse previous goal */
             if (edog && edog->ogoal.x
-                && ((edog->ogoal.x != omx) || (edog->ogoal.y != omy))) {
+                && (edog->ogoal.x != omx || edog->ogoal.y != omy)) {
                 gx = edog->ogoal.x;
                 gy = edog->ogoal.y;
                 edog->ogoal.x = 0;
@@ -659,11 +665,241 @@ int after, udist, whappr;
     return appr;
 }
 
+
+STATIC_OVL struct monst *
+find_targ(mtmp, dx, dy, maxdist)
+register struct monst *mtmp;
+int dx, dy;
+int maxdist;
+{
+    struct monst *targ = 0;
+    int curx = mtmp->mx, cury = mtmp->my;
+    int dist = 0;
+
+    /* Walk outwards */
+    for ( ; dist < maxdist; ++dist) {
+        curx += dx;
+        cury += dy;
+        if (!isok(curx, cury))
+            break;
+
+        /* FIXME: Check if we hit a wall/door/boulder to
+         *        short-circuit unnecessary subsequent checks
+         */
+
+        /* If we can't see up to here, forget it - will this
+         * mean pets in corridors don't breathe at monsters
+         * in rooms? If so, is that necessarily bad?
+         */
+        if (!m_cansee(mtmp, curx, cury))
+            break;
+
+        targ = m_at(curx, cury);
+
+        if (curx == mtmp->mux && cury == mtmp->muy)
+            return &youmonst;
+
+        if (targ) {
+            /* Is the monster visible to the pet? */
+            if ((!targ->minvis || perceives(mtmp->data)) &&
+                !targ->mundetected)
+                break;
+
+            /* If the pet can't see it, it assumes it aint there */
+            targ = 0;
+        }
+    }
+    return targ;
+}
+
+STATIC_OVL int
+find_friends(mtmp, mtarg, maxdist)
+struct monst *mtmp, *mtarg;
+int    maxdist;
+{
+    struct monst *pal;
+    int dx = sgn(mtarg->mx - mtmp->mx),
+        dy = sgn(mtarg->my - mtmp->my);
+    int curx = mtarg->mx, cury = mtarg->my;
+    int dist = distmin(mtarg->mx, mtarg->my, mtmp->mx, mtmp->my);
+
+    for ( ; dist <= maxdist; ++dist) {
+        curx += dx;
+        cury += dy;
+
+        if (!isok(curx, cury))
+            return 0;
+
+        /* If the pet can't see beyond this point, don't
+         * check any farther
+         */
+        if (!m_cansee(mtmp, curx, cury))
+            return 0;
+
+        /* Does pet think you're here? */
+        if (mtmp->mux == curx && mtmp->muy == cury)
+            return 1;
+
+        pal = m_at(curx, cury);
+
+        if (pal) {
+            if (pal->mtame) {
+                /* Pet won't notice invisible pets */
+                if (!pal->minvis || perceives(mtmp->data))
+                    return 1;
+            } else {
+                /* Quest leaders and guardians are always seen */
+                if (pal->data->msound == MS_LEADER
+                    || pal->data->msound == MS_GUARDIAN)
+                    return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+STATIC_OVL long
+score_targ(mtmp, mtarg)
+struct monst *mtmp, *mtarg;
+{
+    long score = 0L;
+
+    /* If the monster is confused, normal scoring is disrupted -
+     * anything may happen
+     */
+
+    /* Give 1 in 3 chance of safe breathing even if pet is confused or
+     * if you're on the quest start level */
+    if (!mtmp->mconf || !rn2(3) || Is_qstart(&u.uz)) {
+        aligntyp align1 = A_NONE, align2 = A_NONE; /* For priests, minions */
+        boolean faith1 = TRUE,  faith2 = TRUE;
+
+        if (mtmp->isminion)
+            align1 = EMIN(mtmp)->min_align;
+        else if (mtmp->ispriest)
+            align1 = EPRI(mtmp)->shralign;
+        else
+            faith1 = FALSE;
+        if (mtarg->isminion)
+            align2 = EMIN(mtarg)->min_align; /* MAR */
+        else if (mtarg->ispriest)
+            align2 = EPRI(mtarg)->shralign; /* MAR */
+        else
+            faith2 = FALSE;
+
+        /* Never target quest friendlies */
+        if (mtarg->data->msound == MS_LEADER
+            || mtarg->data->msound == MS_GUARDIAN)
+            return -5000L;
+        /* D: Fixed angelic beings using gaze attacks on coaligned priests */
+        if (faith1 && faith2 && align1 == align2 && mtarg->mpeaceful) {
+            score -= 5000L;
+            return score;
+        }
+        /* Is monster adjacent? */
+        if (distmin(mtmp->mx, mtmp->my, mtarg->mx, mtarg->my) <= 1) {
+            score -= 3000L;
+            return score;
+        }
+        /* Is the monster peaceful or tame? */
+        if (/*mtarg->mpeaceful ||*/ mtarg->mtame || mtarg == &youmonst) {
+            /* Pets will never be targeted */
+            score -= 3000L;
+            return score;
+        }
+        /* Is master/pet behind monster? Check up to 15 squares beyond pet. */
+        if (find_friends(mtmp, mtarg, 15)) {
+            score -= 3000L;
+            return score;
+        }
+        /* Target hostile monsters in preference to peaceful ones */
+        if (!mtarg->mpeaceful)
+            score += 10;
+        /* Is the monster passive? Don't waste energy on it, if so */
+        if (mtarg->data->mattk[0].aatyp == AT_NONE)
+            score -= 1000;
+        /* Even weak pets with breath attacks shouldn't take on very
+           low-level monsters. Wasting breath on lichens is ridiculous. */
+        if ((mtarg->m_lev < 2 && mtmp->m_lev > 5)
+            || (mtmp->m_lev > 12 && mtarg->m_lev < mtmp->m_lev - 9
+                && u.ulevel > 8 && mtarg->m_lev < u.ulevel - 7))
+            score -= 25;
+        /* And pets will hesitate to attack vastly stronger foes.
+           This penalty will be discarded if master's in trouble. */
+        if (mtarg->m_lev > mtmp->m_lev + 4L)
+            score -= (mtarg->m_lev - mtmp->m_lev) * 20L;
+        /* All things being the same, go for the beefiest monster. This
+           bonus should not be large enough to override the pet's aversion
+           to attacking much stronger monsters. */
+        score += mtarg->m_lev * 2 + mtarg->mhp / 3;
+    }
+    /* Fuzz factor to make things less predictable when very
+       similar targets are abundant. */
+    score += rnd(5);
+    /* Pet may decide not to use ranged attack when confused */
+    if (mtmp->mconf && !rn2(3))
+        score -= 1000;
+    return score;
+}
+
+
+STATIC_OVL struct monst *
+best_target(mtmp)
+struct monst *mtmp;   /* Pet */
+{
+    int dx, dy;
+    long bestscore = -40000L, currscore;
+    struct monst *best_targ = 0, *temp_targ = 0;
+
+    /* Help! */
+    if (!mtmp)
+        return 0;
+
+    /* If the pet is blind, it's not going to see any target */
+    if (!mtmp->mcansee)
+        return 0;
+
+    /* Search for any monsters lined up with the pet, within an arbitrary
+     * distance from the pet (7 squares, even along diagonals). Monsters
+     * are assigned scores and the best score is chosen.
+     */
+    for (dy = -1; dy < 2; ++dy) {
+        for (dx = -1; dx < 2; ++dx) {
+            if (!dx && !dy)
+                continue;
+            /* Traverse the line to find the first monster within 7
+             * squares. Invisible monsters are skipped (if the
+             * pet doesn't have see invisible).
+             */
+            temp_targ = find_targ(mtmp, dx, dy, 7);
+
+            /* Nothing in this line? */
+            if (!temp_targ)
+                continue;
+
+            /* Decide how attractive the target is */
+            currscore = score_targ(mtmp, temp_targ);
+
+            if (currscore > bestscore) {
+                bestscore = currscore;
+                best_targ = temp_targ;
+            }
+        }
+    }
+
+    /* Filter out targets the pet doesn't like */
+    if (bestscore < 0L)
+        best_targ = 0;
+
+    return best_targ;
+}
+
+
 /* return 0 (no move), 1 (move) or 2 (dead) */
 int
 dog_move(mtmp, after)
 register struct monst *mtmp;
-register int after; /* this is extra fast monster movement */
+int after; /* this is extra fast monster movement */
 {
     int omx, omy; /* original mtmp position */
     int appr, whappr, udist;
@@ -847,6 +1083,7 @@ register int after; /* this is extra fast monster movement */
             && better_with_displacing && !undesirable_disp(mtmp, nx, ny)) {
             int mstatus;
             register struct monst *mtmp2 = m_at(nx, ny);
+
             mstatus = mdisplacem(mtmp, mtmp2, FALSE); /* displace monster */
             if (mstatus & MM_DEF_DIED)
                 return 2;
@@ -867,12 +1104,13 @@ register int after; /* this is extra fast monster movement */
                 if (mtmp->mleashed) {
                     if (!Deaf)
                         whimper(mtmp);
-                } else
+                } else {
                     /* 1/40 chance of stepping on it anyway, in case
                      * it has to pass one to follow the player...
                      */
                     if (trap->tseen && rn2(40))
-                    continue;
+                        continue;
+                }
             }
         }
 
@@ -880,9 +1118,9 @@ register int after; /* this is extra fast monster movement */
         /* (minion isn't interested; `cursemsg' stays FALSE) */
         if (has_edog)
             for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) {
-                if (obj->cursed)
+                if (obj->cursed) {
                     cursemsg[i] = TRUE;
-                else if ((otyp = dogfood(mtmp, obj)) < MANFOOD
+                else if ((otyp = dogfood(mtmp, obj)) < MANFOOD
                          && (otyp < ACCFOOD
                              || edog->hungrytime <= monstermoves)) {
                     /* Note: our dog likes the food so much that he
@@ -902,11 +1140,18 @@ register int after; /* this is extra fast monster movement */
             continue;
 
         /* lessen the chance of backtracking to previous position(s) */
-        k = has_edog ? uncursedcnt : cnt;
-        for (j = 0; j < MTSZ && j < k - 1; j++)
-            if (nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
-                if (rn2(MTSZ * (k - j)))
-                    goto nxti;
+        /* This causes unintended issues for pets trying to follow
+           the hero. Thus, only run it if not leashed and >5 tiles
+           away. */
+        if (!mtmp->mleashed &&
+            distmin(mtmp->mx, mtmp->my, u.ux, u.uy) > 5) {
+            k = has_edog ? uncursedcnt : cnt;
+            for (j = 0; j < MTSZ && j < k - 1; j++)
+                if (nx == mtmp->mtrack[j].x &&
+                    ny == mtmp->mtrack[j].y)
+                    if (rn2(MTSZ * (k - j)))
+                        goto nxti;
+        }
 
         j = ((ndist = GDIST(nx, ny)) - nidist) * appr;
         if ((j == 0 && !rn2(++chcnt)) || j < 0
@@ -922,9 +1167,65 @@ register int after; /* this is extra fast monster movement */
     nxti:
         ;
     }
+
+    /* Pet hasn't attacked anything but is considering moving -
+     * now's the time for ranged attacks. Note that the pet can move
+     * after it performs its ranged attack. Should this be changed?
+     */
+    {
+        struct monst *mtarg;
+        int hungry = 0;
+
+        /* How hungry is the pet? */
+        if (!mtmp->isminion) {
+            struct edog *dog = EDOG(mtmp);
+            hungry = (monstermoves > (dog->hungrytime + 300));
+        }
+
+        /* Identify the best target in a straight line from the pet;
+         * if there is such a target, we'll let the pet attempt an
+         * attack.
+         */
+        mtarg = best_target(mtmp);
+
+        /* Hungry pets are unlikely to use breath/spit attacks */
+        if (mtarg && (!hungry || !rn2(5))) {
+            int mstatus;
+
+            if (mtarg == &youmonst) {
+                if (mattacku(mtmp))
+                    return 2;
+            } else {
+                mstatus = mattackm(mtmp, mtarg);
+
+                /* Shouldn't happen, really */
+                if (mstatus & MM_AGR_DIED)
+                    return 2;
+
+                /* Allow the targeted nasty to strike back - if
+                 * the targeted beast doesn't have a ranged attack,
+                 * nothing will happen.
+                 */
+                if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)
+                    && rn2(4) && mtarg != &youmonst) {
+
+                    /* Can monster see? If it can, it can retaliate
+                     * even if the pet is invisible, since it'll see
+                     * the direction from which the ranged attack came;
+                     * if it's blind or unseeing, it can't retaliate
+                     */
+                    if (mtarg->mcansee && haseyes(mtarg->data)) {
+                        mstatus = mattackm(mtarg, mtmp);
+                        if (mstatus & MM_DEF_DIED)
+                            return 2;
+                    }
+                }
+            }
+        }
+    }
+
 newdogpos:
     if (nix != omx || niy != omy) {
-        struct obj *mw_tmp;
         boolean wasseen;
 
         if (info[chi] & ALLOW_U) {
@@ -943,37 +1244,34 @@ newdogpos:
         }
         if (!m_in_out_region(mtmp, nix, niy))
             return 1;
-        if (((IS_ROCK(levl[nix][niy].typ) && may_dig(nix, niy))
-             || closed_door(nix, niy))
-            && mtmp->weapon_check != NO_WEAPON_WANTED
-            && tunnels(mtmp->data) && needspick(mtmp->data)) {
-            if (closed_door(nix, niy)) {
-                if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)
-                    || !is_axe(mw_tmp))
-                    mtmp->weapon_check = NEED_PICK_OR_AXE;
-            } else if (IS_TREE(levl[nix][niy].typ)) {
-                if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
-                    mtmp->weapon_check = NEED_AXE;
-            } else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
-                mtmp->weapon_check = NEED_PICK_AXE;
-            }
-            if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
-                return 0;
-        }
+        if (m_digweapon_check(mtmp, nix,niy))
+            return 0;
+
         /* insert a worm_move() if worms ever begin to eat things */
         wasseen = canseemon(mtmp);
         remove_monster(omx, omy);
         place_monster(mtmp, nix, niy);
-        if (cursemsg[chi] && (wasseen || canseemon(mtmp)))
-/*JP
-            pline("%s moves only reluctantly.", noit_Monnam(mtmp));
-*/
-            pline("%s\82Í\82¢\82â\82¢\82â\93®\82¢\82½\81D", Monnam(mtmp));
+        if (cursemsg[chi] && (wasseen || canseemon(mtmp))) {
+            /* describe top item of pile, not necessarily cursed item itself;
+               don't use glyph_at() here--it would return the pet but we want
+               to know whether an object is remembered at this map location */
+            struct obj *o = (!Hallucination && level.flags.hero_memory
+                             && glyph_is_object(levl[nix][niy].glyph))
+                               ? vobj_at(nix, niy) : 0;
+            const char *what = o ? distant_name(o, doname) : something;
+
+#if 0 /*JP*/
+            pline("%s %s reluctantly over %s.", noit_Monnam(mtmp),
+                  vtense((char *) 0, locomotion(mtmp->data, "step")), what);
+#else
+            pline("%s\82Í%s\82Ì\8fã\82É\82¢\82â\82¢\82â\93®\82¢\82½\81D", noit_Monnam(mtmp), what);
+#endif
+        }
         for (j = MTSZ - 1; j > 0; j--)
             mtmp->mtrack[j] = mtmp->mtrack[j - 1];
         mtmp->mtrack[0].x = omx;
         mtmp->mtrack[0].y = omy;
-        /* We have to know if the pet's gonna do a combined eat and
+        /* We have to know if the pet's going to do a combined eat and
          * move before moving it, but it can't eat until after being
          * moved.  Thus the do_eat flag.
          */
@@ -1073,18 +1371,18 @@ xchar mx, my, fx, fy;
     return FALSE;
 }
 
-/*ARGSUSED*/ /* do_clear_area client */
+/* do_clear_area client */
 STATIC_PTR void
 wantdoor(x, y, distance)
 int x, y;
 genericptr_t distance;
 {
-    int ndist;
+    int ndist, *dist_ptr = (int *) distance;
 
-    if (*(int *) distance > (ndist = distu(x, y))) {
+    if (*dist_ptr > (ndist = distu(x, y))) {
         gx = x;
         gy = y;
-        *(int *) distance = ndist;
+        *dist_ptr = ndist;
     }
 }
 
@@ -1156,8 +1454,8 @@ struct monst *mtmp;
            of its mind as it changes form) */
         newsym(mtmp->mx, mtmp->my);
 #if 0 /*JP*/
-        You("%s %s appear where %s was!",
-            cansee(mtmp->mx, mtmp->my) ? "see" : "sense",
+        You("%s %s %sappear%s where %s was!",
+            cansee(mtmp->mx, mtmp->my) ? "see" : "sense that",
             (mtmp->m_ap_type == M_AP_FURNITURE)
                 ? an(defsyms[mtmp->mappearance].explanation)
                 : (mtmp->m_ap_type == M_AP_OBJECT
@@ -1169,6 +1467,8 @@ struct monst *mtmp;
                             : (mtmp->m_ap_type == M_AP_MONSTER)
                                   ? an(mons[mtmp->mappearance].mname)
                                   : something,
+            cansee(mtmp->mx, mtmp->my) ? "" : "has ",
+            cansee(mtmp->mx, mtmp->my) ? "" : "ed",
             buf);
 #else
         You("%s\82ª\82 \82Á\82½\82Æ\82±\82ë\82É%s\82ª\8c»\82ê\82½\82Ì%s\81I",
index b965677..7d31755 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 dokick.c        $NHDT-Date: 1446955295 2015/11/08 04:01:35 $  $NHDT-Branch: master $:$NHDT-Revision: 1.104 $ */
+/* NetHack 3.6 dokick.c        $NHDT-Date: 1517128663 2018/01/28 08:37:43 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.113 $ */
 /* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -25,9 +25,9 @@ STATIC_DCL void FDECL(kickdmg, (struct monst *, BOOLEAN_P));
 STATIC_DCL boolean FDECL(maybe_kick_monster, (struct monst *,
                                               XCHAR_P, XCHAR_P));
 STATIC_DCL void FDECL(kick_monster, (struct monst *, XCHAR_P, XCHAR_P));
-STATIC_DCL int FDECL(kick_object, (XCHAR_P, XCHAR_P));
+STATIC_DCL int FDECL(kick_object, (XCHAR_P, XCHAR_P, char *));
 STATIC_DCL int FDECL(really_kick_object, (XCHAR_P, XCHAR_P));
-STATIC_DCL char *FDECL(kickstr, (char *));
+STATIC_DCL char *FDECL(kickstr, (char *, const char *));
 STATIC_DCL void FDECL(otransit_msg, (struct obj *, BOOLEAN_P, long));
 STATIC_DCL void FDECL(drop_to, (coord *, SCHAR_P));
 
@@ -130,7 +130,7 @@ register boolean clumsy;
         }
     }
 
-    (void) passive(mon, TRUE, mon->mhp > 0, AT_KICK, FALSE);
+    (void) passive(mon, uarmf, TRUE, mon->mhp > 0, AT_KICK, FALSE);
     if (mon->mhp <= 0 && !trapkilled)
         killed(mon);
 
@@ -170,7 +170,7 @@ xchar x, y;
     int i, j;
 
     /* anger target even if wild miss will occur */
-    setmangry(mon);
+    setmangry(mon, TRUE);
 
     if (Levitation && !rn2(3) && verysmall(mon->data)
         && !is_flyer(mon->data)) {
@@ -179,7 +179,7 @@ xchar x, y;
 */
         pline("\8bó\92\86\82É\95\82\82¢\82Ä\82¢\82é\82Ì\82Å\81C\91å\82«\82­\8aO\82µ\82½\81I");
         exercise(A_DEX, FALSE);
-        (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+        (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
         return;
     }
 
@@ -241,13 +241,13 @@ xchar x, y;
 */
                 You("%s\82ð\8fR\82Á\82½\81D", mon_nam(mon));
                 sum = damageum(mon, uattk);
-                (void) passive(mon, (boolean) (sum > 0), (sum != 2), AT_KICK,
-                               FALSE);
+                (void) passive(mon, uarmf, (boolean) (sum > 0),
+                               (sum != 2), AT_KICK, FALSE);
                 if (sum == 2)
                     break; /* Defender died */
             } else {
                 missum(mon, uattk, (tmp + armorpenalty > kickdieroll));
-                (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+                (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
             }
         }
         return;
@@ -264,7 +264,7 @@ xchar x, y;
             Your("clumsy kick does no damage.");
 */
             Your("\95s\8aí\97p\82È\8fR\82è\82Å\83_\83\81\81[\83W\82ð\97^\82¦\82ç\82ê\82È\82©\82Á\82½\81D");
-            (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+            (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
             return;
         }
         if (i < j / 10)
@@ -296,16 +296,13 @@ doit:
             pline("%s\82Í\82 \82È\82½\82Ì%s\8fR\82è\82ð\96h\82¢\82¾\81D", Monnam(mon),
                   clumsy ? "\95s\8aí\97p\82È" : "");
 #endif
-            (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+            (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
             return;
         } else {
             maybe_mnexto(mon);
             if (mon->mx != x || mon->my != y) {
-                if (glyph_is_invisible(levl[x][y].glyph)) {
-                    unmap_object(x, y);
-                    newsym(x, y);
-                }
-#if 0 /*JP*/
+                (void) unmap_invisible(x, y);
+#if 0 /*JP:T*/
                 pline("%s %s, %s evading your %skick.", Monnam(mon),
                       (!level.flags.noteleport && can_teleport(mon->data))
                           ? "teleports"
@@ -321,7 +318,8 @@ doit:
                 pline("%s\82Í%s\81C%s\82 \82È\82½\82Ì%s\8fR\82è\82ð\82½\82­\82Ý\82É\94ð\82¯\82½\81D", Monnam(mon),
                       (!level.flags.noteleport && can_teleport(mon->data))
                           ? "\8fu\8aÔ\88Ú\93®\82µ"
-                          : is_floater(mon->data) ? "\95\82\82«"
+                          : is_floater(mon->data)
+                                ? "\95\82\82«"
                                 : is_flyer(mon->data) ? "\82Í\82Î\82½\82«"
                                                       : (nolimbs(mon->data)
                                                          || slithy(mon->data))
@@ -329,7 +327,7 @@ doit:
                                                             : "\92µ\82Ë",
                       clumsy ? "\8ay\81X\82Æ" : "\91f\91\81\82­", clumsy ? "\95s\8aí\97p\82È" : "");
 #endif
-                (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+                (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
                 return;
             }
         }
@@ -350,7 +348,7 @@ register struct obj *gold;
 
     if (!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest
         && !mtmp->isgd && !is_mercenary(mtmp->data)) {
-        wakeup(mtmp);
+        wakeup(mtmp, TRUE);
     } else if (!mtmp->mcanmove) {
         /* too light to do real damage */
         if (canseemon(mtmp)) {
@@ -369,7 +367,7 @@ register struct obj *gold;
         mtmp->msleeping = 0;
         finish_meating(mtmp);
         if (!mtmp->isgd && !rn2(4)) /* not always pleasing */
-            setmangry(mtmp);
+            setmangry(mtmp, TRUE);
         /* greedy monsters catch gold */
         if (cansee(mtmp->mx, mtmp->my))
 /*JP
@@ -576,15 +574,18 @@ xchar x, y; /* coordinates where object was before the impact, not after */
 
 /* jacket around really_kick_object */
 STATIC_OVL int
-kick_object(x, y)
+kick_object(x, y, kickobjnam)
 xchar x, y;
+char *kickobjnam;
 {
     int res = 0;
 
+    *kickobjnam = '\0';
     /* if a pile, the "top" object gets kicked */
     kickedobj = level.objects[x][y];
     if (kickedobj) {
         /* kick object; if doing is fatal, done() will clean up kickedobj */
+        Strcpy(kickobjnam, killer_xname(kickedobj)); /* matters iff res==0 */
         res = really_kick_object(x, y);
         kickedobj = (struct obj *) 0;
     }
@@ -607,23 +608,27 @@ xchar x, y;
         || kickedobj == uchain)
         return 0;
 
-    if ((trap = t_at(x, y)) != 0
-        && (((trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) && !Passes_walls)
-            || trap->ttyp == WEB)) {
-        if (!trap->tseen)
-            find_trap(trap);
-#if 0 /*JP*/
-        You_cant("kick %s that's in a %s!", something,
-                 Hallucination ? "tizzy" : (trap->ttyp == WEB) ? "web"
-                                                               : "pit");
+    if ((trap = t_at(x, y)) != 0) {
+        if (((trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) && !Passes_walls)
+            || trap->ttyp == WEB) {
+            if (!trap->tseen)
+                find_trap(trap);
+#if 0 /*JP:T*/
+            You_cant("kick %s that's in a %s!", something,
+                     Hallucination ? "tizzy" :
+                     (trap->ttyp == WEB) ? "web" : "pit");
 #else
-        You("%s\82Å\82Í%s\82ð\8fR\82é\82±\82Æ\82ª\82Å\82«\82È\82¢\81I",
-            Hallucination ? "\8d¬\97\90\82µ\82½\8fó\91Ô"
-                          : trap->ttyp == WEB
-                             ? "\82­\82à\82Ì\91\83\82Ì\92\86" : "\97\8e\82µ\8c\8a\82Ì\92\86",
-            something);
+            You("%s\82Å\82Í%s\82ð\8fR\82é\82±\82Æ\82ª\82Å\82«\82È\82¢\81I",
+                Hallucination ? "\8d¬\97\90\82µ\82½\8fó\91Ô" :
+                (trap->ttyp == WEB) ? "\82­\82à\82Ì\91\83\82Ì\92\86" : "\97\8e\82µ\8c\8a\82Ì\92\86",
+                something);
 #endif
-        return 1;
+            return 1;
+        }
+        if (trap->ttyp == STATUE_TRAP) {
+            activate_statue_trap(trap, x,y, FALSE);
+            return 1;
+        }
     }
 
     if (Fumbling && !rn2(3)) {
@@ -894,13 +899,14 @@ xchar x, y;
 
 /* cause of death if kicking kills kicker */
 STATIC_OVL char *
-kickstr(buf)
+kickstr(buf, kickobjnam)
 char *buf;
+const char *kickobjnam;
 {
     const char *what;
 
-    if (kickedobj)
-        what = killer_xname(kickedobj);
+    if (*kickobjnam)
+        what = kickobjnam;
     else if (maploc == &nowhere)
 /*JP
         what = "nothing";
@@ -992,8 +998,9 @@ dokick()
     int dmg = 0, glyph, oldglyph = -1;
     register struct monst *mtmp;
     boolean no_kick = FALSE;
-    char buf[BUFSZ];
+    char buf[BUFSZ], kickobjnam[BUFSZ];
 
+    kickobjnam[0] = '\0';
     if (nolimbs(youmonst.data) || slithy(youmonst.data)) {
 /*JP
         You("have no legs to kick with.");
@@ -1115,6 +1122,7 @@ dokick()
                 pline("%s\82Í\91å\82«\82È\83Q\83b\83v\82ð\82µ\82½\81D", Monnam(u.ustuck));
                 break;
             }
+            /*FALLTHRU*/
         default:
 /*JP
             Your("feeble kick has no effect.");
@@ -1221,22 +1229,19 @@ dokick()
         }
         return 1;
     }
-    if (glyph_is_invisible(levl[x][y].glyph)) {
-        unmap_object(x, y);
-        newsym(x, y);
-    }
+    (void) unmap_invisible(x, y);
     if (is_pool(x, y) ^ !!u.uinwater) {
         /* objects normally can't be removed from water by kicking */
 /*JP
-        You("splash some water around.");
+        You("splash some %s around.", hliquid("water"));
 */
-        You("\90\85\82ð\89ñ\82è\82É\82Ü\82«\82¿\82ç\82µ\82½\81D");
+        You("%s\82ð\89ñ\82è\82É\82Ü\82«\82¿\82ç\82µ\82½\81D", hliquid("water"));
         return 1;
     }
 
     if (OBJ_AT(x, y) && (!Levitation || Is_airlevel(&u.uz)
                          || Is_waterlevel(&u.uz) || sobj_at(BOULDER, x, y))) {
-        if (kick_object(x, y)) {
+        if (kick_object(x, y, kickobjnam)) {
             if (Is_airlevel(&u.uz))
                 hurtle(-u.dx, -u.dy, 1, TRUE); /* assume it's light */
             return 1;
@@ -1418,6 +1423,7 @@ dokick()
             goto ouch;
         if (IS_TREE(maploc->typ)) {
             struct obj *treefruit;
+
             /* nothing, fruit or trouble? 75:23.5:1.5% */
             if (rn2(3)) {
                 if (!rn2(6) && !(mvitals[PM_KILLER_BEE].mvflags & G_GONE))
@@ -1432,7 +1438,9 @@ dokick()
                 && (treefruit = rnd_treefruit_at(x, y))) {
                 long nfruit = 8L - rnl(7), nfall;
                 short frtype = treefruit->otyp;
+
                 treefruit->quan = nfruit;
+                treefruit->owt = weight(treefruit);
                 if (is_plural(treefruit))
 /*JP
                     pline("Some %s fall from the tree!", xname(treefruit));
@@ -1467,6 +1475,7 @@ dokick()
                 int cnt = rnl(4) + 2;
                 int made = 0;
                 coord mm;
+
                 mm.x = x;
                 mm.y = y;
                 while (cnt--) {
@@ -1594,7 +1603,7 @@ dokick()
             if (!rn2(3))
                 set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
             dmg = rnd(ACURR(A_CON) > 15 ? 3 : 5);
-            losehp(Maybe_Half_Phys(dmg), kickstr(buf), KILLED_BY);
+            losehp(Maybe_Half_Phys(dmg), kickstr(buf, kickobjnam), KILLED_BY);
             if (Is_airlevel(&u.uz) || Levitation)
                 hurtle(-u.dx, -u.dy, rn1(2, 4), TRUE); /* assume it's heavy */
             return 1;
@@ -1665,7 +1674,7 @@ dokick()
         feel_newsym(x, y); /* we know we broke it */
         unblock_point(x, y); /* vision */
         if (shopdoor) {
-            add_damage(x, y, 400L);
+            add_damage(x, y, SHOP_DOOR_COST);
 /*JP
             pay_for_damage("break", FALSE);
 */
@@ -1735,7 +1744,8 @@ schar loc;
         } else if (In_endgame(&u.uz) || Is_botlevel(&u.uz)) {
             cc->y = cc->x = 0;
             break;
-        } /* else fall to the next cases */
+        }
+        /*FALLTHRU*/
     case MIGR_STAIRS_UP:
     case MIGR_LADDER_UP:
         cc->x = u.uz.dnum;
index 3ac71dd..78631be 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 dothrow.c       $NHDT-Date: 1446975465 2015/11/08 09:37:45 $  $NHDT-Branch: master $:$NHDT-Revision: 1.113 $ */
+/* NetHack 3.6 dothrow.c       $NHDT-Date: 1522967321 2018/04/05 22:28:41 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.135 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* Contains code for 't' (throw) */
@@ -21,7 +22,6 @@ STATIC_DCL void FDECL(check_shop_obj, (struct obj *, XCHAR_P, XCHAR_P,
                                        BOOLEAN_P));
 STATIC_DCL void FDECL(breakmsg, (struct obj *, BOOLEAN_P));
 STATIC_DCL boolean FDECL(toss_up, (struct obj *, BOOLEAN_P));
-STATIC_DCL boolean FDECL(throwing_weapon, (struct obj *));
 STATIC_DCL void FDECL(sho_obj_return_to_u, (struct obj * obj));
 STATIC_DCL boolean FDECL(mhurtle_step, (genericptr_t, int, int));
 
@@ -401,8 +401,14 @@ dofire()
      * If quiver is empty, we use autoquiver to fill it when the
      * corresponding option is on.  If the option is off or if
      * autoquiver doesn't select anything, we ask what to throw.
-     * For the last, if player's response is a stack, we put
-     * that stack into quiver slot provided it's not wielded.
+     * Then we put the chosen item into the quiver slot unless
+     * it is already in another slot.  [Matters most if it is a
+     * stack but also matters for single item if this throw gets
+     * aborted (ESC at the direction prompt).  Already wielded
+     * item is excluded because wielding might be necessary
+     * (Mjollnir) or make the throw behave differently (aklys),
+     * and alt-wielded item is excluded because switching slots
+     * would end two-weapon combat even if throw gets aborted.]
      */
     if (!ok_to_throw(&shotlimit))
         return 0;
@@ -509,7 +515,22 @@ genericptr_t arg;
     int x, y, dx, dy, x_change, y_change, err, i, prev_x, prev_y;
     boolean keep_going = TRUE;
 
-    /* Use Bresenham's Line Algorithm to walk from src to dest */
+    /* Use Bresenham's Line Algorithm to walk from src to dest.
+     *
+     * This should be replaced with a more versatile algorithm
+     * since it handles slanted moves in a suboptimal way.
+     * Going from 'x' to 'y' needs to pass through 'z', and will
+     * fail if there's an obstable there, but it could choose to
+     * pass through 'Z' instead if that way imposes no obstacle.
+     *     ..y          .Zy
+     *     xz.    vs    x..
+     * Perhaps we should check both paths and accept whichever
+     * one isn't blocked.  But then multiple zigs and zags could
+     * potentially produce a meandering path rather than the best
+     * attempt at a straight line.  And (*check_proc)() would
+     * need to work more like 'travel', distinguishing between
+     * testing a possible move and actually attempting that move.
+     */
     dx = dest_cc->x - src_cc->x;
     dy = dest_cc->y - src_cc->y;
     prev_x = x = src_cc->x;
@@ -565,6 +586,25 @@ genericptr_t arg;
     return FALSE;
 }
 
+/* hack for hurtle_step() -- it ought to be changed to take an argument
+   indicating lev/fly-to-dest vs lev/fly-to-dest-minus-one-land-on-dest
+   vs drag-to-dest; original callers use first mode, jumping wants second,
+   grappling hook backfire and thrown chained ball need third */
+boolean
+hurtle_jump(arg, x, y)
+genericptr_t arg;
+int x, y;
+{
+    boolean res;
+    long save_EWwalking = EWwalking;
+
+    /* prevent jumping over water from being placed in that water */
+    EWwalking |= I_SPECIAL;
+    res = hurtle_step(arg, x, y);
+    EWwalking = save_EWwalking;
+    return res;
+}
+
 /*
  * Single step for the hero flying through the air from jumping, flying,
  * etc.  Called from hurtle() and jump() via walk_path().  We expect the
@@ -608,9 +648,15 @@ int x, y;
     }
 
     if (!Passes_walls || !(may_pass = may_passwall(x, y))) {
-        if (IS_ROCK(levl[x][y].typ) || closed_door(x, y)) {
+        boolean odoor_diag = (IS_DOOR(levl[x][y].typ)
+                              && (levl[x][y].doormask & D_ISOPEN)
+                              && (u.ux - x) && (u.uy - y));
+
+        if (IS_ROCK(levl[x][y].typ) || closed_door(x, y) || odoor_diag) {
             const char *s;
 
+            if (odoor_diag)
+                You("hit the door edge!");
 /*JP
             pline("Ouch!");
 */
@@ -683,8 +729,8 @@ int x, y;
         }
         if ((u.ux - x) && (u.uy - y) && bad_rock(youmonst.data, u.ux, y)
             && bad_rock(youmonst.data, x, u.uy)) {
-            boolean too_much =
-                (invent && (inv_weight() + weight_cap() > 600));
+            boolean too_much = (invent && (inv_weight() + weight_cap() > 600));
+
             /* Move at a diagonal. */
             if (bigmonst(youmonst.data) || too_much) {
 #if 0 /*JP*/
@@ -708,16 +754,46 @@ int x, y;
         }
     }
 
-    if ((mon = m_at(x, y)) != 0) {
+    if ((mon = m_at(x, y)) != 0
+#if 0   /* we can't include these two exceptions unless we know we're
+         * going to end up past the current spot rather than on it;
+         * for that, we need to know that the range is not exhausted
+         * and also that the next spot doesn't contain an obstacle */
+        && !(mon->mundetected && hides_under(mon) && (Flying || Levitation))
+        && !(mon->mundetected && mon->data->mlet == S_EEL
+             && (Flying || Levitation || Wwalking))
+#endif
+        ) {
+        const char *mnam, *pronoun;
+        int glyph = glyph_at(x, y);
+
+        mon->mundetected = 0; /* wakeup() will handle mimic */
+        mnam = a_monnam(mon); /* after unhiding */
+        pronoun = mhim(mon);
+        if (!strcmp(mnam, "it")) {
+            /* mhim() uses pronoun_gender() which forces neuter if monster
+               can't be seen; we want him/her for humanoid sensed by touch */
+            if (!strcmp(pronoun, "it") && humanoid(mon->data))
+                pronoun = genders[mon->female].him;
+            mnam = !strcmp(pronoun, "it") ? "something" : "someone";
+        }
+        if (!glyph_is_monster(glyph) && !glyph_is_invisible(glyph))
+            You("find %s by bumping into %s.", mnam, pronoun);
+        else
 /*JP
-        You("bump into %s.", a_monnam(mon));
+            You("bump into %s.", mnam);
 */
-        You("%s\82É\82Ô\82¿\82 \82½\82Á\82½\81D", a_monnam(mon));
-        wakeup(mon);
-        wake_nearto(x,y, 10);
+            You("%s\82É\82Ô\82¿\82 \82½\82Á\82½\81D", mnam);
+        wakeup(mon, FALSE);
+        if (!canspotmon(mon))
+            map_invisible(mon->mx, mon->my);
+        setmangry(mon, FALSE);
+        wake_nearto(x, y, 10);
         return FALSE;
     }
-    if ((u.ux - x) && (u.uy - y) && bad_rock(youmonst.data, u.ux, y)
+
+    if ((u.ux - x) && (u.uy - y)
+        && bad_rock(youmonst.data, u.ux, y)
         && bad_rock(youmonst.data, x, u.uy)) {
         /* Move at a diagonal. */
         if (Sokoban) {
@@ -729,12 +805,32 @@ int x, y;
         }
     }
 
+    /* Caller has already determined that dragging the ball is allowed */
+    if (Punished && uball->where == OBJ_FLOOR) {
+        int bc_control;
+        xchar ballx, bally, chainx, chainy;
+        boolean cause_delay;
+
+        if (drag_ball(x, y, &bc_control, &ballx, &bally, &chainx,
+                      &chainy, &cause_delay, TRUE))
+            move_bc(0, bc_control, ballx, bally, chainx, chainy);
+    }
+
     ox = u.ux;
     oy = u.uy;
     u_on_newpos(x, y); /* set u.<ux,uy>, u.usteed-><mx,my>; cliparound(); */
     newsym(ox, oy);    /* update old position */
     vision_recalc(1);  /* update for new position */
     flush_screen(1);
+
+    if (is_pool(x, y) && !u.uinwater
+        && ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER)
+            || !(Levitation || Flying || Wwalking))) {
+        multi = 0; /* can move, so drown() allows crawling out of water */
+        (void) drown();
+        return FALSE;
+    }
+
     /* FIXME:
      * Each trap should really trigger on the recoil if
      * it would trigger during normal movement. However,
@@ -834,7 +930,7 @@ boolean verbose;
             u.utraptype == TT_WEB
                 ? "web"
                 : u.utraptype == TT_LAVA
-                      ? "lava"
+                      ? hliquid("lava")
                       : u.utraptype == TT_INFLOOR
                             ? surface(u.ux, u.uy)
                             : u.utraptype == TT_BURIEDBALL ? "buried ball"
@@ -883,8 +979,7 @@ boolean verbose;
     (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range);
 }
 
-/* Move a monster through the air for a few squares.
- */
+/* Move a monster through the air for a few squares. */
 void
 mhurtle(mon, dx, dy, range)
 struct monst *mon;
@@ -1001,7 +1096,7 @@ boolean hitsroof;
     /* object now hits you */
 
     if (obj->oclass == POTION_CLASS) {
-        potionhit(&youmonst, obj, TRUE);
+        potionhit(&youmonst, obj, POTHIT_HERO_THROW);
     } else if (breaktest(obj)) {
         int otyp = obj->otyp;
         int blindinc;
@@ -1029,6 +1124,7 @@ boolean hitsroof;
                     Your("%s\82Í\82 \82È\82½\82ð\8eç\82ê\82È\82©\82Á\82½\81D", helm_simple_name(uarmh));
                 goto petrify;
             }
+            /*FALLTHRU*/
         case CREAM_PIE:
         case BLINDING_VENOM:
 /*JP
@@ -1126,7 +1222,7 @@ boolean hitsroof;
 }
 
 /* return true for weapon meant to be thrown; excludes ammo */
-STATIC_OVL boolean
+boolean
 throwing_weapon(obj)
 struct obj *obj;
 {
@@ -1144,11 +1240,11 @@ sho_obj_return_to_u(obj)
 struct obj *obj;
 {
     /* might already be our location (bounced off a wall) */
-    if (bhitpos.x != u.ux || bhitpos.y != u.uy) {
+    if ((u.dx || u.dy) && (bhitpos.x != u.ux || bhitpos.y != u.uy)) {
         int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
 
         tmp_at(DISP_FLASH, obj_to_glyph(obj));
-        while (x != u.ux || y != u.uy) {
+        while (isok(x,y) && (x != u.ux || y != u.uy)) {
             tmp_at(x, y);
             delay_output();
             x -= u.dx;
@@ -1163,8 +1259,7 @@ void
 throwit(obj, wep_mask, twoweap)
 struct obj *obj;
 long wep_mask; /* used to re-equip returning boomerang */
-boolean
-    twoweap; /* used to restore twoweapon mode if wielded weapon returns */
+boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */
 {
     register struct monst *mon;
     register int range, urange;
@@ -1174,6 +1269,7 @@ boolean
     notonhead = FALSE; /* reset potentially stale value */
     if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) {
         boolean slipok = TRUE;
+
         if (ammo_and_launcher(obj, uwep))
 /*JP
             pline("%s!", Tobjnam(obj, "misfire"));
@@ -1224,7 +1320,11 @@ boolean
         bhitpos.x = mon->mx;
         bhitpos.y = mon->my;
     } else if (u.dz) {
-        if (u.dz < 0 && Role_if(PM_VALKYRIE) && obj->oartifact == ART_MJOLLNIR
+        if (u.dz < 0
+            /* Mjollnir must we wielded to be thrown--caller verifies this;
+               aklys must we wielded as primary to return when thrown */
+            && ((Role_if(PM_VALKYRIE) && obj->oartifact == ART_MJOLLNIR)
+                || (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0))
             && !impaired) {
 #if 0 /*JP*/
             pline("%s the %s and returns to your hand!", Tobjnam(obj, "hit"),
@@ -1235,6 +1335,8 @@ boolean
 #endif
             obj = addinv(obj);
             (void) encumber_msg();
+            if (obj->owornmask & W_QUIVER) /* in case addinv() autoquivered */
+                setuqwep((struct obj *) 0);
             setuwep(obj);
             u.twoweap = twoweap;
         } else if (u.dz < 0) {
@@ -1243,7 +1345,7 @@ boolean
                    && rn2(6)) {
             /* alternative to prayer or wand of opening/spell of knock
                for dealing with cursed saddle:  throw holy water > */
-            potionhit(u.usteed, obj, TRUE);
+            potionhit(u.usteed, obj, POTHIT_HERO_THROW);
         } else {
             hitfloor(obj);
         }
@@ -1312,6 +1414,10 @@ boolean
             range = 20; /* you must be giant */
         else if (obj->oartifact == ART_MJOLLNIR)
             range = (range + 1) / 2; /* it's heavy */
+        else if (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0)
+            /* if an aklys is going to return, range is limited by the
+               length of the attached cord [implicit aspect of item] */
+            range = min(range, BOLT_LIM / 2);
         else if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
             range = 1;
 
@@ -1362,73 +1468,91 @@ boolean
             (void) mpickobj(u.ustuck, obj);
         thrownobj = (struct obj *) 0;
     } else {
-        /* the code following might become part of dropy() */
-        if (obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE)
-            && rn2(100)) {
-            /* we must be wearing Gauntlets of Power to get here */
-            sho_obj_return_to_u(obj); /* display its flight */
-
-            if (!impaired && rn2(100)) {
+        /* Mjollnir must we wielded to be thrown--caller verifies this;
+           aklys must we wielded as primary to return when thrown */
+        if ((obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE))
+            || (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0)) {
+            if (rn2(100)) {
+                sho_obj_return_to_u(obj); /* display its flight */
+
+                if (!impaired && rn2(100)) {
 /*JP
                 pline("%s to your hand!", Tobjnam(obj, "return"));
 */
                 pline("%s\82Í\82 \82È\82½\82Ì\8eè\82É\96ß\82Á\82Ä\82«\82½\81I", xname(obj));
-                obj = addinv(obj);
-                (void) encumber_msg();
-                setuwep(obj);
-                u.twoweap = twoweap;
-                if (cansee(bhitpos.x, bhitpos.y))
-                    newsym(bhitpos.x, bhitpos.y);
-            } else {
-                int dmg = rn2(2);
-                if (!dmg) {
-#if 0 /*JP*/
-                    pline(Blind ? "%s lands %s your %s."
-                                : "%s back to you, landing %s your %s.",
-                          Blind ? Something : Tobjnam(obj, "return"),
-                          Levitation ? "beneath" : "at",
-                          makeplural(body_part(FOOT)));
+                    obj = addinv(obj);
+                    (void) encumber_msg();
+                    /* addinv autoquivers an aklys if quiver is empty;
+                       if obj is quivered, remove it before wielding */
+                    if (obj->owornmask & W_QUIVER)
+                        setuqwep((struct obj *) 0);
+                    setuwep(obj);
+                    u.twoweap = twoweap;
+                    if (cansee(bhitpos.x, bhitpos.y))
+                        newsym(bhitpos.x, bhitpos.y);
+                } else {
+                    int dmg = rn2(2);
+
+                    if (!dmg) {
+#if 0 /*JP:T*/
+                        pline(Blind ? "%s lands %s your %s."
+                                    : "%s back to you, landing %s your %s.",
+                              Blind ? Something : Tobjnam(obj, "return"),
+                              Levitation ? "beneath" : "at",
+                              makeplural(body_part(FOOT)));
 #else
-                    pline("%s\82Í%s\82 \82È\82½\82Ì%s\82Ì%s\82É\97\8e\82¿\82½\81D",
-                          xname(obj),
-                          Blind ? "" : "\96ß\82Á\82Ä\82«\82Ä\81C",
-                          body_part(FOOT),
-                          Levitation ? "\89º" : "\82»\82Î");
+                        pline("%s\82Í%s\82 \82È\82½\82Ì%s\82Ì%s\82É\97\8e\82¿\82½\81D",
+                              xname(obj),
+                              Blind ? "" : "\96ß\82Á\82Ä\82«\82Ä\81C",
+                              body_part(FOOT),
+                              Levitation ? "\89º" : "\82»\82Î");
 #endif
-                } else {
-                    dmg += rnd(3);
-#if 0 /*JP*/
-                    pline(Blind ? "%s your %s!"
-                                : "%s back toward you, hitting your %s!",
-                          Tobjnam(obj, Blind ? "hit" : "fly"),
-                          body_part(ARM));
+                    } else {
+                        dmg += rnd(3);
+#if 0 /*JP:T*/
+                        pline(Blind ? "%s your %s!"
+                                    : "%s back toward you, hitting your %s!",
+                              Tobjnam(obj, Blind ? "hit" : "fly"),
+                              body_part(ARM));
 #else
-                    pline("%s\82Í%s\82 \82È\82½\82Ì%s\82É\96½\92\86\82µ\82½\81I",
-                          xname(obj),
-                          Blind ? "" : "\96ß\82Á\82Ä\82«\82Ä\81C",
-                          body_part(ARM));
+                        pline("%s\82Í%s\82 \82È\82½\82Ì%s\82É\96½\92\86\82µ\82½\81I",
+                              xname(obj),
+                              Blind ? "" : "\96ß\82Á\82Ä\82«\82Ä\81C",
+                              body_part(ARM));
 #endif
-                    (void) artifact_hit((struct monst *) 0, &youmonst, obj,
-                                        &dmg, 0);
+                        if (obj->oartifact)
+                            (void) artifact_hit((struct monst *) 0, &youmonst,
+                                                obj, &dmg, 0);
 #if 0 /*JP*/
-                    losehp(Maybe_Half_Phys(dmg), killer_xname(obj),
-                           KILLED_BY);
+                        losehp(Maybe_Half_Phys(dmg), killer_xname(obj),
+                               KILLED_BY);
 #else
-                    {
-                        char jbuf[BUFSZ];
-                        Sprintf(jbuf, "%s\82Å", xname(obj));
-                        losehp(Maybe_Half_Phys(dmg), jbuf, KILLED_BY);
-                    }
+                        {
+                            char jbuf[BUFSZ];
+                            Sprintf(jbuf, "%s\82Å", xname(obj));
+                            losehp(Maybe_Half_Phys(dmg), jbuf, KILLED_BY);
+                        }
 #endif
+                    }
+                    if (ship_object(obj, u.ux, u.uy, FALSE)) {
+                        thrownobj = (struct obj *) 0;
+                        return;
+                    }
+                    dropy(obj);
                 }
-                if (ship_object(obj, u.ux, u.uy, FALSE)) {
-                    thrownobj = (struct obj *) 0;
-                    return;
-                }
-                dropy(obj);
+                thrownobj = (struct obj *) 0;
+                return;
+            } else {
+                /* when this location is stepped on, the weapon will be
+                   auto-picked up due to 'obj->was_thrown' of 1;
+                   addinv() prevents thrown Mjollnir from being placed
+                   into the quiver slot, but an aklys will end up there if
+                   that slot is empty at the time; since hero will need to
+                   explicitly rewield the weapon to get throw-and-return
+                   capability back anyway, quivered or not shouldn't matter */
+                pline("%s to return!", Tobjnam(obj, "fail"));
+                /* continue below with placing 'obj' at target location */
             }
-            thrownobj = (struct obj *) 0;
-            return;
         }
 
         if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) && breaktest(obj)) {
@@ -1555,7 +1679,7 @@ boolean maybe_wakeup;
     else
         miss(missile, mon);
     if (maybe_wakeup && !rn2(3))
-        wakeup(mon);
+        wakeup(mon, TRUE);
     return;
 }
 
@@ -1578,9 +1702,11 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
     register int disttmp; /* distance modifier */
     int otyp = obj->otyp, hmode;
     boolean guaranteed_hit = (u.uswallow && mon == u.ustuck);
+    int dieroll;
 
-    hmode = (obj == uwep) ? HMON_APPLIED : (obj == kickedobj) ? HMON_KICKED
-                                                              : HMON_THROWN;
+    hmode = (obj == uwep) ? HMON_APPLIED
+              : (obj == kickedobj) ? HMON_KICKED
+                : HMON_THROWN;
 
     /* Differences from melee weapons:
      *
@@ -1662,7 +1788,8 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
        at leader... (kicked artifact is ok too; HMON_APPLIED could
        occur if quest artifact polearm or grapnel ever gets added) */
     if (hmode != HMON_APPLIED && quest_arti_hits_leader(obj, mon)) {
-        /* not wakeup(), which angers non-tame monsters */
+        /* AIS: changes to wakeup() means that it's now less inappropriate here
+           than it used to be, but the manual version works just as well */
         mon->msleeping = 0;
         mon->mstrategy &= ~STRAT_WAITMASK;
 
@@ -1697,6 +1824,8 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
         return 0;
     }
 
+    dieroll = rnd(20);
+
     if (obj->oclass == WEAPON_CLASS || is_weptool(obj)
         || obj->oclass == GEM_CLASS) {
         if (hmode == HMON_KICKED) {
@@ -1737,19 +1866,23 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
             tmp += weapon_hit_bonus(obj);
         }
 
-        if (tmp >= rnd(20)) {
+        if (tmp >= dieroll) {
+            boolean wasthrown = (thrownobj != 0);
+
+            /* attack hits mon */
             if (hmode == HMON_APPLIED)
                 u.uconduct.weaphit++;
-            if (hmon(mon, obj, hmode)) { /* mon still alive */
+            if (hmon(mon, obj, hmode, dieroll)) { /* mon still alive */
                 cutworm(mon, bhitpos.x, bhitpos.y, obj);
             }
             exercise(A_DEX, TRUE);
-            /* if hero is swallowed and projectile kills the engulfer,
-               obj gets added to engulfer's inventory and then dropped,
+            /* if hero was swallowed and projectile killed the engulfer,
+               'obj' got added to engulfer's inventory and then dropped,
                so we can't safely use that pointer anymore; it escapes
                the chance to be used up here... */
-            if (!thrownobj)
+            if (wasthrown && !thrownobj)
                 return 1;
+
             /* projectiles other than magic stones
                sometimes disappear when thrown */
             if (objects[otyp].oc_skill < P_NONE
@@ -1760,6 +1893,7 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
                  * but we need ammo to stay around longer on average.
                  */
                 int broken, chance;
+
                 chance = 3 + greatest_erosion(obj) - obj->spe;
                 if (chance > 1)
                     broken = rn2(chance);
@@ -1779,16 +1913,16 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
         } else {
             tmiss(obj, mon, TRUE);
             if (hmode == HMON_APPLIED)
-                wakeup(mon);
+                wakeup(mon, TRUE);
         }
 
     } else if (otyp == HEAVY_IRON_BALL) {
         exercise(A_STR, TRUE);
-        if (tmp >= rnd(20)) {
+        if (tmp >= dieroll) {
             int was_swallowed = guaranteed_hit;
 
             exercise(A_DEX, TRUE);
-            if (!hmon(mon, obj, hmode)) { /* mon killed */
+            if (!hmon(mon, obj, hmode, dieroll)) { /* mon killed */
                 if (was_swallowed && !u.uswallow && obj == uball)
                     return 1; /* already did placebc() */
             }
@@ -1798,9 +1932,9 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
 
     } else if (otyp == BOULDER) {
         exercise(A_STR, TRUE);
-        if (tmp >= rnd(20)) {
+        if (tmp >= dieroll) {
             exercise(A_DEX, TRUE);
-            (void) hmon(mon, obj, hmode);
+            (void) hmon(mon, obj, hmode, dieroll);
         } else {
             tmiss(obj, mon, TRUE);
         }
@@ -1808,12 +1942,12 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
     } else if ((otyp == EGG || otyp == CREAM_PIE || otyp == BLINDING_VENOM
                 || otyp == ACID_VENOM)
                && (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
-        (void) hmon(mon, obj, hmode);
+        (void) hmon(mon, obj, hmode, dieroll);
         return 1; /* hmon used it up */
 
     } else if (obj->oclass == POTION_CLASS
                && (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
-        potionhit(mon, obj, TRUE);
+        potionhit(mon, obj, POTHIT_HERO_THROW);
         return 1;
 
     } else if (befriend_with_obj(mon->data, obj)
@@ -1827,7 +1961,7 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
         }
     } else if (guaranteed_hit) {
         /* this assumes that guaranteed_hit is due to swallowing */
-        wakeup(mon);
+        wakeup(mon, TRUE);
         if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
             if (is_animal(u.ustuck->data)) {
                 minstapetrify(u.ustuck, TRUE);
@@ -2177,6 +2311,7 @@ boolean in_view;
     default: /* glass or crystal wand */
         if (obj->oclass != WAND_CLASS)
             impossible("breaking odd object?");
+        /*FALLTHRU*/
     case CRYSTAL_PLATE_MAIL:
     case LENSES:
     case MIRROR:
index c0bbe64..41fd51f 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 drawing.c       $NHDT-Date: 1447124657 2015/11/10 03:04:17 $  $NHDT-Branch: master $:$NHDT-Revision: 1.49 $ */
+/* NetHack 3.6 drawing.c       $NHDT-Date: 1463706747 2016/05/20 01:12:27 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */
 /* Copyright (c) NetHack Development Team 1992.                   */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -450,7 +450,7 @@ const struct symdef defsyms[MAXPCHARS] = {
        { '<', "ladder up", C(CLR_BROWN) },           /* upladder */
        { '>', "ladder down", C(CLR_BROWN) },         /* dnladder */
        { '_', "altar", C(CLR_GRAY) },                /* altar */
-       { '|', "grave", C(CLR_GRAY) },                /* grave */
+       { '|', "grave", C(CLR_WHITE) },               /* grave */
        { '\\', "opulent throne", C(HI_GOLD) },       /* throne */
 #else
 /*20*/ { '.', "\95\94\89®\82Ì\88Ã\82¢\95\94\95ª", C(CLR_BLACK) },      /* dark room */
@@ -461,12 +461,12 @@ const struct symdef defsyms[MAXPCHARS] = {
        { '<', "\8fã\82è\82Í\82µ\82²", C(CLR_BROWN) },          /* upladder */
        { '>', "\89º\82è\82Í\82µ\82²", C(CLR_BROWN) },          /* dnladder */
        { '_', "\8dÕ\92d", C(CLR_GRAY) },                 /* altar */
-       { '|', "\95æ", C(CLR_GRAY) },                   /* grave */
+       { '|', "\95æ", C(CLR_WHITE) },                  /* grave */
        { '\\', "\89Ø\82â\82©\82È\8bÊ\8dÀ", C(HI_GOLD) },         /* throne */
 #endif
 #if 0 /*JP*/
 /*30*/ { '#', "sink", C(CLR_GRAY) },                 /* sink */
-       { '{', "fountain", C(CLR_BLUE) },             /* fountain */
+       { '{', "fountain", C(CLR_BRIGHT_BLUE) },      /* fountain */
        { '}', "water", C(CLR_BLUE) },                /* pool */
        { '.', "ice", C(CLR_CYAN) },                  /* ice */
        { '}', "molten lava", C(CLR_RED) },           /* lava */
@@ -477,7 +477,7 @@ const struct symdef defsyms[MAXPCHARS] = {
        { ' ', "air", C(CLR_CYAN) },                  /* open air */
 #else
 /*30*/ { '#', "\97¬\82µ\91ä", C(CLR_GRAY) },               /* sink */
-       { '{', "\90ò", C(CLR_BLUE) },                   /* fountain */
+       { '{', "\90ò", C(CLR_BRIGHT_BLUE) },            /* fountain */
        { '}', "\90\85\82Ì\82½\82Ü\82Á\82½\8fê\8f\8a", C(CLR_BLUE) },     /* pool */
        { '.', "\95X", C(CLR_CYAN) },                   /* ice */
        { '}', "\97n\8aâ", C(CLR_RED) },                  /* lava */
@@ -538,11 +538,12 @@ const struct symdef defsyms[MAXPCHARS] = {
        { '^', "magic trap", C(HI_ZAP) },               /* trap */
        { '^', "anti-magic field", C(HI_ZAP) },         /* trap */
        { '^', "polymorph trap", C(CLR_BRIGHT_GREEN) }, /* trap */
-       { '^', "vibrating square", C(CLR_YELLOW) },     /* trap */
-       { '|', "wall", C(CLR_GRAY) },            /* vbeam */
-       { '-', "wall", C(CLR_GRAY) },            /* hbeam */
-       { '\\', "wall", C(CLR_GRAY) },           /* lslant */
-       { '/', "wall", C(CLR_GRAY) },            /* rslant */
+       { '~', "vibrating square", C(CLR_MAGENTA) },    /* "trap" */
+       /* zap colors are changed by mapglyph() to match type of beam */
+       { '|', "", C(CLR_GRAY) },                /* vbeam */
+       { '-', "", C(CLR_GRAY) },                /* hbeam */
+       { '\\', "", C(CLR_GRAY) },               /* lslant */
+       { '/', "", C(CLR_GRAY) },                /* rslant */
        { '*', "", C(CLR_WHITE) },               /* dig beam */
        { '!', "", C(CLR_WHITE) },               /* camera flash beam */
        { ')', "", C(HI_WOOD) },                 /* boomerang open left */
@@ -551,7 +552,8 @@ const struct symdef defsyms[MAXPCHARS] = {
        { '^', "\96\82\96@\82Ìã©", C(HI_ZAP) },                 /* trap */
        { '^', "\94½\96\82\96@\8bó\8aÔ\82Ìã©", C(HI_ZAP) },           /* trap */
        { '^', "\95Ï\89»\82Ìã©", C(CLR_BRIGHT_GREEN) },       /* trap */
-       { '^', "\90U\93®\82µ\82Ä\82¢\82é\8fê\8f\8a", C(CLR_YELLOW) },     /* trap */
+       { '~', "\90U\93®\82µ\82Ä\82¢\82é\8fê\8f\8a", C(CLR_MAGENTA) },    /* "trap" */
+       /* zap colors are changed by mapglyph() to match type of beam */
        { '|', "\95Ç", C(CLR_GRAY) },              /* vbeam */
        { '-', "\95Ç", C(CLR_GRAY) },              /* hbeam */
        { '\\', "\95Ç", C(CLR_GRAY) },             /* lslant */
@@ -572,6 +574,7 @@ const struct symdef defsyms[MAXPCHARS] = {
        { '#', "\93Å\89_", C(CLR_BRIGHT_GREEN) },           /* part of a cloud */
        { '?', "\97L\8cø\82È\88Ê\92u", C(CLR_BRIGHT_GREEN) },     /*  target position */
 #endif
+       /* swallow colors are changed by mapglyph() to match engulfing monst */
        { '/', "", C(CLR_GREEN) },         /* swallow top left      */
        { '-', "", C(CLR_GREEN) },         /* swallow top center    */
        { '\\', "", C(CLR_GREEN) },        /* swallow top right     */
@@ -580,6 +583,7 @@ const struct symdef defsyms[MAXPCHARS] = {
        { '\\', "", C(CLR_GREEN) },        /* swallow bottom left   */
        { '-', "", C(CLR_GREEN) },         /* swallow bottom center */
        { '/', "", C(CLR_GREEN) },         /* swallow bottom right  */
+       /* explosion colors are changed by mapglyph() to match type of expl. */
        { '/', "", C(CLR_ORANGE) },        /* explosion top left     */
        { '-', "", C(CLR_ORANGE) },        /* explosion top center   */
        { '\\', "", C(CLR_ORANGE) },       /* explosion top right    */
@@ -947,6 +951,7 @@ struct symparse loadsyms[] = {
     { SYM_PCHAR, S_bars, "S_bars" },
     { SYM_PCHAR, S_tree, "S_tree" },
     { SYM_PCHAR, S_room, "S_room" },
+    { SYM_PCHAR, S_darkroom, "S_darkroom" },
     { SYM_PCHAR, S_corr, "S_corr" },
     { SYM_PCHAR, S_litcorr, "S_litcorr" },
     { SYM_PCHAR, S_upstair, "S_upstair" },
@@ -991,6 +996,7 @@ struct symparse loadsyms[] = {
     { SYM_PCHAR, S_magic_trap, "S_magic_trap" },
     { SYM_PCHAR, S_anti_magic_trap, "S_anti_magic_trap" },
     { SYM_PCHAR, S_polymorph_trap, "S_polymorph_trap" },
+    { SYM_PCHAR, S_vibrating_square, "S_vibrating_square" },
     { SYM_PCHAR, S_vbeam, "S_vbeam" },
     { SYM_PCHAR, S_hbeam, "S_hbeam" },
     { SYM_PCHAR, S_lslant, "S_lslant" },
@@ -1021,6 +1027,7 @@ struct symparse loadsyms[] = {
     { SYM_PCHAR, S_explode7, "S_explode7" },
     { SYM_PCHAR, S_explode8, "S_explode8" },
     { SYM_PCHAR, S_explode9, "S_explode9" },
+    { SYM_OC, ILLOBJ_CLASS + SYM_OFF_O, "S_strange_obj" },
     { SYM_OC, WEAPON_CLASS + SYM_OFF_O, "S_weapon" },
     { SYM_OC, ARMOR_CLASS + SYM_OFF_O, "S_armor" },
     { SYM_OC, ARMOR_CLASS + SYM_OFF_O, "S_armour" },
index 45bbf30..b114244 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 dungeon.c       $NHDT-Date: 1448862377 2015/11/30 05:46:17 $  $NHDT-Branch: master $:$NHDT-Revision: 1.69 $ */
+/* NetHack 3.6 dungeon.c       $NHDT-Date: 1523308357 2018/04/09 21:12:37 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.87 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
@@ -57,11 +58,13 @@ STATIC_DCL boolean FDECL(unreachable_level, (d_level *, BOOLEAN_P));
 STATIC_DCL void FDECL(tport_menu, (winid, char *, struct lchoice *, d_level *,
                                    BOOLEAN_P));
 STATIC_DCL const char *FDECL(br_string, (int));
+STATIC_DCL char FDECL(chr_u_on_lvl, (d_level *));
 STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P,
                                      struct lchoice *));
 STATIC_DCL mapseen *FDECL(load_mapseen, (int));
 STATIC_DCL void FDECL(save_mapseen, (int, mapseen *));
 STATIC_DCL mapseen *FDECL(find_mapseen, (d_level *));
+STATIC_DCL mapseen *FDECL(find_mapseen_by_str, (const char *));
 STATIC_DCL void FDECL(print_mapseen, (winid, mapseen *, int, int, BOOLEAN_P));
 STATIC_DCL boolean FDECL(interest_mapseen, (mapseen *));
 STATIC_DCL void FDECL(traverse_mapseenchn, (BOOLEAN_P, winid,
@@ -246,7 +249,7 @@ dlb *stream;
         panic(
   "Premature EOF on dungeon description file!\r\nExpected %d bytes - got %d.",
               (size * nitems), (size * cnt));
-        terminate(EXIT_FAILURE);
+        nh_terminate(EXIT_FAILURE);
     }
 }
 
@@ -490,6 +493,7 @@ struct proto_dungeon *pd;
 
     branch_num = find_branch(dungeons[dgn].dname, pd);
     new_branch = (branch *) alloc(sizeof(branch));
+    (void) memset((genericptr_t)new_branch, 0, sizeof(branch));
     new_branch->next = (branch *) 0;
     new_branch->id = branch_id++;
     new_branch->type = correct_branch_type(&pd->tmpbranch[branch_num]);
@@ -545,6 +549,7 @@ struct proto_dungeon *pd;
 
     pd->final_lev[proto_index] = new_level =
         (s_level *) alloc(sizeof(s_level));
+    (void) memset((genericptr_t)new_level, 0, sizeof(s_level));
     /* load new level with data */
     Strcpy(new_level->proto, tlevel->name);
     new_level->boneid = tlevel->boneschar;
@@ -852,7 +857,7 @@ init_dungeons()
              * its branch.  First, the depth of the entry point:
              *
              *  depth of branch from "parent" dungeon
-             *  + -1 or 1 depending on a up or down stair or
+             *  + -1 or 1 depending on an up or down stair or
              *    0 if portal
              *
              * Followed by the depth of the top of the dungeon:
@@ -974,7 +979,7 @@ init_dungeons()
            instead of 0, so adjust the start point to shift endgame up */
         if (dunlevs_in_dungeon(&x->dlevel) > 1 - dungeons[i].depth_start)
             dungeons[i].depth_start -= 1;
-        /* TO DO: strip "dummy" out all the way here,
+        /* TODO: strip "dummy" out all the way here,
            so that it's hidden from <ctrl/O> feedback. */
     }
 
@@ -1228,16 +1233,16 @@ int upflag;
            destination instead of its enclosing region.
            Note: up vs down doesn't matter in this case
            because both specify the same exclusion area. */
-        place_lregion(dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy, 0, 0, 0,
-                      0, LR_DOWNTELE, (d_level *) 0);
+        place_lregion(dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy,
+                      0, 0, 0, 0, LR_DOWNTELE, (d_level *) 0);
     else if (up)
-        place_lregion(updest.lx, updest.ly, updest.hx, updest.hy, updest.nlx,
-                      updest.nly, updest.nhx, updest.nhy, LR_UPTELE,
-                      (d_level *) 0);
+        place_lregion(updest.lx, updest.ly, updest.hx, updest.hy,
+                      updest.nlx, updest.nly, updest.nhx, updest.nhy,
+                      LR_UPTELE, (d_level *) 0);
     else
-        place_lregion(dndest.lx, dndest.ly, dndest.hx, dndest.hy, dndest.nlx,
-                      dndest.nly, dndest.nhx, dndest.nhy, LR_DOWNTELE,
-                      (d_level *) 0);
+        place_lregion(dndest.lx, dndest.ly, dndest.hx, dndest.hy,
+                      dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy,
+                      LR_DOWNTELE, (d_level *) 0);
 }
 
 /* place you on the special staircase */
@@ -1616,6 +1621,25 @@ level_difficulty()
              * The same applies to Vlad's Tower, although the increment
              * there is inconsequential compared to overall depth.
              */
+#if 0
+        /*
+         * The inside of the Wizard's Tower is also effectively a
+         * builds-up area, reached from a portal an arbitrary distance
+         * below rather than stairs 1 level beneath the entry level.
+         */
+        else if (On_W_tower_level(&u.uz) && In_W_tower(some_X, some_Y, &u.uz))
+            res += (fakewiz1.dlev - u.uz.dlev);
+            /*
+             * Handling this properly would need more information here:
+             * an inside/outside flag, or coordinates to calculate it.
+             * Unfortunately level difficulty may be wanted before
+             * coordinates have been chosen so simply extending this
+             * routine to take extra arguments is not sufficient to cope.
+             * The difference beyond naive depth-from-surface is small
+             * relative to the overall depth, so just ignore complications
+             * posed by W_tower.
+             */
+#endif /*0*/
     }
     return (xchar) res;
 }
@@ -1628,30 +1652,40 @@ lev_by_name(nam)
 const char *nam;
 {
     schar lev = 0;
-    s_level *slev;
+    s_level *slev = (s_level *)0;
     d_level dlev;
     const char *p;
     int idx, idxtoo;
     char buf[BUFSZ];
+    mapseen *mseen;
 
-    /* allow strings like "the oracle level" to find "oracle" */
-    if (!strncmpi(nam, "the ", 4))
-        nam += 4;
-    if ((p = strstri(nam, " level")) != 0 && p == eos((char *) nam) - 6) {
-        nam = strcpy(buf, nam);
-        *(eos(buf) - 6) = '\0';
-    }
-    /* hell is the old name, and wouldn't match; gehennom would match its
-       branch, yielding the castle level instead of the valley of the dead */
-    if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
-        if (In_V_tower(&u.uz))
-            nam = " to Vlad's tower"; /* branch to... */
-        else
-            nam = "valley";
+    /* look at the player's custom level annotations first */
+    if ((mseen = find_mapseen_by_str(nam)) != 0) {
+        dlev = mseen->lev;
+    } else {
+        /* no matching annotation, check whether they used a name we know */
+
+        /* allow strings like "the oracle level" to find "oracle" */
+        if (!strncmpi(nam, "the ", 4))
+            nam += 4;
+        if ((p = strstri(nam, " level")) != 0 && p == eos((char *) nam) - 6) {
+            nam = strcpy(buf, nam);
+            *(eos(buf) - 6) = '\0';
+        }
+        /* hell is the old name, and wouldn't match; gehennom would match its
+           branch, yielding the castle level instead of the valley of the dead */
+        if (!strcmpi(nam, "gehennom") || !strcmpi(nam, "hell")) {
+            if (In_V_tower(&u.uz))
+                nam = " to Vlad's tower"; /* branch to... */
+            else
+                nam = "valley";
+        }
+
+        if ((slev = find_level(nam)) != 0)
+            dlev = slev->dlevel;
     }
 
-    if ((slev = find_level(nam)) != 0) {
-        dlev = slev->dlevel;
+    if (mseen || slev) {
         idx = ledger_no(&dlev);
         if ((dlev.dnum == u.uz.dnum
              /* within same branch, or else main dungeon <-> gehennom */
@@ -1663,7 +1697,7 @@ const char *nam;
                 wizard
                 || (level_info[idx].flags & (FORGOTTEN | VISITED))
                        == VISITED)) {
-            lev = depth(&slev->dlevel);
+            lev = depth(&dlev);
         }
     } else { /* not a specific level; try branch names */
         idx = find_branch(nam, (struct proto_dungeon *) 0);
@@ -1765,7 +1799,10 @@ int type;
     case BR_PORTAL:
         return "Portal";
     case BR_NO_END1:
+/*JP
         return "Connection";
+*/
+        return "\90Ú\91±\95\94";
     case BR_NO_END2:
         return "One way stair";
     case BR_STAIR:
@@ -1774,6 +1811,13 @@ int type;
     return " (unknown)";
 }
 
+STATIC_OVL char
+chr_u_on_lvl(dlev)
+d_level *dlev;
+{
+    return u.uz.dnum == dlev->dnum && u.uz.dlevel == dlev->dlevel ? '*' : ' ';
+}
+
 /* Print all child branches between the lower and upper bounds. */
 STATIC_OVL void
 print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices_p)
@@ -1791,7 +1835,9 @@ struct lchoice *lchoices_p;
     for (br = branches; br; br = br->next) {
         if (br->end1.dnum == dnum && lower_bound < br->end1.dlevel
             && br->end1.dlevel <= upper_bound) {
-            Sprintf(buf, "   %s to %s: %d", br_string(br->type),
+            Sprintf(buf, "%c %s to %s: %d",
+                    bymenu ? chr_u_on_lvl(&br->end1) : ' ',
+                    br_string(br->type),
                     dungeons[br->end2.dnum].dname, depth(&br->end1));
             if (bymenu)
                 tport_menu(win, buf, lchoices_p, &br->end1,
@@ -1818,8 +1864,8 @@ xchar *rdgn;
     branch *br;
     anything any;
     struct lchoice lchoices;
-
     winid win = create_nhwindow(NHW_MENU);
+
     if (bymenu) {
         start_menu(win);
         lchoices.idx = 0;
@@ -1865,7 +1911,9 @@ xchar *rdgn;
             print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu,
                          &lchoices);
 
-            Sprintf(buf, "   %s: %d", slev->proto, depth(&slev->dlevel));
+            Sprintf(buf, "%c %s: %d",
+                    chr_u_on_lvl(&slev->dlevel),
+                    slev->proto, depth(&slev->dlevel));
             if (Is_stronghold(&slev->dlevel))
                 Sprintf(eos(buf), " (tune %s)", tune);
             if (bymenu)
@@ -1920,26 +1968,35 @@ xchar *rdgn;
         Sprintf(buf, "Invocation position @ (%d,%d), hero @ (%d,%d)",
                 inv_pos.x, inv_pos.y, u.ux, u.uy);
         putstr(win, 0, buf);
-    }
-    /*
-     * The following is based on the assumption that the inter-level portals
-     * created by the level compiler (not the dungeon compiler) only exist
-     * one per level (currently true, of course).
-     */
-    else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz)
-             || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)) {
+    } else {
         struct trap *trap;
+
+        /* if current level has a magic portal, report its location;
+           this assumes that there is at most one magic portal on any
+           given level; quest and ft.ludios have pairs (one in main
+           dungeon matched with one in the corresponding branch), the
+           elemental planes have singletons (connection to next plane) */
+        *buf = '\0';
         for (trap = ftrap; trap; trap = trap->ntrap)
             if (trap->ttyp == MAGIC_PORTAL)
                 break;
 
-        putstr(win, 0, "");
         if (trap)
-            Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)", trap->tx,
-                    trap->ty, u.ux, u.uy);
-        else
-            Sprintf(buf, "No portal found.");
-        putstr(win, 0, buf);
+            Sprintf(buf, "Portal @ (%d,%d), hero @ (%d,%d)",
+                    trap->tx, trap->ty, u.ux, u.uy);
+
+        /* only report "no portal found" when actually expecting a portal */
+        else if (Is_earthlevel(&u.uz) || Is_waterlevel(&u.uz)
+                 || Is_firelevel(&u.uz) || Is_airlevel(&u.uz)
+                 || Is_qstart(&u.uz) || at_dgn_entrance("The Quest")
+                 || Is_knox(&u.uz))
+            Strcpy(buf, "No portal found.");
+
+        /* only give output if we found a portal or expected one and didn't */
+        if (*buf) {
+            putstr(win, 0, "");
+            putstr(win, 0, buf);
+        }
     }
 
     display_nhwindow(win, TRUE);
@@ -2007,24 +2064,36 @@ donamelevel()
     if (!(mptr = find_mapseen(&u.uz)))
         return 0;
 
+    nbuf[0] = '\0';
+#ifdef EDIT_GETLIN
+    if (mptr->custom) {
+        (void) strncpy(nbuf, mptr->custom, BUFSZ);
+        nbuf[BUFSZ - 1] = '\0';
+    }
+#else
     if (mptr->custom) {
         char tmpbuf[BUFSZ];
+
 #if 0 /*JP*/
         Sprintf(tmpbuf, "Replace annotation \"%.30s%s\" with?", mptr->custom,
-                strlen(mptr->custom) > 30 ? "..." : "");
-        getlin(tmpbuf, nbuf);
+                (strlen(mptr->custom) > 30) ? "..." : "");
 #else
-        Sprintf(tmpbuf, "\8c»\8dÝ\82Ì\96¼\91O\81u%.30s%s\81v\82ð\89½\82É\8f\91\82«\8a·\82¦\82é\81H", mptr->custom,
+        Sprintf(tmpbuf, "\8c»\8dÝ\82Ì\83\81\83\82\81u%.30s%s\81v\82ð\89½\82É\8f\91\82«\8a·\82¦\82é\81H", mptr->custom,
                 strlen(mptr->custom) > 30 ? "..." : "");
-        getlin(tmpbuf, nbuf);
 #endif
+        getlin(tmpbuf, nbuf);
     } else
+#endif
 /*JP
         getlin("What do you want to call this dungeon level?", nbuf);
 */
         getlin("\82±\82Ì\8aK\82ð\89½\82Æ\8cÄ\82Ô\81H", nbuf);
-    if (index(nbuf, '\033'))
+
+    /* empty input or ESC means don't add or change annotation;
+       space-only means discard current annotation without adding new one */
+    if (!*nbuf || *nbuf == '\033')
         return 0;
+    /* strip leading and trailing spaces, compress out consecutive spaces */
     (void) mungspaces(nbuf);
 
     /* discard old annotation, if any */
@@ -2033,7 +2102,8 @@ donamelevel()
         mptr->custom = (char *) 0;
         mptr->custom_lth = 0;
     }
-    /* add new annotation, unless it's empty or a single space */
+    /* add new annotation, unless it's all spaces (which will be an
+       empty string after mungspaces() above) */
     if (*nbuf && strcmp(nbuf, " ")) {
         mptr->custom = dupstr(nbuf);
         mptr->custom_lth = strlen(mptr->custom);
@@ -2055,6 +2125,20 @@ d_level *lev;
     return mptr;
 }
 
+STATIC_OVL mapseen *
+find_mapseen_by_str(s)
+const char *s;
+{
+    mapseen *mptr;
+
+    for (mptr = mapseenchn; mptr; mptr = mptr->next)
+        if (mptr->custom && !strcmpi(s, mptr->custom))
+            break;
+
+    return mptr;
+}
+
+
 void
 forget_mapseen(ledger_num)
 int ledger_num;
@@ -2084,6 +2168,39 @@ int ledger_num;
     }
 }
 
+void
+rm_mapseen(ledger_num)
+int ledger_num;
+{
+    mapseen *mptr, *mprev = (mapseen *)0;
+    struct cemetery *bp, *bpnext;
+
+    for (mptr = mapseenchn; mptr; mprev = mptr, mptr = mptr->next)
+        if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel == ledger_num)
+            break;
+
+    if (!mptr)
+        return;
+
+    if (mptr->custom)
+        free((genericptr_t) mptr->custom);
+
+    bp = mptr->final_resting_place;
+    while (bp) {
+        bpnext = bp->next;
+        free(bp);
+        bp = bpnext;
+    }
+
+    if (mprev) {
+        mprev->next = mptr->next;
+        free(mptr);
+    } else {
+        mapseenchn = mptr->next;
+        free(mptr);
+    }
+}
+
 STATIC_OVL void
 save_mapseen(fd, mptr)
 int fd;
@@ -2140,6 +2257,50 @@ int fd;
     return load;
 }
 
+/* to support '#stats' wizard-mode command */
+void
+overview_stats(win, statsfmt, total_count, total_size)
+winid win;
+const char *statsfmt;
+long *total_count, *total_size;
+{
+    char buf[BUFSZ], hdrbuf[QBUFSZ];
+    long ocount, osize, bcount, bsize, acount, asize;
+    struct cemetery *ce;
+    mapseen *mptr = find_mapseen(&u.uz);
+
+    ocount = bcount = acount = osize = bsize = asize = 0L;
+    for (mptr = mapseenchn; mptr; mptr = mptr->next) {
+        ++ocount;
+        osize += (long) sizeof *mptr;
+        for (ce = mptr->final_resting_place; ce; ce = ce->next) {
+            ++bcount;
+            bsize += (long) sizeof *ce;
+        }
+        if (mptr->custom_lth) {
+            ++acount;
+            asize += (long) (mptr->custom_lth + 1);
+        }
+    }
+
+    Sprintf(hdrbuf, "general, size %ld", (long) sizeof (mapseen));
+    Sprintf(buf, statsfmt, hdrbuf, ocount, osize);
+    putstr(win, 0, buf);
+    if (bcount) {
+        Sprintf(hdrbuf, "cemetery, size %ld",
+                (long) sizeof (struct cemetery));
+        Sprintf(buf, statsfmt, hdrbuf, bcount, bsize);
+        putstr(win, 0, buf);
+    }
+    if (acount) {
+        Sprintf(hdrbuf, "annotations, text");
+        Sprintf(buf, statsfmt, hdrbuf, acount, asize);
+        putstr(win, 0, buf);
+    }
+    *total_count += ocount + bcount + acount;
+    *total_size += osize + bsize + asize;
+}
+
 /* Remove all mapseen objects for a particular dnum.
  * Useful during quest expulsion to remove quest levels.
  * [No longer deleted, just marked as unreachable.  #overview will
@@ -2445,6 +2606,9 @@ recalc_mapseen()
             /*  An automatic annotation is added to the Castle and
              *  to Fort Ludios once their structure's main entrance
              *  has been seen (in person or via magic mapping).
+             *  For the Fort, that entrance is just a secret door
+             *  which will be converted into a regular one when
+             *  located (or destroyed).
              * DOOR: possibly a lowered drawbridge's open portcullis;
              * DBWALL: a raised drawbridge's "closed door";
              * DRAWBRIDGE_DOWN: the span provided by lowered bridge,
@@ -2454,15 +2618,33 @@ recalc_mapseen()
              *  the adjacent DBWALL has been seen.
              */
             case DOOR:
+                if (Is_knox(&u.uz)) {
+                    int ty, tx = x - 4;
+
+                    /* Throne is four columns left, either directly in
+                     * line or one row higher or lower, and doesn't have
+                     * to have been seen yet.
+                     *   ......|}}}.
+                     *   ..\...S}...
+                     *   ..\...S}...
+                     *   ......|}}}.
+                     * For 3.6.0 and earlier, it was always in direct line:
+                     * both throne and door on the lower of the two rows.
+                     */
+                    for (ty = y - 1; ty <= y + 1; ++ty)
+                        if (isok(tx, ty) && IS_THRONE(levl[tx][ty].typ)) {
+                            mptr->flags.ludios = 1;
+                            break;
+                        }
+                    break;
+                }
                 if (is_drawbridge_wall(x, y) < 0)
                     break;
-            /* else FALLTHRU */
+                /*FALLTHRU*/
             case DBWALL:
             case DRAWBRIDGE_DOWN:
                 if (Is_stronghold(&u.uz))
                     mptr->flags.castle = 1, mptr->flags.castletune = 1;
-                else if (Is_knox(&u.uz))
-                    mptr->flags.ludios = 1;
                 break;
             default:
                 break;
@@ -2621,11 +2803,7 @@ branch *br;
 */
         return closed_portal ? "\95\95\88ó\82³\82ê\82½\96\82\96@\82Ì\93ü\8cû" : "\96\82\96@\82Ì\93ü\8cû";
     case BR_NO_END1:
-#if 0 /*JP*/
         return "Connection";
-#else
-        return "\90Ú\91±\95\94";
-#endif
     case BR_NO_END2:
 /*JP
         return br->end1_up ? "One way stairs up" : "One way stairs down";
@@ -2884,10 +3062,6 @@ boolean printdun;
     if (In_endgame(&mptr->lev))
         Sprintf(buf, "%s%s:", TAB, endgamelevelname(tmpbuf, i));
     else
-        /* FIXME: when this branch has only one level (Ft.Ludios),
-         * listing "Level 1:" for it might confuse inexperienced
-         * players into thinking there's more than one.
-         */
 /*JP
         Sprintf(buf, "%sLevel %d:", TAB, i);
 */
@@ -2902,14 +3076,18 @@ boolean printdun;
     }
     /* [perhaps print custom annotation on its own line when it's long] */
     if (mptr->custom)
-        Sprintf(eos(buf), " (%s)", mptr->custom);
+        Sprintf(eos(buf), " \"%s\"", mptr->custom);
     if (on_level(&u.uz, &mptr->lev))
 #if 0 /*JP*/
         Sprintf(eos(buf), " <- You %s here.",
-                (!final || (final == 1 && how == ASCENDED)) ? "are" : "were");
+                (!final || (final == 1 && how == ASCENDED)) ? "are"
+                  : (final == 1 && how == ESCAPED) ? "left from"
+                    : "were");
 #else
-        Sprintf(eos(buf), " <- \82±\82±\82É%s\81D",
-                (!final || (final == 1 && how == ASCENDED)) ? "\82¢\82é" : "\82¢\82½");
+        Sprintf(eos(buf), " <- \82±\82±%s\81D",
+                (!final || (final == 1 && how == ASCENDED)) ? "\82É\82¢\82é"
+                  : (final == 1 && how == ESCAPED) ? "\82©\82ç\94²\82¯\82½"
+                    : "\82É\82¢\82½");
 #endif
     putstr(win, !final ? ATR_BOLD : 0, buf);
 
@@ -3011,11 +3189,6 @@ boolean printdun;
         Sprintf(buf, "%sA primitive area.", PREFIX);
 */
         Sprintf(buf, "%s\92P\8f\83\82È\95\94\89®\81D", PREFIX);
-    } else if (mptr->flags.quest_summons) {
-/*JP
-        Sprintf(buf, "%sSummoned by %s.", PREFIX, ldrname());
-*/
-        Sprintf(buf, "%s%s\82©\82ç\8cÄ\82Ñ\8fo\82³\82ê\82½\81D", PREFIX, ldrname());
     } else if (on_level(&mptr->lev, &qstart_level)) {
 #if 0 /*JP*/
         Sprintf(buf, "%sHome%s.", PREFIX,
@@ -3060,6 +3233,14 @@ boolean printdun;
     }
     if (*buf)
         putstr(win, 0, buf);
+    /* quest entrance is not mutually-exclusive with bigroom or rogue level */
+    if (mptr->flags.quest_summons) {
+/*JP
+        Sprintf(buf, "%sSummoned by %s.", PREFIX, ldrname());
+*/
+        Sprintf(buf, "%s%s\82©\82ç\8cÄ\82Ñ\8fo\82³\82ê\82½\81D", PREFIX, ldrname());
+        putstr(win, 0, buf);
+    }
 
     /* print out branches */
     if (mptr->br) {
@@ -3101,7 +3282,7 @@ boolean printdun;
             if (died_here) {
                 /* disclosure occurs before bones creation, so listing dead
                    hero here doesn't give away whether bones are produced */
-                formatkiller(tmpbuf, sizeof tmpbuf, how);
+                formatkiller(tmpbuf, sizeof tmpbuf, how, TRUE);
 #if 0 /*JP*/
                 /* rephrase a few death reasons to work with "you" */
                 (void) strsubst(tmpbuf, " himself", " yourself");
index b74b413..8e9fec7 100644 (file)
--- a/src/eat.c
+++ b/src/eat.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 eat.c   $NHDT-Date: 1449269916 2015/12/04 22:58:36 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.154 $ */
+/* NetHack 3.6 eat.c   $NHDT-Date: 1502754159 2017/08/14 23:42:39 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.179 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 
 STATIC_PTR int NDECL(eatmdone);
 STATIC_PTR int NDECL(eatfood);
-STATIC_PTR void FDECL(costly_tin, (int));
+STATIC_PTR struct obj *FDECL(costly_tin, (int));
 STATIC_PTR int NDECL(opentin);
 STATIC_PTR int NDECL(unfaint);
 
 STATIC_DCL const char *FDECL(food_xname, (struct obj *, BOOLEAN_P));
 STATIC_DCL void FDECL(choke, (struct obj *));
 STATIC_DCL void NDECL(recalc_wt);
+STATIC_DCL unsigned FDECL(obj_nutrition, (struct obj *));
 STATIC_DCL struct obj *FDECL(touchfood, (struct obj *));
 STATIC_DCL void NDECL(do_reset_eat);
 STATIC_DCL void FDECL(done_eating, (BOOLEAN_P));
@@ -102,6 +104,12 @@ register struct obj *obj;
         && (youmonst.data != &mons[PM_RUST_MONSTER] || is_rustprone(obj)))
         return TRUE;
 
+    /* Ghouls only eat non-veggy corpses or eggs (see dogfood()) */
+    if (u.umonnum == PM_GHOUL)
+        return (boolean)((obj->otyp == CORPSE
+                          && !vegan(&mons[obj->corpsenm]))
+                         || (obj->otyp == EGG));
+
     if (u.umonnum == PM_GELATINOUS_CUBE && is_organic(obj)
         /* [g.cubes can eat containers and retain all contents
             as engulfed items, but poly'd player can't do that] */
@@ -115,8 +123,11 @@ register struct obj *obj;
 void
 init_uhunger()
 {
+    context.botl = (u.uhs != NOT_HUNGRY || ATEMP(A_STR) < 0);
     u.uhunger = 900;
     u.uhs = NOT_HUNGRY;
+    if (ATEMP(A_STR) < 0)
+        ATEMP(A_STR) = 0;
 }
 
 /* tin types [SPINACH_TIN = -1, overrides corpsenm, nut==600] */
@@ -355,6 +366,32 @@ reset_eat()
     return;
 }
 
+/* base nutrition of a food-class object */
+STATIC_OVL unsigned
+obj_nutrition(otmp)
+struct obj *otmp;
+{
+    unsigned nut = (otmp->otyp == CORPSE) ? mons[otmp->corpsenm].cnutrit
+                      : otmp->globby ? otmp->owt
+                         : (unsigned) objects[otmp->otyp].oc_nutrition;
+
+    if (otmp->otyp == LEMBAS_WAFER) {
+        if (maybe_polyd(is_elf(youmonst.data), Race_if(PM_ELF)))
+            nut += nut / 4; /* 800 -> 1000 */
+        else if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC)))
+            nut -= nut / 4; /* 800 -> 600 */
+        /* prevent polymorph making a partly eaten wafer
+           become more nutritious than an untouched one */
+        if (otmp->oeaten >= nut)
+            otmp->oeaten = (otmp->oeaten < objects[LEMBAS_WAFER].oc_nutrition)
+                              ? (nut - 1) : nut;
+    } else if (otmp->otyp == CRAM_RATION) {
+        if (maybe_polyd(is_dwarf(youmonst.data), Race_if(PM_DWARF)))
+            nut += nut / 6; /* 600 -> 700 */
+    }
+    return nut;
+}
+
 STATIC_OVL struct obj *
 touchfood(otmp)
 struct obj *otmp;
@@ -369,9 +406,7 @@ struct obj *otmp;
 
     if (!otmp->oeaten) {
         costly_alteration(otmp, COST_BITE);
-        otmp->oeaten =
-            (otmp->otyp == CORPSE ? mons[otmp->corpsenm].cnutrit
-                                  : objects[otmp->otyp].oc_nutrition);
+        otmp->oeaten = obj_nutrition(otmp);
     }
 
     if (carried(otmp)) {
@@ -473,7 +508,9 @@ STATIC_OVL void
 done_eating(message)
 boolean message;
 {
-    context.victual.piece->in_use = TRUE;
+    struct obj *piece = context.victual.piece;
+
+    piece->in_use = TRUE;
     occupation = 0; /* do this early, so newuhs() knows we're done */
     newuhs(FALSE);
     if (nomovemsg) {
@@ -482,19 +519,19 @@ boolean message;
         nomovemsg = 0;
     } else if (message)
 /*JP
-        You("finish eating %s.", food_xname(context.victual.piece, TRUE));
+        You("finish eating %s.", food_xname(piece, TRUE));
 */
-        You("%s\82ð\90H\82×\8fI\82¦\82½\81D",  food_xname(context.victual.piece, TRUE));
+        You("%s\82ð\90H\82×\8fI\82¦\82½\81D",  food_xname(piece, TRUE));
 
-    if (context.victual.piece->otyp == CORPSE)
-        cpostfx(context.victual.piece->corpsenm);
+    if (piece->otyp == CORPSE || piece->globby)
+        cpostfx(piece->corpsenm);
     else
-        fpostfx(context.victual.piece);
+        fpostfx(piece);
 
-    if (carried(context.victual.piece))
-        useup(context.victual.piece);
+    if (carried(piece))
+        useup(piece);
     else
-        useupf(context.victual.piece, 1L);
+        useupf(piece, 1L);
     context.victual.piece = (struct obj *) 0;
     context.victual.o_id = 0;
     context.victual.fullwarn = context.victual.eating =
@@ -544,7 +581,7 @@ int *dmg_p; /* for dishing out extra damage in lieu of Int loss */
 */
         Your("\94]\82Í\90H\82×\82ç\82ê\82½\81I");
     } else { /* monster against monster */
-        if (visflag)
+        if (visflag && canspotmon(mdef))
 /*JP
             pline("%s brain is eaten!", s_suffix(Monnam(mdef)));
 */
@@ -561,7 +598,7 @@ int *dmg_p; /* for dishing out extra damage in lieu of Int loss */
         } else {
             /* no need to check for poly_when_stoned or Stone_resistance;
                mind flayers don't have those capabilities */
-            if (visflag)
+            if (visflag && canseemon(magr))
 /*JP
                 pline("%s turns to stone!", Monnam(magr));
 */
@@ -574,7 +611,7 @@ int *dmg_p; /* for dishing out extra damage in lieu of Int loss */
                 if (magr->mtame && !visflag)
                     /* parallels mhitm.c's brief_feeling */
 /*JP
-                    You("have a sad thought for a moment, then is passes.");
+                    You("have a sad thought for a moment, then it passes.");
 */
                     You("\94ß\82µ\82¢\8dl\82¦\82É\82¨\82»\82í\82ê\82½\82ª\81A\82·\82®\82É\89ß\82¬\82³\82Á\82½\81D");
                 return MM_AGR_DIED;
@@ -675,7 +712,7 @@ int *dmg_p; /* for dishing out extra damage in lieu of Int loss */
          * monster mind flayer is eating another monster's brain
          */
         if (mindless(pd)) {
-            if (visflag)
+            if (visflag && canspotmon(mdef))
 /*JP
                 pline("%s doesn't notice.", Monnam(mdef));
 */
@@ -690,12 +727,14 @@ int *dmg_p; /* for dishing out extra damage in lieu of Int loss */
         } else {
             *dmg_p += xtra_dmg;
             give_nutrit = TRUE;
-            if (*dmg_p >= mdef->mhp && visflag)
-/*JP
+            if (*dmg_p >= mdef->mhp && visflag && canspotmon(mdef))
+#if 0 /*JP*/
                 pline("%s last thought fades away...",
-*/
-                pline("%s\82Ì\8dÅ\8cã\82Ì\8ev\82¢\82ª\82æ\82¬\82é\81D\81D\81D",
                       s_suffix(Monnam(mdef)));
+#else
+                pline("%s\82Ì\8dÅ\8cã\82Ì\8ev\82¢\82ª\82æ\82¬\82é\81D\81D\81D",
+                      Monnam(mdef));
+#endif
         }
     }
 
@@ -728,7 +767,9 @@ boolean allowmsg;
            and also shouldn't eat current species when polymorphed
            (even if having the form of something which doesn't care
            about cannibalism--hero's innate traits aren't altered) */
-        && (your_race(fptr) || (Upolyd && same_race(youmonst.data, fptr)))) {
+        && (your_race(fptr)
+            || (Upolyd && same_race(youmonst.data, fptr))
+            || (u.ulycn >= LOW_PM && were_beastie(pm) == u.ulycn))) {
         if (allowmsg) {
             if (Upolyd && your_race(fptr))
 /*JP
@@ -1082,7 +1123,7 @@ cpostfx(pm)
 register int pm;
 {
     register int tmp = 0;
-    boolean catch_lycanthropy = FALSE;
+    int catch_lycanthropy = NON_PM;
 
     /* in case `afternmv' didn't get called for previously mimicking
        gold, clean up now to avoid `eatmbuf' memory leak */
@@ -1113,22 +1154,20 @@ register int pm;
         pluslvl(FALSE);
         break;
     case PM_HUMAN_WERERAT:
-        catch_lycanthropy = TRUE;
-        u.ulycn = PM_WERERAT;
+        catch_lycanthropy = PM_WERERAT;
         break;
     case PM_HUMAN_WEREJACKAL:
-        catch_lycanthropy = TRUE;
-        u.ulycn = PM_WEREJACKAL;
+        catch_lycanthropy = PM_WEREJACKAL;
         break;
     case PM_HUMAN_WEREWOLF:
-        catch_lycanthropy = TRUE;
-        u.ulycn = PM_WEREWOLF;
+        catch_lycanthropy = PM_WEREWOLF;
         break;
     case PM_NURSE:
         if (Upolyd)
             u.mh = u.mhmax;
         else
             u.uhp = u.uhpmax;
+        make_blinded(0L, !u.ucreamed);
         context.botl = 1;
         break;
     case PM_STALKER:
@@ -1320,12 +1359,14 @@ register int pm;
             gainstr((struct obj *) 0, 0, TRUE);
         else if (tmp > 0)
             givit(tmp, ptr);
-    } break;
-    }
+        break;
+    } /* default case */
+    } /* switch */
 
-    if (catch_lycanthropy)
+    if (catch_lycanthropy >= LOW_PM) {
+        set_ulycn(catch_lycanthropy);
         retouch_equipment(2);
-
+    }
     return;
 }
 
@@ -1345,7 +1386,7 @@ violated_vegetarian()
 
 /* common code to check and possibly charge for 1 context.tin.tin,
  * will split() context.tin.tin if necessary */
-STATIC_PTR void
+STATIC_PTR struct obj *
 costly_tin(alter_type)
 int alter_type; /* COST_xxx */
 {
@@ -1359,6 +1400,7 @@ int alter_type; /* COST_xxx */
         }
         costly_alteration(tin, alter_type);
     }
+    return tin;
 }
 
 int
@@ -1518,7 +1560,7 @@ const char *mesg;
         b_trapped("tin", 0);
 */
         b_trapped("\8aÊ", 0);
-        costly_tin(COST_DSTROY);
+        tin = costly_tin(COST_DSTROY);
         goto use_up_tin;
     }
 
@@ -1532,7 +1574,7 @@ const char *mesg;
 */
             pline("\8aÊ\82Í\8bó\82Á\82Û\82¾\82Á\82½\81D");
             tin->dknown = tin->known = 1;
-            costly_tin(COST_OPEN);
+            tin = costly_tin(COST_OPEN);
             goto use_up_tin;
         }
 
@@ -1573,7 +1615,7 @@ const char *mesg;
                 You("\8aJ\82¯\82½\8aÊ\82ð\8eÌ\82Ä\82½\81D");
             if (!Hallucination)
                 tin->dknown = tin->known = 1;
-            costly_tin(COST_OPEN);
+            tin = costly_tin(COST_OPEN);
             goto use_up_tin;
         }
 
@@ -1600,7 +1642,7 @@ const char *mesg;
         cpostfx(mnum);
 
         /* charge for one at pre-eating cost */
-        costly_tin(COST_OPEN);
+        tin = costly_tin(COST_OPEN);
 
         if (tintxts[r].nut < 0) /* rotten */
             make_vomiting((long) rn1(15, 10), FALSE);
@@ -1645,7 +1687,7 @@ const char *mesg;
                 You("discard the open tin.");
 */
                 You("\8aJ\82¯\82½\8aÊ\82ð\8eÌ\82Ä\82½\81D");
-            costly_tin(COST_OPEN);
+            tin = costly_tin(COST_OPEN);
             goto use_up_tin;
         }
 
@@ -1653,8 +1695,7 @@ const char *mesg;
          * Same order as with non-spinach above:
          * conduct update, side-effects, shop handling, and nutrition.
          */
-        u.uconduct
-            .food++; /* don't need vegan/vegetarian checks for spinach */
+        u.uconduct.food++; /* don't need vegetarian checks for spinach */
         if (!tin->cursed)
 #if 0 /*JP:T*/
             pline("This makes you feel like %s!",
@@ -1665,7 +1706,7 @@ const char *mesg;
 #endif
         gainstr(tin, 0, FALSE);
 
-        costly_tin(COST_OPEN);
+        tin = costly_tin(COST_OPEN);
 
         lesshungry(tin->blessed
                       ? 600                   /* blessed */
@@ -1760,6 +1801,8 @@ struct obj *otmp;
         case ELVEN_DAGGER:
         case ORCISH_DAGGER:
         case ATHAME:
+        case KNIFE:
+        case STILETTO:
         case CRYSKNIFE:
             tmp = 3;
             break;
@@ -1818,8 +1861,10 @@ int
 Hear_again(VOID_ARGS)
 {
     /* Chance of deafness going away while fainted/sleeping/etc. */
-    if (!rn2(2))
+    if (!rn2(2)) {
         make_deaf(0L, FALSE);
+        context.botl = TRUE;
+    }
     return 0;
 }
 
@@ -1849,7 +1894,9 @@ struct obj *obj;
         pline("Everything suddenly goes dark.");
 */
         pline("\93Ë\91R\91S\82Ä\82ª\88Ã\82­\82È\82Á\82½\81D");
-        make_blinded((long) d(2, 10), FALSE);
+        /* hero is not Blind, but Blinded timer might be nonzero if
+           blindness is being overridden by the Eyes of the Overworld */
+        make_blinded((Blinded & TIMEOUT) + (long) d(2, 10), FALSE);
         if (!Blind)
             Your1(vision_clears);
     } else if (!rn2(3)) {
@@ -1880,6 +1927,7 @@ struct obj *obj;
 */
         pline("\90¢\8aE\82ª\89ñ\93]\82µ\81C%s%s\81D", where, what);
         incr_itimeout(&HDeaf, duration);
+        context.botl = TRUE;
         nomul(-duration);
 /*JP
         multi_reason = "unconscious from rotten food";
@@ -1900,11 +1948,13 @@ STATIC_OVL int
 eatcorpse(otmp)
 struct obj *otmp;
 {
-    int tp = 0, mnum = otmp->corpsenm;
+    int retcode = 0, tp = 0, mnum = otmp->corpsenm;
     long rotted = 0L;
-    int retcode = 0;
     boolean stoneable = (flesh_petrifies(&mons[mnum]) && !Stone_resistance
-                         && !poly_when_stoned(youmonst.data));
+                         && !poly_when_stoned(youmonst.data)),
+            slimeable = (mnum == PM_GREEN_SLIME && !Slimed && !Unchanging
+                         && !slimeproof(youmonst.data)),
+            glob = otmp->globby ? TRUE : FALSE;
 
     /* KMH, conduct */
     if (!vegan(&mons[mnum]))
@@ -1922,21 +1972,19 @@ struct obj *otmp;
             rotted -= 2L;
     }
 
-    if (mnum != PM_ACID_BLOB && !stoneable && rotted > 5L) {
+    if (mnum != PM_ACID_BLOB && !stoneable && !slimeable && rotted > 5L) {
         boolean cannibal = maybe_cannibal(mnum, FALSE);
 
 #if 0 /*JP*/
         pline("Ulch - that %s was tainted%s!",
-              mons[mnum].mlet == S_FUNGUS
-                  ? "fungoid vegetation"
-                  : !vegetarian(&mons[mnum]) ? "meat" : "protoplasm",
+              (mons[mnum].mlet == S_FUNGUS) ? "fungoid vegetation"
+                  : glob ? "glob"
+                      : vegetarian(&mons[mnum]) ? "protoplasm"
+                          : "meat",
               cannibal ? ", you cannibal" : "");
-#else
-        pline("\83I\83F\81I\82±\82Ì%s\82Í\95\85\82Á\82Ä\82¢\82é%s\81I", 
-              mons[mnum].mlet == S_FUNGUS
-                  ? "\8d×\8bÛ\82É\89\98\90õ\82³\82ê\82½\90A\95¨"
-                  : !vegetarian(&mons[mnum]) ? "\93÷" : "\90\95¨",
-              cannibal ? "\81D\82µ\82©\82à\8b¤\90H\82¢\82¾" : "");
+#else /* \93ú\96{\8cê\82Å\82Í\92P\8f\83\82É */
+        pline("\83I\83F\81I\82±\82ê\82Í\95\85\82Á\82Ä\82¢\82é\81I%s", 
+              cannibal ? "\82µ\82©\82à\8b¤\90H\82¢\82¾\81I" : "");
 #endif
         if (Sick_resistance) {
 /*JP
@@ -1950,13 +1998,15 @@ struct obj *otmp;
             /* make sure new ill doesn't result in improvement */
             if (Sick && (sick_time > Sick))
                 sick_time = (Sick > 1L) ? Sick - 1L : 1L;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             make_sick(sick_time, corpse_xname(otmp, "rotted", CXN_NORMAL),
                       TRUE, SICK_VOMITABLE);
 #else
             make_sick(sick_time, corpse_xname(otmp, "\95\85\82Á\82½", CXN_NORMAL),
                       TRUE, SICK_VOMITABLE);
 #endif
+
+            pline("(It must have died too long ago to be safe to eat.)");
         }
         if (carried(otmp))
             useup(otmp);
@@ -1970,9 +2020,10 @@ struct obj *otmp;
 #else
         pline("\88Ý\8e_\82Ì\92²\8eq\82ª\82Æ\82Ä\82à\88«\82¢\81D");
 #endif
-#if 0 /*JP*/
-        losehp(rnd(15), "acidic corpse", KILLED_BY_AN); /* acid damage */
-#else
+#if 0 /*JP:T*/
+        losehp(rnd(15), !glob ? "acidic corpse" : "acidic glob",
+               KILLED_BY_AN); /* acid damage */
+#else /* \93ú\96{\8cê\82Å\82Í\8bæ\95Ê\82µ\82È\82¢ */
         losehp(rnd(15), "\8e_\82Ì\8e\80\91Ì\82Å", KILLED_BY_AN);
 #endif
     } else if (poisonous(&mons[mnum]) && rn2(5)) {
@@ -1983,16 +2034,18 @@ struct obj *otmp;
         pline("\83E\83Q\83F\81[\81C\97L\93Å\82¾\82Á\82½\82É\82¿\82ª\82¢\82È\82¢\81I");  
         if (!Poison_resistance) {
             losestr(rnd(4));
-/*JP
-            losehp(rnd(15), "poisonous corpse", KILLED_BY_AN);
-*/
+#if 0 /*JP*/
+            losehp(rnd(15), !glob ? "poisonous corpse" : "poisonous glob",
+                   KILLED_BY_AN);
+#else
             losehp(rnd(15), "\93Å\82Ì\8e\80\91Ì\82Å", KILLED_BY_AN);
+#endif
         } else
 /*JP
             You("seem unaffected by the poison.");
 */
             You("\93Å\82Ì\89e\8b¿\82ð\8eó\82¯\82È\82¢\82æ\82¤\82¾\81D");
-        /* now any corpse left too long will make you mildly ill */
+    /* now any corpse left too long will make you mildly ill */
     } else if ((rotted > 5L || (rotted > 3L && rn2(5))) && !Sick_resistance) {
         tp++;
 /*JP
@@ -2000,13 +2053,13 @@ struct obj *otmp;
 */
         You("%s\8bC\95ª\82ª\88«\82¢\81D", (Sick) ? "\82Æ\82Ä\82à" : "");
 /*JP
-        losehp(rnd(8), "cadaver", KILLED_BY_AN);
+        losehp(rnd(8), !glob ? "cadaver" : "rotted glob", KILLED_BY_AN);
 */
         losehp(rnd(8), "\95\85\97\90\8e\80\91Ì\82Å", KILLED_BY_AN);
     }
 
     /* delay is weight dependent */
-    context.victual.reqtime = 3 + (mons[mnum].cwt >> 6);
+    context.victual.reqtime = 3 + ((!glob ? mons[mnum].cwt : otmp->owt) >> 6);
 
     if (!tp && !nonrotting_corpse(mnum) && (otmp->orotten || !rn2(7))) {
         if (rottenfood(otmp)) {
@@ -2043,31 +2096,44 @@ struct obj *otmp;
 */
         You("\96Ú\8bÊ\82ð\82Â\82ñ\82Â\82ñ\82Â\82Â\82¢\82½\81D");
     } else {
-        /* [is this right?  omnivores end up always disliking the taste] */
-        boolean yummy = vegan(&mons[mnum])
-                           ? (!carnivorous(youmonst.data)
-                              && herbivorous(youmonst.data))
-                           : (carnivorous(youmonst.data)
-                              && !herbivorous(youmonst.data));
+        /* yummy is always False for omnivores, palatable always True */
+        boolean yummy = (vegan(&mons[mnum])
+                            ? (!carnivorous(youmonst.data)
+                               && herbivorous(youmonst.data))
+                            : (carnivorous(youmonst.data)
+                               && !herbivorous(youmonst.data))),
+            palatable = ((vegetarian(&mons[mnum])
+                          ? herbivorous(youmonst.data)
+                          : carnivorous(youmonst.data))
+                         && rn2(10)
+                         && ((rotted < 1) ? TRUE : !rn2(rotted+1)));
+        const char *pmxnam = food_xname(otmp, FALSE);
 
 #if 0 /*JP*/
-        pline("%s%s %s!",
+        if (!strncmpi(pmxnam, "the ", 4))
+            pmxnam += 4;
+        pline("%s%s %s %s%c",
               type_is_pname(&mons[mnum])
                  ? "" : the_unique_pm(&mons[mnum]) ? "The " : "This ",
-              food_xname(otmp, FALSE),
+              pmxnam,
+              Hallucination ? "is" : "tastes",
+                  /* tiger reference is to TV ads for "Frosted Flakes",
+                     breakfast cereal targeted at kids by "Tony the tiger" */
               Hallucination
-                  ? (yummy ? ((u.umonnum == PM_TIGER) ? "is gr-r-reat"
-                                                      : "is gnarly")
-                           : "is grody")
-                  : (yummy ? "is delicious" : "tastes terrible"));
+                 ? (yummy ? ((u.umonnum == PM_TIGER) ? "gr-r-reat" : "gnarly")
+                          : palatable ? "copacetic" : "grody")
+                 : (yummy ? "delicious" : palatable ? "okay" : "terrible"),
+              (yummy || !palatable) ? '!' : '.');
 #else
-        pline("\82±\82Ì%s\82Í%s\81I",
-              food_xname(otmp, FALSE),
+        pline("\82±\82Ì%s\82Í%s%s",
+              pmxnam,
               Hallucination
-                  ? (yummy ? ((u.umonnum == PM_TIGER) ? "\83O\83D\83\8c\83C\83g\83D"
-                                                      : "\83C\83P\82Ä\82é")
-                           : "\83C\83P\82Ä\82È\82¢")
-                  : (yummy ? "\82Æ\82Ä\82à\8e|\82¢" : "\82Ð\82Ç\82¢\96¡\82¾"));
+                 ? (yummy ? ((u.umonnum == PM_TIGER) ? "\83O\83D\83\8c\83C\83g\83D"
+                                                     : "\83C\83P\82Ä\82é")
+                          : palatable ? "\82Ü\82 \82 \82è\82¾" : "\83C\83P\82Ä\82È\82¢")
+                 : (yummy ? "\82Æ\82Ä\82à\8e|\82¢" : palatable ? "\82Ü\82 \82Ü\82 \82¾"
+                                                     : "\82Ð\82Ç\82¢\96¡\82¾"),
+              (yummy || !palatable) ? "\81I" : "\81D");
 #endif
     }
 
@@ -2081,8 +2147,12 @@ struct obj *otmp;
 {
     const char *old_nomovemsg, *save_nomovemsg;
 
-    debugpline2("start_eating: %lx (victual = %lx)", (unsigned long) otmp,
-                (unsigned long) context.victual.piece);
+    debugpline2("start_eating: %s (victual = %s)",
+                /* note: fmt_ptr() returns a static buffer but supports
+                   several such so we don't need to copy the first result
+                   before calling it a second time */
+                fmt_ptr((genericptr_t) otmp),
+                fmt_ptr((genericptr_t) context.victual.piece));
     debugpline1("reqtime = %d", context.victual.reqtime);
     debugpline1("(original reqtime = %d)", objects[otmp->otyp].oc_delay);
     debugpline1("nmod = %d", context.victual.nmod);
@@ -2181,6 +2251,15 @@ struct obj *otmp;
                 make_vomiting((long) rn1(context.victual.reqtime, 14), FALSE);
         }
         break;
+    case LEMBAS_WAFER:
+        if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC))) {
+            pline("%s", "!#?&* elf kibble!");
+            break;
+        } else if (maybe_polyd(is_elf(youmonst.data), Race_if(PM_ELF))) {
+            pline("A little goes a long way.");
+            break;
+        }
+        goto give_feedback;
     case MEATBALL:
     case MEAT_STICK:
     case HUGE_CHUNK_OF_MEAT:
@@ -2191,7 +2270,7 @@ struct obj *otmp;
             make_vomiting((long) rn1(context.victual.reqtime, 5), FALSE);
             break;
         }
-        /* else FALLTHRU */
+        /*FALLTHRU*/
     default:
         if (otmp->otyp == SLIME_MOLD && !otmp->cursed
             && otmp->spe == context.current_fruit) {
@@ -2242,6 +2321,9 @@ struct obj *otmp;
 #else
             pline("\83E\83Q\83F\81[\95\85\82Á\82½\97\91\82¾\81D");
 #endif
+            /* increasing existing nausea means that it will take longer
+               before eventual vomit, but also means that constitution
+               will be abused more times before illness completes */
             make_vomiting((Vomiting & TIMEOUT) + (long) d(10, 4), TRUE);
         } else {
         give_feedback:
@@ -2499,12 +2581,23 @@ eatspecial()
         vault_gd_watching(GD_EATGOLD);
         return;
     }
+    if (objects[otmp->otyp].oc_material == PAPER) {
 #ifdef MAIL
-    if (otmp->otyp == SCR_MAIL) {
-        /* no nutrition */
-        pline("This junk mail is less than satisfying.");
-    }
+        if (otmp->otyp == SCR_MAIL)
+            /* no nutrition */
+            pline("This junk mail is less than satisfying.");
+        else
 #endif
+        if (otmp->otyp == SCR_SCARE_MONSTER)
+            /* to eat scroll, hero is currently polymorphed into a monster */
+            pline("Yuck%c", otmp->blessed ? '!' : '.');
+        else if (otmp->oclass == SCROLL_CLASS
+                 /* check description after checking for specific scrolls */
+                 && !strcmpi(OBJ_DESCR(objects[otmp->otyp]), "YUM YUM"))
+            pline("Yum%c", otmp->blessed ? '!' : '.');
+        else
+            pline("Needs salt...");
+    }
     if (otmp->oclass == POTION_CLASS) {
         otmp->quan++; /* dopotion() does a useup() */
         (void) dopotion(otmp);
@@ -2720,7 +2813,8 @@ struct obj *otmp;
      */
     char buf[BUFSZ], foodsmell[BUFSZ],
          it_or_they[QBUFSZ], eat_it_anyway[QBUFSZ];
-    boolean cadaver = (otmp->otyp == CORPSE), stoneorslime = FALSE;
+    boolean cadaver = (otmp->otyp == CORPSE || otmp->globby),
+            stoneorslime = FALSE;
     int material = objects[otmp->otyp].oc_material, mnum = otmp->corpsenm;
     long rotted = 0L;
 
@@ -2747,6 +2841,7 @@ struct obj *otmp;
 
         if (cadaver && !nonrotting_corpse(mnum)) {
             long age = peek_at_iced_corpse_age(otmp);
+
             /* worst case rather than random
                in this calculation to force prompt */
             rotted = (monstermoves - age) / (10L + 0 /* was rn2(20) */);
@@ -2938,6 +3033,7 @@ doeat()
 
     if (u.uedibility) {
         int res = edibility_prompts(otmp);
+
         if (res) {
 #if 0 /*JP*/
             Your(
@@ -2958,10 +3054,7 @@ doeat()
      * mails, players who polymorph back to human in the middle of their
      * metallic meal, etc....
      */
-    if (!(carried(otmp) ? retouch_object(&otmp, FALSE)
-                        : touch_artifact(otmp, &youmonst))) {
-        return 1;
-    } else if (!is_edible(otmp)) {
+    if (!is_edible(otmp)) {
 /*JP
         You("cannot eat that!");
 */
@@ -2975,6 +3068,9 @@ doeat()
 */
         You("\90g\82É\82Â\82¯\82Ä\82¢\82é\8aÔ\82Í\90H\82×\82ê\82È\82¢\81D");
         return 0;
+    } else if (!(carried(otmp) ? retouch_object(&otmp, FALSE)
+                               : touch_artifact(otmp, &youmonst))) {
+        return 1; /* got blasted so use a turn */
     }
     if (is_metallic(otmp) && u.umonnum == PM_RUST_MONSTER
         && otmp->oerodeproof) {
@@ -2992,18 +3088,31 @@ doeat()
         /* The regurgitated object's rustproofing is gone now */
         otmp->oerodeproof = 0;
         make_stunned((HStun & TIMEOUT) + (long) rn2(10), TRUE);
+        /*
+         * We don't expect rust monsters to be wielding welded weapons
+         * or wearing cursed rings which were rustproofed, but guard
+         * against the possibility just in case.
+         */
+        if (welded(otmp) || (otmp->cursed && (otmp->owornmask & W_RING))) {
+            otmp->bknown = 1; /* for ring; welded() does this for weapon */
+            You("spit out %s.", the(xname(otmp)));
+        } else {
 #if 0 /*JP*/
-        You("spit %s out onto the %s.", the(xname(otmp)),
-            surface(u.ux, u.uy));
+            You("spit %s out onto the %s.", the(xname(otmp)),
+                surface(u.ux, u.uy));
 #else
-        You("%s\82ð%s\82É\93f\82«\8fo\82µ\82½\81D", the(xname(otmp)),
-            surface(u.ux, u.uy));
+            You("%s\82ð%s\82É\93f\82«\8fo\82µ\82½\81D", the(xname(otmp)),
+                surface(u.ux, u.uy));
 #endif
-        if (carried(otmp)) {
-            freeinv(otmp);
-            dropy(otmp);
+            if (carried(otmp)) {
+                /* no need to check for leash in use; it's not metallic */
+                if (otmp->owornmask)
+                    remove_worn_item(otmp, FALSE);
+                freeinv(otmp);
+                dropy(otmp);
+            }
+            stackobj(otmp);
         }
-        stackobj(otmp);
         return 1;
     }
     /* KMH -- Slow digestion is... indigestible */
@@ -3056,8 +3165,11 @@ doeat()
             u.uconduct.unvegan++;
         u.uconduct.food++;
 
-        if (otmp->cursed)
+        if (otmp->cursed) {
             (void) rottenfood(otmp);
+            nodelicious = TRUE;
+        } else if (objects[otmp->otyp].oc_material == PAPER)
+            nodelicious = TRUE;
 
         if (otmp->oclass == WEAPON_CLASS && otmp->opoisoned) {
 /*JP
@@ -3080,7 +3192,7 @@ doeat()
                 You("seem unaffected by the poison.");
 */
                 You("\93Å\82Ì\89e\8b¿\82ð\8eó\82¯\82È\82¢\82æ\82¤\82¾\81D");
-        } else if (!otmp->cursed && !nodelicious) {
+        } else if (!nodelicious) {
 #if 0 /*JP*/
             pline("%s%s is delicious!",
                   (obj_is_pname(otmp)
@@ -3190,20 +3302,16 @@ doeat()
     }
 
     /* re-calc the nutrition */
-    if (otmp->otyp == CORPSE)
-        basenutrit = mons[otmp->corpsenm].cnutrit;
-    else
-        basenutrit = objects[otmp->otyp].oc_nutrition;
+    basenutrit = (int) obj_nutrition(otmp);
 
-    debugpline1("before rounddiv: context.victual.reqtime == %d",
-                context.victual.reqtime);
-    debugpline2("oeaten == %d, basenutrit == %d", otmp->oeaten, basenutrit);
-    context.victual.reqtime = (basenutrit == 0)
-                                 ? 0
-                                 : rounddiv(context.victual.reqtime
-                                            * (long) otmp->oeaten,
-                                            basenutrit);
-    debugpline1("after rounddiv: context.victual.reqtime == %d",
+    debugpline3(
+     "before rounddiv: victual.reqtime == %d, oeaten == %d, basenutrit == %d",
+                context.victual.reqtime, otmp->oeaten, basenutrit);
+
+    context.victual.reqtime = (basenutrit == 0) ? 0
+        : rounddiv(context.victual.reqtime * (long) otmp->oeaten, basenutrit);
+
+    debugpline1("after rounddiv: victual.reqtime == %d",
                 context.victual.reqtime);
     /*
      * calculate the modulo value (nutrit. units per round eating)
@@ -3226,6 +3334,42 @@ doeat()
     return 1;
 }
 
+int
+use_tin_opener(obj)
+struct obj *obj;
+{
+    struct obj *otmp;
+    int res = 0;
+
+    if (!carrying(TIN)) {
+/*JP
+        You("have no tin to open.");
+*/
+        You("\8aÊ\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81D");
+        return 0;
+    }
+
+    if (obj != uwep) {
+        if (obj->cursed && obj->bknown) {
+            char qbuf[QBUFSZ];
+
+            if (ynq(safe_qbuf(qbuf, "Really wield ", "?",
+                              obj, doname, thesimpleoname, "that")) != 'y')
+                return 0;
+        }
+        if (!wield_tool(obj, "use"))
+            return 0;
+        res = 1;
+    }
+
+    otmp = getobj(comestibles, "open");
+    if (!otmp)
+        return res;
+
+    start_tin(otmp);
+    return 1;
+}
+
 /* Take a single bite from a piece of food, checking for choking and
  * modifying usedtime.  Returns 1 if they choked and survived, 0 otherwise.
  */
@@ -3255,15 +3399,21 @@ bite()
     return 0;
 }
 
-/* as time goes by - called by moveloop() and domove() */
+/* as time goes by - called by moveloop(every move) & domove(melee attack) */
 void
 gethungry()
 {
     if (u.uinvulnerable)
         return; /* you don't feel hungrier */
 
-    if ((!u.usleep || !rn2(10)) /* slow metabolic rate while asleep */
-        && (carnivorous(youmonst.data) || herbivorous(youmonst.data))
+    /* being polymorphed into a creature which doesn't eat prevents
+       this first uhunger decrement, but to stay in such form the hero
+       will need to wear an Amulet of Unchanging so still burn a small
+       amount of nutrition in the 'moves % 20' ring/amulet check below */
+    if ((!Unaware || !rn2(10)) /* slow metabolic rate while asleep */
+        && (carnivorous(youmonst.data)
+            || herbivorous(youmonst.data)
+            || metallivorous(youmonst.data))
         && !Slow_digestion)
         u.uhunger--; /* ordinary food consumption */
 
@@ -3280,8 +3430,8 @@ gethungry()
         /* Conflict uses up food too */
         if (HConflict || (EConflict & (~W_ARTI)))
             u.uhunger--;
-        /* +0 charged rings don't do anything, so don't affect hunger */
-        /* Slow digestion still uses ring hunger */
+        /* +0 charged rings don't do anything, so don't affect hunger.
+           Slow digestion cancels move hunger but still causes ring hunger. */
         switch ((int) (moves % 20)) { /* note: use even cases only */
         case 4:
             if (uleft && (uleft->spe || !objects[uleft->otyp].oc_charged))
@@ -3454,11 +3604,14 @@ boolean incr;
     }
 
     if (newhs == FAINTING) {
+        /* u,uhunger is likely to be negative at this point */
+        int uhunger_div_by_10 = sgn(u.uhunger) * ((abs(u.uhunger) + 5) / 10);
+
         if (is_fainted())
             newhs = FAINTED;
-        if (u.uhs <= WEAK || rn2(20 - u.uhunger / 10) >= 19) {
+        if (u.uhs <= WEAK || rn2(20 - uhunger_div_by_10) >= 19) {
             if (!is_fainted() && multi >= 0 /* %% */) {
-                int duration = 10 - (u.uhunger / 10);
+                int duration = 10 - uhunger_div_by_10;
 
                 /* stop what you're doing, then faint */
                 stop_occupation();
@@ -3466,12 +3619,8 @@ boolean incr;
                 You("faint from lack of food.");
 */
                 You("\95 \82ª\8c¸\82Á\82Ä\93|\82ê\82½\81D");
-                if (!Levitation)
-/*JP
-                    selftouch("Falling, you");
-*/
-                    selftouch("\97\8e\82¿\82È\82ª\82ç\81C\82 \82È\82½\82Í");
                 incr_itimeout(&HDeaf, duration);
+                context.botl = TRUE;
                 nomul(-duration);
 /*JP
                 multi_reason = "fainted from lack of food";
@@ -3483,8 +3632,17 @@ boolean incr;
                 nomovemsg = "\82 \82È\82½\82Í\90³\8bC\82Ã\82¢\82½\81D";
                 afternmv = unfaint;
                 newhs = FAINTED;
+                if (!Levitation)
+/*JP
+                    selftouch("Falling, you");
+*/
+                    selftouch("\97\8e\82¿\82È\82ª\82ç\81C\82 \82È\82½\82Í");
             }
-        } else if (u.uhunger < -(int) (200 + 20 * ACURR(A_CON))) {
+
+        /* this used to be -(200 + 20 * Con) but that was when being asleep
+           suppressed per-turn uhunger decrement but being fainted didn't;
+           now uhunger becomes more negative at a slower rate */
+        } else if (u.uhunger < -(100 + 10 * (int) ACURR(A_CON))) {
             u.uhs = STARVED;
             context.botl = 1;
             bot();
@@ -3504,10 +3662,23 @@ boolean incr;
     }
 
     if (newhs != u.uhs) {
-        if (newhs >= WEAK && u.uhs < WEAK)
-            losestr(1); /* this may kill you -- see below */
-        else if (newhs < WEAK && u.uhs >= WEAK)
-            losestr(-1);
+        if (newhs >= WEAK && u.uhs < WEAK) {
+            /* this used to be losestr(1) which had the potential to
+               be fatal (still handled below) by reducing HP if it
+               tried to take base strength below minimum of 3 */
+            ATEMP(A_STR) = -1; /* temporary loss overrides Fixed_abil */
+            /* defer context.botl status update until after hunger message */
+        } else if (newhs < WEAK && u.uhs >= WEAK) {
+            /* this used to be losestr(-1) which could be abused by
+               becoming weak while wearing ring of sustain ability,
+               removing ring, eating to 'restore' strength which boosted
+               strength by a point each time the cycle was performed;
+               substituting "while polymorphed" for sustain ability and
+               "rehumanize" for ring removal might have done that too */
+            ATEMP(A_STR) = 0; /* repair of loss also overrides Fixed_abil */
+            /* defer context.botl status update until after hunger message */
+        }
+
         switch (newhs) {
         case HUNGRY:
             if (Hallucination) {
@@ -3630,7 +3801,8 @@ int corpsecheck; /* 0, no check, 1, corpses, 2, tinnable corpses */
 #endif
 
     /* if we can't touch floor objects then use invent food only */
-    if (!can_reach_floor(TRUE) || (feeding && u.usteed)
+    if (iflags.menu_requested /* command was preceded by 'm' prefix */
+        || !can_reach_floor(TRUE) || (feeding && u.usteed)
         || (is_pool_or_lava(u.ux, u.uy)
             && (Wwalking || is_clinger(youmonst.data)
                 || (Flying && !Breathless))))
@@ -3694,6 +3866,16 @@ int corpsecheck; /* 0, no check, 1, corpses, 2, tinnable corpses */
             char qsfx[QBUFSZ];
             boolean one = (otmp->quan == 1L);
 
+            /* if blind and without gloves, attempting to eat (or tin or
+               offer) a cockatrice corpse is fatal before asking whether
+               or not to use it; otherwise, 'm<dir>' followed by 'e' could
+               be used to locate cockatrice corpses without touching them */
+            if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
+                feel_cockatrice(otmp, FALSE);
+                /* if life-saved (or poly'd into stone golem), terminate
+                   attempt to eat off floor */
+                return (struct obj *) 0;
+            }
             /* "There is <an object> here; <verb> it?" or
                "There are <N objects> here; <verb> one?" */
 #if 0 /*JP*/
@@ -3718,8 +3900,8 @@ skipfloor:
     /* We cannot use ALL_CLASSES since that causes getobj() to skip its
      * "ugly checks" and we need to check for inedible items.
      */
-    otmp =
-        getobj(feeding ? allobj : offering ? offerfodder : comestibles, verb);
+    otmp = getobj(feeding ? allobj : offering ? offerfodder : comestibles,
+                  verb);
     if (corpsecheck && otmp && !(offering && otmp->oclass == AMULET_CLASS))
         if (otmp->otyp != CORPSE || (corpsecheck == 2 && !tinnable(otmp))) {
 /*JP
@@ -3736,21 +3918,33 @@ skipfloor:
 void
 vomit() /* A good idea from David Neves */
 {
-    if (cantvomit(youmonst.data))
+    if (cantvomit(youmonst.data)) {
         /* doesn't cure food poisoning; message assumes that we aren't
            dealing with some esoteric body_part() */
 /*JP
         Your("jaw gapes convulsively.");
 */
         Your("\82 \82²\82Í\94­\8dì\93I\82É\91å\82«\82­\8aJ\82¢\82½\81D");
-    else
+    } else {
         make_sick(0L, (char *) 0, TRUE, SICK_VOMITABLE);
-    nomul(-2);
+        /* if not enough in stomach to actually vomit then dry heave;
+           vomiting_dialog() gives a vomit message when its countdown
+           reaches 0, but only if u.uhs < FAINTING (and !cantvomit()) */
+        if (u.uhs >= FAINTING)
+            Your("%s heaves convulsively!", body_part(STOMACH));
+    }
+
+    /* nomul()/You_can_move_again used to be unconditional, which was
+       viable while eating but not for Vomiting countdown where hero might
+       be immobilized for some other reason at the time vomit() is called */
+    if (multi >= -2) {
+        nomul(-2);
 /*JP
     multi_reason = "vomiting";
 */
     multi_reason = "\9aq\93f\82µ\82Ä\82¢\82é\8dÅ\92\86\82É";
-    nomovemsg = You_can_move_again;
+        nomovemsg = You_can_move_again;
+    }
 }
 
 int
@@ -3760,10 +3954,9 @@ struct obj *obj;
 {
     long uneaten_amt, full_amount;
 
+    /* get full_amount first; obj_nutrition() might modify obj->oeaten */
+    full_amount = (long) obj_nutrition(obj);
     uneaten_amt = (long) obj->oeaten;
-    full_amount = (obj->otyp == CORPSE)
-                      ? (long) mons[obj->corpsenm].cnutrit
-                      : (long) objects[obj->otyp].oc_nutrition;
     if (uneaten_amt > full_amount) {
         impossible(
           "partly eaten food (%ld) more nutritious than untouched food (%ld)",
index e884ec1..1f223be 100644 (file)
--- a/src/end.c
+++ b/src/end.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 end.c   $NHDT-Date: 1448241780 2015/11/23 01:23:00 $  $NHDT-Branch: master $:$NHDT-Revision: 1.108 $ */
+/* NetHack 3.6 end.c   $NHDT-Date: 1512803167 2017/12/09 07:06:07 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.137 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #define NEED_VARARGS /* comment line for pre-compiled headers */
@@ -50,9 +51,16 @@ STATIC_DCL void FDECL(artifact_score, (struct obj *, BOOLEAN_P, winid));
 STATIC_DCL void FDECL(really_done, (int)) NORETURN;
 STATIC_DCL boolean FDECL(odds_and_ends, (struct obj *, int));
 STATIC_DCL void FDECL(savelife, (int));
+STATIC_PTR int FDECL(CFDECLSPEC vanqsort_cmp, (const genericptr,
+                                               const genericptr));
+STATIC_DCL int NDECL(set_vanq_order);
 STATIC_DCL void FDECL(list_vanquished, (CHAR_P, BOOLEAN_P));
 STATIC_DCL void FDECL(list_genocided, (CHAR_P, BOOLEAN_P));
 STATIC_DCL boolean FDECL(should_query_disclose_option, (int, char *));
+#ifdef DUMPLOG
+STATIC_DCL void NDECL(dump_plines);
+#endif
+STATIC_DCL void FDECL(dump_everything, (int, time_t));
 STATIC_DCL int NDECL(num_extinct);
 
 #if defined(__BEOS__) || defined(MICRO) || defined(WIN32) || defined(OS2)
@@ -182,9 +190,9 @@ NH_abort()
         gdb_prio++;
 
     if (gdb_prio > libc_prio) {
-        NH_panictrace_gdb() || (libc_prio && NH_panictrace_libc());
+        (void) (NH_panictrace_gdb() || (libc_prio && NH_panictrace_libc()));
     } else {
-        NH_panictrace_libc() || (gdb_prio && NH_panictrace_gdb());
+        (void) (NH_panictrace_libc() || (gdb_prio && NH_panictrace_gdb()));
     }
 
 #else /* VMS */
@@ -581,6 +589,44 @@ int how;
     return;
 }
 
+/* some special cases for overriding while-helpless reason */
+static const struct {
+    int why, unmulti;
+    const char *exclude, *include;
+} death_fixups[] = {
+    /* "petrified by <foo>, while getting stoned" -- "while getting stoned"
+       prevented any last-second recovery, but it was not the cause of
+       "petrified by <foo>" */
+    { STONING, 1, "getting stoned", (char *) 0 },
+    /* "died of starvation, while fainted from lack of food" is accurate
+       but sounds a fairly silly (and doesn't actually appear unless you
+       splice together death and while-helpless from xlogfile) */
+    { STARVING, 0, "fainted from lack of food", "fainted" },
+};
+
+/* clear away while-helpless when the cause of death caused that
+   helplessness (ie, "petrified by <foo> while getting stoned") */
+STATIC_DCL void
+fixup_death(how)
+int how;
+{
+    int i;
+
+    if (multi_reason) {
+        for (i = 0; i < SIZE(death_fixups); ++i)
+            if (death_fixups[i].why == how
+                && !strcmp(death_fixups[i].exclude, multi_reason)) {
+                if (death_fixups[i].include) /* substitute alternate reason */
+                    multi_reason = death_fixups[i].include;
+                else /* remove the helplessness reason */
+                    multi_reason = (char *) 0;
+                if (death_fixups[i].unmulti) /* possibly hide helplessness */
+                    multi = 0L;
+                break;
+            }
+    }
+}
+
 #if defined(WIN32) && !defined(SYSCF)
 #define NOTIFY_NETHACK_BUGS
 #endif
@@ -687,7 +733,7 @@ int category;
 char *defquery;
 {
     int idx;
-    char *dop;
+    char disclose, *dop;
 
     *defquery = 'n';
     if ((dop = index(disclosure_options, category)) != 0) {
@@ -699,15 +745,22 @@ char *defquery;
             *defquery = DISCLOSE_PROMPT_DEFAULT_YES;
             return TRUE;
         }
-        if (flags.end_disclose[idx] == DISCLOSE_YES_WITHOUT_PROMPT) {
+        disclose = flags.end_disclose[idx];
+        if (disclose == DISCLOSE_YES_WITHOUT_PROMPT) {
             *defquery = 'y';
             return FALSE;
-        } else if (flags.end_disclose[idx] == DISCLOSE_NO_WITHOUT_PROMPT) {
+        } else if (disclose == DISCLOSE_SPECIAL_WITHOUT_PROMPT) {
+            *defquery = 'a';
+            return FALSE;
+        } else if (disclose == DISCLOSE_NO_WITHOUT_PROMPT) {
             *defquery = 'n';
             return FALSE;
-        } else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_YES) {
+        } else if (disclose == DISCLOSE_PROMPT_DEFAULT_YES) {
             *defquery = 'y';
             return TRUE;
+        } else if (disclose == DISCLOSE_PROMPT_DEFAULT_SPECIAL) {
+            *defquery = 'a';
+            return TRUE;
         } else {
             *defquery = 'n';
             return TRUE;
@@ -717,6 +770,102 @@ char *defquery;
     return TRUE;
 }
 
+#ifdef DUMPLOG
+STATIC_OVL void
+dump_plines()
+{
+    int i, j;
+    char buf[BUFSZ], **strp;
+    extern char *saved_plines[];
+    extern unsigned saved_pline_index;
+
+    Strcpy(buf, " "); /* one space for indentation */
+    putstr(0, 0, "Latest messages:");
+    for (i = 0, j = (int) saved_pline_index; i < DUMPLOG_MSG_COUNT;
+         ++i, j = (j + 1) % DUMPLOG_MSG_COUNT) {
+        strp = &saved_plines[j];
+        if (*strp) {
+            copynchars(&buf[1], *strp, BUFSZ - 1 - 1);
+            putstr(0, 0, buf);
+#ifdef FREE_ALL_MEMORY
+            free(*strp), *strp = 0;
+#endif
+        }
+    }
+}
+#endif
+
+/*ARGSUSED*/
+STATIC_OVL void
+dump_everything(how, when)
+int how;
+time_t when; /* date+time at end of game */
+{
+#ifdef DUMPLOG
+    char pbuf[BUFSZ], datetimebuf[24]; /* [24]: room for 64-bit bogus value */
+
+    dump_redirect(TRUE);
+    if (!iflags.in_dumplog)
+        return;
+
+    init_symbols(); /* revert to default symbol set */
+
+    /* one line version ID, which includes build date+time;
+       it's conceivable that the game started with a different
+       build date+time or even with an older nethack version,
+       but we only have access to the one it finished under */
+    putstr(0, 0, getversionstring(pbuf));
+    putstr(0, 0, "");
+
+    /* game start and end date+time to disambiguate version date+time */
+    Strcpy(datetimebuf, yyyymmddhhmmss(ubirthday));
+    Sprintf(pbuf, "Game began %4.4s-%2.2s-%2.2s %2.2s:%2.2s:%2.2s",
+            &datetimebuf[0], &datetimebuf[4], &datetimebuf[6],
+            &datetimebuf[8], &datetimebuf[10], &datetimebuf[12]);
+    Strcpy(datetimebuf, yyyymmddhhmmss(when));
+    Sprintf(eos(pbuf), ", ended %4.4s-%2.2s-%2.2s %2.2s:%2.2s:%2.2s.",
+            &datetimebuf[0], &datetimebuf[4], &datetimebuf[6],
+            &datetimebuf[8], &datetimebuf[10], &datetimebuf[12]);
+    putstr(0, 0, pbuf);
+    putstr(0, 0, "");
+
+    /* character name and basic role info */
+    Sprintf(pbuf, "%s, %s %s %s %s", plname,
+            aligns[1 - u.ualign.type].adj,
+            genders[flags.female].adj,
+            urace.adj,
+            (flags.female && urole.name.f) ? urole.name.f : urole.name.m);
+    putstr(0, 0, pbuf);
+    putstr(0, 0, "");
+
+    dump_map();
+    putstr(0, 0, do_statusline1());
+    putstr(0, 0, do_statusline2());
+    putstr(0, 0, "");
+
+    dump_plines();
+    putstr(0, 0, "");
+    putstr(0, 0, "Inventory:");
+    display_inventory((char *) 0, TRUE);
+    container_contents(invent, TRUE, TRUE, FALSE);
+    enlightenment((BASICENLIGHTENMENT | MAGICENLIGHTENMENT),
+                  (how >= PANICKED) ? ENL_GAMEOVERALIVE : ENL_GAMEOVERDEAD);
+    putstr(0, 0, "");
+    list_vanquished('d', FALSE); /* 'd' => 'y' */
+    putstr(0, 0, "");
+    list_genocided('d', FALSE); /* 'd' => 'y' */
+    putstr(0, 0, "");
+    show_conduct((how >= PANICKED) ? 1 : 2);
+    putstr(0, 0, "");
+    show_overview((how >= PANICKED) ? 1 : 2, how);
+    putstr(0, 0, "");
+    dump_redirect(FALSE);
+#else
+    nhUse(how);
+    nhUse(when);
+#endif
+}
+
 STATIC_OVL void
 disclose(how, taken)
 int how;
@@ -744,14 +893,7 @@ boolean taken;
         ask = should_query_disclose_option('i', &defquery);
         c = ask ? yn_function(qbuf, ynqchars, defquery) : defquery;
         if (c == 'y') {
-            struct obj *obj;
-
-            for (obj = invent; obj; obj = obj->nobj) {
-                makeknown(obj->otyp);
-                obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
-                if (Is_container(obj) || obj->otyp == STATUE)
-                    obj->cknown = obj->lknown = 1;
-            }
+            /* caller has already ID'd everything */
             (void) display_inventory((char *) 0, TRUE);
             container_contents(invent, TRUE, TRUE, FALSE);
         }
@@ -860,6 +1002,8 @@ int how;
     u.ugrave_arise = NON_PM;
     HUnchanging = 0L;
     curs_on_u();
+    if (!context.mon_moving)
+        endmultishot(FALSE);
 }
 
 /*
@@ -1009,6 +1153,18 @@ int how;
             return;
         }
     }
+    if (program_state.panicking
+#ifdef HANGUPHANDLING
+        || program_state.done_hup
+#endif
+        ) {
+        /* skip status update if panicking or disconnected */
+        context.botl = context.botlx = FALSE;
+    } else {
+        /* otherwise force full status update */
+        context.botlx = TRUE;
+        bot();
+    }
 
     if (how == ASCENDED || (!killer.name[0] && how == GENOCIDED))
         killer.format = NO_KILLER_PREFIX;
@@ -1062,11 +1218,13 @@ int how;
             return;
         }
     }
-    if ((wizard || discover) && (how <= GENOCIDED) &&
-/*JP
-        !paranoid_query(ParanoidDie, "Die?")) {
-*/
-        !paranoid_query(ParanoidDie, "\8e\80\82ñ\82Å\82Ý\82é\81H")) {
+#if 0 /*JP*/
+    if ((wizard || discover) && (how <= GENOCIDED)
+        && !paranoid_query(ParanoidDie, "Die?")) {
+#else
+    if ((wizard || discover) && (how <= GENOCIDED)
+        && !paranoid_query(ParanoidDie, "\8e\80\82ñ\82Å\82Ý\82é\81H")) {
+#endif
 /*JP
         pline("OK, so you don't %s.", (how == CHOKING) ? "choke" : "die");
 */
@@ -1115,14 +1273,10 @@ int how;
     /* remember time of death here instead of having bones, rip, and
        topten figure it out separately and possibly getting different
        time or even day if player is slow responding to --More-- */
-#if 0 /*C360-19*/
-    endtime = getnow();
-    urealtime.realtime += (long) (endtime - urealtime.restored);
-#else
     urealtime.finish_time = endtime = getnow();
     urealtime.realtime += (long) (endtime - urealtime.start_timing);
-#endif
 
+    dump_open_log(endtime);
     /* Sometimes you die on the first move.  Life's not fair.
      * On those rare occasions you get hosed immediately, go out
      * smiling... :-)  -3.
@@ -1158,11 +1312,6 @@ int how;
     else if (how == TURNED_SLIME)
         u.ugrave_arise = PM_GREEN_SLIME;
 
-    /* if pets will contribute to score, populate mydogs list now
-       (bones creation isn't a factor, but pline() messaging is) */
-    if (how == ESCAPED || how == ASCENDED)
-        keepdogs(TRUE);
-
     if (how == QUIT) {
         killer.format = NO_KILLER_PREFIX;
         if (u.uhp < 1) {
@@ -1177,6 +1326,8 @@ int how;
     if (how == ESCAPED || how == PANICKED)
         killer.format = NO_KILLER_PREFIX;
 
+    fixup_death(how); /* actually, fixup multi_reason */
+
     if (how != PANICKED) {
         /* these affect score and/or bones, but avoid them during panic */
         taken = paybill((how == ESCAPED) ? -1 : (how != QUIT));
@@ -1190,8 +1341,33 @@ int how;
     if (have_windows)
         display_nhwindow(WIN_MESSAGE, FALSE);
 
-    if (strcmp(flags.end_disclose, "none") && how != PANICKED)
-        disclose(how, taken);
+    if (how != PANICKED) {
+        struct obj *obj;
+
+        /*
+         * This is needed for both inventory disclosure and dumplog.
+         * Both are optional, so do it once here instead of duplicating
+         * it in both of those places.
+         */
+        for (obj = invent; obj; obj = obj->nobj) {
+            makeknown(obj->otyp);
+            obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
+            if (Is_container(obj) || obj->otyp == STATUE)
+                obj->cknown = obj->lknown = 1;
+        }
+
+        if (strcmp(flags.end_disclose, "none"))
+            disclose(how, taken);
+
+        dump_everything(how, endtime);
+    }
+
+    /* if pets will contribute to score, populate mydogs list now
+       (bones creation isn't a factor, but pline() messaging is; used to
+       be done ever sooner, but we need it to come after dump_everything()
+       so that any accompanying pets are still on the map during dump) */
+    if (how == ESCAPED || how == ASCENDED)
+        keepdogs(TRUE);
 
     /* finish_paybill should be called after disclosure but before bones */
     if (bones_ok && taken)
@@ -1217,7 +1393,7 @@ int how;
         Sprintf(pbuf, "%s, ", plname);
 */
         Sprintf(pbuf, "%s\82Ì\95æ\81C", plname);
-        formatkiller(eos(pbuf), sizeof pbuf - strlen(pbuf), how);
+        formatkiller(eos(pbuf), sizeof pbuf - strlen(pbuf), how, TRUE);
         make_grave(u.ux, u.uy, pbuf);
     }
     pbuf[0] = '\0'; /* clear grave text; also lint suppression */
@@ -1282,11 +1458,14 @@ int how;
     if (have_windows) {
         wait_synch();
         free_pickinv_cache(); /* extra persistent window if perm_invent */
-        if (WIN_INVEN != WIN_ERR)
+        if (WIN_INVEN != WIN_ERR) {
             destroy_nhwindow(WIN_INVEN),  WIN_INVEN = WIN_ERR;
+            /* precaution in case any late update_inventory() calls occur */
+            flags.perm_invent = 0;
+        }
         display_nhwindow(WIN_MESSAGE, TRUE);
         destroy_nhwindow(WIN_MAP),  WIN_MAP = WIN_ERR;
-#ifndef STATUS_VIA_WINDOWPORT
+#ifndef STATUS_HILITES
         destroy_nhwindow(WIN_STATUS),  WIN_STATUS = WIN_ERR;
 #endif
         destroy_nhwindow(WIN_MESSAGE),  WIN_MESSAGE = WIN_ERR;
@@ -1299,6 +1478,16 @@ int how;
     } else
         done_stopprint = 1; /* just avoid any more output */
 
+#ifdef DUMPLOG
+    /* 'how' reasons beyond genocide shouldn't show tombstone;
+       for normal end of game, genocide doesn't either */
+    if (how <= GENOCIDED) {
+        dump_redirect(TRUE);
+        if (iflags.in_dumplog)
+            genl_outrip(0, how, endtime);
+        dump_redirect(FALSE);
+    }
+#endif
     if (u.uhave.amulet) {
 /*JP
         Strcat(killer.name, " (with the Amulet)");
@@ -1318,26 +1507,24 @@ int how;
         /* don't bother counting to see whether it should be plural */
     }
 
-    if (!done_stopprint) {
 #if 0 /*JP*/
-        Sprintf(pbuf, "%s %s the %s...", Goodbye(), plname,
-                (how != ASCENDED)
-                 ? (const char *) ((flags.female && urole.name.f)
-                                      ? urole.name.f
-                                      : urole.name.m)
-                 : (const char *) (flags.female ? "Demigoddess" : "Demigod"));
+    Sprintf(pbuf, "%s %s the %s...", Goodbye(), plname,
+            (how != ASCENDED)
+                ? (const char *) ((flags.female && urole.name.f)
+                    ? urole.name.f
+                    : urole.name.m)
+                : (const char *) (flags.female ? "Demigoddess" : "Demigod"));
 #else
-        Sprintf(pbuf, "%s%s\82Ì%s\81D\81D\81D", Goodbye(),
-                how != ASCENDED
+    Sprintf(pbuf, "%s%s\82Ì%s\81D\81D\81D", Goodbye(),
+            (how != ASCENDED)
                 ? (const char *) ((flags.female && urole.name.f)
-                                      ? urole.name.f
-                                      : urole.name.m)
+                    ? urole.name.f
+                    : urole.name.m)
                 : (const char *) (flags.female ? "\8f\97\90_" : "\90_"),
                 plname);
 #endif
-        putstr(endwin, 0, pbuf);
-        putstr(endwin, 0, "");
-    }
+    dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
+    dump_forward_putstr(endwin, 0, "", done_stopprint);
 
     if (how == ESCAPED || how == ASCENDED) {
         struct monst *mtmp;
@@ -1365,7 +1552,6 @@ int how;
 
         viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */
         mtmp = mydogs;
-        if (!done_stopprint)
 /*JP
             Strcpy(pbuf, "You");
 */
@@ -1374,9 +1560,9 @@ int how;
             Schroedingers_cat = odds_and_ends(invent, CAT_CHECK);
         if (Schroedingers_cat) {
             int mhp, m_lev = adj_lev(&mons[PM_HOUSECAT]);
+
             mhp = d(m_lev, 8);
             nowrap_add(u.urexp, mhp);
-            if (!done_stopprint)
 /*JP
                 Strcat(eos(pbuf), " and Schroedinger's cat");
 */
@@ -1384,7 +1570,6 @@ int how;
         }
         if (mtmp) {
             while (mtmp) {
-                if (!done_stopprint)
 /*JP
                     Sprintf(eos(pbuf), " and %s", mon_nam(mtmp));
 */
@@ -1397,32 +1582,34 @@ int how;
             if (!done_stopprint)
                 Strcat(pbuf, "\82Í");
 #endif
-            if (!done_stopprint)
-                putstr(endwin, 0, pbuf);
+            dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
             pbuf[0] = '\0';
         } else {
-            if (!done_stopprint)
 /*JP
                 Strcat(pbuf, " ");
 */
                 Strcat(pbuf, "\82Í");
         }
-        if (!done_stopprint) {
 #if 0 /*JP*/
-            Sprintf(eos(pbuf), "%s with %ld point%s,",
-                    how == ASCENDED ? "went to your reward"
-                                    : "escaped from the dungeon",
-                    u.urexp, plur(u.urexp));
+        Sprintf(eos(pbuf), "%s with %ld point%s,",
+                how == ASCENDED ? "went to your reward"
+                                 : "escaped from the dungeon",
+                u.urexp, plur(u.urexp));
 #else
-            Sprintf(eos(pbuf), "%ld\83|\83C\83\93\83g\83}\81[\83N\82µ%s\81D",
-                    u.urexp,
-                    how==ASCENDED ? "\8f¸\93V\82µ\82½" : "\96À\8b{\82©\82ç\92E\8fo\82µ\82½");
+        Sprintf(eos(pbuf), "%ld\83|\83C\83\93\83g\83}\81[\83N\82µ%s\81D",
+                u.urexp,
+                how==ASCENDED ? "\8f¸\93V\82µ\82½" : "\96À\8b{\82©\82ç\92E\8fo\82µ\82½");
 #endif
-            putstr(endwin, 0, pbuf);
-        }
+        dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
 
         if (!done_stopprint)
             artifact_score(invent, FALSE, endwin); /* list artifacts */
+#ifdef DUMPLOG
+        dump_redirect(TRUE);
+        if (iflags.in_dumplog)
+            artifact_score(invent, FALSE, 0);
+        dump_redirect(FALSE);
+#endif
 
         /* list valuables here */
         for (val = valuables; val->list; val++) {
@@ -1460,11 +1647,11 @@ int how;
                             count);
 #endif
                 }
-                putstr(endwin, 0, pbuf);
+                dump_forward_putstr(endwin, 0, pbuf, 0);
             }
         }
 
-    } else if (!done_stopprint) {
+    } else {
         /* did not escape or ascend */
         if (u.uz.dnum == 0 && u.uz.dlevel <= 0) {
             /* level teleported out of the dungeon; `how' is DIED,
@@ -1503,37 +1690,34 @@ int how;
         Sprintf(eos(pbuf), " with %ld point%s,", u.urexp, plur(u.urexp));
 */
         Sprintf(eos(pbuf), " %ld\83|\83C\83\93\83g\82ð\83}\81[\83N\82µ\81C", u.urexp);
-        putstr(endwin, 0, pbuf);
+        dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
     }
 
-    if (!done_stopprint) {
-#if 0 /*JP*/
-        Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.", umoney,
-                plur(umoney), moves, plur(moves));
+#if 0 /*JP:T*/
+    Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.", umoney,
+            plur(umoney), moves, plur(moves));
 #else
-        Sprintf(pbuf, "%ld\96\87\82Ì\8bà\89Ý\82ð\8e\9d\82Á\82Ä\81C%ld\95à\93®\82¢\82½\81D",
-                umoney, moves);
+    Sprintf(pbuf, "%ld\96\87\82Ì\8bà\89Ý\82ð\8e\9d\82Á\82Ä\81C%ld\95à\93®\82¢\82½\81D", umoney,
+            moves);
 #endif
-        putstr(endwin, 0, pbuf);
-    }
-    if (!done_stopprint) {
-#if 0 /*JP*/
-        Sprintf(pbuf,
+    dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
+#if 0 /*JP:T*/
+    Sprintf(pbuf,
             "You were level %d with a maximum of %d hit point%s when you %s.",
-                u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]);
+            u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]);
 #else
-        Sprintf(pbuf,
-                "%s\82Æ\82«\81C\82 \82È\82½\82Í\83\8c\83x\83\8b%u\82Å\81C\8dÅ\91å\91Ì\97Í\82Í%d\82Å\82 \82Á\82½\81D",
-                ends[how],u.ulevel, u.uhpmax);
+    Sprintf(pbuf,
+            "%s\82Æ\82«\81C\82 \82È\82½\82Í\83\8c\83x\83\8b%u\82Å\81C\8dÅ\91å\91Ì\97Í\82Í%d\82Å\82 \82Á\82½\81D",
+            ends[how],u.ulevel, u.uhpmax);
 #endif
-        putstr(endwin, 0, pbuf);
-        putstr(endwin, 0, "");
-    }
+    dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
+    dump_forward_putstr(endwin, 0, "", done_stopprint);
     if (!done_stopprint)
         display_nhwindow(endwin, TRUE);
     if (endwin != WIN_ERR)
         destroy_nhwindow(endwin);
 
+    dump_close_log();
     /* "So when I die, the first thing I will see in Heaven is a
      * score list?" */
     if (have_windows && !iflags.toptenwin)
@@ -1546,7 +1730,7 @@ int how;
         raw_print("");
         raw_print("");
     }
-    terminate(EXIT_SUCCESS);
+    nh_terminate(EXIT_SUCCESS);
 }
 
 void
@@ -1555,9 +1739,6 @@ struct obj *list;
 boolean identified, all_containers, reportempty;
 {
     register struct obj *box, *obj;
-    struct obj **oarray;
-    int i, n;
-    char *invlet;
     char buf[BUFSZ];
     boolean cat, deadcat;
 
@@ -1581,46 +1762,27 @@ boolean identified, all_containers, reportempty;
             } else if (box->cobj) {
                 winid tmpwin = create_nhwindow(NHW_MENU);
 
-                /* count the number of items */
-                for (n = 0, obj = box->cobj; obj; obj = obj->nobj)
-                    n++;
-                /* Make a temporary array to store the objects sorted */
-                oarray = objarr_init(n);
-
-                /* Add objects to the array */
-                i = 0;
-                invlet = flags.inv_order;
-            nextclass:
-                for (obj = box->cobj; obj; obj = obj->nobj) {
-                    if (!flags.sortpack || obj->oclass == *invlet) {
-                        objarr_set(
-                            obj, i++, oarray,
-                            (flags.sortloot == 'f' || flags.sortloot == 'l'));
-                    }
-                } /* for loop */
-                if (flags.sortpack) {
-                    if (*++invlet)
-                        goto nextclass;
-                }
-
+                sortloot(&box->cobj,
+                         (((flags.sortloot == 'l' || flags.sortloot == 'f')
+                           ? SORTLOOT_LOOT : 0)
+                          | (flags.sortpack ? SORTLOOT_PACK : 0)),
+                         FALSE);
 /*JP
                 Sprintf(buf, "Contents of %s:", the(xname(box)));
 */
                 Sprintf(buf, "%s\82Ì\92\86\90g\81F", the(xname(box)));
                 putstr(tmpwin, 0, buf);
                 putstr(tmpwin, 0, "");
-                for (i = 0; i < n; i++) {
-                    obj = oarray[i];
+                for (obj = box->cobj; obj; obj = obj->nobj) {
                     if (identified) {
                         makeknown(obj->otyp);
-                        obj->known = obj->bknown = obj->dknown = obj->rknown =
-                            1;
+                        obj->known = obj->bknown = obj->dknown
+                            = obj->rknown = 1;
                         if (Is_container(obj) || obj->otyp == STATUE)
                             obj->cknown = obj->lknown = 1;
                     }
                     putstr(tmpwin, 0, doname(obj));
                 }
-                free(oarray);
                 if (cat)
 /*JP
                     putstr(tmpwin, 0, "Schroedinger's cat");
@@ -1660,7 +1822,7 @@ boolean identified, all_containers, reportempty;
 
 /* should be called with either EXIT_SUCCESS or EXIT_FAILURE */
 void
-terminate(status)
+nh_terminate(status)
 int status;
 {
     program_state.in_moveloop = 0; /* won't be returning to normal play */
@@ -1677,7 +1839,7 @@ int status;
 #ifdef VMS
     /*
      *  This is liable to draw a warning if compiled with gcc, but it's
-     *  more important to flag panic() -> really_done() -> terminate()
+     *  more important to flag panic() -> really_done() -> nh_terminate()
      *  as __noreturn__ then to avoid the warning.
      */
     /* don't call exit() if already executing within an exit handler;
@@ -1692,6 +1854,147 @@ int status;
     nethack_exit(status);
 }
 
+extern const int monstr[];
+
+enum vanq_order_modes {
+    VANQ_MLVL_MNDX = 0,
+    VANQ_MSTR_MNDX,
+    VANQ_ALPHA_SEP,
+    VANQ_ALPHA_MIX,
+    VANQ_MCLS_HTOL,
+    VANQ_MCLS_LTOH,
+    VANQ_COUNT_H_L,
+    VANQ_COUNT_L_H,
+
+    NUM_VANQ_ORDER_MODES
+};
+
+static const char *vanqorders[NUM_VANQ_ORDER_MODES] = {
+    "traditional: by monster level, by internal monster index",
+    "by monster toughness, by internal monster index",
+    "alphabetically, first unique monsters, then others",
+    "alphabetically, unique monsters and others intermixed",
+    "by monster class, high to low level within class",
+    "by monster class, low to high level within class",
+    "by count, high to low, by internal index within tied count",
+    "by count, low to high, by internal index within tied count",
+};
+static int vanq_sortmode = VANQ_MLVL_MNDX;
+
+STATIC_PTR int CFDECLSPEC
+vanqsort_cmp(vptr1, vptr2)
+const genericptr vptr1;
+const genericptr vptr2;
+{
+    int indx1 = *(short *) vptr1, indx2 = *(short *) vptr2,
+        mlev1, mlev2, mstr1, mstr2, uniq1, uniq2, died1, died2, res;
+    const char *name1, *name2, *punct;
+    schar mcls1, mcls2;
+
+    switch (vanq_sortmode) {
+    default:
+    case VANQ_MLVL_MNDX:
+        /* sort by monster level */
+        mlev1 = mons[indx1].mlevel, mlev2 = mons[indx2].mlevel;
+        res = mlev2 - mlev1; /* mlevel high to low */
+        break;
+    case VANQ_MSTR_MNDX:
+        /* sort by monster toughness */
+        mstr1 = monstr[indx1], mstr2 = monstr[indx2];
+        res = mstr2 - mstr1; /* monstr high to low */
+        break;
+    case VANQ_ALPHA_SEP:
+        uniq1 = ((mons[indx1].geno & G_UNIQ) && indx1 != PM_HIGH_PRIEST);
+        uniq2 = ((mons[indx2].geno & G_UNIQ) && indx2 != PM_HIGH_PRIEST);
+        if (uniq1 ^ uniq2) { /* one or other uniq, but not both */
+            res = uniq2 - uniq1;
+            break;
+        } /* else both unique or neither unique */
+        /*FALLTHRU*/
+    case VANQ_ALPHA_MIX:
+        name1 = mons[indx1].mname, name2 = mons[indx2].mname;
+        res = strcmpi(name1, name2); /* caseblind alhpa, low to high */
+        break;
+    case VANQ_MCLS_HTOL:
+    case VANQ_MCLS_LTOH:
+        /* mons[].mlet is a small integer, 1..N, of type plain char;
+           if 'char' happens to be unsigned, (mlet1 - mlet2) would yield
+           an inappropriate result when mlet2 is greater than mlet1,
+           so force our copies (mcls1, mcls2) to be signed */
+        mcls1 = (schar) mons[indx1].mlet, mcls2 = (schar) mons[indx2].mlet;
+        /* S_ANT through S_ZRUTY correspond to lowercase monster classes,
+           S_ANGEL through S_ZOMBIE correspond to uppercase, and various
+           punctuation characters are used for classes beyond those */
+        if (mcls1 > S_ZOMBIE && mcls2 > S_ZOMBIE) {
+            /* force a specific order to the punctuation classes that's
+               different from the internal order;
+               internal order is ok if neither or just one is punctuation
+               since letters have lower values so come out before punct */
+            static const char punctclasses[] = {
+                S_LIZARD, S_EEL, S_GOLEM, S_GHOST, S_DEMON, S_HUMAN, '\0'
+            };
+
+            if ((punct = index(punctclasses, mcls1)) != 0)
+                mcls1 = (schar) (S_ZOMBIE + 1 + (int) (punct - punctclasses));
+            if ((punct = index(punctclasses, mcls2)) != 0)
+                mcls2 = (schar) (S_ZOMBIE + 1 + (int) (punct - punctclasses));
+        }
+        res = mcls1 - mcls2; /* class */
+        if (res == 0) {
+            mlev1 = mons[indx1].mlevel, mlev2 = mons[indx2].mlevel;
+            res = mlev1 - mlev2; /* mlevel low to high */
+            if (vanq_sortmode == VANQ_MCLS_HTOL)
+                res = -res; /* mlevel high to low */
+        }
+        break;
+    case VANQ_COUNT_H_L:
+    case VANQ_COUNT_L_H:
+        died1 = mvitals[indx1].died, died2 = mvitals[indx2].died;
+        res = died2 - died1; /* dead count high to low */
+        if (vanq_sortmode == VANQ_COUNT_L_H)
+            res = -res; /* dead count low to high */
+        break;
+    }
+    /* tiebreaker: internal mons[] index */
+    if (res == 0)
+        res = indx1 - indx2; /* mndx low to high */
+    return res;
+}
+
+/* returns -1 if cancelled via ESC */
+STATIC_OVL int
+set_vanq_order()
+{
+    winid tmpwin;
+    menu_item *selected;
+    anything any;
+    int i, n, choice;
+
+    tmpwin = create_nhwindow(NHW_MENU);
+    start_menu(tmpwin);
+    any = zeroany; /* zero out all bits */
+    for (i = 0; i < SIZE(vanqorders); i++) {
+        if (i == VANQ_ALPHA_MIX || i == VANQ_MCLS_HTOL) /* skip these */
+            continue;
+        any.a_int = i + 1;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, vanqorders[i],
+                 (i == vanq_sortmode) ? MENU_SELECTED : MENU_UNSELECTED);
+    }
+    end_menu(tmpwin, "Sort order for vanquished monster counts");
+
+    n = select_menu(tmpwin, PICK_ONE, &selected);
+    destroy_nhwindow(tmpwin);
+    if (n > 0) {
+        choice = selected[0].item.a_int - 1;
+        /* skip preselected entry if we have more than one item chosen */
+        if (n > 1 && choice == vanq_sortmode)
+            choice = selected[1].item.a_int - 1;
+        free((genericptr_t) selected);
+        vanq_sortmode = choice;
+    }
+    return (n < 0) ? -1 : vanq_sortmode;
+}
+
 /* #vanquished command */
 int
 dovanquished()
@@ -1700,35 +2003,48 @@ dovanquished()
     return 0;
 }
 
+/* high priests aren't unique but are flagged as such to simplify something */
+#define UniqCritterIndx(mndx) ((mons[mndx].geno & G_UNIQ) \
+                               && mndx != PM_HIGH_PRIEST)
+
 STATIC_OVL void
 list_vanquished(defquery, ask)
 char defquery;
 boolean ask;
 {
-    register int i, lev;
-    int ntypes = 0, max_lev = 0, nkilled;
+    register int i;
+    int pfx, nkilled;
+    unsigned ntypes, ni;
     long total_killed = 0L;
-    char c;
     winid klwin;
-    char buf[BUFSZ];
+    short mindx[NUMMONS];
+    char c, buf[BUFSZ], buftoo[BUFSZ];
+    boolean dumping; /* for DUMPLOG; doesn't need to be conditional */
+
+    dumping = (defquery == 'd');
+    if (dumping)
+        defquery = 'y';
 
     /* get totals first */
+    ntypes = 0;
     for (i = LOW_PM; i < NUMMONS; i++) {
-        if (mvitals[i].died)
-            ntypes++;
-        total_killed += (long) mvitals[i].died;
-        if (mons[i].mlevel > max_lev)
-            max_lev = mons[i].mlevel;
+        if ((nkilled = (int) mvitals[i].died) == 0)
+            continue;
+        mindx[ntypes++] = i;
+        total_killed += (long) nkilled;
     }
 
     /* vanquished creatures list;
      * includes all dead monsters, not just those killed by the player
      */
     if (ntypes != 0) {
-#if 0 /*JP*/
+        char mlet, prev_mlet = 0; /* used as small integer, not character */
+        boolean class_header, uniq_header, was_uniq = FALSE;
+
+#if 0 /*JP:T*/
         c = ask ? yn_function(
                             "Do you want an account of creatures vanquished?",
-                              ynqchars, defquery)
+                              ynaqchars, defquery)
                 : defquery;
 #else
         c = ask ? yn_function(
@@ -1739,65 +2055,96 @@ boolean ask;
         if (c == 'q')
             done_stopprint++;
         if (c == 'y' || c == 'a') {
+            if (c == 'a') { /* ask player to choose sort order */
+                /* choose value for vanq_sortmode via menu; ESC cancels list
+                   of vanquished monsters but does not set 'done_stopprint' */
+                if (set_vanq_order() < 0)
+                    return;
+            }
+            uniq_header = (vanq_sortmode == VANQ_ALPHA_SEP);
+            class_header = (vanq_sortmode == VANQ_MCLS_LTOH
+                            || vanq_sortmode == VANQ_MCLS_HTOL);
+
             klwin = create_nhwindow(NHW_MENU);
 /*JP
             putstr(klwin, 0, "Vanquished creatures:");
 */
             putstr(klwin, 0, "\93|\82µ\82½\93G\81F");
-            putstr(klwin, 0, "");
-
-            /* countdown by monster "toughness" */
-            for (lev = max_lev; lev >= 0; lev--)
-                for (i = LOW_PM; i < NUMMONS; i++)
-                    if (mons[i].mlevel == lev
-                        && (nkilled = mvitals[i].died) > 0) {
-                        if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST) {
+            if (!dumping)
+                putstr(klwin, 0, "");
+
+            qsort((genericptr_t) mindx, ntypes, sizeof *mindx, vanqsort_cmp);
+            for (ni = 0; ni < ntypes; ni++) {
+                i = mindx[ni];
+                nkilled = mvitals[i].died;
+                mlet = mons[i].mlet;
+                if (class_header && mlet != prev_mlet) {
+                    Strcpy(buf, def_monsyms[(int) mlet].explain);
+                    putstr(klwin, ask ? 0 : iflags.menu_headings,
+                           upstart(buf));
+                    prev_mlet = mlet;
+                }
+                if (UniqCritterIndx(i)) {
 #if 0 /*JP*/
-                            Sprintf(buf, "%s%s",
-                                    !type_is_pname(&mons[i]) ? "The " : "",
-                                    mons[i].mname);
+                    Sprintf(buf, "%s%s",
+                            !type_is_pname(&mons[i]) ? "the " : "",
+                            mons[i].mname);
 #else
-                            Sprintf(buf, "%s", mons[i].mname);
+                    Sprintf(buf, "%s", mons[i].mname);
 #endif
-                            if (nkilled > 1) {
-#if 0 /*JP*/
-                                switch (nkilled) {
-                                case 2:
-                                    Sprintf(eos(buf), " (twice)");
-                                    break;
-                                case 3:
-                                    Sprintf(eos(buf), " (thrice)");
-                                    break;
-                                default:
-                                    Sprintf(eos(buf), " (%d times)", nkilled);
-                                    break;
-                                }
-#else
-                                Sprintf(eos(buf)," (%d\89ñ)", nkilled);
-#endif
-                            }
-                        } else {
-                            /* trolls or undead might have come back,
-                               but we don't keep track of that */
-                            if (nkilled == 1)
-                                Strcpy(buf, an(mons[i].mname));
-                            else
+                    if (nkilled > 1) {
 #if 0 /*JP*/
-                                Sprintf(buf, "%d %s", nkilled,
-                                        makeplural(mons[i].mname));
+                        switch (nkilled) {
+                        case 2:
+                            Sprintf(eos(buf), " (twice)");
+                            break;
+                        case 3:
+                            Sprintf(eos(buf), " (thrice)");
+                            break;
+                        default:
+                            Sprintf(eos(buf), " (%d times)", nkilled);
+                            break;
+                        }
 #else
-                                Sprintf(buf, "%d\91Ì\82Ì%s", nkilled,
-                                        mons[i].mname);
+                        Sprintf(eos(buf)," (%d\89ñ)", nkilled);
 #endif
-                        }
-                        putstr(klwin, 0, buf);
                     }
+                    was_uniq = TRUE;
+                } else {
+                    if (uniq_header && was_uniq) {
+                        putstr(klwin, 0, "");
+                        was_uniq = FALSE;
+                    }
+                    /* trolls or undead might have come back,
+                       but we don't keep track of that */
+                    if (nkilled == 1)
+                        Strcpy(buf, an(mons[i].mname));
+                    else
+#if 0 /*JP:T*/
+                        Sprintf(buf, "%3d %s", nkilled,
+                                makeplural(mons[i].mname));
+#else
+                        Sprintf(buf, "%d\91Ì\82Ì%s", nkilled,
+                                mons[i].mname);
+#endif
+                }
+                /* number of leading spaces to match 3 digit prefix */
+                pfx = !strncmpi(buf, "the ", 3) ? 0
+                      : !strncmpi(buf, "an ", 3) ? 1
+                        : !strncmpi(buf, "a ", 2) ? 2
+                          : !digit(buf[2]) ? 4 : 0;
+                if (class_header)
+                    ++pfx;
+                Sprintf(buftoo, "%*s%s", pfx, "", buf);
+                putstr(klwin, 0, buftoo);
+            }
             /*
              * if (Hallucination)
              *     putstr(klwin, 0, "and a partridge in a pear tree");
              */
             if (ntypes > 1) {
-                putstr(klwin, 0, "");
+                if (!dumping)
+                    putstr(klwin, 0, "");
 /*JP
                 Sprintf(buf, "%ld creatures vanquished.", total_killed);
 */
@@ -1810,9 +2157,13 @@ boolean ask;
     } else if (defquery == 'a') {
         /* #dovanquished rather than final disclosure, so pline() is ok */
 /*JP
-        pline("No monsters have been vanquished.");
+        pline("No creatures have been vanquished.");
 */
         pline("\93|\82µ\82½\93G\82Í\82¢\82È\82©\82Á\82½\81D");
+#ifdef DUMPLOG
+    } else if (dumping) {
+        putstr(0, 0, "No creatures were vanquished."); /* not pline() */
+#endif
     }
 }
 
@@ -1822,23 +2173,28 @@ num_genocides()
 {
     int i, n = 0;
 
-    for (i = LOW_PM; i < NUMMONS; ++i)
-        if (mvitals[i].mvflags & G_GENOD)
+    for (i = LOW_PM; i < NUMMONS; ++i) {
+        if (mvitals[i].mvflags & G_GENOD) {
             ++n;
-
+            if (UniqCritterIndx(i))
+                impossible("unique creature '%d: %s' genocided?",
+                           i, mons[i].mname);
+        }
+    }
     return n;
 }
 
-int
+STATIC_OVL int
 num_extinct()
 {
     int i, n = 0;
 
-    for (i = LOW_PM; i < NUMMONS; ++i)
-        if (!(mvitals[i].mvflags & G_GENOD) && (mvitals[i].mvflags & G_GONE)
-            && !(mons[i].geno & G_UNIQ))
+    for (i = LOW_PM; i < NUMMONS; ++i) {
+        if (UniqCritterIndx(i))
+            continue;
+        if ((mvitals[i].mvflags & G_GONE) == G_EXTINCT)
             ++n;
-
+    }
     return n;
 }
 
@@ -1852,13 +2208,18 @@ boolean ask;
     char c;
     winid klwin;
     char buf[BUFSZ];
+    boolean dumping; /* for DUMPLOG; doesn't need to be conditional */
+
+    dumping = (defquery == 'd');
+    if (dumping)
+        defquery = 'y';
 
     ngenocided = num_genocides();
     nextinct = num_extinct();
 
     /* genocided or extinct species list */
     if (ngenocided != 0 || nextinct != 0) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         Sprintf(buf, "Do you want a list of %sspecies%s%s?",
                 (nextinct && !ngenocided) ? "extinct " : "",
                 (ngenocided) ? " genocided" : "",
@@ -1884,29 +2245,32 @@ boolean ask;
                     (nextinct && ngenocided) ? "\82Ü\82½\82Í\90â\96Å" : "");
 #endif
             putstr(klwin, 0, buf);
-            putstr(klwin, 0, "");
+            if (!dumping)
+                putstr(klwin, 0, "");
 
-            for (i = LOW_PM; i < NUMMONS; i++)
-                if (mvitals[i].mvflags & G_GONE && !(mons[i].geno & G_UNIQ)) {
-                    if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST)
-#if 0 /*JP*/
-                        Sprintf(buf, "%s%s",
-                                !type_is_pname(&mons[i]) ? "" : "the ",
-                                mons[i].mname);
-#else
-                        Sprintf(buf, "%s", mons[i].mname);
-#endif
-                    else
-                        Strcpy(buf, makeplural(mons[i].mname));
-                    if (!(mvitals[i].mvflags & G_GENOD))
+            for (i = LOW_PM; i < NUMMONS; i++) {
+                /* uniques can't be genocided but can become extinct;
+                   however, they're never reported as extinct, so skip them */
+                if (UniqCritterIndx(i))
+                    continue;
+                if (mvitals[i].mvflags & G_GONE) {
+                    Sprintf(buf, " %s", makeplural(mons[i].mname));
+                    /*
+                     * "Extinct" is unfortunate terminology.  A species
+                     * is marked extinct when its birth limit is reached,
+                     * but there might be members of the species still
+                     * alive, contradicting the meaning of the word.
+                     */
+                    if ((mvitals[i].mvflags & G_GONE) == G_EXTINCT)
 /*JP
                         Strcat(buf, " (extinct)");
 */
                         Strcat(buf, "(\90â\96Å)");
                     putstr(klwin, 0, buf);
                 }
-
-            putstr(klwin, 0, "");
+            }
+            if (!dumping)
+                putstr(klwin, 0, "");
             if (ngenocided > 0) {
 /*JP
                 Sprintf(buf, "%d species genocided.", ngenocided);
@@ -1925,6 +2289,10 @@ boolean ask;
             display_nhwindow(klwin, TRUE);
             destroy_nhwindow(klwin);
         }
+#ifdef DUMPLOG
+    } else if (dumping) {
+        putstr(0, 0, "No species were genocided or became extinct.");
+#endif
     }
 }
 
@@ -1940,6 +2308,7 @@ const char *killername;
     if (k == (struct kinfo *) 0) {
         /* no match, add a new delayed killer to the list */
         k = (struct kinfo *) alloc(sizeof(struct kinfo));
+        (void) memset((genericptr_t)k, 0, sizeof(struct kinfo));
         k->id = id;
         k->next = killer.next;
         killer.next = k;
index 52660f4..97ed53e 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 engrave.c       $NHDT-Date: 1445388915 2015/10/21 00:55:15 $  $NHDT-Branch: master $:$NHDT-Revision: 1.59 $ */
+/* NetHack 3.6 engrave.c       $NHDT-Date: 1456304550 2016/02/24 09:02:30 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.61 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -223,10 +224,13 @@ register int x, y;
 */
         return "\8bó\92\86";
     else if (is_pool(x, y))
-/*JP
-        return (Underwater && !Is_waterlevel(&u.uz)) ? "bottom" : "water";
-*/
-        return (Underwater && !Is_waterlevel(&u.uz)) ? "\90\85\82Ì\92ê" : "\90\85\92\86";
+#if 0 /*JP*/
+        return (Underwater && !Is_waterlevel(&u.uz))
+            ? "bottom" : hliquid("water");
+#else
+        return (Underwater && !Is_waterlevel(&u.uz))
+            ? "\90\85\82Ì\92ê" : hliquid("\90\85\92\86");
+#endif
     else if (is_ice(x, y))
 /*JP
         return "ice";
@@ -234,9 +238,9 @@ register int x, y;
         return "\95X";
     else if (is_lava(x, y))
 /*JP
-        return "lava";
+        return hliquid("lava");
 */
-        return "\97n\8aâ";
+        return hliquid("\97n\8aâ");
     else if (lev->typ == DRAWBRIDGE_DOWN)
 /*JP
         return "bridge";
@@ -345,8 +349,7 @@ xchar x, y;
  * Ignore headstones, in case the player names herself "Elbereth".
  *
  * If strict checking is requested, the word is only considered to be
- * present if it is intact and is the first word in the engraving.
- * ("Elbereth burrito" matches; "o Elbereth" does not.)
+ * present if it is intact and is the entire content of the engraving.
  */
 int
 sengr_at(s, x, y, strict)
@@ -357,9 +360,10 @@ boolean strict;
     register struct engr *ep = engr_at(x, y);
 
     if (ep && ep->engr_type != HEADSTONE && ep->engr_time <= moves) {
-        return strict ? (strncmpi(ep->engr_txt, s, strlen(s)) == 0)
+        return strict ? (fuzzymatch(ep->engr_txt, s, "", TRUE))
                       : (strstri(ep->engr_txt, s) != 0);
     }
+
     return FALSE;
 }
 
@@ -499,10 +503,12 @@ long e_time;
 xchar e_type;
 {
     struct engr *ep;
+    unsigned smem = strlen(s) + 1;
 
     if ((ep = engr_at(x, y)) != 0)
         del_engr(ep);
-    ep = newengr(strlen(s) + 1);
+    ep = newengr(smem);
+    (void) memset((genericptr_t)ep, 0, smem + sizeof(struct engr));
     ep->nxt_engr = head_engr;
     head_engr = ep;
     ep->engr_x = x;
@@ -514,7 +520,7 @@ xchar e_type;
         exercise(A_WIS, TRUE);
     ep->engr_time = e_time;
     ep->engr_type = e_type > 0 ? e_type : rnd(N_ENGRAVE - 1);
-    ep->engr_lth = strlen(s) + 1;
+    ep->engr_lth = smem;
 }
 
 /* delete any engraving at location <x,y> */
@@ -529,7 +535,7 @@ int x, y;
 }
 
 /*
- *     freehand - returns true if player has a free hand
+ * freehand - returns true if player has a free hand
  */
 int
 freehand()
@@ -544,30 +550,30 @@ static NEARDATA const char styluses[] = { ALL_CLASSES, ALLOW_NONE,
                                           RING_CLASS,  0 };
 
 /* Mohs' Hardness Scale:
- *  1 - Talc            6 - Orthoclase
- *  2 - Gypsum          7 - Quartz
- *  3 - Calcite                 8 - Topaz
- *  4 - Fluorite        9 - Corundum
- *  5 - Apatite                10 - Diamond
+ *  1 - Talc             6 - Orthoclase
+ *  2 - Gypsum           7 - Quartz
+ *  3 - Calcite          8 - Topaz
+ *  4 - Fluorite         9 - Corundum
+ *  5 - Apatite         10 - Diamond
  *
  * Since granite is an igneous rock hardness ~ 7, anything >= 8 should
  * probably be able to scratch the rock.
  * Devaluation of less hard gems is not easily possible because obj struct
  * does not contain individual oc_cost currently. 7/91
  *
- * steel     - 5-8.5   (usu. weapon)
- * diamond    - 10                     * jade       -  5-6      (nephrite)
- * ruby       -  9     (corundum)      * turquoise  -  5-6
- * sapphire   -  9     (corundum)      * opal       -  5-6
- * topaz      -  8                     * glass      - ~5.5
- * emerald    -  7.5-8 (beryl)         * dilithium  -  4-5??
- * aquamarine -  7.5-8 (beryl)         * iron       -  4-5
- * garnet     -  7.25  (var. 6.5-8)    * fluorite   -  4
- * agate      -  7     (quartz)        * brass      -  3-4
- * amethyst   -  7     (quartz)        * gold       -  2.5-3
- * jasper     -  7     (quartz)        * silver     -  2.5-3
- * onyx       -  7     (quartz)        * copper     -  2.5-3
- * moonstone  -  6     (orthoclase)    * amber      -  2-2.5
+ * steel      - 5-8.5   (usu. weapon)
+ * diamond    - 10                      * jade       -  5-6      (nephrite)
+ * ruby       -  9      (corundum)      * turquoise  -  5-6
+ * sapphire   -  9      (corundum)      * opal       -  5-6
+ * topaz      -  8                      * glass      - ~5.5
+ * emerald    -  7.5-8  (beryl)         * dilithium  -  4-5??
+ * aquamarine -  7.5-8  (beryl)         * iron       -  4-5
+ * garnet     -  7.25   (var. 6.5-8)    * fluorite   -  4
+ * agate      -  7      (quartz)        * brass      -  3-4
+ * amethyst   -  7      (quartz)        * gold       -  2.5-3
+ * jasper     -  7      (quartz)        * silver     -  2.5-3
+ * onyx       -  7      (quartz)        * copper     -  2.5-3
+ * moonstone  -  6      (orthoclase)    * amber      -  2-2.5
  */
 
 /* return 1 if action took 1 (or more) moves, 0 if error or aborted */
@@ -669,9 +675,9 @@ doengrave()
 
     if (otmp == &zeroobj) {
 /*JP
-        Strcat(strcpy(fbuf, "your "), makeplural(body_part(FINGER)));
+        Strcat(strcpy(fbuf, "your "), body_part(FINGERTIP));
 */
-        Strcat(strcpy(fbuf, "\82 \82È\82½\82Ì"), makeplural(body_part(FINGER)));
+        Strcat(strcpy(fbuf, "\82 \82È\82½\82Ì"), body_part(FINGERTIP));
         writer = fbuf;
     } else
         writer = yname(otmp);
@@ -885,6 +891,7 @@ doengrave()
                            "\95X\82Ì\82©\82¯\82ç\82ª\8fñ\82©\82ç\82±\82Ú\82ê\97\8e\82¿\82½\81D");
                 if (!oep || (oep->engr_type != BURN))
                     break;
+                /*FALLTHRU*/
             case WAN_CANCELLATION:
             case WAN_MAKE_INVISIBLE:
                 if (oep && oep->engr_type != HEADSTONE) {
@@ -922,16 +929,18 @@ doengrave()
                 }
 #if 0 /*JP*/
                 Strcpy(post_engr_text,
-                       Blind
+                       (Blind && !Deaf)
                           ? "You hear drilling!"
-                          : IS_GRAVE(levl[u.ux][u.uy].typ)
-                             ? "Chips fly out from the headstone."
-                             : is_ice(u.ux, u.uy)
-                                ? "Ice chips fly up from the ice surface!"
-                                : (level.locations[u.ux][u.uy].typ
-                                   == DRAWBRIDGE_DOWN)
-                                   ? "Splinters fly up from the bridge."
-                                   : "Gravel flies up from the floor.");
+                          : Blind
+                             ? "You feel tremors."
+                             : IS_GRAVE(levl[u.ux][u.uy].typ)
+                                 ? "Chips fly out from the headstone."
+                                 : is_ice(u.ux, u.uy)
+                                    ? "Ice chips fly up from the ice surface!"
+                                    : (level.locations[u.ux][u.uy].typ
+                                       == DRAWBRIDGE_DOWN)
+                                       ? "Splinters fly up from the bridge."
+                                       : "Gravel flies up from the floor.");
 #else
                 Strcpy(post_engr_text,
                        Blind
@@ -984,10 +993,15 @@ doengrave()
                     Strcpy(post_engr_text, "\89Î\89Ô\82ª\8fñ\82©\82ç\94ò\82Ñ\8eU\82Á\82½\81D");
                     doblind = TRUE;
                 } else
-/*JP
-                    Strcpy(post_engr_text, "You hear crackling!");
-*/
-                    Strcpy(post_engr_text, "\83p\83`\83p\83`\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81I");
+#if 0 /*JP*/
+                    Strcpy(post_engr_text, !Deaf
+                                ? "You hear crackling!"
+                                : "Your hair stands up!");
+#else
+                    Strcpy(post_engr_text, !Deaf
+                                ? "\83p\83`\83p\83`\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81I"
+                                : "\83]\83b\82Æ\82µ\82½\81I");
+#endif
                 break;
 
             /* type = MARK wands */
@@ -1311,11 +1325,9 @@ doengrave()
         You("%s\82Å%s\82É%s\81D", doname(otmp), eloc, jpast(everb));
     else
 #if 0 /*JP*/
-        You("%s the %s with your %s.", everb, eloc,
-            makeplural(body_part(FINGER)));
+        You("%s the %s with your %s.", everb, eloc, body_part(FINGERTIP));
 #else
-        You("%s\82Å%s\82É%s\81D", body_part(FINGER),
-            eloc, jpast(everb));
+        You("%s\82Å%s\82É%s\81D", body_part(FINGER), eloc, jpast(everb));
 #endif
 
     /* Prompt for engraving! */
@@ -1582,6 +1594,23 @@ int fd;
     }
 }
 
+/* to support '#stats' wizard-mode command */
+void
+engr_stats(hdrfmt, hdrbuf, count, size)
+const char *hdrfmt;
+char *hdrbuf;
+long *count, *size;
+{
+    struct engr *ep;
+
+    Sprintf(hdrbuf, hdrfmt, (long) sizeof (struct engr));
+    *count = *size = 0L;
+    for (ep = head_engr; ep; ep = ep->nxt_engr) {
+        ++*count;
+        *size += (long) sizeof *ep + (long) ep->engr_lth;
+    }
+}
+
 void
 del_engr(ep)
 register struct engr *ep;
index d7b8478..40132f7 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 exper.c $NHDT-Date: 1446975467 2015/11/08 09:37:47 $  $NHDT-Branch: master $:$NHDT-Revision: 1.26 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2007. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -304,12 +305,17 @@ boolean incr; /* true iff via incremental experience growth */
             u.uexp = newuexp(u.ulevel);
         }
         ++u.ulevel;
+#if 0 /*JP*/
+        pline("Welcome %sto experience level %d.",
+              u.ulevelmax < u.ulevel ? "" : "back ",
+              u.ulevel);
+#else
+        pline("%s\83\8c\83x\83\8b%d\82É\82æ\82¤\82±\82»\81D",
+              u.ulevelmax < u.ulevel ? "" : "\8dÄ\82Ñ",
+              u.ulevel);
+#endif
         if (u.ulevelmax < u.ulevel)
             u.ulevelmax = u.ulevel;
-/*JP
-        pline("Welcome to experience level %d.", u.ulevel);
-*/
-        pline("\83\8c\83x\83\8b%d\82É\82æ\82¤\82±\82»\81D", u.ulevel);
         adjabil(u.ulevel - 1, u.ulevel); /* give new intrinsics */
         reset_rndmonst(NON_PM);          /* new monster selection */
     }
index 1e040e6..a77964d 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 explode.c       $NHDT-Date: 1446955298 2015/11/08 04:01:38 $  $NHDT-Branch: master $:$NHDT-Revision: 1.44 $ */
+/* NetHack 3.6 explode.c       $NHDT-Date: 1522454717 2018/03/31 00:05:17 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.56 $ */
 /*      Copyright (C) 1990 by Ken Arromdee */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -45,11 +45,11 @@ int expltype;
     int idamres, idamnonres;
     struct monst *mtmp, *mdef = 0;
     uchar adtyp;
-    int explmask[3][3];
-    /* 0=normal explosion, 1=do shieldeff, 2=do nothing */
+    int explmask[3][3]; /* 0=normal explosion, 1=do shieldeff, 2=do nothing */
     boolean shopdamage = FALSE, generic = FALSE, physical_dmg = FALSE,
-            do_hallu = FALSE, inside_engulfer;
-    char hallu_buf[BUFSZ];
+            do_hallu = FALSE, inside_engulfer, grabbed, grabbing;
+    coord grabxy;
+    char hallu_buf[BUFSZ], killr_buf[BUFSZ];
     short exploding_wand_typ = 0;
 
     if (olet == WAND_CLASS) { /* retributive strike */
@@ -93,10 +93,38 @@ int expltype;
     /* if hero is engulfed and caused the explosion, only hero and
        engulfer will be affected */
     inside_engulfer = (u.uswallow && type >= 0);
+    /* held but not engulfed implies holder is reaching into second spot
+       so might get hit by double damage */
+    grabbed = grabbing = FALSE;
+    if (u.ustuck && !u.uswallow) {
+        if (Upolyd && sticks(youmonst.data))
+            grabbing = TRUE;
+        else
+            grabbed = TRUE;
+        grabxy.x = u.ustuck->mx;
+        grabxy.y = u.ustuck->my;
+    } else
+        grabxy.x = grabxy.y = 0; /* lint suppression */
+    /* FIXME:
+     *  It is possible for a grabber to be outside the explosion
+     *  radius and reaching inside to hold the hero.  If so, it ought
+     *  to take damage (the extra half of double damage).  It is also
+     *  possible for poly'd hero to be outside the radius and reaching
+     *  in to hold a monster.  Hero should take damage in that situation.
+     *
+     *  Probably the simplest way to handle this would be to expand
+     *  the radius used when collecting targets but exclude everything
+     *  beyond the regular radius which isn't reaching inside.  Then
+     *  skip harm to gear of any extended targets when inflicting damage.
+     */
 
     if (olet == MON_EXPLODE) {
-        str = killer.name;
-        do_hallu = Hallucination && strstri(str, "'s explosion");
+        /* when explode() is called recursively, killer.name might change so
+           we need to retain a copy of the current value for this explosion */
+        str = strcpy(killr_buf, killer.name);
+        do_hallu = (Hallucination
+                    && (strstri(str, "'s explosion")
+                        || strstri(str, "s' explosion")));
         adtyp = AD_PHYS;
     } else
         switch (abs(type) % 10) {
@@ -205,7 +233,7 @@ int expltype;
                     break;
                 }
             }
-            /* can be both you and mtmp if you're swallowed */
+            /* can be both you and mtmp if you're swallowed or riding */
             mtmp = m_at(i + x - 1, j + y - 1);
             if (!mtmp && i + x - 1 == u.ux && j + y - 1 == u.uy)
                 mtmp = u.usteed;
@@ -248,11 +276,8 @@ int expltype;
             }
             if (mtmp && cansee(i + x - 1, j + y - 1) && !canspotmon(mtmp))
                 map_invisible(i + x - 1, j + y - 1);
-            else if (!mtmp && glyph_is_invisible(
-                                  levl[i + x - 1][j + y - 1].glyph)) {
-                unmap_object(i + x - 1, j + y - 1);
-                newsym(i + x - 1, j + y - 1);
-            }
+            else if (!mtmp)
+                (void) unmap_invisible(i + x - 1, j + y - 1);
             if (cansee(i + x - 1, j + y - 1))
                 visible = TRUE;
             if (explmask[i][j] == 1)
@@ -347,12 +372,13 @@ int expltype;
                        so avoid any which begins with a capital letter) */
                     do {
                         Sprintf(hallu_buf, "%s explosion",
-                                s_suffix(rndmonnam(NULL)));
+                                s_suffix(rndmonnam((char *) 0)));
                     } while (*hallu_buf != lowc(*hallu_buf));
                     str = hallu_buf;
                 }
                 if (u.uswallow && mtmp == u.ustuck) {
-                    const char *adj = NULL;
+                    const char *adj = (char *) 0;
+
                     if (is_animal(u.ustuck->data)) {
                         switch (adtyp) {
                         case AD_FIRE:
@@ -485,8 +511,7 @@ int expltype;
                 } else {
                     /* call resist with 0 and do damage manually so 1) we can
                      * get out the message before doing the damage, and 2) we
-                     * can
-                     * call mondied, not killed, if it's not your blast
+                     * can call mondied, not killed, if it's not your blast
                      */
                     int mdam = dam;
 
@@ -499,8 +524,15 @@ int expltype;
                             pline("%s\82Í%s\82É\92ï\8dR\82µ\82½\81I", Monnam(mtmp), str);
                         mdam = (dam + 1) / 2;
                     }
-                    if (mtmp == u.ustuck)
+                    /* if grabber is reaching into hero's spot and
+                       hero's spot is within explosion radius, grabber
+                       gets hit by double damage */
+                    if (grabbed && mtmp == u.ustuck && distu(x, y) <= 2)
                         mdam *= 2;
+                    /* being resistant to opposite type of damage makes
+                       target more vulnerable to current type of damage
+                       (when target is also resistant to current type,
+                       we won't get here) */
                     if (resists_cold(mtmp) && adtyp == AD_FIRE)
                         mdam *= 2;
                     else if (resists_fire(mtmp) && adtyp == AD_COLD)
@@ -509,13 +541,35 @@ int expltype;
                     mtmp->mhp -= (idamres + idamnonres);
                 }
                 if (mtmp->mhp <= 0) {
-                    if (mdef ? (mtmp == mdef) : !context.mon_moving)
-                        killed(mtmp);
-                    else
+                    int xkflg = ((adtyp == AD_FIRE
+                                  && completelyburns(mtmp->data))
+                                 ? XKILL_NOCORPSE : 0);
+
+                    if (!context.mon_moving) {
+                        xkilled(mtmp, XKILL_GIVEMSG | xkflg);
+                    } else if (mdef && mtmp == mdef) {
+                        /* 'mdef' killed self trying to cure being turned
+                         * into slime due to some action by the player.
+                         * Hero gets the credit (experience) and most of
+                         * the blame (possible loss of alignment and/or
+                         * luck and/or telepathy depending on mtmp) but
+                         * doesn't break pacifism.  xkilled()'s message
+                         * would be "you killed <mdef>" so give our own.
+                         */
+                        if (cansee(mtmp->mx, mtmp->my) || canspotmon(mtmp))
+                            pline("%s is %s!", Monnam(mtmp),
+                                  xkflg ? "burned completely"
+                                        : nonliving(mtmp->data) ? "destroyed"
+                                                                : "killed");
+                        xkilled(mtmp, XKILL_NOMSG | XKILL_NOCONDUCT | xkflg);
+                    } else {
+                        if (xkflg)
+                            adtyp = AD_RBRE; /* no corpse */
                         monkilled(mtmp, "", (int) adtyp);
+                    }
                 } else if (!context.mon_moving) {
                     /* all affected monsters, even if mdef is set */
-                    setmangry(mtmp);
+                    setmangry(mtmp, TRUE);
                 }
             }
 
@@ -527,7 +581,7 @@ int expltype;
             if (do_hallu) { /* (see explanation above) */
                 do {
                     Sprintf(hallu_buf, "%s explosion",
-                            s_suffix(rndmonnam(NULL)));
+                            s_suffix(rndmonnam((char *) 0)));
                 } while (*hallu_buf != lowc(*hallu_buf));
                 str = hallu_buf;
             }
@@ -558,6 +612,13 @@ int expltype;
 
         ugolemeffects((int) adtyp, damu);
         if (uhurt == 2) {
+            /* if poly'd hero is grabbing another victim, hero takes
+               double damage (note: don't rely on u.ustuck here because
+               that victim might have been killed when hit by the blast) */
+            if (grabbing && dist2((int) grabxy.x, (int) grabxy.y, x, y) <= 2)
+                damu *= 2;
+            /* hero does not get same fire-resistant vs cold and
+               cold-resistant vs fire double damage as monsters [why not?] */
             if (Upolyd)
                 u.mh -= damu;
             else
@@ -570,9 +631,8 @@ int expltype;
                 rehumanize();
             } else {
                 if (olet == MON_EXPLODE) {
-                    /* killer handled by caller */
-                    if (generic)
-                        killer.name[0] = 0;
+                    if (generic) /* explosion was unseen; str=="explosion", */
+                        ;        /* killer.name=="gas spore's explosion"    */
                     else if (str != killer.name && str != hallu_buf)
                         Strcpy(killer.name, str);
                     killer.format = KILLED_BY_AN;
@@ -603,8 +663,7 @@ int expltype;
 #endif
                 }
                 if (iflags.last_msg == PLNMSG_CAUGHT_IN_EXPLOSION
-                    || iflags.last_msg
-                           == PLNMSG_TOWER_OF_FLAME) /*seffects()*/
+                    || iflags.last_msg == PLNMSG_TOWER_OF_FLAME) /*seffects()*/
 /*JP
                     pline("It is fatal.");
 */
@@ -624,12 +683,10 @@ int expltype;
 
     if (shopdamage) {
 #if 0 /*JP*/
-        pay_for_damage(adtyp == AD_FIRE
-                           ? "burn away"
-                           : adtyp == AD_COLD
-                                 ? "shatter"
-                                 : adtyp == AD_DISN ? "disintegrate"
-                                                    : "destroy",
+        pay_for_damage((adtyp == AD_FIRE) ? "burn away"
+                          : (adtyp == AD_COLD) ? "shatter"
+                             : (adtyp == AD_DISN) ? "disintegrate"
+                                : "destroy",
                        FALSE);
 #else
         pay_for_damage(adtyp == AD_FIRE
@@ -692,7 +749,7 @@ struct obj *obj; /* only scatter this obj        */
     struct scatter_chain *schain = (struct scatter_chain *) 0;
     long total = 0L;
 
-    while ((otmp = individual_object ? obj : level.objects[sx][sy]) != 0) {
+    while ((otmp = (individual_object ? obj : level.objects[sx][sy])) != 0) {
         if (otmp->quan > 1L) {
             qtmp = otmp->quan - 1L;
             if (qtmp > LARGEST_INT)
@@ -706,14 +763,17 @@ struct obj *obj; /* only scatter this obj        */
         used_up = FALSE;
 
         /* 9 in 10 chance of fracturing boulders or statues */
-        if ((scflags & MAY_FRACTURE)
-            && ((otmp->otyp == BOULDER) || (otmp->otyp == STATUE))
+        if ((scflags & MAY_FRACTURE) != 0
+            && (otmp->otyp == BOULDER || otmp->otyp == STATUE)
             && rn2(10)) {
             if (otmp->otyp == BOULDER) {
+                if (cansee(sx, sy))
 /*JP
                 pline("%s apart.", Tobjnam(otmp, "break"));
 */
                 pline("%s\82Í\88ê\95\94\95ª\82ª\8dÓ\82¯\82½\81D",xname(otmp));
+                else
+                    You_hear("stone breaking.");
                 fracture_rock(otmp);
                 place_object(otmp, sx, sy);
                 if ((otmp = sobj_at(BOULDER, sx, sy)) != 0) {
@@ -726,10 +786,13 @@ struct obj *obj; /* only scatter this obj        */
 
                 if ((trap = t_at(sx, sy)) && trap->ttyp == STATUE_TRAP)
                     deltrap(trap);
+                if (cansee(sx, sy))
 /*JP
                 pline("%s.", Tobjnam(otmp, "crumble"));
 */
                 pline("%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81D",xname(otmp));
+                else
+                    You_hear("stone crumbling.");
                 (void) break_statue(otmp);
 #ifndef FIX_BUG_C340_2
                 place_object(otmp, sx, sy); /* put fragments on floor */
@@ -738,7 +801,7 @@ struct obj *obj; /* only scatter this obj        */
             used_up = TRUE;
 
             /* 1 in 10 chance of destruction of obj; glass, egg destruction */
-        } else if ((scflags & MAY_DESTROY)
+        } else if ((scflags & MAY_DESTROY) != 0
                    && (!rn2(10) || (objects[otmp->otyp].oc_material == GLASS
                                     || otmp->otyp == EGG))) {
             if (breaks(otmp, (xchar) sx, (xchar) sy))
@@ -746,8 +809,7 @@ struct obj *obj; /* only scatter this obj        */
         }
 
         if (!used_up) {
-            stmp =
-                (struct scatter_chain *) alloc(sizeof(struct scatter_chain));
+            stmp = (struct scatter_chain *) alloc(sizeof *stmp);
             stmp->next = (struct scatter_chain *) 0;
             stmp->obj = otmp;
             stmp->ox = sx;
@@ -803,7 +865,9 @@ struct obj *obj; /* only scatter this obj        */
                         if (bigmonst(youmonst.data))
                             hitvalu++;
                         hitu = thitu(hitvalu, dmgval(stmp->obj, &youmonst),
-                                     stmp->obj, (char *) 0);
+                                     &stmp->obj, (char *) 0);
+                        if (!stmp->obj)
+                            stmp->stopped = TRUE;
                         if (hitu) {
                             stmp->range -= 3;
                             stop_occupation();
index 77d5af3..8ee8cff 100644 (file)
@@ -1,7 +1,10 @@
-/* NetHack 3.6 files.c $NHDT-Date: 1449296293 2015/12/05 06:18:13 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.192 $ */
+/* NetHack 3.6 files.c $NHDT-Date: 1524413723 2018/04/22 16:15:23 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.235 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
+#define NEED_VARARGS
+
 /* JNetHack Copyright */
 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016            */
@@ -193,15 +196,24 @@ STATIC_DCL boolean FDECL(make_compressed_name, (const char *, char *));
 #ifndef USE_FCNTL
 STATIC_DCL char *FDECL(make_lockname, (const char *, char *));
 #endif
+STATIC_DCL void FDECL(set_configfile_name, (const char *));
 STATIC_DCL FILE *FDECL(fopen_config_file, (const char *, int));
-STATIC_DCL int FDECL(get_uchars, (FILE *, char *, char *, uchar *, BOOLEAN_P,
+STATIC_DCL int FDECL(get_uchars, (char *, uchar *, BOOLEAN_P,
                                   int, const char *));
-int FDECL(parse_config_line, (FILE *, char *, int));
+boolean FDECL(proc_wizkit_line, (char *));
+boolean FDECL(parse_config_line, (char *));
+STATIC_DCL boolean FDECL(parse_conf_file, (FILE *, boolean (*proc)(char *)));
 STATIC_DCL FILE *NDECL(fopen_sym_file);
+boolean FDECL(proc_symset_line, (char *));
 STATIC_DCL void FDECL(set_symhandling, (char *, int));
 #ifdef NOCWD_ASSUMPTIONS
 STATIC_DCL void FDECL(adjust_prefix, (char *, int));
 #endif
+STATIC_DCL boolean FDECL(config_error_nextline, (const char *));
+STATIC_DCL void NDECL(free_config_sections);
+STATIC_DCL char *FDECL(choose_random_part, (char *, CHAR_P));
+STATIC_DCL boolean FDECL(is_config_section, (const char *));
+STATIC_DCL boolean FDECL(handle_config_section, (char *));
 #ifdef SELF_RECOVER
 STATIC_DCL boolean FDECL(copy_bytes, (int, int));
 #endif
@@ -209,6 +221,10 @@ STATIC_DCL boolean FDECL(copy_bytes, (int, int));
 STATIC_DCL int FDECL(open_levelfile_exclusively, (const char *, int, int));
 #endif
 
+
+static char *config_section_chosen = (char *) 0;
+static char *config_section_current = (char *) 0;
+
 /*
  * fname_encode()
  *
@@ -633,6 +649,7 @@ const char *name;
 int lev, oflag;
 {
     int reslt, fd;
+
     if (!lftrack.init) {
         lftrack.init = 1;
         lftrack.fd = -1;
@@ -665,13 +682,17 @@ int lev, oflag;
 void
 really_close()
 {
-    int fd = lftrack.fd;
+    int fd;
+    
+    if (lftrack.init) {
+        fd = lftrack.fd;
 
-    lftrack.nethack_thinks_it_is_open = FALSE;
-    lftrack.fd = -1;
-    lftrack.oflag = 0;
-    if (fd != -1)
-        (void) close(fd);
+        lftrack.nethack_thinks_it_is_open = FALSE;
+        lftrack.fd = -1;
+        lftrack.oflag = 0;
+        if (fd != -1)
+            (void) close(fd);
+    }
     return;
 }
 
@@ -687,7 +708,7 @@ int fd;
     }
     return close(fd);
 }
-#else
+#else /* !HOLD_LOCKFILE_OPEN */
 
 int
 nhclose(fd)
@@ -695,7 +716,7 @@ int fd;
 {
     return close(fd);
 }
-#endif
+#endif /* ?HOLD_LOCKFILE_OPEN */
 
 /* ----------  END LEVEL FILE HANDLING ----------- */
 
@@ -712,17 +733,47 @@ d_level *lev;
     s_level *sptr;
     char *dptr;
 
-    Sprintf(file, "bon%c%s", dungeons[lev->dnum].boneid,
+    /*
+     * "bonD0.nn"   = bones for level nn in the main dungeon;
+     * "bonM0.T"    = bones for Minetown;
+     * "bonQBar.n"  = bones for level n in the Barbarian quest;
+     * "bon3D0.nn"  = \
+     * "bon3M0.T"   =  > same as above, but for bones pool #3.
+     * "bon3QBar.n" = /
+     *
+     * Return value for content validation skips "bon" and the
+     * pool number (if present), making it feasible for the admin
+     * to manually move a bones file from one pool to another by
+     * renaming it.
+     */
+    Strcpy(file, "bon");
+#ifdef SYSCF
+    if (sysopt.bones_pools > 1) {
+        unsigned poolnum = min((unsigned) sysopt.bones_pools, 10);
+
+        poolnum = (unsigned) ubirthday % poolnum; /* 0..9 */
+        Sprintf(eos(file), "%u", poolnum);
+    }
+#endif
+    dptr = eos(file); /* this used to be after the following Sprintf()
+                         and the return value was (dptr - 2) */
+    /* when this naming scheme was adopted, 'filecode' was one letter;
+       3.3.0 turned it into a three letter string (via roles[] in role.c);
+       from that version through 3.6.0, 'dptr' pointed past the filecode
+       and the return value of (dptr - 2)  was wrong for bones produced
+       in the quest branch, skipping the boneid character 'Q' and the
+       first letter of the role's filecode; bones loading still worked
+       because the bonesid used for validation had the same error */
+    Sprintf(dptr, "%c%s", dungeons[lev->dnum].boneid,
             In_quest(lev) ? urole.filecode : "0");
-    dptr = eos(file);
     if ((sptr = Is_special(lev)) != 0)
-        Sprintf(dptr, ".%c", sptr->boneid);
+        Sprintf(eos(dptr), ".%c", sptr->boneid);
     else
-        Sprintf(dptr, ".%d", lev->dlevel);
+        Sprintf(eos(dptr), ".%d", lev->dlevel);
 #ifdef VMS
     Strcat(dptr, ";1");
 #endif
-    return (dptr - 2);
+    return dptr;
 }
 
 /* set up temporary file name for writing bones, to avoid another game's
@@ -1223,7 +1274,7 @@ boolean uncomp;
     if (freopen(filename, mode, stream) == (FILE *) 0) {
         (void) fprintf(stderr, "freopen of %s for %scompress failed\n",
                        filename, uncomp ? "un" : "");
-        terminate(EXIT_FAILURE);
+        nh_terminate(EXIT_FAILURE);
     }
 }
 
@@ -1332,7 +1383,7 @@ boolean uncomp;
         perror((char *) 0);
         (void) fprintf(stderr, "Exec to %scompress %s failed.\n",
                        uncomp ? "un" : "", filename);
-        terminate(EXIT_FAILURE);
+        nh_terminate(EXIT_FAILURE);
     } else if (f == -1) {
         perror((char *) 0);
         pline("Fork to %scompress %s failed.", uncomp ? "un" : "", filename);
@@ -1664,8 +1715,10 @@ int retryct;
 #ifdef USE_FCNTL
     lockfd = open(filename, O_RDWR);
     if (lockfd == -1) {
-        HUP raw_printf("Cannot open file %s. This is a program bug.",
+        HUP raw_printf("Cannot open file %s. Is NetHack installed correctly?",
                        filename);
+        nesting--;
+        return FALSE;
     }
     sflock.l_type = F_WRLCK;
     sflock.l_whence = SEEK_SET;
@@ -1844,7 +1897,7 @@ const char *filename;
 
 /* ----------  BEGIN CONFIG FILE HANDLING ----------- */
 
-const char *configfile =
+const char *default_configfile =
 #ifdef UNIX
     ".nethackrc";
 #else
@@ -1860,7 +1913,7 @@ const char *configfile =
 #endif
 
 /* used for messaging */
-char lastconfigfile[BUFSZ];
+char configfile[BUFSZ];
 
 #ifdef MSDOS
 /* conflict with speed-dial under windows
@@ -1873,6 +1926,16 @@ char lastconfigfile[BUFSZ];
 const char *backward_compat_configfile = "nethack.cnf";
 #endif
 
+/* remember the name of the file we're accessing;
+   if may be used in option reject messages */
+STATIC_OVL void
+set_configfile_name(fname)
+const char *fname;
+{
+    (void) strncpy(configfile, fname, sizeof configfile - 1);
+    configfile[sizeof configfile - 1] = '\0';
+}
+
 #ifndef MFLOPPY
 #define fopenp fopen
 #endif
@@ -1888,84 +1951,86 @@ int src;
     char *envp;
 #endif
 
+    if (src == SET_IN_SYS) {
+        /* SYSCF_FILE; if we can't open it, caller will bail */
+        if (filename && *filename) {
+            set_configfile_name(fqname(filename, SYSCONFPREFIX, 0));
+            fp = fopenp(configfile, "r");
+        } else
+            fp = (FILE *) 0;
+        return  fp;
+    }
     /* If src != SET_IN_SYS, "filename" is an environment variable, so it
      * should hang around. If set, it is expected to be a full path name
-     * (if relevant) */
-    if (filename) {
+     * (if relevant)
+     */
+    if (filename && *filename) {
+        set_configfile_name(filename);
 #ifdef UNIX
-        if ((src != SET_IN_SYS) && access(filename, 4) == -1) {
-            /* 4 is R_OK on newer systems */
+        if (access(configfile, 4) == -1) { /* 4 is R_OK on newer systems */
             /* nasty sneaky attempt to read file through
              * NetHack's setuid permissions -- this is the only
              * place a file name may be wholly under the player's
              * control (but SYSCF_FILE is not under the player's
              * control so it's OK).
              */
-            raw_printf("Access to %s denied (%d).", filename, errno);
+            raw_printf("Access to %s denied (%d).", configfile, errno);
             wait_synch();
             /* fall through to standard names */
         } else
 #endif
-#ifdef PREFIXES_IN_USE
-            if (src == SET_IN_SYS) {
-            (void) strncpy(lastconfigfile, fqname(filename, SYSCONFPREFIX, 0),
-                           BUFSZ - 1);
-        } else
-#endif
-            /* always honor sysconf first before anything else */
-            (void) strncpy(lastconfigfile, filename, BUFSZ - 1);
-        lastconfigfile[BUFSZ - 1] = '\0';
-        if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0)
-            return  fp;
-        if ((fp = fopenp(filename, "r")) != (FILE *) 0) {
+        if ((fp = fopenp(configfile, "r")) != (FILE *) 0) {
             return  fp;
 #if defined(UNIX) || defined(VMS)
         } else {
             /* access() above probably caught most problems for UNIX */
             raw_printf("Couldn't open requested config file %s (%d).",
-                       filename, errno);
+                       configfile, errno);
             wait_synch();
-/* fall through to standard names */
 #endif
         }
     }
+    /* fall through to standard names */
 
 #if defined(MICRO) || defined(MAC) || defined(__BEOS__) || defined(WIN32)
-    if ((fp = fopenp(fqname(configfile, CONFIGPREFIX, 0), "r")) != (FILE *) 0)
-        return fp;
-    if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
+    set_configfile_name(fqname(default_configfile, CONFIGPREFIX, 0));
+    if ((fp = fopenp(configfile, "r")) != (FILE *) 0) {
         return fp;
+    } else if (strcmp(default_configfile, configfile)) {
+        set_configfile_name(default_configfile);
+        if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
+            return fp;
+    }
 #ifdef MSDOS
-    if ((fp = fopenp(fqname(backward_compat_configfile, CONFIGPREFIX, 0),
-                     "r")) != (FILE *) 0)
-        return fp;
-    if ((fp = fopenp(backward_compat_configfile, "r")) != (FILE *) 0)
+    set_configfile_name(fqname(backward_compat_configfile, CONFIGPREFIX, 0));
+    if ((fp = fopenp(configfile, "r")) != (FILE *) 0) {
         return fp;
+    } else if (strcmp(backward_compat_configfile, configfile)) {
+        set_configfile_name(backward_compat_configfile);
+        if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
+            return fp;
+    }
 #endif
 #else
 /* constructed full path names don't need fqname() */
 #ifdef VMS
-    (void) strncpy(lastconfigfile, fqname("nethackini", CONFIGPREFIX, 0),
-                   BUFSZ - 1);
-    lastconfigfile[BUFSZ - 1] = '\0';
-    if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0) {
+    /* no punctuation, so might be a logical name */
+    set_configfile_name(fqname("nethackini", CONFIGPREFIX, 0));
+    if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
         return fp;
-    }
-    (void) strncpy(lastconfigfile, "sys$login:nethack.ini", BUFSZ - 1);
-    lastconfigfile[BUFSZ - 1] = '\0';
-    if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0) {
+    set_configfile_name("sys$login:nethack.ini");
+    if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
         return fp;
-    }
 
     envp = nh_getenv("HOME");
-    if (!envp)
+    if (!envp || !*envp)
         Strcpy(tmp_config, "NetHack.cnf");
     else
-        Sprintf(tmp_config, "%s%s", envp, "NetHack.cnf");
-
-    (void) strncpy(lastconfigfile, tmp_config, BUFSZ - 1);
-    lastconfigfile[BUFSZ - 1] = '\0';
-    if ((fp = fopenp(tmp_config, "r")) != (FILE *) 0)
+        Sprintf(tmp_config, "%s%s%s", envp,
+                !index(":]>/", envp[strlen(envp) - 1]) ? "/" : "",
+                "NetHack.cnf");
+    set_configfile_name(tmp_config);
+    if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
         return fp;
 #else /* should be only UNIX left */
     envp = nh_getenv("HOME");
@@ -1975,8 +2040,8 @@ int src;
     else
         Sprintf(tmp_config, "%s/%s", envp, ".jnethackrc");
 
-    (void) strncpy(lastconfigfile, tmp_config, BUFSZ - 1);
-    if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0)
+    set_configfile_name(tmp_config);
+    if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
         return fp;
 #endif
     if (!envp)
@@ -1984,56 +2049,52 @@ int src;
     else
         Sprintf(tmp_config, "%s/%s", envp, ".nethackrc");
 
-    (void) strncpy(lastconfigfile, tmp_config, BUFSZ - 1);
-    lastconfigfile[BUFSZ - 1] = '\0';
-    if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0)
+    set_configfile_name(tmp_config);
+    if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
         return fp;
-#if defined(__APPLE__)
+#if defined(__APPLE__) /* UNIX+__APPLE__ => MacOSX */
     /* try an alternative */
     if (envp) {
+        /* OSX-style configuration settings */
         Sprintf(tmp_config, "%s/%s", envp,
                 "Library/Preferences/NetHack Defaults");
-        (void) strncpy(lastconfigfile, tmp_config, BUFSZ - 1);
-        lastconfigfile[BUFSZ - 1] = '\0';
-        if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0)
+        set_configfile_name(tmp_config);
+        if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
             return fp;
+        /* may be easier for user to edit if filename as '.txt' suffix */
         Sprintf(tmp_config, "%s/%s", envp,
                 "Library/Preferences/NetHack Defaults.txt");
-        (void) strncpy(lastconfigfile, tmp_config, BUFSZ - 1);
-        lastconfigfile[BUFSZ - 1] = '\0';
-        if ((fp = fopenp(lastconfigfile, "r")) != (FILE *) 0)
+        set_configfile_name(tmp_config);
+        if ((fp = fopenp(configfile, "r")) != (FILE *) 0)
             return fp;
     }
-#endif
+#endif /*__APPLE__*/
     if (errno != ENOENT) {
         const char *details;
 
-/* e.g., problems when setuid NetHack can't search home
- * directory restricted to user */
-
+        /* e.g., problems when setuid NetHack can't search home
+           directory restricted to user */
 #if defined(NHSTDC) && !defined(NOTSTDC)
         if ((details = strerror(errno)) == 0)
 #endif
             details = "";
         raw_printf("Couldn't open default config file %s %s(%d).",
-                   lastconfigfile, details, errno);
+                   configfile, details, errno);
         wait_synch();
     }
-#endif /* Unix */
-#endif
+#endif /* !VMS => Unix */
+#endif /* !(MICRO || MAC || __BEOS__ || WIN32) */
     return (FILE *) 0;
 }
 
 /*
- * Retrieve a list of integers from a file into a uchar array.
+ * Retrieve a list of integers from buf into a uchar array.
  *
  * NOTE: zeros are inserted unless modlist is TRUE, in which case the list
  *  location is unchanged.  Callers must handle zeros if modlist is FALSE.
  */
 STATIC_OVL int
-get_uchars(fp, buf, bufp, list, modlist, size, name)
-FILE *fp;         /* input file pointer */
-char *buf;        /* read buffer, must be of size BUFSZ */
+get_uchars(bufp, list, modlist, size, name)
 char *bufp;       /* current pointer */
 uchar *list;      /* return list */
 boolean modlist;  /* TRUE: list is being modified in place */
@@ -2079,13 +2140,7 @@ const char *name; /* name of option for error message */
             break;
 
         case '\\':
-            if (fp == (FILE *) 0)
-                goto gi_error;
-            do {
-                if (!fgets(buf, BUFSZ, fp))
-                    goto gi_error;
-            } while (buf[0] == '#');
-            bufp = buf;
+            goto gi_error;
             break;
 
         default:
@@ -2119,13 +2174,111 @@ int prefixid;
 }
 #endif
 
+/* Choose at random one of the sep separated parts from str. Mangles str. */
+STATIC_OVL char *
+choose_random_part(str,sep)
+char *str;
+char sep;
+{
+    int nsep = 1;
+    int csep;
+    int len = 0;
+    char *begin = str;
+
+    if (!str)
+        return (char *) 0;
+
+    while (*str) {
+       if (*str == sep) nsep++;
+       str++;
+    }
+    csep = rn2(nsep);
+    str = begin;
+    while ((csep > 0) && *str) {
+       str++;
+       if (*str == sep) csep--;
+    }
+    if (*str) {
+       if (*str == sep) str++;
+       begin = str;
+       while (*str && *str != sep) {
+           str++;
+           len++;
+       }
+       *str = '\0';
+       if (len)
+            return begin;
+    }
+    return (char *) 0;
+}
+
+STATIC_OVL void
+free_config_sections()
+{
+    if (config_section_chosen) {
+        free(config_section_chosen);
+        config_section_chosen = NULL;
+    }
+    if (config_section_current) {
+        free(config_section_current);
+        config_section_current = NULL;
+    }
+}
+
+STATIC_OVL boolean
+is_config_section(str)
+const char *str;
+{
+    const char *a = rindex(str, ']');
+
+    return (a && *str == '[' && *(a+1) == '\0' && (int)(a - str) > 0);
+}
+
+STATIC_OVL boolean
+handle_config_section(buf)
+char *buf;
+{
+    if (is_config_section(buf)) {
+        char *send;
+        if (config_section_current) {
+            free(config_section_current);
+        }
+        config_section_current = dupstr(&buf[1]);
+        send = rindex(config_section_current, ']');
+        *send = '\0';
+        debugpline1("set config section: '%s'", config_section_current);
+        return TRUE;
+    }
+
+    if (config_section_current) {
+        if (!config_section_chosen)
+            return TRUE;
+        if (strcmp(config_section_current, config_section_chosen))
+            return TRUE;
+    }
+    return FALSE;
+}
+
 #define match_varname(INP, NAM, LEN) match_optname(INP, NAM, LEN, TRUE)
 
-int
-parse_config_line(fp, origbuf, src)
-FILE *fp;
+/* find the '=' or ':' */
+char *
+find_optparam(buf)
+const char *buf;
+{
+    char *bufp, *altp;
+
+    bufp = index(buf, '=');
+    altp = index(buf, ':');
+    if (!bufp || (altp && altp < bufp))
+        bufp = altp;
+
+    return bufp;
+}
+
+boolean
+parse_config_line(origbuf)
 char *origbuf;
-int src;
 {
 #if defined(MICRO) && !defined(NOCWD_ASSUMPTIONS)
     static boolean ramdisk_specified = FALSE;
@@ -2133,25 +2286,23 @@ int src;
 #ifdef SYSCF
     int n;
 #endif
-    char *bufp, *altp, buf[BUFSZ];
+    char *bufp, buf[4 * BUFSZ];
     uchar translate[MAXPCHARS];
     int len;
+    boolean retval = TRUE;
+    int src = iflags.parse_config_file_src;
 
     /* convert any tab to space, condense consecutive spaces into one,
        remove leading and trailing spaces (exception: if there is nothing
        but spaces, one of them will be kept even though it leads/trails) */
     mungspaces(strcpy(buf, origbuf));
-    /* lines beginning with '#' are comments; accept empty lines too */
-    if (!*buf || *buf == '#' || !strcmp(buf, " "))
-        return 1;
 
     /* find the '=' or ':' */
-    bufp = index(buf, '=');
-    altp = index(buf, ':');
-    if (!bufp || (altp && altp < bufp))
-        bufp = altp;
-    if (!bufp)
-        return 0;
+    bufp = find_optparam(buf);
+    if (!bufp) {
+        config_error_add("Not a config statement, missing '='");
+        return FALSE;
+    }
     /* skip past '=', then space between it and value, if any */
     ++bufp;
     if (*bufp == ' ')
@@ -2165,19 +2316,21 @@ int src;
         /* hack: un-mungspaces to allow consecutive spaces in
            general options until we verify that this is unnecessary;
            '=' or ':' is guaranteed to be present */
-        bufp = index(origbuf, '=');
-        altp = index(origbuf, ':');
-        if (!bufp || (altp && altp < bufp))
-            bufp = altp;
+        bufp = find_optparam(origbuf);
         ++bufp; /* skip '='; parseoptions() handles spaces */
 
-        parseoptions(bufp, TRUE, TRUE);
-        if (plname[0])      /* If a name was given */
-            plnamesuffix(); /* set the character class */
+        if (!parseoptions(bufp, TRUE, TRUE))
+            retval = FALSE;
     } else if (match_varname(buf, "AUTOPICKUP_EXCEPTION", 5)) {
         add_autopickup_exception(bufp);
+    } else if (match_varname(buf, "BINDINGS", 4)) {
+        if (!parsebindings(bufp))
+            retval = FALSE;
+    } else if (match_varname(buf, "AUTOCOMPLETE", 5)) {
+        parseautocomplete(bufp, TRUE);
     } else if (match_varname(buf, "MSGTYPE", 7)) {
-        (void) msgtype_parse_add(bufp);
+        if (!msgtype_parse_add(bufp))
+            retval = FALSE;
 #ifdef NOCWD_ASSUMPTIONS
     } else if (match_varname(buf, "HACKDIR", 4)) {
         adjust_prefix(bufp, HACKPREFIX);
@@ -2248,7 +2401,6 @@ int src;
 
     } else if (match_varname(buf, "NAME", 4)) {
         (void) strncpy(plname, bufp, PL_NSIZ - 1);
-        plnamesuffix();
     } else if (match_varname(buf, "ROLE", 4)
                || match_varname(buf, "CHARACTER", 4)) {
         if ((len = str2role(bufp)) >= 0)
@@ -2288,6 +2440,24 @@ int src;
                 free((genericptr_t) sysopt.debugfiles);
             sysopt.debugfiles = dupstr(bufp);
         }
+    } else if (src == SET_IN_SYS && match_varname(buf, "DUMPLOGFILE", 7)) {
+#ifdef DUMPLOG
+        if (sysopt.dumplogfile)
+            free((genericptr_t) sysopt.dumplogfile);
+        sysopt.dumplogfile = dupstr(bufp);
+#endif
+    } else if (src == SET_IN_SYS && match_varname(buf, "GENERICUSERS", 12)) {
+        if (sysopt.genericusers)
+            free((genericptr_t) sysopt.genericusers);
+        sysopt.genericusers = dupstr(bufp);
+    } else if (src == SET_IN_SYS && match_varname(buf, "BONES_POOLS", 10)) {
+        /* max value of 10 guarantees (N % bones.pools) will be one digit
+           so we don't lose control of the length of bones file names */
+        n = atoi(bufp);
+        sysopt.bones_pools = (n <= 0) ? 0 : min(n, 10);
+        /* note: right now bones_pools==0 is the same as bones_pools==1,
+           but we could change that and make bones_pools==0 become an
+           indicator to suppress bones usage altogether */
     } else if (src == SET_IN_SYS && match_varname(buf, "SUPPORT", 7)) {
         if (sysopt.support)
             free((genericptr_t) sysopt.support);
@@ -2300,58 +2470,62 @@ int src;
                && match_varname(buf, "CHECK_SAVE_UID", 14)) {
         n = atoi(bufp);
         sysopt.check_save_uid = n;
+    } else if (src == SET_IN_SYS
+               && match_varname(buf, "CHECK_PLNAME", 12)) {
+        n = atoi(bufp);
+        sysopt.check_plname = n;
     } else if (match_varname(buf, "SEDUCE", 6)) {
         n = !!atoi(bufp); /* XXX this could be tighter */
         /* allow anyone to turn it off, but only sysconf to turn it on*/
         if (src != SET_IN_SYS && n != 0) {
-            raw_printf("Illegal value in SEDUCE");
-            return 0;
+            config_error_add("Illegal value in SEDUCE");
+            return FALSE;
         }
         sysopt.seduce = n;
         sysopt_seduce_set(sysopt.seduce);
     } else if (src == SET_IN_SYS && match_varname(buf, "MAXPLAYERS", 10)) {
         n = atoi(bufp);
         /* XXX to get more than 25, need to rewrite all lock code */
-        if (n < 1 || n > 25) {
-            raw_printf("Illegal value in MAXPLAYERS (maximum is 25).");
-            return 0;
+        if (n < 0 || n > 25) {
+            config_error_add("Illegal value in MAXPLAYERS (maximum is 25).");
+            return FALSE;
         }
         sysopt.maxplayers = n;
     } else if (src == SET_IN_SYS && match_varname(buf, "PERSMAX", 7)) {
         n = atoi(bufp);
         if (n < 1) {
-            raw_printf("Illegal value in PERSMAX (minimum is 1).");
-            return 0;
+            config_error_add("Illegal value in PERSMAX (minimum is 1).");
+            return FALSE;
         }
         sysopt.persmax = n;
     } else if (src == SET_IN_SYS && match_varname(buf, "PERS_IS_UID", 11)) {
         n = atoi(bufp);
         if (n != 0 && n != 1) {
-            raw_printf("Illegal value in PERS_IS_UID (must be 0 or 1).");
-            return 0;
+            config_error_add("Illegal value in PERS_IS_UID (must be 0 or 1).");
+            return FALSE;
         }
         sysopt.pers_is_uid = n;
     } else if (src == SET_IN_SYS && match_varname(buf, "ENTRYMAX", 8)) {
         n = atoi(bufp);
         if (n < 10) {
-            raw_printf("Illegal value in ENTRYMAX (minimum is 10).");
-            return 0;
+            config_error_add("Illegal value in ENTRYMAX (minimum is 10).");
+            return FALSE;
         }
         sysopt.entrymax = n;
     } else if ((src == SET_IN_SYS) && match_varname(buf, "POINTSMIN", 9)) {
         n = atoi(bufp);
         if (n < 1) {
-            raw_printf("Illegal value in POINTSMIN (minimum is 1).");
-            return 0;
+            config_error_add("Illegal value in POINTSMIN (minimum is 1).");
+            return FALSE;
         }
         sysopt.pointsmin = n;
     } else if (src == SET_IN_SYS
                && match_varname(buf, "MAX_STATUENAME_RANK", 10)) {
         n = atoi(bufp);
         if (n < 1) {
-            raw_printf(
+            config_error_add(
                 "Illegal value in MAX_STATUENAME_RANK (minimum is 1).");
-            return 0;
+            return FALSE;
         }
         sysopt.tt_oname_maxrank = n;
 
@@ -2361,8 +2535,8 @@ int src;
         n = atoi(bufp);
 #if defined(PANICTRACE) && defined(PANICTRACE_LIBC)
         if (n < 0 || n > 2) {
-            raw_printf("Illegal value in PANICTRACE_LIBC (not 0,1,2).");
-            return 0;
+            config_error_add("Illegal value in PANICTRACE_LIBC (not 0,1,2).");
+            return FALSE;
         }
 #endif
         sysopt.panictrace_libc = n;
@@ -2371,16 +2545,16 @@ int src;
         n = atoi(bufp);
 #if defined(PANICTRACE)
         if (n < 0 || n > 2) {
-            raw_printf("Illegal value in PANICTRACE_GDB (not 0,1,2).");
-            return 0;
+            config_error_add("Illegal value in PANICTRACE_GDB (not 0,1,2).");
+            return FALSE;
         }
 #endif
         sysopt.panictrace_gdb = n;
     } else if (src == SET_IN_SYS && match_varname(buf, "GDBPATH", 7)) {
 #if defined(PANICTRACE) && !defined(VMS)
         if (!file_exists(bufp)) {
-            raw_printf("File specified in GDBPATH does not exist.");
-            return 0;
+            config_error_add("File specified in GDBPATH does not exist.");
+            return FALSE;
         }
 #endif
         if (sysopt.gdbpath)
@@ -2389,8 +2563,8 @@ int src;
     } else if (src == SET_IN_SYS && match_varname(buf, "GREPPATH", 7)) {
 #if defined(PANICTRACE) && !defined(VMS)
         if (!file_exists(bufp)) {
-            raw_printf("File specified in GREPPATH does not exist.");
-            return 0;
+            config_error_add("File specified in GREPPATH does not exist.");
+            return FALSE;
         }
 #endif
         if (sysopt.greppath)
@@ -2399,42 +2573,25 @@ int src;
 #endif /* SYSCF */
 
     } else if (match_varname(buf, "BOULDER", 3)) {
-        (void) get_uchars(fp, buf, bufp, &iflags.bouldersym, TRUE, 1,
+        (void) get_uchars(bufp, &iflags.bouldersym, TRUE, 1,
                           "BOULDER");
     } else if (match_varname(buf, "MENUCOLOR", 9)) {
-        (void) add_menu_coloring(bufp);
+        if (!add_menu_coloring(bufp))
+            retval = FALSE;
+    } else if (match_varname(buf, "HILITE_STATUS", 6)) {
+#ifdef STATUS_HILITES
+        if (!parse_status_hl1(bufp, TRUE))
+            retval = FALSE;
+#endif
     } else if (match_varname(buf, "WARNINGS", 5)) {
-        (void) get_uchars(fp, buf, bufp, translate, FALSE, WARNCOUNT,
+        (void) get_uchars(bufp, translate, FALSE, WARNCOUNT,
                           "WARNINGS");
         assign_warnings(translate);
     } else if (match_varname(buf, "SYMBOLS", 4)) {
-        char *op, symbuf[BUFSZ];
-        boolean morelines;
-
-        do {
-            /* check for line continuation (trailing '\') */
-            op = eos(bufp);
-            morelines = (--op >= bufp && *op == '\\');
-            if (morelines) {
-                *op = '\0';
-                /* strip trailing space now that '\' is gone */
-                if (--op >= bufp && *op == ' ')
-                    *op = '\0';
-            }
-            /* parse here */
-            parsesymbols(bufp);
-            if (morelines) {
-                do {
-                    *symbuf = '\0';
-                    if (!fgets(symbuf, BUFSZ, fp)) {
-                        morelines = FALSE;
-                        break;
-                    }
-                    mungspaces(symbuf);
-                    bufp = symbuf;
-                } while (*bufp == '#');
-            }
-        } while (morelines);
+        if (!parsesymbols(bufp)) {
+            config_error_add("Error in SYMBOLS definition '%s'", bufp);
+            retval = FALSE;
+        }
         switch_symbols(TRUE);
     } else if (match_varname(buf, "WIZKIT", 6)) {
         (void) strncpy(wizkit, bufp, WIZKIT_MAX - 1);
@@ -2555,31 +2712,38 @@ int src;
     } else if (match_varname(buf, "SOUND", 5)) {
         add_sound_mapping(bufp);
 #endif
-#ifdef QT_GRAPHICS
-        /* These should move to wc_ options */
     } else if (match_varname(buf, "QT_TILEWIDTH", 12)) {
+#ifdef QT_GRAPHICS
         extern char *qt_tilewidth;
 
         if (qt_tilewidth == NULL)
             qt_tilewidth = dupstr(bufp);
+#endif
     } else if (match_varname(buf, "QT_TILEHEIGHT", 13)) {
+#ifdef QT_GRAPHICS
         extern char *qt_tileheight;
 
         if (qt_tileheight == NULL)
             qt_tileheight = dupstr(bufp);
+#endif
     } else if (match_varname(buf, "QT_FONTSIZE", 11)) {
+#ifdef QT_GRAPHICS
         extern char *qt_fontsize;
 
         if (qt_fontsize == NULL)
             qt_fontsize = dupstr(bufp);
+#endif
     } else if (match_varname(buf, "QT_COMPACT", 10)) {
+#ifdef QT_GRAPHICS
         extern int qt_compact_mode;
 
         qt_compact_mode = atoi(bufp);
 #endif
-    } else
-        return 0;
-    return 1;
+    } else {
+        config_error_add("Unknown config statement");
+        return FALSE;
+    }
+    return retval;
 }
 
 #ifdef USER_SOUNDS
@@ -2591,45 +2755,148 @@ const char *filename;
 }
 #endif /* USER_SOUNDS */
 
+struct _config_error_frame {
+    int line_num;
+    int num_errors;
+    boolean origline_shown;
+    boolean fromfile;
+    boolean secure;
+    char origline[4 * BUFSZ];
+    char source[BUFSZ];
+    struct _config_error_frame *next;
+};
+
+struct _config_error_frame *config_error_data = (struct _config_error_frame *)0;
+
+void
+config_error_init(from_file, sourcename, secure)
+boolean from_file;
+const char *sourcename;
+boolean secure;
+{
+    struct _config_error_frame *tmp = (struct _config_error_frame *)
+        alloc(sizeof(struct _config_error_frame));
+
+    tmp->line_num = 0;
+    tmp->num_errors = 0;
+    tmp->origline_shown = FALSE;
+    tmp->fromfile = from_file;
+    tmp->secure = secure;
+    tmp->origline[0] = '\0';
+    if (sourcename && sourcename[0]) {
+        (void) strncpy(tmp->source, sourcename, sizeof(tmp->source)-1);
+        tmp->source[sizeof(tmp->source)-1] = '\0';
+    } else
+        tmp->source[0] = '\0';
+
+    tmp->next = config_error_data;
+    config_error_data = tmp;
+}
+
+STATIC_OVL boolean
+config_error_nextline(line)
+const char *line;
+{
+    struct _config_error_frame *ced = config_error_data;
+
+    if (!ced)
+        return FALSE;
+
+    if (ced->num_errors && ced->secure)
+        return FALSE;
+
+    ced->line_num++;
+    ced->origline_shown = FALSE;
+    if (line && line[0]) {
+        (void) strncpy(ced->origline, line, sizeof(ced->origline)-1);
+        ced->origline[sizeof(ced->origline)-1] = '\0';
+    } else
+        ced->origline[0] = '\0';
+
+    return TRUE;
+}
+
+/*VARARGS1*/
+void config_error_add
+VA_DECL(const char *, str)
+{
+    char buf[BUFSZ];
+    char lineno[QBUFSZ];
+
+    VA_START(str);
+    VA_INIT(str, char *);
+
+    Vsprintf(buf, str, VA_ARGS);
+
+    if (!config_error_data) {
+        pline("%s.", *buf ? buf : "Unknown error");
+        wait_synch();
+        return;
+    }
+
+    config_error_data->num_errors++;
+    if (!config_error_data->origline_shown
+        && !config_error_data->secure) {
+        pline("\n%s", config_error_data->origline);
+        config_error_data->origline_shown = TRUE;
+    }
+    if (config_error_data->line_num > 0
+        && !config_error_data->secure) {
+        Sprintf(lineno, "Line %i: ", config_error_data->line_num);
+    } else
+        lineno[0] = '\0';
+    pline("%s %s%s.",
+          config_error_data->secure ? "Error:" : " *",
+          lineno,
+          *buf ? buf : "Unknown error");
+
+    VA_END();
+}
+
+int
+config_error_done()
+{
+    int n;
+    struct _config_error_frame *tmp = config_error_data;
+
+    if (!config_error_data)
+        return 0;
+    n = config_error_data->num_errors;
+    if (n) {
+        pline("\n%i error%s in %s.\n", n,
+                   (n > 1) ? "s" : "",
+                   *config_error_data->source
+              ? config_error_data->source : configfile);
+        wait_synch();
+    }
+
+    config_error_data = tmp->next;
+
+    free(tmp);
+
+    return n;
+}
+
 boolean
 read_config_file(filename, src)
 const char *filename;
 int src;
 {
-    char buf[4 * BUFSZ], *p;
     FILE *fp;
-    boolean rv = TRUE; /* assume successful parse */
+    boolean rv = TRUE;
 
     if (!(fp = fopen_config_file(filename, src)))
         return FALSE;
 
     /* begin detection of duplicate configfile options */
     set_duplicate_opt_detection(1);
+    free_config_sections();
+    iflags.parse_config_file_src = src;
 
-    while (fgets(buf, sizeof buf, fp)) {
-#ifdef notyet
-/*
-XXX Don't call read() in parse_config_line, read as callback or reassemble
-line at this level.
-OR: Forbid multiline stuff for alternate config sources.
-*/
-#endif
-        if ((p = index(buf, '\n')) != 0)
-            *p = '\0';
-        if (!parse_config_line(fp, buf, src)) {
-            static const char badoptionline[] = "Bad option line: \"%s\"";
-
-            /* truncate buffer if it's long; this is actually conservative */
-            if (strlen(buf) > BUFSZ - sizeof badoptionline)
-                buf[BUFSZ - sizeof badoptionline] = '\0';
-
-            raw_printf(badoptionline, buf);
-            wait_synch();
-            rv = FALSE;
-        }
-    }
+    rv = parse_conf_file(fp, parse_config_line);
     (void) fclose(fp);
 
+    free_config_sections();
     /* turn off detection of duplicate configfile options */
     set_duplicate_opt_detection(0);
     return rv;
@@ -2733,47 +3000,171 @@ struct obj *obj;
     }
 }
 
+
+boolean
+proc_wizkit_line(buf)
+char *buf;
+{
+    struct obj *otmp = readobjnam(buf, (struct obj *) 0);
+
+    if (otmp) {
+        if (otmp != &zeroobj)
+            wizkit_addinv(otmp);
+    } else {
+        /* .60 limits output line width to 79 chars */
+        config_error_add("Bad wizkit item: \"%.60s\"", buf);
+        return FALSE;
+    }
+    return TRUE;
+}
+
 void
 read_wizkit()
 {
     FILE *fp;
-    char *ep, buf[BUFSZ];
-    struct obj *otmp;
-    boolean bad_items = FALSE, skip = FALSE;
 
     if (!wizard || !(fp = fopen_wizkit_file()))
         return;
 
     program_state.wizkit_wishing = 1;
-    while (fgets(buf, (int) (sizeof buf), fp)) {
-        ep = index(buf, '\n');
+    config_error_init(TRUE, "WIZKIT", FALSE);
+
+    parse_conf_file(fp, proc_wizkit_line);
+    (void) fclose(fp);
+
+    config_error_done();
+    program_state.wizkit_wishing = 0;
+
+    return;
+}
+
+/* parse_conf_file
+ *
+ * Read from file fp, handling comments, empty lines, config sections,
+ * CHOOSE, and line continuation, calling proc for every valid line.
+ *
+ * Continued lines are merged together with one space in between.
+ */
+STATIC_OVL boolean
+parse_conf_file(fp, proc)
+FILE *fp;
+boolean FDECL((*proc), (char *));
+{
+    char inbuf[4 * BUFSZ];
+    boolean rv = TRUE; /* assume successful parse */
+    char *ep;
+    boolean skip = FALSE, morelines = FALSE;
+    char *buf = (char *) 0;
+
+    free_config_sections();
+
+    while (fgets(inbuf, (int) (sizeof inbuf), fp)) {
+        ep = index(inbuf, '\n');
         if (skip) { /* in case previous line was too long */
             if (ep)
                 skip = FALSE; /* found newline; next line is normal */
         } else {
-            if (!ep)
+            if (!ep) {
+                config_error_add("Line too long, skipping");
                 skip = TRUE; /* newline missing; discard next fgets */
-            else
+            } else {
+                char *tmpbuf = (char *) 0;
+                int len;
+                boolean ignoreline = FALSE;
+                boolean oldline = FALSE;
+
                 *ep = '\0'; /* remove newline */
 
-            if (buf[0]) {
-                otmp = readobjnam(buf, (struct obj *) 0);
-                if (otmp) {
-                    if (otmp != &zeroobj)
-                        wizkit_addinv(otmp);
-                } else {
-                    /* .60 limits output line width to 79 chars */
-                    raw_printf("Bad wizkit item: \"%.60s\"", buf);
-                    bad_items = TRUE;
+                /* line continuation (trailing '\') */
+                morelines = (--ep >= inbuf && *ep == '\\');
+                if (morelines)
+                    *ep = '\0';
+
+                /* trim off spaces at end of line */
+                while (--ep >= inbuf && (*ep == ' ' || *ep == '\t' || *ep == '\r'))
+                    *ep = '\0';
+
+                if (!config_error_nextline(inbuf)) {
+                    rv = FALSE;
+                    if (buf)
+                        free(buf), buf = (char *) 0;
+                    break;
                 }
+
+                ep = inbuf;
+                while (*ep == ' ' || *ep == '\t') ep++;
+
+                /* lines beginning with '#' are comments. ignore empty lines. */
+                if (!*ep || *ep == '#')
+                    ignoreline = TRUE;
+
+                if (buf)
+                    oldline = TRUE;
+
+                /* merge now read line with previous ones, if necessary */
+                if (!ignoreline) {
+                    len = strlen(inbuf) + 1;
+                    if (buf)
+                        len += strlen(buf);
+                    tmpbuf = (char *) alloc(len);
+                    if (buf) {
+                        Sprintf(tmpbuf, "%s %s", buf, inbuf);
+                        free(buf);
+                    } else
+                        Strcpy(tmpbuf, inbuf);
+                    buf = tmpbuf;
+                }
+
+                if (morelines || (ignoreline && !oldline))
+                    continue;
+
+                if (handle_config_section(ep)) {
+                    free(buf);
+                    buf = (char *) 0;
+                    continue;
+                }
+
+                /* from here onwards, we'll handle buf only */
+
+                if (match_varname(buf, "CHOOSE", 6)) {
+                    char *section;
+                    char *bufp = find_optparam(buf);
+                    if (!bufp) {
+                        config_error_add("Format is CHOOSE=section1,section2,...");
+                        rv = FALSE;
+                        free(buf);
+                        buf = (char *) 0;
+                        continue;
+                    }
+                    bufp++;
+                    if (config_section_chosen)
+                        free(config_section_chosen);
+                    section = choose_random_part(bufp, ',');
+                    if (section)
+                        config_section_chosen = dupstr(section);
+                    else {
+                        config_error_add("No config section to choose");
+                        rv = FALSE;
+                    }
+                    free(buf);
+                    buf = (char *) 0;
+                    continue;
+                }
+
+                if (!proc(buf))
+                    rv = FALSE;
+
+                free(buf);
+                buf = (char *) 0;
             }
         }
     }
-    program_state.wizkit_wishing = 0;
-    if (bad_items)
-        wait_synch();
-    (void) fclose(fp);
-    return;
+
+    if (buf)
+        free(buf);
+
+    free_config_sections();
+    return rv;
 }
 
 extern struct symsetentry *symset_list;  /* options.c */
@@ -2782,6 +3173,7 @@ extern const char *known_handling[];     /* drawing.c */
 extern const char *known_restrictions[]; /* drawing.c */
 static int symset_count = 0;             /* for pick-list building only */
 static boolean chosen_symset_start = FALSE, chosen_symset_end = FALSE;
+static int symset_which_set = 0;
 
 STATIC_OVL
 FILE *
@@ -2801,7 +3193,6 @@ int
 read_sym_file(which_set)
 int which_set;
 {
-    char buf[4 * BUFSZ];
     FILE *fp;
 
     if (!(fp = fopen_sym_file()))
@@ -2809,24 +3200,42 @@ int which_set;
 
     symset_count = 0;
     chosen_symset_start = chosen_symset_end = FALSE;
-    while (fgets(buf, 4 * BUFSZ, fp)) {
-        if (!parse_sym_line(buf, which_set)) {
-            raw_printf("Bad symbol line:  \"%.50s\"", buf);
-            wait_synch();
-        }
-    }
+    symset_which_set = which_set;
+
+    config_error_init(TRUE, "symbols", FALSE);
+
+    parse_conf_file(fp, proc_symset_line);
     (void) fclose(fp);
-    if (!chosen_symset_end && !chosen_symset_start)
+
+    if (!chosen_symset_start && !chosen_symset_end) {
+        /* name caller put in symset[which_set].name was not found;
+           if it looks like "Default symbols", null it out and return
+           success to use the default; otherwise, return failure */
+        if (symset[which_set].name
+            && (fuzzymatch(symset[which_set].name, "Default symbols",
+                           " -_", TRUE)
+                || !strcmpi(symset[which_set].name, "default")))
+            clear_symsetentry(which_set, TRUE);
+        config_error_done();
         return (symset[which_set].name == 0) ? 1 : 0;
-    if (!chosen_symset_end) {
-        raw_printf("Missing finish for symset \"%s\"",
+    }
+    if (!chosen_symset_end)
+        config_error_add("Missing finish for symset \"%s\"",
                    symset[which_set].name ? symset[which_set].name
                                           : "unknown");
-        wait_synch();
-    }
+
+    config_error_done();
+
     return 1;
 }
 
+boolean
+proc_symset_line(buf)
+char *buf;
+{
+    return !((boolean) parse_sym_line(buf, symset_which_set));
+}
+
 /* returns 0 on error */
 int
 parse_sym_line(buf, which_set)
@@ -2840,16 +3249,14 @@ int which_set;
     /* convert each instance of whitespace (tabs, consecutive spaces)
        into a single space; leading and trailing spaces are stripped */
     mungspaces(buf);
-    if (!*buf || *buf == '#' || !strcmp(buf, " "))
-        return 1;
-    /* remove trailing comment, if any */
-    if ((commentp = rindex(buf, '#')) != 0) {
-        *commentp = '\0';
-        /* remove space preceding the stripped comment, if any;
-           we know 'commentp > buf' because *buf=='#' was caught above */
-        if (commentp[-1] == ' ')
-            *--commentp = '\0';
-    }
+
+    /* remove trailing comment, if any (this isn't strictly needed for
+       individual symbols, and it won't matter if "X#comment" without
+       separating space slips through; for handling or set description,
+       symbol set creator is responsible for preceding '#' with a space
+       and that comment itself doesn't contain " #") */
+    if ((commentp = rindex(buf, '#')) != 0 && commentp[-1] == ' ')
+        commentp[-1] = '\0';
 
     /* find the '=' or ':' */
     bufp = index(buf, '=');
@@ -2864,6 +3271,7 @@ int which_set;
             chosen_symset_start = FALSE;
             return 1;
         }
+        config_error_add("No \"finish\"");
         return 0;
     }
     /* skip '=' and space which follows, if any */
@@ -2872,8 +3280,10 @@ int which_set;
         ++bufp;
 
     symp = match_sym(buf);
-    if (!symp)
+    if (!symp) {
+        config_error_add("Unknown sym keyword");
         return 0;
+    }
 
     if (!symset[which_set].name) {
         /* A null symset name indicates that we're just
@@ -3063,8 +3473,8 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW;
 #ifdef VMS /* must be stream-lf to use UPDATE_RECORD_IN_PLACE */
         if (!file_is_stmlf(fd)) {
             raw_printf(
-                "Warning: scoreboard file %s is not in stream_lf format",
-                fq_record);
+                   "Warning: scoreboard file '%s' is not in stream_lf format",
+                       fq_record);
             wait_synch();
         }
 #endif
@@ -3076,7 +3486,7 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW;
         (void) chmod(fq_record, FCMASK | 007);
 #endif /* VMS && !SECURE */
     } else {
-        raw_printf("Warning: cannot write scoreboard file %s", fq_record);
+        raw_printf("Warning: cannot write scoreboard file '%s'", fq_record);
         wait_synch();
     }
 #endif /* !UNIX && !VMS */
@@ -3097,24 +3507,51 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW;
     Strcpy(tmp, RECORD);
     fq_record = fqname(RECORD, SCOREPREFIX, 0);
 #endif
+#ifdef WIN32
+    /* If dir is NULL it indicates create but
+       only if it doesn't already exist */
+    if (!dir) {
+        char buf[BUFSZ];
+
+        buf[0] = '\0';
+        fd = open(fq_record, O_RDWR);
+        if (!(fd == -1 && errno == ENOENT)) {
+            if (fd >= 0) {
+                (void) nhclose(fd);
+            } else {
+                /* explanation for failure other than missing file */
+                Sprintf(buf, "error   \"%s\", (errno %d).",
+                        fq_record, errno);
+                paniclog("scorefile", buf);
+            }
+            return;
+        }
+        Sprintf(buf, "missing \"%s\", creating new scorefile.",
+                fq_record);
+        paniclog("scorefile", buf);
+    }
+#endif
 
     if ((fd = open(fq_record, O_RDWR)) < 0) {
-/* try to create empty record */
+        /* try to create empty 'record' */
 #if defined(AZTEC_C) || defined(_DCC) \
     || (defined(__GNUC__) && defined(__AMIGA__))
         /* Aztec doesn't use the third argument */
         /* DICE doesn't like it */
-        if ((fd = open(fq_record, O_CREAT | O_RDWR)) < 0) {
+        fd = open(fq_record, O_CREAT | O_RDWR);
 #else
-        if ((fd = open(fq_record, O_CREAT | O_RDWR, S_IREAD | S_IWRITE))
-            < 0) {
+        fd = open(fq_record, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
 #endif
-            raw_printf("Warning: cannot write record %s", tmp);
+        if (fd <= 0) {
+            raw_printf("Warning: cannot write record '%s'", tmp);
             wait_synch();
-        } else
+        } else {
             (void) nhclose(fd);
-    } else /* open succeeded */
+        }
+    } else {
+        /* open succeeded => 'record' exists */
         (void) nhclose(fd);
+    }
 #else /* MICRO || WIN32*/
 
 #ifdef MAC
@@ -3146,6 +3583,11 @@ const char *reason; /* explanation */
         program_state.in_paniclog = 1;
         lfile = fopen_datafile(PANICLOG, "a", TROUBLEPREFIX);
         if (lfile) {
+#ifdef PANICLOG_FMT2
+            (void) fprintf(lfile, "%ld %s: %s %s\n",
+                           ubirthday, (plname ? plname : "(none)"),
+                           type, reason);
+#else
             time_t now = getnow();
             int uid = getuid();
             char playmode = wizard ? 'D' : discover ? 'X' : '-';
@@ -3153,6 +3595,7 @@ const char *reason; /* explanation */
             (void) fprintf(lfile, "%s %08ld %06ld %d %c: %s %s\n",
                            version_string(buf), yyyymmdd(now), hhmmss(now),
                            uid, playmode, type, reason);
+#endif /* !PANICLOG_FMT2 */
             (void) fclose(lfile);
         }
         program_state.in_paniclog = 0;
@@ -3252,6 +3695,7 @@ recover_savefile()
         raw_printf("\nError writing %s; recovery failed.", SAVEF);
         (void) nhclose(gfd);
         (void) nhclose(sfd);
+        (void) nhclose(lfd);
         delete_savefile();
         return FALSE;
     }
@@ -3261,6 +3705,7 @@ recover_savefile()
                    SAVEF);
         (void) nhclose(gfd);
         (void) nhclose(sfd);
+        (void) nhclose(lfd);
         delete_savefile();
         return FALSE;
     }
@@ -3271,6 +3716,7 @@ recover_savefile()
                    SAVEF);
         (void) nhclose(gfd);
         (void) nhclose(sfd);
+        (void) nhclose(lfd);
         delete_savefile();
         return FALSE;
     }
@@ -3280,13 +3726,15 @@ recover_savefile()
                    SAVEF);
         (void) nhclose(gfd);
         (void) nhclose(sfd);
+        (void) nhclose(lfd);
         delete_savefile();
         return FALSE;
     }
 
     if (!copy_bytes(lfd, sfd)) {
-        (void) nhclose(lfd);
+        (void) nhclose(gfd);
         (void) nhclose(sfd);
+        (void) nhclose(lfd);
         delete_savefile();
         return FALSE;
     }
@@ -3294,7 +3742,7 @@ recover_savefile()
     processed[savelev] = 1;
 
     if (!copy_bytes(gfd, sfd)) {
-        (void) nhclose(lfd);
+        (void) nhclose(gfd);
         (void) nhclose(sfd);
         delete_savefile();
         return FALSE;
@@ -3335,6 +3783,7 @@ recover_savefile()
     for (lev = 0; lev < 256; lev++) {
         if (processed[lev]) {
             const char *fq_lock;
+
             set_levelfile_name(lock, lev);
             fq_lock = fqname(lock, LEVELPREFIX, 3);
             (void) unlink(fq_lock);
@@ -3381,7 +3830,11 @@ assure_syscf_file()
      * VMS overrides open() usage with a macro which requires it.
      */
 #ifndef VMS
+# if defined(NOCWD_ASSUMPTIONS) && defined(WIN32)
+    fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY);
+# else
     fd = open(SYSCF_FILE, O_RDONLY);
+# endif
 #else
     fd = open(SYSCF_FILE, O_RDONLY, 0);
 #endif
@@ -3480,7 +3933,7 @@ boolean wildcards;
 #define TITLESCOPE 2
 #define PASSAGESCOPE 3
 
-#define MAXPASSAGES SIZE(context.novel.pasg) /* 30 */
+#define MAXPASSAGES SIZE(context.novel.pasg) /* 20 */
 
 static int FDECL(choose_passage, (int, unsigned));
 
@@ -3488,24 +3941,35 @@ static int FDECL(choose_passage, (int, unsigned));
    been chosen, reset the tracking to make all passages available again */
 static int
 choose_passage(passagecnt, oid)
-int passagecnt; /* total of available passages, 1..MAXPASSAGES */
+int passagecnt; /* total of available passages */
 unsigned oid; /* book.o_id, used to determine whether re-reading same book */
 {
     int idx, res;
 
     if (passagecnt < 1)
         return 0;
-    if (passagecnt > MAXPASSAGES)
-        passagecnt = MAXPASSAGES;
 
     /* if a different book or we've used up all the passages already,
        reset in order to have all 'passagecnt' passages available */
     if (oid != context.novel.id || context.novel.count == 0) {
+        int i, range = passagecnt, limit = MAXPASSAGES;
+
         context.novel.id = oid;
-        context.novel.count = passagecnt;
-        for (idx = 0; idx < MAXPASSAGES; idx++)
-            context.novel.pasg[idx] = (xchar) ((idx < passagecnt) ? idx + 1
-                                                                  : 0);
+        if (range <= limit) {
+            /* collect all of the N indices */
+            context.novel.count = passagecnt;
+            for (idx = 0; idx < MAXPASSAGES; idx++)
+                context.novel.pasg[idx] = (xchar) ((idx < passagecnt)
+                                                   ? idx + 1 : 0);
+        } else {
+            /* collect MAXPASSAGES of the N indices */
+            context.novel.count = MAXPASSAGES;
+            for (idx = i = 0; i < passagecnt; ++i, --range)
+                if (range > 0 && rn2(range) < limit) {
+                    context.novel.pasg[idx++] = (xchar) (i + 1);
+                    --limit;
+                }
+        }
     }
 
     idx = rn2(context.novel.count);
@@ -3525,7 +3989,6 @@ char *nowin_buf;
 unsigned oid; /* book identifier */
 {
     dlb *fp;
-    char *endp;
     char line[BUFSZ], lastline[BUFSZ];
 
     int scope = 0;
@@ -3539,6 +4002,9 @@ unsigned oid; /* book identifier */
     boolean grasped = FALSE;
     boolean foundpassage = FALSE;
 
+    if (nowin_buf)
+        *nowin_buf = '\0';
+
     /* check for mandatories */
     if (!tribsection || !tribtitle) {
         if (!nowin_buf)
@@ -3585,19 +4051,15 @@ unsigned oid; /* book identifier */
     *line = *lastline = '\0';
     while (dlb_fgets(line, sizeof line, fp) != 0) {
         linect++;
-        if ((endp = index(line, '\n')) != 0)
-            *endp = 0;
+        (void) strip_newline(line);
         switch (line[0]) {
         case '%':
-            if (!strncmpi(&line[1], "section ", sizeof("section ") - 1)) {
+            if (!strncmpi(&line[1], "section ", sizeof "section " - 1)) {
                 char *st = &line[9]; /* 9 from "%section " */
 
                 scope = SECTIONSCOPE;
-                if (!strcmpi(st, tribsection))
-                    matchedsection = TRUE;
-                else
-                    matchedsection = FALSE;
-            } else if (!strncmpi(&line[1], "title ", sizeof("title ") - 1)) {
+                matchedsection = !strcmpi(st, tribsection) ? TRUE : FALSE;
+            } else if (!strncmpi(&line[1], "title ", sizeof "title " - 1)) {
                 char *st = &line[7]; /* 7 from "%title " */
                 char *p1, *p2;
 
@@ -3607,8 +4069,6 @@ unsigned oid; /* book identifier */
                     if ((p2 = index(p1, ')')) != 0) {
                         *p2 = '\0';
                         passagecnt = atoi(p1);
-                        if (passagecnt > MAXPASSAGES)
-                            passagecnt = MAXPASSAGES;
                         scope = TITLESCOPE;
                         if (matchedsection && !strcmpi(st, tribtitle)) {
                             matchedtitle = TRUE;
@@ -3622,27 +4082,25 @@ unsigned oid; /* book identifier */
                     }
                 }
             } else if (!strncmpi(&line[1], "passage ",
-                                 sizeof("passage ") - 1)) {
+                                 sizeof "passage " - 1)) {
                 int passagenum = 0;
                 char *st = &line[9]; /* 9 from "%passage " */
 
-                while (*st == ' ' || *st == '\t')
-                    st++;
-                if (*st && digit(*st) && (strlen(st) < 3))
-                    passagenum = atoi(st);
-                if (passagenum && (passagenum <= passagecnt)) {
+                mungspaces(st);
+                passagenum = atoi(st);
+                if (passagenum > 0 && passagenum <= passagecnt) {
                     scope = PASSAGESCOPE;
-                    if (matchedtitle && (passagenum == targetpassage)) {
-                        if (!nowin_buf)
+                    if (matchedtitle && passagenum == targetpassage) {
+                        foundpassage = TRUE;
+                        if (!nowin_buf) {
                             tribwin = create_nhwindow(NHW_MENU);
-                        else
-                            foundpassage = TRUE;
+                            if (tribwin == WIN_ERR)
+                                goto cleanup;
+                        }
                     }
                 }
-            } else if (!strncmpi(&line[1], "e ", sizeof("e ") - 1)) {
-                if (matchedtitle && scope == PASSAGESCOPE
-                    && ((!nowin_buf && tribwin != WIN_ERR)
-                        || (nowin_buf && foundpassage)))
+            } else if (!strncmpi(&line[1], "e ", sizeof "e " - 1)) {
+                if (foundpassage)
                     goto cleanup;
                 if (scope == TITLESCOPE)
                     matchedtitle = FALSE;
@@ -3659,13 +4117,16 @@ unsigned oid; /* book identifier */
             /* comment only, next! */
             break;
         default:
-            if (matchedtitle && scope == PASSAGESCOPE) {
-                if (!nowin_buf && tribwin != WIN_ERR) {
+            if (foundpassage) {
+                if (!nowin_buf) {
+                    /* outputting multi-line passage to text window */
                     putstr(tribwin, 0, line);
-                    Strcpy(lastline, line);
-                } else if (nowin_buf) {
-                    if ((int) strlen(line) < bufsz - 1)
-                        Strcpy(nowin_buf, line);
+                    if (*line)
+                        Strcpy(lastline, line);
+                } else {
+                    /* fetching one-line passage into buffer */
+                    copynchars(nowin_buf, line, bufsz - 1);
+                    goto cleanup; /* don't wait for "%e passage" */
                 }
             }
         }
@@ -3673,29 +4134,33 @@ unsigned oid; /* book identifier */
 
 cleanup:
     (void) dlb_fclose(fp);
-    if (!nowin_buf && tribwin != WIN_ERR) {
-        if (matchedtitle && scope == PASSAGESCOPE) {
-            display_nhwindow(tribwin, FALSE);
-            /* put the final attribution line into message history,
-               analogous to the summary line from long quest messages */
-            if (index(lastline, '['))
-                mungspaces(lastline); /* to remove leading spaces */
-            else /* construct one if necessary */
-                Sprintf(lastline, "[%s, by Terry Pratchett]", tribtitle);
-            putmsghistory(lastline, FALSE);
-        }
-        destroy_nhwindow(tribwin);
-        tribwin = WIN_ERR;
-        grasped = TRUE;
+    if (nowin_buf) {
+        /* one-line buffer */
+        grasped = *nowin_buf ? TRUE : FALSE;
     } else {
-        if (!nowin_buf)
+        if (tribwin != WIN_ERR) { /* implies 'foundpassage' */
+            /* multi-line window, normal case;
+               if lastline is empty, there were no non-empty lines between
+               "%passage n" and "%e passage" so we leave 'grasped' False */
+            if (*lastline) {
+                display_nhwindow(tribwin, FALSE);
+                /* put the final attribution line into message history,
+                   analogous to the summary line from long quest messages */
+                if (index(lastline, '['))
+                    mungspaces(lastline); /* to remove leading spaces */
+                else /* construct one if necessary */
+                    Sprintf(lastline, "[%s, by Terry Pratchett]", tribtitle);
+                putmsghistory(lastline, FALSE);
+                grasped = TRUE;
+            }
+            destroy_nhwindow(tribwin);
+        }
+        if (!grasped)
+            /* multi-line window, problem */
 /*JP
             pline("It seems to be %s of \"%s\"!", badtranslation, tribtitle);
 */
             pline("\82±\82ê\82Í\81u%s\81v\82Ì%s\82Ì\82æ\82¤\82¾\81I", tribtitle, badtranslation);
-        else
-            if (foundpassage)
-                grasped = TRUE;
     }
     return grasped;
 }
index 775e798..a5ddf8a 100644 (file)
@@ -1,5 +1,5 @@
-/* NetHack 3.6 fountain.c      $NHDT-Date: 1444937416 2015/10/15 19:30:16 $  $NHDT-Branch: master $:$NHDT-Revision: 1.55 $ */
-/*     Copyright Scott R. Turner, srt@ucla, 10/27/86 */
+/* NetHack 3.6 fountain.c      $NHDT-Date: 1455402364 2016/02/13 22:26:04 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.56 $ */
+/*      Copyright Scott R. Turner, srt@ucla, 10/27/86 */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -243,6 +243,7 @@ boolean isyou;
                     continue;
                 if (is_watch(mtmp->data) && couldsee(mtmp->mx, mtmp->my)
                     && mtmp->mpeaceful) {
+                    if (!Deaf) {
 /*JP
                     pline("%s yells:", Amonnam(mtmp));
 */
@@ -251,6 +252,15 @@ boolean isyou;
                     verbalize("Hey, stop using that fountain!");
 */
                     verbalize("\82¨\82¢\81C\90ò\82ð\89\98\82·\82È\81I");
+                    } else {
+                        pline("%s earnestly %s %s %s!",
+                              Amonnam(mtmp),
+                              nolimbs(mtmp->data) ? "shakes" : "waves",
+                              mhis(mtmp),
+                              nolimbs(mtmp->data)
+                                      ? mbodypart(mtmp, HEAD)
+                                      : makeplural(mbodypart(mtmp, ARM)));
+                    }
                     break;
                 }
             }
@@ -449,6 +459,7 @@ drinkfountain()
                 dofindgem();
                 break;
             }
+            /*FALLTHRU*/
         case 28: /* Water Nymph */
             dowaternymph();
             break;
@@ -456,10 +467,13 @@ drinkfountain()
         {
             register struct monst *mtmp;
 
-/*JP
-            pline("This water gives you bad breath!");
-*/
-            pline("\90\85\82ð\88ù\82ñ\82¾\82ç\91§\82ª\8fL\82­\82È\82Á\82½\81I");
+#if 0 /*JP:T*/
+            pline("This %s gives you bad breath!",
+                  hliquid("water"));
+#else
+            pline("%s\82ð\88ù\82ñ\82¾\82ç\91§\82ª\8fL\82­\82È\82Á\82½\81I",
+                  hliquid("\90\85"));
+#endif
             for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
                 if (DEADMONSTER(mtmp))
                     continue;
@@ -471,10 +485,13 @@ drinkfountain()
             dogushforth(TRUE);
             break;
         default:
-/*JP
-            pline("This tepid water is tasteless.");
-*/
-            pline("\82±\82Ì\82È\82Ü\82Ê\82é\82¢\90\85\82Í\96¡\82ª\82È\82¢\81D");
+#if 0 /*JP*/
+            pline("This tepid %s is tasteless.",
+                  hliquid("water"));
+#else
+            pline("\82±\82Ì\82È\82Ü\82Ê\82é\82¢%s\82Í\96¡\82ª\82È\82¢\81D",
+                  hliquid("\90\85"));
+#endif
             break;
         }
     }
@@ -500,11 +517,13 @@ register struct obj *obj;
         && !exist_artifact(LONG_SWORD, artiname(ART_EXCALIBUR))) {
         if (u.ualign.type != A_LAWFUL) {
             /* Ha!  Trying to cheat her. */
-            pline(
-/*JP
-             "A freezing mist rises from the water and envelopes the sword.");
-*/
-             "\95X\82Ì\96\82ª\90\85\82©\82ç\97§\82¿\8f¸\82è\81C\8c\95\82ð\82Â\82Â\82ñ\82¾\81D");
+#if 0 /*JP*/
+            pline("A freezing mist rises from the %s and envelopes the sword.",
+                  hliquid("water"));
+#else
+            pline("\97â\82½\82¢\96\82ª%s\82©\82ç\97§\82¿\8f¸\82è\81C\8c\95\82ð\82Â\82Â\82ñ\82¾\81D",
+                  hliquid("\90\85"));
+#endif
 /*JP
             pline_The("fountain disappears!");
 */
@@ -564,9 +583,9 @@ register struct obj *obj;
         if (obj->cursed) {
             if (!Blind)
 /*JP
-                pline_The("water glows for a moment.");
+                pline_The("%s glows for a moment.", hliquid("water"));
 */
-                pline("\90\85\82Í\8bP\82«\82¾\82µ\82½\81D");
+                pline_The("%s\82Í\8bP\82«\82¾\82µ\82½\81D", hliquid("\90\85"));
             uncurse(obj);
         } else {
 /*JP
@@ -589,6 +608,7 @@ register struct obj *obj;
             dofindgem();
             break;
         }
+        /*FALLTHRU*/
     case 25: /* Water gushes forth */
         dogushforth(FALSE);
         break;
@@ -639,7 +659,7 @@ register struct obj *obj;
     case 29: /* You see coins */
         /* We make fountains have more coins the closer you are to the
          * surface.  After all, there will have been more people going
-         * by. Just like a shopping mall!  Chris Woodbury  */
+         * by.  Just like a shopping mall!  Chris Woodbury  */
 
         if (FOUNTAIN_IS_LOOTED(u.ux, u.uy))
             break;
@@ -648,10 +668,13 @@ register struct obj *obj;
                                    + 1) * 2) + 5),
                       u.ux, u.uy);
         if (!Blind)
-/*JP
-            pline("Far below you, you see coins glistening in the water.");
-*/
-            You("\97y\82©\89º\82Ì\90\85\92\86\82É\8bà\89Ý\82Ì\8bP\82«\82ð\82Ý\82Â\82¯\82½\81D");
+#if 0 /*JP:T*/
+            pline("Far below you, you see coins glistening in the %s.",
+                  hliquid("water"));
+#else
+            pline("\97y\82©\89º\82Å\81A%s\82Ì\92\86\82Å\8bà\89Ý\82ª\8bP\82¢\82Ä\82¢\82é\82Ì\82ð\82Ý\82Â\82¯\82½\81D",
+                  hliquid("\90\85"));
+#endif
         exercise(A_WIS, TRUE);
         newsym(u.ux, u.uy);
         break;
@@ -692,21 +715,21 @@ drinksink()
     switch (rn2(20)) {
     case 0:
 /*JP
-        You("take a sip of very cold water.");
+        You("take a sip of very cold %s.", hliquid("water"));
 */
-        You("\82Æ\82Ä\82à\97â\82½\82¢\90\85\82ð\88ê\8cû\88ù\82ñ\82¾\81D");
+        You("\82Æ\82Ä\82à\97â\82½\82¢%s\82ð\88ê\8cû\88ù\82ñ\82¾\81D", hliquid("\90\85"));
         break;
     case 1:
 /*JP
-        You("take a sip of very warm water.");
+        You("take a sip of very warm %s.", hliquid("water"));
 */
-        You("\82Æ\82Ä\82à\82 \82½\82½\82©\82¢\90\85\82ð\88ê\8cû\88ù\82ñ\82¾\81D");
+        You("\82Æ\82Ä\82à\82 \82½\82½\82©\82¢%s\82ð\88ê\8cû\88ù\82ñ\82¾\81D", hliquid("\90\85"));
         break;
     case 2:
 /*JP
-        You("take a sip of scalding hot water.");
+        You("take a sip of scalding hot %s.", hliquid("water"));
 */
-        You("\82Æ\82Ä\82à\94M\82¢\90\85\82ð\88ê\8cû\88ù\82ñ\82¾\81D");
+        You("\82Æ\82Ä\82à\94M\82¢%s\82ð\88ê\8cû\88ù\82ñ\82¾\81D", hliquid("\93\92"));
         if (Fire_resistance)
 /*JP
             pline("It seems quite tasty.");
@@ -774,18 +797,18 @@ drinksink()
             newsym(u.ux, u.uy);
         } else
 /*JP
-            pline("Some dirty water backs up in the drain.");
+            pline("Some dirty %s backs up in the drain.", hliquid("water"));
 */
-            pline("\89\98\90\85\82ª\94r\90\85\8cû\82©\82ç\8bt\97¬\82µ\82Ä\82«\82½\81D");
+            pline("\89\98\82¢%s\82ª\94r\90\85\8cû\82©\82ç\8bt\97¬\82µ\82Ä\82«\82½\81D", hliquid("\90\85"));
         break;
     case 6:
         breaksink(u.ux, u.uy);
         break;
     case 7:
 /*JP
-        pline_The("water moves as though of its own will!");
+        pline_The("%s moves as though of its own will!", hliquid("water"));
 */
-        pline("\90\85\82ª\88Ó\8ev\82ð\8e\9d\82Á\82Ä\82¢\82é\82©\82Ì\82æ\82¤\82É\93®\82¢\82½\81I");
+        pline_The("%s\82ª\88Ó\8ev\82ð\8e\9d\82Á\82Ä\82¢\82é\82©\82Ì\82æ\82¤\82É\93®\82¢\82½\81I", hliquid("\90\85"));
         if ((mvitals[PM_WATER_ELEMENTAL].mvflags & G_GONE)
             || !makemon(&mons[PM_WATER_ELEMENTAL], u.ux, u.uy, NO_MM_FLAGS))
 /*JP
@@ -795,9 +818,9 @@ drinksink()
         break;
     case 8:
 /*JP
-        pline("Yuk, this water tastes awful.");
+        pline("Yuk, this %s tastes awful.", hliquid("water"));
 */
-        pline("\83I\83F\81C\82Æ\82Ä\82à\82Ð\82Ç\82¢\96¡\82ª\82·\82é\81D");
+        pline("\83I\83F\81C\82±\82Ì%s\82Í\82Æ\82Ä\82à\82Ð\82Ç\82¢\96¡\82ª\82·\82é\81D", hliquid("\90\85"));
         more_experienced(1, 0);
         newexplevel();
         break;
@@ -811,9 +834,9 @@ drinksink()
         break;
     case 10:
 /*JP
-        pline("This water contains toxic wastes!");
+        pline("This %s contains toxic wastes!", hliquid("water"));
 */
-        pline("\82±\82Ì\90\85\82Í\97L\93Å\82È\94r\90\85\82ð\8aÜ\82ñ\82Å\82¢\82é\81I");
+        pline("\82±\82Ì%s\82Í\97L\93Å\82È\94p\8aü\95¨\82ð\8aÜ\82ñ\82Å\82¢\82é\81I", hliquid("\90\85"));
         if (!Unchanging) {
 /*JP
             You("undergo a freakish metamorphosis!");
@@ -843,13 +866,16 @@ drinksink()
             pline("\88Ã\82¢\94r\90\85\8cû\82©\82ç\81C\8eè\82ª\90L\82Ñ\82Ä\82«\82½\81D\81D--\82¨\82Á\82Æ--");
             break;
         }
+        /*FALLTHRU*/
     default:
 #if 0 /*JP*/
-        You("take a sip of %s water.",
-            rn2(3) ? (rn2(2) ? "cold" : "warm") : "hot");
+        You("take a sip of %s %s.",
+            rn2(3) ? (rn2(2) ? "cold" : "warm") : "hot",
+            hliquid("water"));
 #else
-        You("%s\90\85\82ð\88ê\8cû\88ù\82ñ\82¾\81D",
-            rn2(3) ? (rn2(2) ? "\97â\82½\82¢" : "\82 \82½\82½\82©\82¢") : "\94M\82¢");
+        You("%s%s\82ð\88ê\8cû\88ù\82ñ\82¾\81D",
+            rn2(3) ? (rn2(2) ? "\97â\82½\82¢" : "\82 \82½\82½\82©\82¢") : "\94M\82¢",
+            hliquid("\90\85"));
 #endif
     }
 }
index 1fa1774..360a6cb 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 hack.c  $NHDT-Date: 1446604111 2015/11/04 02:28:31 $  $NHDT-Branch: master $:$NHDT-Revision: 1.155 $ */
+/* NetHack 3.6 hack.c  $NHDT-Date: 1518861490 2018/02/17 09:58:10 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.182 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -15,7 +16,7 @@ STATIC_DCL void NDECL(maybe_wail);
 STATIC_DCL int NDECL(moverock);
 STATIC_DCL int FDECL(still_chewing, (XCHAR_P, XCHAR_P));
 STATIC_DCL void NDECL(dosinkfall);
-STATIC_DCL boolean FDECL(findtravelpath, (BOOLEAN_P));
+STATIC_DCL boolean FDECL(findtravelpath, (int));
 STATIC_DCL boolean FDECL(trapmove, (int, int, struct trap *));
 STATIC_DCL void NDECL(switch_terrain);
 STATIC_DCL struct monst *FDECL(monstinroom, (struct permonst *, int));
@@ -24,6 +25,11 @@ STATIC_DCL void FDECL(move_update, (BOOLEAN_P));
 
 #define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
 
+/* mode values for findtravelpath() */
+#define TRAVP_TRAVEL 0
+#define TRAVP_GUESS  1
+#define TRAVP_VALID  2
+
 static anything tmp_anything;
 
 anything *
@@ -166,12 +172,12 @@ moverock()
                                   || (ttmp->ttyp == SPIKED_PIT))))) {
                 if (Blind)
                     feel_location(sx, sy);
-                if (canspotmon(mtmp))
+                if (canspotmon(mtmp)) {
 /*JP
                     pline("There's %s on the other side.", a_monnam(mtmp));
 */
                     pline("\94½\91Î\91¤\82É%s\82ª\82¢\82é\81D", a_monnam(mtmp));
-                else {
+                else {
 /*JP
                     You_hear("a monster behind %s.", the(xname(otmp)));
 */
@@ -381,26 +387,41 @@ moverock()
                 feel_location(sx, sy);
         cannot_push:
             if (throws_rocks(youmonst.data)) {
+                boolean
+                    canpickup = (!Sokoban
+                                 /* similar exception as in can_lift():
+                                    when poly'd into a giant, you can
+                                    pick up a boulder if you have a free
+                                    slot or into the overflow ('#') slot
+                                    unless already carrying at least one */
+                              && (inv_cnt(FALSE) < 52 || !carrying(BOULDER))),
+                    willpickup = (canpickup && autopick_testobj(otmp, TRUE));
+
                 if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
 #if 0 /*JP*/
                     You("aren't skilled enough to %s %s from %s.",
-                        (flags.pickup && !Sokoban) ? "pick up" : "push aside",
+                        willpickup ? "pick up" : "push aside",
                         the(xname(otmp)), y_monnam(u.usteed));
 #else
                     You("%s\82É%s\82ð%s\82é\82Ù\82Ç\8bZ\97Ê\82ª\82È\82¢\81D",
-                        y_monnam(u.usteed),
-                        the(xname(otmp)), 
-                        (flags.pickup && !Sokoban) ? "\8fE\82í\82¹" : "\89\9f\82³\82¹");
+                        y_monnam(u.usteed), the(xname(otmp)), 
+                        willpickup ? "\8fE\82í\82¹" : "\89\9f\82³\82¹");
 #endif
                 } else {
+                    /*
+                     * willpickup:  you easily pick it up
+                     * canpickup:   you could easily pick it up
+                     * otherwise:   you easily push it aside
+                     */
 #if 0 /*JP*/
-                    pline("However, you can easily %s.",
-                          (flags.pickup && !Sokoban) ? "pick it up"
-                                                     : "push it aside");
+                    pline("However, you %seasily %s.",
+                          (willpickup || !canpickup) ? "" : "could ",
+                          (willpickup || canpickup) ? "pick it up"
+                                                    : "push it aside");
 #else
                     pline("\82µ\82©\82µ\81C\82 \82È\82½\82Í\8aÈ\92P\82É\82»\82ê\82ð%s\81D",
-                          (flags.pickup && !Sokoban)
-                          "\8fE\82¦\82½" : "\95Ê\82Ì\95û\82É\89\9f\82¹\82½");
+                          (willpickup || canpickup) ?
+                          "\8fE\82¦\82½" : "\95Ê\82Ì\95û\82É\89\9f\82¹\82½");
 #endif
                     sokoban_guilt();
                     break;
@@ -443,7 +464,7 @@ xchar x, y;
 
     if (context.digging.down) /* not continuing previous dig (w/ pick-axe) */
         (void) memset((genericptr_t) &context.digging, 0,
-                      sizeof(struct dig_info));
+                      sizeof (struct dig_info));
 
     if (!boulder && IS_ROCK(lev->typ) && !may_dig(x, y)) {
 #if 0 /*JP*/
@@ -485,7 +506,7 @@ xchar x, y;
                     ? "tree"
                     : IS_ROCK(lev->typ)
                         ? "rock"
-                        : lev->typ == IRONBARS
+                        : (lev->typ == IRONBARS)
                             ? "bar"
                             : "door");
 #else
@@ -561,13 +582,13 @@ xchar x, y;
             block_point(x, y); /* delobj will unblock the point */
             /* reset dig state */
             (void) memset((genericptr_t) &context.digging, 0,
-                          sizeof(struct dig_info));
+                          sizeof (struct dig_info));
             return 1;
         }
 
     } else if (IS_WALL(lev->typ)) {
         if (*in_rooms(x, y, SHOPBASE)) {
-            add_damage(x, y, 10L * ACURRSTR);
+            add_damage(x, y, SHOP_WALL_DMG);
 /*JP
             dmgtxt = "damage";
 */
@@ -615,7 +636,7 @@ xchar x, y;
 
     } else if (IS_DOOR(lev->typ)) {
         if (*in_rooms(x, y, SHOPBASE)) {
-            add_damage(x, y, 400L);
+            add_damage(x, y, SHOP_DOOR_COST);
 /*JP
             dmgtxt = "break";
 */
@@ -650,7 +671,7 @@ xchar x, y;
     if (dmgtxt)
         pay_for_damage(dmgtxt, FALSE);
     (void) memset((genericptr_t) &context.digging, 0,
-                  sizeof(struct dig_info));
+                  sizeof (struct dig_info));
     return 0;
 }
 
@@ -734,10 +755,10 @@ dosinkfall()
     /*
      * Interrupt multi-turn putting on/taking off of armor (in which
      * case we reached the sink due to being teleported while busy;
-     * in 3.4.3, Boots_on()/Boots_off() [called via (*aftermv)() when
+     * in 3.4.3, Boots_on()/Boots_off() [called via (*afternmv)() when
      * 'multi' reaches 0] triggered a crash if we were donning/doffing
      * levitation boots [because the Boots_off() below causes 'uarmf'
-     * to be null by the time 'aftermv' gets called]).
+     * to be null by the time 'afternmv' gets called]).
      *
      * Interrupt donning/doffing if we fall onto the sink, or if the
      * code below is going to remove levitation boots even when we
@@ -807,9 +828,10 @@ register xchar x, y;
 
 /* caller has already decided that it's a tight diagonal; check whether a
    monster--who might be the hero--can fit through, and if not then return
-   the reason why:  1: can't fit, 2: possessions won't fit, 3: sokoban */
-int /* returns 0 if we can squeeze through */
-    cant_squeeze_thru(mon)
+   the reason why:  1: can't fit, 2: possessions won't fit, 3: sokoban
+   returns 0 if we can squeeze through */
+int
+cant_squeeze_thru(mon)
 struct monst *mon;
 {
     int amt;
@@ -822,8 +844,8 @@ struct monst *mon;
         return 1;
 
     /* lugging too much junk? */
-    amt =
-        (mon == &youmonst) ? inv_weight() + weight_cap() : curr_mon_load(mon);
+    amt = (mon == &youmonst) ? inv_weight() + weight_cap()
+                             : curr_mon_load(mon);
     if (amt > 600)
         return 2;
 
@@ -844,7 +866,7 @@ xchar x, y;
 }
 
 /* return TRUE if (dx,dy) is an OK place to move
- * mode is one of DO_MOVE, TEST_MOVE or TEST_TRAV
+ * mode is one of DO_MOVE, TEST_MOVE, TEST_TRAV, or TEST_TRAP
  */
 boolean
 test_move(ux, uy, dx, dy, mode)
@@ -865,6 +887,14 @@ int mode;
             feel_location(x, y);
         if (Passes_walls && may_passwall(x, y)) {
             ; /* do nothing */
+        } else if (Underwater) {
+            /* note: if water_friction() changes direction due to
+               turbulence, new target destination will always be water,
+               so we won't get here, hence don't need to worry about
+               "there" being somewhere the player isn't sure of */
+            if (mode == DO_MOVE)
+                pline("There is an obstacle there.");
+            return FALSE;
         } else if (tmpr->typ == IRONBARS) {
             if ((dmgtype(youmonst.data, AD_RUST)
                  || dmgtype(youmonst.data, AD_CORR)) && mode == DO_MOVE
@@ -872,7 +902,7 @@ int mode;
                 return FALSE;
             }
             if (!(Passes_walls || passes_bars(youmonst.data))) {
-                if (iflags.mention_walls)
+                if (mode == DO_MOVE && iflags.mention_walls)
 /*JP
                     You("cannot pass through the bars.");
 */
@@ -891,9 +921,9 @@ int mode;
             return FALSE;
         } else {
             if (mode == DO_MOVE) {
-                if (Is_stronghold(&u.uz) && is_db_wall(x, y))
+                if (is_db_wall(x, y))
 /*JP
-                    pline_The("drawbridge is up!");
+                    pline("That drawbridge is up!");
 */
                     pline("\92µ\82Ë\8b´\82Í\8fã\82Á\82Ä\82¢\82é\81I");
                 /* sokoban restriction stays even after puzzle is solved */
@@ -904,10 +934,17 @@ int mode;
 */
                     pline_The("\91q\8cÉ\94Ô\82Ì\95Ç\82Í\82 \82È\82½\82Ì\94\\97Í\82É\92ï\8dR\82µ\82½\81D");
                 else if (iflags.mention_walls)
-/*JP
-                    pline("It's a wall.");
-*/
-                    pline("\82±\82ê\82Í\95Ç\82¾\81D");
+#if 0 /*JP:T*/
+                    pline("It's %s.",
+                          (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "a wall"
+                          : IS_TREE(tmpr->typ) ? "a tree"
+                          : "solid stone");
+#else
+                    pline("\82±\82ê\82Í%s\82¾\81D",
+                          (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "\95Ç"
+                          : IS_TREE(tmpr->typ) ? "\96Ø"
+                          : "\90Î");
+#endif
             }
             return FALSE;
         }
@@ -915,14 +952,18 @@ int mode;
         if (closed_door(x, y)) {
             if (Blind && mode == DO_MOVE)
                 feel_location(x, y);
-            if (Passes_walls)
+            if (Passes_walls) {
                 ; /* do nothing */
-            else if (can_ooze(&youmonst)) {
+            else if (can_ooze(&youmonst)) {
                 if (mode == DO_MOVE)
 /*JP
                     You("ooze under the door.");
 */
                     You("\83h\83A\82Ì\89º\82©\82ç\82É\82\82Ý\8fo\82½\81D");
+            } else if (Underwater) {
+                if (mode == DO_MOVE)
+                    pline("There is an obstacle there.");
+                return FALSE;
             } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
                 /* Eat the door. */
                 if (mode == DO_MOVE && still_chewing(x, y))
@@ -961,7 +1002,7 @@ int mode;
 */
                             pline("\94à\82Í\95Â\82Ü\82Á\82Ä\82¢\82é\81D");
                     }
-                } else if (mode == TEST_TRAV)
+                } else if (mode == TEST_TRAV || mode == TEST_TRAP)
                     goto testdiag;
                 return FALSE;
             }
@@ -970,8 +1011,12 @@ int mode;
             if (dx && dy && !Passes_walls
                 && (!doorless_door(x, y) || block_door(x, y))) {
                 /* Diagonal moves into a door are not allowed. */
-                if (Blind && mode == DO_MOVE)
-                    feel_location(x, y);
+                if (mode == DO_MOVE) {
+                    if (Blind)
+                        feel_location(x, y);
+                    if (Underwater || iflags.mention_walls)
+                        You_cant("move diagonally into an intact doorway.");
+                }
                 return FALSE;
             }
         }
@@ -1016,28 +1061,37 @@ int mode;
     /* Pick travel path that does not require crossing a trap.
      * Avoid water and lava using the usual running rules.
      * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
-    if (context.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) {
+    if (context.run == 8 && (mode != DO_MOVE)
+        && (x != u.ux || y != u.uy)) {
         struct trap *t = t_at(x, y);
 
         if ((t && t->tseen)
             || (!Levitation && !Flying && !is_clinger(youmonst.data)
                 && is_pool_or_lava(x, y) && levl[x][y].seenv))
-            return FALSE;
+            return (mode == TEST_TRAP);
     }
 
+    if (mode == TEST_TRAP)
+        return FALSE; /* do not move through traps */
+
     ust = &levl[ux][uy];
 
     /* Now see if other things block our way . . */
     if (dx && dy && !Passes_walls && IS_DOOR(ust->typ)
         && (!doorless_door(ux, uy) || block_entry(x, y))) {
         /* Can't move at a diagonal out of a doorway with door. */
+        if (mode == DO_MOVE && iflags.mention_walls)
+            You_cant("move diagonally out of an intact doorway.");
         return FALSE;
     }
 
     if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) {
         if (!(Blind || Hallucination) && (context.run >= 2)
-            && mode != TEST_TRAV)
+            && mode != TEST_TRAV) {
+            if (mode == DO_MOVE && iflags.mention_walls)
+                pline("A boulder blocks your path.");
             return FALSE;
+        }
         if (mode == DO_MOVE) {
             /* tunneling monsters will chew before pushing */
             if (tunnels(youmonst.data) && !needspick(youmonst.data)
@@ -1049,6 +1103,10 @@ int mode;
         } else if (mode == TEST_TRAV) {
             struct obj *obj;
 
+            /* never travel through boulders in Sokoban */
+            if (Sokoban)
+                return FALSE;
+
             /* don't pick two boulders in a row, unless there's a way thru */
             if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
                 if (!Passes_walls
@@ -1084,21 +1142,25 @@ int wiz_debug_cmd_traveldisplay()
  * Returns TRUE if a path was found.
  */
 STATIC_OVL boolean
-findtravelpath(guess)
-boolean guess;
+findtravelpath(mode)
+int mode;
 {
     /* if travel to adjacent, reachable location, use normal movement rules */
-    if (!guess && context.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1
+    if ((mode == TRAVP_TRAVEL || mode == TRAVP_VALID) && context.travel1
+        && distmin(u.ux, u.uy, u.tx, u.ty) == 1
         && !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
         context.run = 0;
         if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
-            u.dx = u.tx - u.ux;
-            u.dy = u.ty - u.uy;
-            nomul(0);
-            iflags.travelcc.x = iflags.travelcc.y = -1;
+            if (mode == TRAVP_TRAVEL) {
+                u.dx = u.tx - u.ux;
+                u.dy = u.ty - u.uy;
+                nomul(0);
+                iflags.travelcc.x = iflags.travelcc.y = -1;
+            }
             return TRUE;
         }
-        context.run = 8;
+        if (mode == TRAVP_TRAVEL)
+            context.run = 8;
     }
     if (u.tx != u.ux || u.ty != u.uy) {
         xchar travel[COLNO][ROWNO];
@@ -1114,7 +1176,7 @@ boolean guess;
          * goal is the position the player knows of, or might figure out
          * (couldsee) that is closest to the target on a straight path.
          */
-        if (guess) {
+        if (mode == TRAVP_GUESS || mode == TRAVP_VALID) {
             tx = u.ux;
             ty = u.uy;
             ux = u.tx;
@@ -1141,22 +1203,65 @@ boolean guess;
                 static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
                 /* no diagonal movement for grid bugs */
                 int dirmax = NODIAG(u.umonnum) ? 4 : 8;
+                boolean alreadyrepeated = FALSE;
 
                 for (dir = 0; dir < dirmax; ++dir) {
                     int nx = x + xdir[ordered[dir]];
                     int ny = y + ydir[ordered[dir]];
 
-                    if (!isok(nx, ny))
+                    /*
+                     * When guessing and trying to travel as close as possible
+                     * to an unreachable target space, don't include spaces
+                     * that would never be picked as a guessed target in the
+                     * travel matrix describing hero-reachable spaces.
+                     * This stops travel from getting confused and moving
+                     * the hero back and forth in certain degenerate
+                     * configurations of sight-blocking obstacles, e.g.
+                     *
+                     *  T         1. Dig this out and carry enough to not be
+                     *   ####       able to squeeze through diagonal gaps.
+                     *   #--.---    Stand at @ and target travel at space T.
+                     *    @.....
+                     *    |.....
+                     *
+                     *  T         2. couldsee() marks spaces marked a and x
+                     *   ####       as eligible guess spaces to move the hero
+                     *   a--.---    towards.  Space a is closest to T, so it
+                     *    @xxxxx    gets chosen.  Travel system moves @ right
+                     *    |xxxxx    to travel to space a.
+                     *
+                     *  T         3. couldsee() marks spaces marked b, c and x
+                     *   ####       as eligible guess spaces to move the hero
+                     *   a--c---    towards.  Since findtravelpath() is called
+                     *    b@xxxx    repeatedly during travel, it doesn't
+                     *    |xxxxx    remember that it wanted to go to space a,
+                     *              so in comparing spaces b and c, b is
+                     *              chosen, since it seems like the closest
+                     *              eligible space to T. Travel system moves @
+                     *              left to go to space b.
+                     *
+                     *            4. Go to 2.
+                     *
+                     * By limiting the travel matrix here, space a in the
+                     * example above is never included in it, preventing
+                     * the cycle.
+                     */
+                    if (!isok(nx, ny)
+                        || ((mode == TRAVP_GUESS) && !couldsee(nx, ny)))
                         continue;
                     if ((!Passes_walls && !can_ooze(&youmonst)
-                         && closed_door(x, y)) || sobj_at(BOULDER, x, y)) {
+                         && closed_door(x, y)) || sobj_at(BOULDER, x, y)
+                        || test_move(x, y, nx-x, ny-y, TEST_TRAP)) {
                         /* closed doors and boulders usually
                          * cause a delay, so prefer another path */
                         if (travel[x][y] > radius - 3) {
-                            travelstepx[1 - set][nn] = x;
-                            travelstepy[1 - set][nn] = y;
-                            /* don't change travel matrix! */
-                            nn++;
+                            if (!alreadyrepeated) {
+                                travelstepx[1 - set][nn] = x;
+                                travelstepy[1 - set][nn] = y;
+                                /* don't change travel matrix! */
+                                nn++;
+                                alreadyrepeated = TRUE;
+                            }
                             continue;
                         }
                     }
@@ -1164,15 +1269,15 @@ boolean guess;
                         && (levl[nx][ny].seenv
                             || (!Blind && couldsee(nx, ny)))) {
                         if (nx == ux && ny == uy) {
-                            if (!guess) {
+                            if (mode == TRAVP_TRAVEL || mode == TRAVP_VALID) {
                                 u.dx = x - ux;
                                 u.dy = y - uy;
-                                if (x == u.tx && y == u.ty) {
+                                if (mode == TRAVP_TRAVEL
+                                    && x == u.tx && y == u.ty) {
                                     nomul(0);
                                     /* reset run so domove run checks work */
                                     context.run = 8;
-                                    iflags.travelcc.x = iflags.travelcc.y =
-                                        -1;
+                                    iflags.travelcc.x = iflags.travelcc.y = -1;
                                 }
                                 return TRUE;
                             }
@@ -1208,7 +1313,7 @@ boolean guess;
         }
 
         /* if guessing, find best location in travel matrix and go there */
-        if (guess) {
+        if (mode == TRAVP_GUESS) {
             int px = tx, py = ty; /* pick location */
             int dist, nxtdist, d2, nd2;
 
@@ -1263,7 +1368,7 @@ boolean guess;
             uy = u.uy;
             set = 0;
             n = radius = 1;
-            guess = FALSE;
+            mode = TRAVP_TRAVEL;
             goto noguess;
         }
         return FALSE;
@@ -1276,6 +1381,27 @@ found:
     return FALSE;
 }
 
+boolean
+is_valid_travelpt(x,y)
+int x,y;
+{
+    int tx = u.tx;
+    int ty = u.ty;
+    boolean ret;
+    int g = glyph_at(x,y);
+    if (x == u.ux && y == u.uy)
+        return TRUE;
+    if (isok(x,y) && glyph_is_cmap(g) && S_stone == glyph_to_cmap(g)
+        && !levl[x][y].seenv)
+        return FALSE;
+    u.tx = x;
+    u.ty = y;
+    ret = findtravelpath(TRAVP_VALID);
+    u.tx = tx;
+    u.ty = ty;
+    return ret;
+}
+
 /* try to escape being stuck in a trapped state by walking out of it;
    return true iff moving should continue to intended destination
    (all failures and most successful escapes leave hero at original spot) */
@@ -1284,7 +1410,7 @@ trapmove(x, y, desttrap)
 int x, y;              /* targetted destination, <u.ux+u.dx,u.uy+u.dy> */
 struct trap *desttrap; /* nonnull if another trap at <x,y> */
 {
-    boolean anchored;
+    boolean anchored = FALSE;
     const char *predicament, *culprit;
     char *steedname = !u.usteed ? (char *) 0 : y_monnam(u.usteed);
 
@@ -1312,6 +1438,8 @@ struct trap *desttrap; /* nonnull if another trap at <x,y> */
         /* [why does diagonal movement give quickest escape?] */
         if ((u.dx && u.dy) || !rn2(5))
             u.utrap--;
+        if (!u.utrap)
+            goto wriggle_free;
         break;
     case TT_PIT:
         if (desttrap && desttrap->tseen
@@ -1381,15 +1509,21 @@ struct trap *desttrap; /* nonnull if another trap at <x,y> */
             if ((u.utrap & 0xff) == 0) {
                 u.utrap = 0;
                 if (u.usteed)
-/*JP
-                    You("lead %s to the edge of the lava.", steedname);
-*/
-                    You("%s\82ð\97n\8aâ\82Ì\92[\82Ü\82Å\93±\82¢\82½\81D", steedname);
+#if 0 /*JP:T*/
+                    You("lead %s to the edge of the %s.", steedname,
+                        hliquid("lava"));
+#else
+                    You("%s\82ð%s\82Ì\92[\82Ü\82Å\93±\82¢\82½\81D", steedname,
+                        hliquid("\97n\8aâ"));
+#endif
                 else
-/*JP
-                    You("pull yourself to the edge of the lava.");
-*/
-                    You("\97n\8aâ\82Ì\92[\82Ü\82Å\82©\82ë\82¤\82\82Ä\81C\82½\82Ç\82è\82Â\82¢\82½\81D");
+#if 0 /*JP:T*/
+                    You("pull yourself to the edge of the %s.",
+                        hliquid("lava"));
+#else
+                    You("%s\82Ì\92[\82Ü\82Å\82©\82ë\82¤\82\82Ä\81C\82½\82Ç\82è\82Â\82¢\82½\81D",
+                        hliquid("\97n\8aâ"));
+#endif
             }
         }
         u.umoved = TRUE;
@@ -1460,8 +1594,9 @@ struct trap *desttrap; /* nonnull if another trap at <x,y> */
                     Norep("\82 \82È\82½\82Í%s\82É%s\81D", culprit, predicament);
             }
         } else {
+wriggle_free:
             if (u.usteed)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 pline("%s finally %s free.", upstart(steedname),
                       !anchored ? "lurches" : "wrenches the ball");
 #else
@@ -1469,7 +1604,7 @@ struct trap *desttrap; /* nonnull if another trap at <x,y> */
                       !anchored ? "\82à\82ª\82¢\82Ä" : "\93S\8b\85\82ð\82à\82¬\8eæ\82Á\82Ä");
 #endif
             else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 You("finally %s free.",
                     !anchored ? "wriggle" : "wrench the ball");
 #else
@@ -1583,13 +1718,14 @@ domove()
         on_ice = !Levitation && is_ice(u.ux, u.uy);
         if (on_ice) {
             static int skates = 0;
+
             if (!skates)
                 skates = find_skates();
             if ((uarmf && uarmf->otyp == skates) || resists_cold(&youmonst)
                 || Flying || is_floater(youmonst.data)
-                || is_clinger(youmonst.data) || is_whirly(youmonst.data))
+                || is_clinger(youmonst.data) || is_whirly(youmonst.data)) {
                 on_ice = FALSE;
-            else if (!rn2(Cold_resistance ? 3 : 2)) {
+            else if (!rn2(Cold_resistance ? 3 : 2)) {
                 HFumbling |= FROMOUTSIDE;
                 HFumbling &= ~TIMEOUT;
                 HFumbling += 1; /* slip on next move */
@@ -1631,6 +1767,16 @@ domove()
             || (Blind && !Levitation && !Flying && !is_clinger(youmonst.data)
                 && is_pool_or_lava(x, y) && levl[x][y].seenv)) {
             if (context.run >= 2) {
+                if (iflags.mention_walls) {
+                    if (trap && trap->tseen) {
+                        int tt = what_trap(trap->ttyp);
+                        You("stop in front of %s.",
+                            an(defsyms[trap_to_defsym(tt)].explanation));
+                    } else if (is_pool_or_lava(x,y) && levl[x][y].seenv) {
+                        You("stop at the edge of the %s.",
+                            hliquid(is_pool(x,y) ? "water" : "lava"));
+                    }
+                }
                 nomul(0);
                 context.move = 0;
                 return;
@@ -1693,8 +1839,9 @@ domove()
         }
 
         mtmp = m_at(x, y);
-        if (mtmp) {
+        if (mtmp && !is_safepet(mtmp)) {
             /* Don't attack if you're running, and can see it */
+            /* It's fine to displace pets, though */
             /* We should never get here if forcefight */
             if (context.run && ((!Blind && mon_visible(mtmp)
                                  && ((mtmp->m_ap_type != M_AP_FURNITURE
@@ -1716,7 +1863,11 @@ domove()
 
     /* attack monster */
     if (mtmp) {
-        nomul(0);
+        /* don't stop travel when displacing pets; if the
+           displace fails for some reason, attack() in uhitm.c
+           will stop travel rather than domove */
+        if (!is_safepet(mtmp) || context.forcefight)
+            nomul(0);
         /* only attack if we know it's there */
         /* or if we used the 'F' command to fight blindly */
         /* or if it hides_under, in which case we call attack() to print
@@ -1732,12 +1883,13 @@ domove()
          * attack_check(), which still wastes a turn, but prints a
          * different message and makes the player remember the monster.
          */
-        if (context.nopick
+        if (context.nopick && !context.travel
             && (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))) {
             if (mtmp->m_ap_type && !Protection_from_shape_changers
                 && !sensemon(mtmp))
                 stumble_onto_mimic(mtmp);
             else if (mtmp->mpeaceful && !Hallucination)
+                /* m_monnam(): "dog" or "Fido", no "invisible dog" or "it" */
 /*JP
                 pline("Pardon me, %s.", m_monnam(mtmp));
 */
@@ -1759,6 +1911,20 @@ domove()
         }
     }
 
+    if (context.forcefight && levl[x][y].typ == IRONBARS && uwep) {
+        struct obj *obj = uwep;
+
+        if (breaktest(obj)) {
+            if (obj->quan > 1L)
+                obj = splitobj(obj, 1L);
+            else
+                setuwep((struct obj *)0);
+            freeinv(obj);
+        }
+        hit_bars(&obj, u.ux, u.uy, x, y, TRUE, TRUE);
+        return;
+    }
+
     /* specifying 'F' with no monster wastes a turn */
     if (context.forcefight
         /* remembered an 'I' && didn't use a move command */
@@ -1797,9 +1963,9 @@ domove()
         newsym(x, y);
         glyph = glyph_at(x, y); /* might have just changed */
 
-        if (boulder)
+        if (boulder) {
             Strcpy(buf, ansimpleoname(boulder));
-        else if (Underwater && !is_pool(x, y))
+        } else if (Underwater && !is_pool(x, y)) {
             /* Underwater, targetting non-water; the map just shows blank
                because you don't see remembered terrain while underwater;
                although the hero can attack an adjacent monster this way,
@@ -1813,33 +1979,30 @@ domove()
                              ? "\8bó\8bC\82Ì\96A"
                              : "\89½\82à\82È\82¢\82Æ\82±\82ë");
 #endif
-        else if (solid)
+        } else if (solid) {
             /* glyph might indicate unseen terrain if hero is blind;
                unlike searching, this won't reveal what that terrain is
                (except for solid rock, where the glyph would otherwise
                yield ludicrous "dark part of a room") */
 #if 0 /*JP*/
-            Strcpy(buf,
-                   (levl[x][y].typ == STONE)
-                       ? "solid rock"
-                       : glyph_is_cmap(glyph)
+            Strcpy(buf, (levl[x][y].typ == STONE) ? "solid rock"
+                         : glyph_is_cmap(glyph)
                             ? the(defsyms[glyph_to_cmap(glyph)].explanation)
                             : (const char *) "an unknown obstacle");
 #else
-            Strcpy(buf,
-                   (levl[x][y].typ == STONE)
-                       ? "\90Î"
-                       : glyph_is_cmap(glyph)
+            Strcpy(buf, (levl[x][y].typ == STONE) ? "\90Î"
+                         : glyph_is_cmap(glyph)
                             ? the(defsyms[glyph_to_cmap(glyph)].explanation)
                             : (const char *) "\95s\96¾\82È\8fá\8aQ\95¨");
 #endif
-        /* note: 'solid' is misleadingly named and catches pools
-           of water and lava as well as rock and walls */
-        else
+            /* note: 'solid' is misleadingly named and catches pools
+               of water and lava as well as rock and walls */
+        } else {
 /*JP
             Strcpy(buf, "thin air");
 */
             Strcpy(buf, "\89½\82à\82È\82¢\8bó\92\86");
+        }
 #if 0 /*JP*/
         You("%s%s %s.",
             !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
@@ -1858,10 +2021,7 @@ domove()
         }
         return;
     }
-    if (glyph_is_invisible(levl[x][y].glyph)) {
-        unmap_object(x, y);
-        newsym(x, y);
-    }
+    (void) unmap_invisible(x, y);
     /* not attacking an animal, so we try to move */
     if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
         nomul(0);
@@ -1930,20 +2090,30 @@ domove()
                 yelp(mtmp);
             }
         }
+
+        /* seemimic/newsym should be done before moving hero, otherwise
+           the display code will draw the hero here before we possibly
+           cancel the swap below (we can ignore steed mx,my here) */
+        u.ux = u.ux0, u.uy = u.uy0;
         mtmp->mundetected = 0;
         if (mtmp->m_ap_type)
             seemimic(mtmp);
         else if (!mtmp->mtame)
             newsym(mtmp->mx, mtmp->my);
+        u.ux = mtmp->mx, u.uy = mtmp->my; /* resume swapping positions */
 
         if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
             && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
             && sobj_at(BOULDER, trap->tx, trap->ty)) {
             /* can't swap places with pet pinned in a pit by a boulder */
             u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
+            if (u.usteed)
+                u.usteed->mx = u.ux, u.usteed->my = u.uy;
         } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
             /* can't swap places when pet can't move to your spot */
             u.ux = u.ux0, u.uy = u.uy0;
+            if (u.usteed)
+                u.usteed->mx = u.ux, u.usteed->my = u.uy;
 /*JP
             You("stop.  %s can't move diagonally.", upstart(y_monnam(mtmp)));
 */
@@ -1953,6 +2123,8 @@ domove()
                    && (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
             /* can't swap places when pet won't fit thru the opening */
             u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
+            if (u.usteed)
+                u.usteed->mx = u.ux, u.usteed->my = u.uy;
 /*JP
             You("stop.  %s won't fit through.", upstart(y_monnam(mtmp)));
 */
@@ -2034,8 +2206,8 @@ domove()
                 nomul(0);
     }
 
-    if (hides_under(youmonst.data) || (youmonst.data->mlet == S_EEL) || u.dx
-        || u.dy)
+    if (hides_under(youmonst.data) || youmonst.data->mlet == S_EEL
+        || u.dx || u.dy)
         (void) hideunder(&youmonst);
 
     /*
@@ -2061,7 +2233,8 @@ domove()
     if (Punished) /* put back ball and chain */
         move_bc(0, bc_control, ballx, bally, chainx, chainy);
 
-    spoteffects(TRUE);
+    if (u.umoved)
+        spoteffects(TRUE);
 
     /* delay next move because of ball dragging */
     /* must come after we finished picking up, in spoteffects() */
@@ -2203,8 +2376,7 @@ switch_terrain()
 }
 
 /* extracted from spoteffects; called by spoteffects to check for entering or
-   leaving a pool of water/lava, and by moveloop to check for staying on one
-
+   leaving a pool of water/lava, and by moveloop to check for staying on one;
    returns true to skip rest of spoteffects */
 boolean
 pooleffects(newspot)
@@ -2222,9 +2394,9 @@ boolean newspot;             /* true if called by spoteffects */
                 You("\82Ð\82å\82¢\82Æ\8bó\8bC\82Ì\96A\82É\93ü\82Á\82½\81D");
             else if (is_lava(u.ux, u.uy))
 #if 0 /*JP*/
-                You("leave the water..."); /* oops! */
+                You("leave the %s...", hliquid("water")); /* oops! */
 #else
-                You("\90\85\82©\82ç\94²\82¯\82¾\82µ\82½\81D\81D\81D");  /* oops! */
+                You("%s\90\85\82©\82ç\94²\82¯\82¾\82µ\82½\81D\81D\81D", hliquid("\90\85"));  /* oops! */
 #endif
             else
 #if 0 /*JP*/
@@ -2238,14 +2410,14 @@ boolean newspot;             /* true if called by spoteffects */
             still_inwater = TRUE;
         } else if (Levitation) {
 /*JP
-            You("pop out of the water like a cork!");
+            You("pop out of the %s like a cork!", hliquid("water"));
 */
-            You("\83R\83\8b\83N\82Ì\82æ\82¤\82É\94ò\82Ñ\82¾\82µ\82½\81I");
+            You("\83R\83\8b\83N\82Ì\82æ\82¤\82É%s\82©\82ç\94ò\82Ñ\82¾\82µ\82½\81I", hliquid("\90\85"));
         } else if (Flying) {
 /*JP
-            You("fly out of the water.");
+            You("fly out of the %s.", hliquid("water"));
 */
-            You("\90\85\82©\82ç\94ò\82Ñ\82¾\82µ\82½\81D");
+            You("%s\82©\82ç\94ò\82Ñ\82¾\82µ\82½\81D", hliquid("\90\85"));
         } else if (Wwalking) {
 /*JP
             You("slowly rise above the surface.");
@@ -2311,8 +2483,9 @@ boolean pick;
     static int spotterrain;
     static struct trap *spottrap = (struct trap *) 0;
     static unsigned spottraptyp = NO_TRAP;
+
+    struct monst *mtmp;
     struct trap *trap = t_at(u.ux, u.uy);
-    register struct monst *mtmp;
 
     /* prevent recursion from affecting the hero all over again
        [hero poly'd to iron golem enters water here, drown() inflicts
@@ -2345,8 +2518,8 @@ boolean pick;
            turn, allowing it to do so could give the perception
            that a trap here is being triggered twice, so adjust
            the timeout to prevent that */
-        if (trap && (HLevitation & TIMEOUT) == 1L && !ELevitation
-            && !(HLevitation & ~TIMEOUT)) {
+        if (trap && (HLevitation & TIMEOUT) == 1L
+            && !(ELevitation || (HLevitation & ~(I_SPECIAL | TIMEOUT)))) {
             if (rn2(2)) { /* defer timeout */
                 incr_itimeout(&HLevitation, 1L);
             } else { /* timeout early */
@@ -2359,22 +2532,22 @@ boolean pick;
             }
         }
         /*
-     * If not a pit, pickup before triggering trap.
-     * If pit, trigger trap before pickup.
-     */
+         * If not a pit, pickup before triggering trap.
+         * If pit, trigger trap before pickup.
+         */
         pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
         if (pick && !pit)
             (void) pickup(1);
 
         if (trap) {
             /*
-         * dotrap on a fire trap calls melt_ice() which triggers
-         * spoteffects() (again) which can trigger the same fire
-         * trap (again). Use static spottrap to prevent that.
-         * We track spottraptyp because some traps morph
-         * (landmine to pit) and any new trap type
-         * should get triggered.
-         */
+             * dotrap on a fire trap calls melt_ice() which triggers
+             * spoteffects() (again) which can trigger the same fire
+             * trap (again). Use static spottrap to prevent that.
+             * We track spottraptyp because some traps morph
+             * (landmine to pit) and any new trap type
+             * should get triggered.
+             */
             if (!spottrap || spottraptyp != trap->ttyp) {
                 spottrap = trap;
                 spottraptyp = trap->ttyp;
@@ -2400,10 +2573,11 @@ boolean pick;
 #endif
         };
         long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
+
         if (time_left && time_left < 15L)
-            pline1((time_left < 5L) ? icewarnings[2] : (time_left < 10L)
-                                                           ? icewarnings[1]
-                                                           : icewarnings[0]);
+            pline("%s", icewarnings[(time_left < 5L) ? 2
+                                    : (time_left < 10L) ? 1
+                                      0]);
     }
     if ((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
         mtmp->mundetected = mtmp->msleeping = 0;
@@ -2413,27 +2587,28 @@ boolean pick;
             pline("%s suddenly drops from the %s!", Amonnam(mtmp),
                   ceiling(u.ux, u.uy));
 #else
-            pline("%s\82ª\93Ë\91R%s\82©\82ç\97\8e\82¿\82Ä\82«\82½\81I",
-                  Amonnam(mtmp), ceiling(u.ux,u.uy));
+            pline("%s\82ª\93Ë\91R%s\82©\82ç\97\8e\82¿\82Ä\82«\82½\81I", Amonnam(mtmp),
+                  ceiling(u.ux,u.uy));
 #endif
-            if (mtmp->mtame) /* jumps to greet you, not attack */
+            if (mtmp->mtame) /* jumps to greet you, not attack */
                 ;
-            else if (uarmh && is_metallic(uarmh))
+            } else if (uarmh && is_metallic(uarmh)) {
 /*JP
                 pline("Its blow glances off your %s.",
 */
                 pline("\8dU\8c\82\82Í\82 \82È\82½\82Ì%s\82ð\82©\82·\82ß\82½\82¾\82¯\82¾\82Á\82½\81D",
                       helm_simple_name(uarmh));
-            else if (u.uac + 3 <= rnd(20))
-#if 0 /*JP*/
+            } else if (u.uac + 3 <= rnd(20)) {
+#if 0 /*JP:T*/
                 You("are almost hit by %s!",
                     x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
 #else
                 You("\97\8e\82¿\82Ä\82«\82½%s\82É\82à\82¤\8f­\82µ\82Å\93\96\82½\82é\82Æ\82±\82ë\82¾\82Á\82½\81D",
                     x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
 #endif
-            else {
+            else {
                 int dmg;
+
 #if 0 /*JP*/
                 You("are hit by %s!",
                     x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
@@ -2508,10 +2683,10 @@ register int typewanted;
     int typefound, min_x, min_y, max_x, max_y_offset, step;
     register struct rm *lev;
 
-#define goodtype(rno)                                               \
+#define goodtype(rno)   \
     (!typewanted                                                    \
-     || ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) \
-     || ((typewanted == SHOPBASE) && (typefound > SHOPBASE)))
+     || (typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted   \
+     || (typewanted == SHOPBASE && typefound > SHOPBASE))
 
     switch (rno = levl[x][y].roomno) {
     case NO_ROOM:
@@ -2546,19 +2721,19 @@ register int typewanted;
     for (x = min_x; x <= max_x; x += step) {
         lev = &levl[x][min_y];
         y = 0;
-        if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
+        if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
             && goodtype(rno))
             *(--ptr) = rno;
         y += step;
         if (y > max_y_offset)
             continue;
-        if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
+        if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
             && goodtype(rno))
             *(--ptr) = rno;
         y += step;
         if (y > max_y_offset)
             continue;
-        if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
+        if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
             && goodtype(rno))
             *(--ptr) = rno;
     }
@@ -2611,7 +2786,7 @@ register boolean newlev;
     Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
 
     for (ptr1 = &u.urooms[0], ptr2 = &u.uentered[0], ptr3 = &u.ushops[0],
-        ptr4 = &u.ushops_entered[0];
+         ptr4 = &u.ushops_entered[0];
          *ptr1; ptr1++) {
         if (!index(u.urooms0, *ptr1))
             *(ptr2++) = *ptr1;
@@ -2632,6 +2807,7 @@ register boolean newlev;
     *ptr2 = '\0';
 }
 
+/* possibly deliver a one-time room entry message */
 void
 check_special_room(newlev)
 register boolean newlev;
@@ -2807,11 +2983,13 @@ register boolean newlev;
     return;
 }
 
+/* the ',' command */
 int
 dopickup()
 {
-    int count;
+    int count, tmpcount;
     struct trap *traphere = t_at(u.ux, u.uy);
+
     /* awful kludge to work around parse()'s pre-decrement */
     count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
     multi = 0; /* always reset */
@@ -2837,17 +3015,20 @@ dopickup()
 #endif
             return 1;
         } else {
-            int tmpcount = -count;
+            tmpcount = -count;
             return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
         }
     }
     if (is_pool(u.ux, u.uy)) {
         if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
             || (Flying && !Breathless)) {
-/*JP
-            You("cannot dive into the water to pick things up.");
-*/
-            You("\95¨\82ð\8fE\82¢\82 \82°\82é\82½\82ß\82É\90\85\82É\94ò\82Ñ\82±\82ß\82È\82¢\81D");
+#if 0 /*JP:T*/
+            You("cannot dive into the %s to pick things up.",
+                hliquid("water"));
+#else
+            You("\95¨\82ð\8fE\82¢\82 \82°\82é\82½\82ß\82É%s\82É\94ò\82Ñ\82±\82ß\82È\82¢\81D",
+                hliquid("\90\85"));
+#endif
             return 0;
         } else if (!Underwater) {
 /*JP
@@ -2875,6 +3056,7 @@ dopickup()
     }
     if (!OBJ_AT(u.ux, u.uy)) {
         register struct rm *lev = &levl[u.ux][u.uy];
+
         if (IS_THRONE(lev->typ))
 /*JP
             pline("It must weigh%s a ton!", lev->looted ? " almost" : "");
@@ -2892,9 +3074,9 @@ dopickup()
             pline("\82 \82È\82½\82É\82Í\95æ\90Î\82Í\95s\97v\82¾\81D\81D\81D\8d¡\82Ì\82Æ\82±\82ë\81D");
         else if (IS_FOUNTAIN(lev->typ))
 /*JP
-            You("could drink the water...");
+            You("could drink the %s...", hliquid("water"));
 */
-            You("\90\85\82ð\88ù\82ß\82È\82¢\81D\81D\81D");
+            You("%s\82ð\88ù\82ß\82È\82¢\81D\81D\81D", hliquid("\90\85"));
         else if (IS_DOOR(lev->typ) && (lev->doormask & D_ISOPEN))
 /*JP
             pline("It won't come off the hinges.");
@@ -2937,14 +3119,16 @@ dopickup()
 void
 lookaround()
 {
-    register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
-    register int corrct = 0, noturn = 0;
-    register struct monst *mtmp;
-    register struct trap *trap;
+    register int x, y;
+    int i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
+    int corrct = 0, noturn = 0;
+    struct monst *mtmp;
+    struct trap *trap;
 
     /* Grid bugs stop if trying to move diagonal, even if blind.  Maybe */
     /* they polymorphed while in the middle of a long move. */
-    if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
+    if (NODIAG(u.umonnum) && u.dx && u.dy) {
+        You("cannot move diagonally.");
         nomul(0);
         return;
     }
@@ -2953,21 +3137,22 @@ lookaround()
         return;
     for (x = u.ux - 1; x <= u.ux + 1; x++)
         for (y = u.uy - 1; y <= u.uy + 1; y++) {
-            if (!isok(x, y))
+            if (!isok(x, y) || (x == u.ux && y == u.uy))
                 continue;
-
-            if (u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy)
-                continue;
-
-            if (x == u.ux && y == u.uy)
+            if (NODIAG(u.umonnum) && x != u.ux && y != u.uy)
                 continue;
 
-            if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
+            if ((mtmp = m_at(x, y)) != 0
+                && mtmp->m_ap_type != M_AP_FURNITURE
                 && mtmp->m_ap_type != M_AP_OBJECT
                 && (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
                 if ((context.run != 1 && !mtmp->mtame)
-                    || (x == u.ux + u.dx && y == u.uy + u.dy))
+                    || (x == u.ux + u.dx && y == u.uy + u.dy
+                        && !context.travel)) {
+                    if (iflags.mention_walls)
+                        pline("%s blocks your path.", upstart(a_monnam(mtmp)));
                     goto stop;
+                }
             }
 
             if (levl[x][y].typ == STONE)
@@ -2975,15 +3160,17 @@ lookaround()
             if (x == u.ux - u.dx && y == u.uy - u.dy)
                 continue;
 
-            if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM)
-                || IS_AIR(levl[x][y].typ))
+            if (IS_ROCK(levl[x][y].typ) || levl[x][y].typ == ROOM
+                || IS_AIR(levl[x][y].typ)) {
                 continue;
-            else if (closed_door(x, y)
-                     || (mtmp && is_door_mappear(mtmp))) {
+            } else if (closed_door(x, y) || (mtmp && is_door_mappear(mtmp))) {
                 if (x != u.ux && y != u.uy)
                     continue;
-                if (context.run != 1)
+                if (context.run != 1) {
+                    if (iflags.mention_walls)
+                        You("stop in front of the door.");
                     goto stop;
+                }
                 goto bcorr;
             } else if (levl[x][y].typ == CORR) {
             bcorr:
@@ -3008,20 +3195,30 @@ lookaround()
             } else if ((trap = t_at(x, y)) && trap->tseen) {
                 if (context.run == 1)
                     goto bcorr; /* if you must */
-                if (x == u.ux + u.dx && y == u.uy + u.dy)
+                if (x == u.ux + u.dx && y == u.uy + u.dy) {
+                    if (iflags.mention_walls) {
+                        int tt = what_trap(trap->ttyp);
+                        You("stop in front of %s.",
+                            an(defsyms[trap_to_defsym(tt)].explanation));
+                    }
                     goto stop;
+                }
                 continue;
             } else if (is_pool_or_lava(x, y)) {
                 /* water and lava only stop you if directly in front, and stop
                  * you even if you are running
                  */
                 if (!Levitation && !Flying && !is_clinger(youmonst.data)
-                    && x == u.ux + u.dx && y == u.uy + u.dy)
+                    && x == u.ux + u.dx && y == u.uy + u.dy) {
                     /* No Wwalking check; otherwise they'd be able
                      * to test boots by trying to SHIFT-direction
                      * into a pool and seeing if the game allowed it
                      */
+                    if (iflags.mention_walls)
+                        You("stop at the edge of the %s.",
+                            hliquid(is_pool(x,y) ? "water" : "lava"));
                     goto stop;
+                }
                 continue;
             } else { /* e.g. objects or trap or stairs */
                 if (context.run == 1)
@@ -3039,8 +3236,11 @@ lookaround()
             return;
         } /* end for loops */
 
-    if (corrct > 1 && context.run == 2)
+    if (corrct > 1 && context.run == 2) {
+        if (iflags.mention_walls)
+            pline_The("corridor widens here.");
         goto stop;
+    }
     if ((context.run == 1 || context.run == 3 || context.run == 8) && !noturn
         && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) {
         /* make sure that we do not turn too far */
@@ -3124,9 +3324,7 @@ monster_nearby()
     /* Also see the similar check in dochugw() in monmove.c */
     for (x = u.ux - 1; x <= u.ux + 1; x++)
         for (y = u.uy - 1; y <= u.uy + 1; y++) {
-            if (!isok(x, y))
-                continue;
-            if (x == u.ux && y == u.uy)
+            if (!isok(x, y) || (x == u.ux && y == u.uy))
                 continue;
             if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
                 && mtmp->m_ap_type != M_AP_OBJECT
@@ -3169,9 +3367,13 @@ const char *msg_override;
     nomovemsg = 0;
     u.usleep = 0;
     multi_reason = NULL;
-    if (afternmv)
-        (*afternmv)();
-    afternmv = 0;
+    if (afternmv) {
+        int NDECL((*f)) = afternmv;
+        /* clear afternmv before calling it (to override the
+           encumbrance hack for levitation--see weight_cap()) */
+        afternmv = (int NDECL((*))) 0;
+        (void) (*f)();
+    }
 }
 
 STATIC_OVL void
@@ -3207,9 +3409,9 @@ maybe_wail()
                     ++powercnt;
 
 /*JP
-            pline(powercnt >= 4 ? "%s, all your powers will be lost..."
+            pline((powercnt >= 4) ? "%s, all your powers will be lost..."
 */
-            pline(powercnt >= 4 ? "%s\81C\82 \82È\82½\82Ì\91S\82Ä\82Ì\97Í\82Í\8e¸\82í\82ê\82Â\82Â\82 \82é\81D\81D\81D"
+            pline((powercnt >= 4) ? "%s\81C\82 \82È\82½\82Ì\91S\82Ä\82Ì\97Í\82Í\8e¸\82í\82ê\82Â\82Â\82 \82é\81D\81D\81D"
 /*JP
                                 : "%s, your life force is running out.",
 */
@@ -3249,6 +3451,8 @@ boolean k_format;
     u.uhp -= n;
     if (u.uhp > u.uhpmax)
         u.uhpmax = u.uhp; /* perhaps n was negative */
+    else
+        context.travel = context.travel1 = context.mv = context.run = 0;
     context.botl = 1;
     if (u.uhp < 1) {
         killer.format = k_format;
@@ -3267,7 +3471,16 @@ boolean k_format;
 int
 weight_cap()
 {
-    register long carrcap;
+    long carrcap, save_ELev = ELevitation;
+
+    /* boots take multiple turns to wear but any properties they
+       confer are enabled at the start rather than the end; that
+       causes message sequencing issues for boots of levitation
+       so defer their encumbrance benefit until they're fully worn */
+    if (afternmv == Boots_on && (ELevitation & W_ARMF) != 0L) {
+        ELevitation &= ~W_ARMF;
+        float_vs_flight(); /* in case Levitation is blocking Flying */
+    }
 
     carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50;
     if (Upolyd) {
@@ -3283,9 +3496,9 @@ weight_cap()
     }
 
     if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
-        || (u.usteed && strongmonst(u.usteed->data)))
+        || (u.usteed && strongmonst(u.usteed->data))) {
         carrcap = MAX_CARR_CAP;
-    else {
+    else {
         if (carrcap > MAX_CARR_CAP)
             carrcap = MAX_CARR_CAP;
         if (!Flying) {
@@ -3297,6 +3510,12 @@ weight_cap()
         if (carrcap < 0)
             carrcap = 0;
     }
+
+    if (ELevitation != save_ELev) {
+        ELevitation = save_ELev;
+        float_vs_flight();
+    }
+
     return (int) carrcap;
 }
 
@@ -3386,7 +3605,7 @@ boolean incl_gold;
 }
 
 /* Counts the money in an object chain. */
-/* Intended use is for your or some monsters inventory, */
+/* Intended use is for your or some monster's inventory, */
 /* now that u.gold/m.gold is gone.*/
 /* Counting money in a container might be possible too. */
 long
index 4259f53..30b3857 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 hacklib.c       $NHDT-Date: 1446336792 2015/11/01 00:13:12 $  $NHDT-Branch: master $:$NHDT-Revision: 1.44 $ */
+/* NetHack 3.6 hacklib.c       $NHDT-Date: 1518922474 2018/02/18 02:54:34 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.54 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2007. */
 /* Copyright (c) Robert Patrick Rankin, 1991                      */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -23,6 +24,9 @@
         char *          ucase           (char *)
         char *          upstart         (char *)
         char *          mungspaces      (char *)
+        char *          trimspaces      (char *)
+        char *          strip_newline   (char *)
+        char *          stripchars      (char *, const char *, const char *)
         char *          eos             (char *)
         boolean         str_end_is      (const char *, const char *)
         char *          strkitten       (char *,char)
@@ -36,6 +40,7 @@
         char *          tabexpand       (char *)
         char *          visctrl         (char)
         char *          strsubst        (char *, const char *, const char *)
+        int             strNsubst       (char *,const char *,const char *,int)
         const char *    ordin           (int)
         char *          sitoa           (int)
         int             sgn             (int)
@@ -48,7 +53,7 @@
         boolean         pmatchz         (const char *, const char *)
         int             strncmpi        (const char *, const char *, int)
         char *          strstri         (const char *, const char *)
-        boolean         fuzzymatch      (const char *,const char *,
+        boolean         fuzzymatch      (const char *, const char *,
                                          const char *, boolean)
         void            setrandom       (void)
         time_t          getnow          (void)
         boolean         friday_13th     (void)
         int             night           (void)
         int             midnight        (void)
+        void            strbuf_init     (strbuf *, const char *)
+        void            strbuf_append   (strbuf *, const char *)
+        void            strbuf_reserve  (strbuf *, int)
+        void            strbuf_empty    (strbuf *)
+        void            strbuf_nl_to_crlf (strbuf_t *)
 =*/
 #ifdef LINT
 #define Static /* pacify lint */
@@ -169,6 +179,37 @@ char *bp;
     return bp;
 }
 
+/* remove leading and trailing whitespace, in place */
+char*
+trimspaces(txt)
+char* txt;
+{
+    char* end;
+
+    while (*txt == ' ' || *txt == '\t')
+        txt++;
+    end = eos(txt);
+    while (--end >= txt && (*end == ' ' || *end == '\t'))
+        *end = '\0';
+
+    return txt;
+}
+
+/* remove \n from end of line; remove \r too if one is there */
+char *
+strip_newline(str)
+char *str;
+{
+    char *p = rindex(str, '\n');
+
+    if (p) {
+        if (p > str && *(p - 1) == '\r')
+            --p;
+        *p = '\0';
+    }
+    return str;
+}
+
 /* return the end of a string (pointing at '\0') */
 char *
 eos(s)
@@ -276,7 +317,7 @@ const char *s;
     Static char buf[BUFSZ];
 
     Strcpy(buf, s);
-#if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\8f\8a\97L\8ai\82Ìs\82ð\95t\82¯\82È\82¢*/
+#if 0 /*JP*/
     if (!strcmpi(buf, "it")) /* it -> its */
         Strcat(buf, "s");
     else if (!strcmpi(buf, "you")) /* you -> your */
@@ -285,6 +326,8 @@ const char *s;
         Strcat(buf, "'");
     else /* X -> X's */
         Strcat(buf, "'s");
+#else /* X -> X\82Ì */
+    Strcat(buf, "\82Ì");
 #endif
     return buf;
 }
@@ -294,7 +337,7 @@ char *
 ing_suffix(s)
 const char *s;
 {
-    const char *vowel = "aeiouy";
+    static const char vowel[] = "aeiouwy";
     static char buf[BUFSZ];
     char onoff[10];
     char *p;
@@ -302,21 +345,22 @@ const char *s;
     Strcpy(buf, s);
     p = eos(buf);
     onoff[0] = *p = *(p + 1) = '\0';
-    if ((strlen(buf) > 4)
-        && (!strcmpi(p - 3, " on") || !strcmpi(p - 4, " off")
-            || !strcmpi(p - 5, " with"))) {
-        p = strrchr(buf, ' ');
+    if ((p >= &buf[3] && !strcmpi(p - 3, " on"))
+        || (p >= &buf[4] && !strcmpi(p - 4, " off"))
+        || (p >= &buf[5] && !strcmpi(p - 5, " with"))) {
+        p = rindex(buf, ' ');
         Strcpy(onoff, p);
+        *p = '\0';
     }
-    if (!index(vowel, *(p - 1)) && index(vowel, *(p - 2))
-        && !index(vowel, *(p - 3))) {
+    if (p >= &buf[3] && !index(vowel, *(p - 1))
+        && index(vowel, *(p - 2)) && !index(vowel, *(p - 3))) {
         /* tip -> tipp + ing */
         *p = *(p - 1);
         *(p + 1) = '\0';
-    } else if (!strcmpi(p - 2, "ie")) { /* vie -> vy + ing */
+    } else if (p >= &buf[2] && !strcmpi(p - 2, "ie")) { /* vie -> vy + ing */
         *(p - 2) = 'y';
         *(p - 1) = '\0';
-    } else if (*(p - 1) == 'e') /* grease -> greas + ing */
+    } else if (p >= &buf[1] && *(p - 1) == 'e') /* grease -> greas + ing */
         *(p - 1) = '\0';
     Strcat(buf, "ing");
     if (onoff[0])
@@ -381,28 +425,61 @@ char *sbuf;
     return strcpy(sbuf, buf);
 }
 
+#define VISCTRL_NBUF 5
 /* make a displayable string from a character */
 char *
 visctrl(c)
 char c;
 {
-    Static char ccc[3];
-
+    Static char visctrl_bufs[VISCTRL_NBUF][5];
+    static int nbuf = 0;
+    register int i = 0;
+    char *ccc = visctrl_bufs[nbuf];
+    nbuf = (nbuf + 1) % VISCTRL_NBUF;
+
+    if ((uchar) c & 0200) {
+        ccc[i++] = 'M';
+        ccc[i++] = '-';
+    }
     c &= 0177;
-    ccc[2] = '\0';
     if (c < 040) {
-        ccc[0] = '^';
-        ccc[1] = c | 0100; /* letter */
+        ccc[i++] = '^';
+        ccc[i++] = c | 0100; /* letter */
     } else if (c == 0177) {
-        ccc[0] = '^';
-        ccc[1] = c & ~0100; /* '?' */
+        ccc[i++] = '^';
+        ccc[i++] = c & ~0100; /* '?' */
     } else {
-        ccc[0] = c; /* printable character */
-        ccc[1] = '\0';
+        ccc[i++] = c; /* printable character */
     }
+    ccc[i] = '\0';
     return ccc;
 }
 
+/* strip all the chars in stuff_to_strip from orig */
+/* caller is responsible for ensuring that bp is a
+   valid pointer to a BUFSZ buffer */
+char *
+stripchars(bp, stuff_to_strip, orig)
+char *bp;
+const char *stuff_to_strip, *orig;
+{
+    int i = 0;
+    char *s = bp;
+
+    if (s) {
+        while (*orig && i < (BUFSZ - 1)) {
+            if (!index(stuff_to_strip, *orig)) {
+                *s++ = *orig;
+                i++;
+            }
+            orig++;
+        }
+        *s = '\0';
+    } else
+        impossible("no output buf in stripchars");
+    return bp;
+}
+
 /* substitute a word or phrase in a string (in place) */
 /* caller is responsible for ensuring that bp points to big enough buffer */
 char *
@@ -413,6 +490,7 @@ const char *orig, *replacement;
     char *found, buf[BUFSZ];
 
     if (bp) {
+        /* [this could be replaced by strNsubst(bp, orig, replacement, 1)] */
         found = strstr(bp, orig);
         if (found) {
             Strcpy(buf, found + strlen(orig));
@@ -423,6 +501,52 @@ const char *orig, *replacement;
     return bp;
 }
 
+/* substitute the Nth occurrence of a substring within a string (in place);
+   if N is 0, substitute all occurrences; returns the number of subsitutions;
+   maximum output length is BUFSZ (BUFSZ-1 chars + terminating '\0') */
+int
+strNsubst(inoutbuf, orig, replacement, n)
+char *inoutbuf; /* current string, and result buffer */
+const char *orig, /* old substring; if "" then insert in front of Nth char */
+           *replacement; /* new substring; if "" then delete old substring */
+int n; /* which occurrence to replace; 0 => all */
+{
+    char *bp, *op, workbuf[BUFSZ];
+    const char *rp;
+    unsigned len = (unsigned) strlen(orig);
+    int ocount = 0, /* number of times 'orig' has been matched */
+        rcount = 0; /* number of subsitutions made */
+
+    for (bp = inoutbuf, op = workbuf; *bp && op < &workbuf[BUFSZ - 1]; ) {
+        if ((!len || !strncmp(bp, orig, len)) && (++ocount == n || n == 0)) {
+            /* Nth match found */
+            for (rp = replacement; *rp && op < &workbuf[BUFSZ - 1]; )
+                *op++ = *rp++;
+            ++rcount;
+            if (len) {
+                bp += len; /* skip 'orig' */
+                continue;
+            }
+        }
+        /* no match (or len==0) so retain current character */
+        *op++ = *bp++;
+    }
+    if (!len && n == ocount + 1) {
+        /* special case: orig=="" (!len) and n==strlen(inoutbuf)+1,
+           insert in front of terminator (in other words, append);
+           [when orig=="", ocount will have been incremented once for
+           each input char] */
+        for (rp = replacement; *rp && op < &workbuf[BUFSZ - 1]; )
+            *op++ = *rp++;
+        ++rcount;
+    }
+    if (rcount) {
+        *op = '\0';
+        Strcpy(inoutbuf, workbuf);
+    }
+    return rcount;
+}
+
 /* return the ordinal suffix of a number */
 const char *
 ordin(n)
@@ -998,4 +1122,83 @@ midnight()
     return (getlt()->tm_hour == 0);
 }
 
+/* strbuf_init() initializes strbuf state for use */
+void
+strbuf_init(strbuf)
+strbuf_t *strbuf;
+{
+    strbuf->str = NULL;
+    strbuf->len = 0;
+}
+
+/* strbuf_append() appends given str to strbuf->str */
+void
+strbuf_append(strbuf, str)
+strbuf_t *strbuf;
+const char *str;
+{
+    int len = (int) strlen(str) + 1;
+
+    strbuf_reserve(strbuf,
+                   len + (strbuf->str ? (int) strlen(strbuf->str) : 0));
+    Strcat(strbuf->str, str);
+}
+
+/* strbuf_reserve() ensure strbuf->str has storage for len characters */
+void
+strbuf_reserve(strbuf, len)
+strbuf_t *strbuf;
+int len;
+{
+    if (strbuf->str == NULL) {
+        strbuf->str = strbuf->buf;
+        strbuf->str[0] = '\0';
+        strbuf->len = (int) sizeof strbuf->buf;
+    }
+
+    if (len > strbuf->len) {
+        char *oldbuf = strbuf->str;
+
+        strbuf->len = len + (int) sizeof strbuf->buf;
+        strbuf->str = (char *) alloc(strbuf->len);
+        Strcpy(strbuf->str, oldbuf);
+        if (oldbuf != strbuf->buf)
+            free((genericptr_t) oldbuf);
+    }
+}
+
+/* strbuf_empty() frees allocated memory and set strbuf to initial state */
+void
+strbuf_empty(strbuf)
+strbuf_t *strbuf;
+{
+    if (strbuf->str != NULL && strbuf->str != strbuf->buf)
+        free((genericptr_t) strbuf->str);
+    strbuf_init(strbuf);
+}
+
+/* strbuf_nl_to_crlf() converts all occurences of \n to \r\n */
+void
+strbuf_nl_to_crlf(strbuf)
+strbuf_t *strbuf;
+{
+    if (strbuf->str) {
+        int len = (int) strlen(strbuf->str);
+        int count = 0;
+        char *cp = strbuf->str;
+
+        while (*cp)
+            if (*cp++ == '\n')
+                count++;
+        if (count) {
+            strbuf_reserve(strbuf, len + count + 1);
+            for (cp = strbuf->str + len + count; count; --cp)
+                if ((*cp = cp[-count]) == '\n') {
+                    *--cp = '\r';
+                    --count;
+                }
+        }
+    }
+}
+
 /*hacklib.c*/
index eebb0f1..dbbeb6c 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 invent.c        $NHDT-Date: 1447576348 2015/11/15 08:32:28 $  $NHDT-Branch: master $:$NHDT-Revision: 1.179 $ */
+/* NetHack 3.6 invent.c        $NHDT-Date: 1519672703 2018/02/26 19:18:23 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.225 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 
 #define NOINVSYM '#'
 #define CONTAINED_SYM '>' /* designator for inside a container */
+#define HANDS_SYM '-'
 
-STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (struct obj *, struct obj *));
+STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (const genericptr,
+                                               const genericptr));
 STATIC_DCL void NDECL(reorder_invent);
-STATIC_DCL boolean FDECL(mergable, (struct obj *, struct obj *));
 STATIC_DCL void FDECL(noarmor, (BOOLEAN_P));
 STATIC_DCL void FDECL(invdisp_nothing, (const char *, const char *));
 STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *));
 STATIC_DCL boolean FDECL(only_here, (struct obj *));
 STATIC_DCL void FDECL(compactify, (char *));
-STATIC_DCL boolean FDECL(splittable, (struct obj *));
 STATIC_DCL boolean FDECL(taking_off, (const char *));
 STATIC_DCL boolean FDECL(putting_on, (const char *));
 STATIC_PTR int FDECL(ckunpaid, (struct obj *));
 STATIC_PTR int FDECL(ckvalidcat, (struct obj *));
 STATIC_PTR char *FDECL(safeq_xprname, (struct obj *));
 STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
-STATIC_DCL char FDECL(display_pickinv, (const char *, BOOLEAN_P, long *));
+STATIC_DCL char FDECL(display_pickinv, (const char *, const char *,
+                                        const char *, BOOLEAN_P, long *));
 STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
-STATIC_DCL void FDECL(tally_BUCX,
-                      (struct obj *, int *, int *, int *, int *, int *));
 STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
 STATIC_DCL void NDECL(dounpaid);
 STATIC_DCL struct obj *FDECL(find_unpaid, (struct obj *, struct obj **));
@@ -51,96 +51,207 @@ static int lastinvnr = 51; /* 0 ... 51 (never saved&restored) */
  */
 static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
 
+struct sortloot_item {
+    struct obj *obj;
+    int indx;
+};
+unsigned sortlootmode = 0;
+
+/* qsort comparison routine for sortloot() */
 STATIC_OVL int CFDECLSPEC
-sortloot_cmp(obj1, obj2)
-struct obj *obj1;
-struct obj *obj2;
+sortloot_cmp(vptr1, vptr2)
+const genericptr vptr1;
+const genericptr vptr2;
 {
-    int val1 = 0;
-    int val2 = 0;
-
-    /* Sort object names in lexicographical order, ignoring quantity. */
-    int name_cmp = strcmpi(cxname_singular(obj1), cxname_singular(obj2));
-
-    if (name_cmp != 0) {
-        return name_cmp;
+    struct sortloot_item *sli1 = (struct sortloot_item *) vptr1,
+                         *sli2 = (struct sortloot_item *) vptr2;
+    struct obj *obj1 = sli1->obj,
+               *obj2 = sli2->obj,
+               sav1, sav2;
+    char *cls1, *cls2, nam1[BUFSZ], nam2[BUFSZ];
+    int val1, val2, c, namcmp;
+
+    /* order by object class like inventory display */
+    if ((sortlootmode & SORTLOOT_PACK) != 0) {
+        cls1 = index(flags.inv_order, obj1->oclass);
+        cls2 = index(flags.inv_order, obj2->oclass);
+        if (cls1 != cls2)
+            return (int) (cls1 - cls2);
+
+        if ((sortlootmode & SORTLOOT_INVLET) != 0) {
+            ; /* skip sub-classes when sorting by packorder+invlet */
+
+        /* for armor, group by sub-category */
+        } else if (obj1->oclass == ARMOR_CLASS) {
+            static int armcat[7 + 1];
+
+            if (!armcat[7]) {
+                /* one-time init; we want to control the order */
+                armcat[ARM_HELM]   = 1; /* [2] */
+                armcat[ARM_GLOVES] = 2; /* [3] */
+                armcat[ARM_BOOTS]  = 3; /* [4] */
+                armcat[ARM_SHIELD] = 4; /* [1] */
+                armcat[ARM_CLOAK]  = 5; /* [5] */
+                armcat[ARM_SHIRT]  = 6; /* [6] */
+                armcat[ARM_SUIT]   = 7; /* [0] */
+                armcat[7]          = 8;
+            }
+            val1 = armcat[objects[obj1->otyp].oc_armcat];
+            val2 = armcat[objects[obj2->otyp].oc_armcat];
+            if (val1 != val2)
+                return val1 - val2;
+
+        /* for weapons, group by ammo (arrows, bolts), launcher (bows),
+           missile (dart, boomerang), stackable (daggers, knives, spears),
+           'other' (swords, axes, &c), polearm */
+        } else if (obj1->oclass == WEAPON_CLASS) {
+            val1 = objects[obj1->otyp].oc_skill;
+            val1 = (val1 < 0)
+                    ? (val1 >= -P_CROSSBOW && val1 <= -P_BOW) ? 1 : 3
+                    : (val1 >= P_BOW && val1 <= P_CROSSBOW) ? 2
+                       : (val1 == P_SPEAR || val1 == P_DAGGER
+                          || val1 == P_KNIFE) ? 4 : !is_pole(obj1) ? 5 : 6;
+            val2 = objects[obj2->otyp].oc_skill;
+            val2 = (val2 < 0)
+                    ? (val2 >= -P_CROSSBOW && val2 <= -P_BOW) ? 1 : 3
+                    : (val2 >= P_BOW && val2 <= P_CROSSBOW) ? 2
+                       : (val2 == P_SPEAR || val2 == P_DAGGER
+                          || val2 == P_KNIFE) ? 4 : !is_pole(obj2) ? 5 : 6;
+            if (val1 != val2)
+                return val1 - val2;
+        }
     }
 
-    /* Sort by BUC. Map blessed to 4, uncursed to 2, cursed to 1, and unknown
-     * to 0. */
-    val1 = obj1->bknown
-               ? (obj1->blessed << 2)
-                     + ((!obj1->blessed && !obj1->cursed) << 1) + obj1->cursed
-               : 0;
-    val2 = obj2->bknown
-               ? (obj2->blessed << 2)
-                     + ((!obj2->blessed && !obj2->cursed) << 1) + obj2->cursed
-               : 0;
-    if (val1 != val2) {
-        return val2 - val1; /* Because bigger is better. */
+    /* order by assigned inventory letter */
+    if ((sortlootmode & SORTLOOT_INVLET) != 0) {
+        c = obj1->invlet;
+        val1 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
+               : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
+                 : (c == '$') ? 1
+                   : (c == '#') ? 1 + 52 + 1
+                     : 1 + 52 + 1 + 1; /* none of the above */
+        c = obj2->invlet;
+        val2 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
+               : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
+                 : (c == '$') ? 1
+                   : (c == '#') ? 1 + 52 + 1
+                     : 1 + 52 + 1 + 1; /* none of the above */
+        if (val1 != val2)
+            return val1 - val2;
     }
 
-    /* Sort by greasing. This will put the objects in degreasing order. */
+    if ((sortlootmode & SORTLOOT_LOOT) == 0)
+        goto tiebreak;
+
+    /*
+     * Sort object names in lexicographical order, ignoring quantity.
+     */
+    /* Force diluted potions to come out after undiluted of same type;
+       obj->odiluted overloads obj->oeroded. */
+    sav1.odiluted = obj1->odiluted;
+    sav2.odiluted = obj2->odiluted;
+    if (obj1->oclass == POTION_CLASS)
+        obj1->odiluted = 0;
+    if (obj1->oclass == POTION_CLASS)
+        obj2->odiluted = 0;
+    /* Force holy and unholy water to sort adjacent to water rather
+       than among 'h's and 'u's.  BUCX order will keep them distinct. */
+    Strcpy(nam1, cxname_singular(obj1));
+    if (obj1->otyp == POT_WATER && obj1->bknown
+        && (obj1->blessed || obj1->cursed))
+        (void) strsubst(nam1, obj1->blessed ? "holy " : "unholy ", "");
+    Strcpy(nam2, cxname_singular(obj2));
+    if (obj2->otyp == POT_WATER && obj2->bknown
+        && (obj2->blessed || obj2->cursed))
+        (void) strsubst(nam2, obj2->blessed ? "holy " : "unholy ", "");
+    obj1->odiluted = sav1.odiluted;
+    obj2->odiluted = sav2.odiluted;
+
+    if ((namcmp = strcmpi(nam1, nam2)) != 0)
+        return namcmp;
+
+    /* Sort by BUCX. */
+    val1 = obj1->bknown ? (obj1->blessed ? 3 : !obj1->cursed ? 2 : 1) : 0;
+    val2 = obj2->bknown ? (obj2->blessed ? 3 : !obj2->cursed ? 2 : 1) : 0;
+    if (val1 != val2)
+        return val2 - val1; /* bigger is better */
+
+    /* Sort by greasing.  This will put the objects in degreasing order. */
     val1 = obj1->greased;
     val2 = obj2->greased;
-    if (val1 != val2) {
-        return val2 - val1; /* Because bigger is better. */
-    }
+    if (val1 != val2)
+        return val2 - val1; /* bigger is better */
 
-    /* Sort by erosion. The effective amount is what matters. */
+    /* Sort by erosion.  The effective amount is what matters. */
     val1 = greatest_erosion(obj1);
     val2 = greatest_erosion(obj2);
-    if (val1 != val2) {
-        return val1 - val2; /* Because bigger is WORSE. */
-    }
+    if (val1 != val2)
+        return val1 - val2; /* bigger is WORSE */
 
-    /* Sort by erodeproofing. Map known-invulnerable to 1, and both
-     * known-vulnerable and unknown-vulnerability to 0, because that's how
-     * they're displayed. */
+    /* Sort by erodeproofing.  Map known-invulnerable to 1, and both
+       known-vulnerable and unknown-vulnerability to 0, because that's
+       how they're displayed. */
     val1 = obj1->rknown && obj1->oerodeproof;
     val2 = obj2->rknown && obj2->oerodeproof;
-    if (val1 != val2) {
-        return val2 - val1; /* Because bigger is better. */
-    }
-
-    /* Sort by enchantment. Map unknown to -1000, which is comfortably below
-     * the range of ->spe. */
-    val1 = obj1->known ? obj1->spe : -1000;
-    val2 = obj2->known ? obj2->spe : -1000;
-    if (val1 != val2) {
-        return val2 - val1; /* Because bigger is better. */
+    if (val1 != val2)
+        return val2 - val1; /* bigger is better */
+
+    /* Sort by enchantment.  Map unknown to -1000, which is comfortably
+       below the range of obj->spe.  oc_uses_known means that obj->known
+       matters, which usually indirectly means that obj->spe is relevant.
+       Lots of objects use obj->spe for some other purpose (see obj.h). */
+    if (objects[obj1->otyp].oc_uses_known
+        /* exclude eggs (laid by you) and tins (homemade, pureed, &c) */
+        && obj1->oclass != FOOD_CLASS) {
+        val1 = obj1->known ? obj1->spe : -1000;
+        val2 = obj2->known ? obj2->spe : -1000;
+        if (val1 != val2)
+            return val2 - val1; /* bigger is better */
     }
 
-    /* They're identical, as far as we're concerned,
-       but we want to force a determistic order between them. */
-    return (obj1->o_id > obj2->o_id) ? 1 : -1;
-}
-
-struct obj **
-objarr_init(n)
-int n;
-{
-    return (struct obj **) alloc(n * sizeof(struct obj *));
+tiebreak:
+    /* They're identical, as far as we're concerned.  We want
+       to force a deterministic order, and do so by producing a
+       stable sort: maintain the original order of equal items. */
+    return (sli1->indx - sli2->indx);
 }
 
 void
-objarr_set(otmp, idx, oarray, dosort)
-struct obj *otmp;
-int idx;
-struct obj **oarray;
-boolean dosort;
+sortloot(olist, mode, by_nexthere)
+struct obj **olist;
+unsigned mode; /* flags for sortloot_cmp() */
+boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
 {
-    if (dosort) {
-        int j;
-        for (j = idx; j; j--) {
-            if (sortloot_cmp(otmp, oarray[j - 1]) > 0)
-                break;
-            oarray[j] = oarray[j - 1];
+    struct sortloot_item *sliarray, osli, nsli;
+    struct obj *o, **nxt_p;
+    unsigned n, i;
+    boolean already_sorted = TRUE;
+
+    sortlootmode = mode; /* extra input for sortloot_cmp() */
+    for (n = osli.indx = 0, osli.obj = *olist; (o = osli.obj) != 0;
+         osli = nsli) {
+        nsli.obj = by_nexthere ? o->nexthere : o->nobj;
+        nsli.indx = (int) ++n;
+        if (nsli.obj && already_sorted
+            && sortloot_cmp((genericptr_t) &osli, (genericptr_t) &nsli) > 0)
+            already_sorted = FALSE;
+    }
+    if (n > 1 && !already_sorted) {
+        sliarray = (struct sortloot_item *) alloc(n * sizeof *sliarray);
+        for (i = 0, o = *olist; o;
+             ++i, o = by_nexthere ? o->nexthere : o->nobj)
+            sliarray[i].obj = o, sliarray[i].indx = (int) i;
+
+        qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp);
+        for (i = 0; i < n; ++i) {
+            o = sliarray[i].obj;
+            nxt_p = by_nexthere ? &(o->nexthere) : &(o->nobj);
+            *nxt_p = (i < n - 1) ? sliarray[i + 1].obj : (struct obj *) 0;
         }
-        oarray[j] = otmp;
-    } else {
-        oarray[idx] = otmp;
+        *olist = sliarray[0].obj;
+        free((genericptr_t) sliarray);
     }
+    sortlootmode = 0;
 }
 
 void
@@ -276,16 +387,18 @@ struct obj **potmp, **pobj;
          *
          * Don't do the age manipulation if lit.  We would need
          * to stop the burn on both items, then merge the age,
-         * then restart the burn.
+         * then restart the burn.  Glob ages are averaged in the
+         * absorb routine, which uses weight rather than quantity
+         * to adjust for proportion (glob quantity is always 1).
          */
-        if (!obj->lamplit)
+        if (!obj->lamplit && !obj->globby)
             otmp->age = ((otmp->age * otmp->quan) + (obj->age * obj->quan))
                         / (otmp->quan + obj->quan);
 
         otmp->quan += obj->quan;
         /* temporary special case for gold objects!!!! */
         if (otmp->oclass == COIN_CLASS)
-            otmp->owt = weight(otmp);
+            otmp->owt = weight(otmp), otmp->bknown = 0;
         /* and puddings!!!1!!one! */
         else if (!Is_pudding(otmp))
             otmp->owt += obj->owt;
@@ -337,10 +450,9 @@ struct obj **potmp, **pobj;
 #endif /*0*/
         }
 
-        /* handle puddings a bit differently; absorption will
-         * free the other object automatically so we can just
-         * return out from here.  */
-        if (Is_pudding(obj)) {
+        /* handle puddings a bit differently; absorption will free the
+           other object automatically so we can just return out from here */
+        if (obj->globby) {
             pudding_merge_message(otmp, obj);
             obj_absorb(potmp, pobj);
             return 1;
@@ -398,14 +510,21 @@ struct obj *obj;
         }
         set_artifact_intrinsic(obj, 1, W_ART);
     }
-    if (obj->otyp == LUCKSTONE && obj->record_achieve_special) {
+
+    /* "special achievements" aren't discoverable during play, they
+       end up being recorded in XLOGFILE at end of game, nowhere else;
+       record_achieve_special overloads corpsenm which is ordinarily
+       initialized to NON_PM (-1) rather than to 0; any special prize
+       must never be a corpse, egg, tin, figurine, or statue because
+       their use of obj->corpsenm for monster type would conflict,
+       nor be a leash (corpsenm overloaded for m_id of leashed
+       monster) or a novel (corpsenm overloaded for novel index) */
+    if (is_mines_prize(obj)) {
         u.uachieve.mines_luckstone = 1;
-        obj->record_achieve_special = 0;
-    } else if ((obj->otyp == AMULET_OF_REFLECTION
-                || obj->otyp == BAG_OF_HOLDING)
-               && obj->record_achieve_special) {
+        obj->record_achieve_special = NON_PM;
+    } else if (is_soko_prize(obj)) {
         u.uachieve.finish_sokoban = 1;
-        obj->record_achieve_special = 0;
+        obj->record_achieve_special = NON_PM;
     }
 }
 
@@ -439,6 +558,7 @@ struct obj *obj;
 {
     struct obj *otmp, *prev;
     int saved_otyp = (int) obj->otyp; /* for panic */
+    boolean obj_was_thrown;
 
     if (obj->where != OBJ_FREE)
         panic("addinv: obj not free");
@@ -447,6 +567,7 @@ struct obj *obj;
     obj->no_charge = 0; /* should not be set in hero's invent */
     if (Has_contents(obj))
         picked_container(obj); /* clear no_charge */
+    obj_was_thrown = obj->was_thrown;
     obj->was_thrown = 0;       /* not meaningful for invent */
 
     addinv_core1(obj);
@@ -481,6 +602,15 @@ struct obj *obj;
     }
     obj->where = OBJ_INVENT;
 
+    /* fill empty quiver if obj was thrown */
+    if (flags.pickup_thrown && !uquiver && obj_was_thrown
+        /* if Mjollnir is thrown and fails to return, we want to
+           auto-pick it when we move to its spot, but not into quiver;
+           aklyses behave like Mjollnir when thrown while wielded, but
+           we lack sufficient information here make them exceptions */
+        && obj->oartifact != ART_MJOLLNIR
+        && (throwing_weapon(obj) || is_ammo(obj)))
+        setuqwep(obj);
 added:
     addinv_core2(obj);
     carry_obj_effects(obj); /* carrying affects the obj */
@@ -498,8 +628,7 @@ void
 carry_obj_effects(obj)
 struct obj *obj;
 {
-    /* Cursed figurines can spontaneously transform
-       when carried. */
+    /* Cursed figurines can spontaneously transform when carried. */
     if (obj->otyp == FIGURINE) {
         if (obj->cursed && obj->corpsenm != NON_PM
             && !dead_species(obj->corpsenm, TRUE)) {
@@ -853,7 +982,7 @@ have_lizard()
     return FALSE;
 }
 
-/* 3.6.0 tribute */
+/* 3.6 tribute */
 struct obj *
 u_have_novel()
 {
@@ -948,7 +1077,7 @@ register char *buf;
 }
 
 /* some objects shouldn't be split when count given to getobj or askchain */
-STATIC_OVL boolean
+boolean
 splittable(obj)
 struct obj *obj;
 {
@@ -998,14 +1127,15 @@ register const char *let, *word;
     register int foo = 0;
     register char *bp = buf;
     xchar allowcnt = 0; /* 0, 1 or 2 */
-    struct obj *firstobj = invent;
     boolean usegold = FALSE; /* can't use gold because its illegal */
     boolean allowall = FALSE;
     boolean allownone = FALSE;
     boolean useboulder = FALSE;
     xchar foox = 0;
-    long cnt, prevcnt;
-    boolean prezero;
+    long cnt;
+    boolean cntgiven = FALSE;
+    boolean msggiven = FALSE;
+    boolean oneloop = FALSE;
     long dummymask;
 
 #if 1 /*JP*/
@@ -1049,15 +1179,20 @@ register const char *let, *word;
         useboulder = TRUE;
 
     if (allownone)
-        *bp++ = '-';
-    if (bp > buf && bp[-1] == '-')
-        *bp++ = ' ';
+        *bp++ = HANDS_SYM, *bp++ = ' '; /* '-' */
     ap = altlets;
 
     if (!flags.invlet_constant)
         reassign();
+    else
+        /* in case invent is in packorder, force it to be in invlet
+           order before collecing candidate inventory letters;
+           if player responds with '?' or '*' it will be changed
+           back by display_pickinv(), but by then we'll have 'lets'
+           and so won't have to re-sort in the for(;;) loop below */
+        sortloot(&invent, SORTLOOT_INVLET, FALSE);
 
-    for (otmp = firstobj; otmp; otmp = otmp->nobj) {
+    for (otmp = invent; otmp; otmp = otmp->nobj) {
         if (&bp[foo] == &buf[sizeof buf - 1]
             || ap == &altlets[sizeof altlets - 1]) {
             /* we must have a huge number of NOINVSYM items somehow */
@@ -1069,8 +1204,8 @@ register const char *let, *word;
             || (usegold && otmp->invlet == GOLD_SYM)
             || (useboulder && otmp->otyp == BOULDER)) {
             register int otyp = otmp->otyp;
-            bp[foo++] = otmp->invlet;
 
+            bp[foo++] = otmp->invlet;
 /* clang-format off */
 /* *INDENT-OFF* */
             /* ugly check: remove inappropriate things */
@@ -1083,8 +1218,9 @@ register const char *let, *word;
              || (!strcmp(word, "wield")
                  && (otmp->owornmask & W_WEP))
 #endif
-             || (!strcmp(word, "ready") /* exclude if wielded */
-                 && (otmp == uwep || (otmp == uswapwep && u.twoweap)))
+             || (!strcmp(word, "ready")    /* exclude when wielded... */
+                 && ((otmp == uwep || (otmp == uswapwep && u.twoweap))
+                     && otmp->quan == 1L)) /* ...unless more than one */
              || ((!strcmp(word, "dip") || !strcmp(word, "grease"))
                  && inaccessible_equipment(otmp, (const char *) 0, FALSE))
              ) {
@@ -1150,7 +1286,10 @@ register const char *let, *word;
                  && (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown
                      || !objects[HORN_OF_PLENTY].oc_name_known))
              || (!strcmp(word, "charge") && !is_chargeable(otmp))
+             || (!strcmp(word, "open") && otyp != TIN)
              || (!strcmp(word, "call") && !objtyp_is_callable(otyp))
+             || (!strcmp(word, "adjust") && otmp->oclass == COIN_CLASS
+                 && !usegold)
              ) {
                 foo--;
             }
@@ -1175,9 +1314,14 @@ register const char *let, *word;
                  && (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
              /* suppress container being stashed into */
              || (!strcmp(word, "stash") && !ck_bag(otmp))
-             /* worn armor or accessory covered by cursed worn armor */
+             /* worn armor (shirt, suit) covered by worn armor (suit, cloak)
+                or accessory (ring) covered by cursed worn armor (gloves) */
              || (taking_off(word)
-                 && inaccessible_equipment(otmp, (const char *) 0, TRUE))
+                 && inaccessible_equipment(otmp, (const char *) 0,
+                                      (boolean) (otmp->oclass == RING_CLASS)))
+             || (!strcmp(word, "write on")
+                 && (!(otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER)
+                     || !otmp->dknown || !objects[otyp].oc_name_known))
              ) {
                 /* acceptable but not listed as likely candidate */
                 foo--;
@@ -1207,59 +1351,58 @@ register const char *let, *word;
 */
         You("%s%s\82à\82Ì\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81D", foox ? "\91¼\82É" : "", jconj(jword, "\82ê\82é"));
         return (struct obj *) 0;
+    } else if (!strcmp(word, "write on")) { /* ugly check for magic marker */
+        /* we wanted all scrolls and books in altlets[], but that came with
+           'allowall' which we don't want since it prevents "silly thing"
+           result if anything other than scroll or spellbook is chosen */
+        allowall = FALSE;
     }
     for (;;) {
         cnt = 0;
-        if (allowcnt == 2)
-            allowcnt = 1; /* abort previous count */
-        prezero = FALSE;
-        if (!buf[0]) {
-/*JP
-            Sprintf(qbuf, "What do you want to %s? [*]", word);
-*/
-            Sprintf(qbuf, "%s%s%s\82©\81H[*]", what, joshi, jpolite(jword));
-        } else {
+        cntgiven = FALSE;
 /*JP
-            Sprintf(qbuf, "What do you want to %s? [%s or ?*]", word, buf);
+        Sprintf(qbuf, "What do you want to %s?", word);
 */
-            Sprintf(qbuf, "%s%s%s\82©\81H[%s or ?*]", what, joshi, jpolite(jword), buf);
-        }
+        Sprintf(qbuf, "%s%s%s\82©\81H", what, joshi, jpolite(jword));
         if (in_doagain)
             ilet = readchar();
-        else
+        else if (iflags.force_invmenu) {
+            /* don't overwrite a possible quitchars */
+            if (!oneloop)
+                ilet = *let ? '?' : '*';
+            if (!msggiven)
+                putmsghistory(qbuf, FALSE);
+            msggiven = TRUE;
+            oneloop = TRUE;
+        } else {
+            if (!buf[0])
+                Strcat(qbuf, " [*]");
+            else
+                Sprintf(eos(qbuf), " [%s or ?*]", buf);
             ilet = yn_function(qbuf, (char *) 0, '\0');
-        if (digit(ilet) && !allowcnt) {
+        }
+        if (digit(ilet)) {
+            long tmpcnt = 0;
+
+            if (!allowcnt) {
 /*JP
             pline("No count allowed with this command.");
 */
             pline("\82±\82Ì\83R\83}\83\93\83h\82É\90\94\8e\9a\82Í\82Â\82©\82¦\82È\82¢\81D");
-            continue;
-        }
-        if (ilet == '0')
-            prezero = TRUE;
-        while (digit(ilet)) {
-            if (ilet != '?' && ilet != '*')
-                savech(ilet);
-            /* accumulate unless cnt has overflowed */
-            if (allowcnt < 3) {
-                prevcnt = cnt;
-                cnt = 10L * cnt + (long) (ilet - '0');
-                /* signal presence of cnt */
-                allowcnt = (cnt >= prevcnt) ? 2 : 3;
+                continue;
+            }
+            ilet = get_count(NULL, ilet, LARGEST_INT, &tmpcnt, TRUE);
+            if (tmpcnt) {
+                cnt = tmpcnt;
+                cntgiven = TRUE;
             }
-            ilet = readchar();
-        }
-        if (allowcnt == 3) {
-            /* overflow detected; force cnt to be invalid */
-            cnt = -1L;
-            allowcnt = 2;
         }
         if (index(quitchars, ilet)) {
             if (flags.verbose)
                 pline1(Never_mind);
             return (struct obj *) 0;
         }
-        if (ilet == '-') {
+        if (ilet == HANDS_SYM) { /* '-' */
             if (!allownone) {
                 char *suf = (char *) 0;
 
@@ -1283,29 +1426,49 @@ register const char *let, *word;
             }
             return (allownone ? &zeroobj : (struct obj *) 0);
         }
+redo_menu:
         /* since gold is now kept in inventory, we need to do processing for
            select-from-invent before checking whether gold has been picked */
         if (ilet == '?' || ilet == '*') {
             char *allowed_choices = (ilet == '?') ? lets : (char *) 0;
             long ctmp = 0;
+            char menuquery[QBUFSZ];
+
+            menuquery[0] = qbuf[0] = '\0';
+            if (iflags.force_invmenu)
+                Sprintf(menuquery, "What do you want to %s?", word);
+            if (!strcmp(word, "grease"))
+                Sprintf(qbuf, "your %s", makeplural(body_part(FINGER)));
+            else if (!strcmp(word, "write with"))
+                Sprintf(qbuf, "your %s", body_part(FINGERTIP));
+            else if (!strcmp(word, "wield"))
+                Sprintf(qbuf, "your %s %s%s", uarmg ? "gloved" : "bare",
+                        makeplural(body_part(HAND)),
+                        !uwep ? " (wielded)" : "");
+            else if (!strcmp(word, "ready"))
+                Sprintf(qbuf, "empty quiver%s",
+                        !uquiver ? " (nothing readied)" : "");
 
             if (ilet == '?' && !*lets && *altlets)
                 allowed_choices = altlets;
-            ilet = display_pickinv(allowed_choices, TRUE,
-                                   allowcnt ? &ctmp : (long *) 0);
+            ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0,
+                                   menuquery,
+                                   TRUE, allowcnt ? &ctmp : (long *) 0);
             if (!ilet)
                 continue;
-            if (allowcnt && ctmp >= 0) {
-                cnt = ctmp;
-                if (!cnt)
-                    prezero = TRUE;
-                allowcnt = 2;
-            }
+            if (ilet == HANDS_SYM)
+                return &zeroobj;
             if (ilet == '\033') {
                 if (flags.verbose)
                     pline1(Never_mind);
                 return (struct obj *) 0;
             }
+            if (ilet == '*')
+                goto redo_menu;
+            if (allowcnt && ctmp >= 0) {
+                cnt = ctmp;
+                cntgiven = TRUE;
+            }
             /* they typed a letter (not a space) at the prompt */
         }
         /* find the item which was picked */
@@ -1330,8 +1493,8 @@ register const char *let, *word;
              * to your money supply.  The LRS is the tax bureau
              * from Larn.
              */
-            if (allowcnt == 2 && cnt <= 0) {
-                if (cnt < 0 || !prezero)
+            if (cntgiven && cnt <= 0) {
+                if (cnt < 0)
                     pline_The(
 /*JP
                   "LRS would be very interested to know you have that much.");
@@ -1340,16 +1503,14 @@ register const char *let, *word;
                 return (struct obj *) 0;
             }
         }
-        if (allowcnt == 2 && !strcmp(word, "throw")) {
+        if (cntgiven && !strcmp(word, "throw")) {
             /* permit counts for throwing gold, but don't accept
              * counts for other things since the throw code will
              * split off a single item anyway */
-            if (ilet != def_oc_syms[COIN_CLASS].sym
-                && !(otmp && otmp->oclass == COIN_CLASS))
-                allowcnt = 1;
-            if (cnt == 0 && prezero)
+            if (cnt == 0)
                 return (struct obj *) 0;
-            if (cnt > 1) {
+            if (cnt > 1 && (ilet != def_oc_syms[COIN_CLASS].sym
+                && !(otmp && otmp->oclass == COIN_CLASS))) {
 /*JP
                 You("can only throw one item at a time.");
 */
@@ -1390,7 +1551,7 @@ register const char *let, *word;
 #endif
         return (struct obj *) 0;
     }
-    if (allowcnt == 2) { /* cnt given */
+    if (cntgiven) {
         if (cnt == 0)
             return (struct obj *) 0;
         if (cnt != otmp->quan) {
@@ -1413,7 +1574,7 @@ struct obj *otmp;
 #if 1 /* 'P','R' vs 'W','T' handling is obsolete */
     nhUse(otmp);
 #else
-    const char *s1, *s2, *s3, *what;
+    const char *s1, *s2, *s3;
     int ocls = otmp->oclass, otyp = otmp->otyp;
 
     s1 = s2 = s3 = 0;
@@ -1441,24 +1602,19 @@ struct obj *otmp;
             s1 = "R", s2 = "remove", s3 = "";
 #else
         if (!strcmp(word, "\90g\82É\82Â\82¯\82é"))
-          s1 = "P", s2 = "\90g\82É\82Â\82¯\82é", s3 = "";
+            s1 = "P", s2 = "\90g\82É\82Â\82¯\82é", s3 = "";
         else if (!strcmp(word, "\82Í\82¸\82·"))
-          s1 = "R", s2 = "\82Í\82¸\82·", s3 = "";
+            s1 = "R", s2 = "\82Í\82¸\82·", s3 = "";
 #endif
     }
-    if (s1) {
+    if (s1)
 #if 0 /*JP*/
-        what = "that";
-        /* quantity for armor and accessory objects is always 1,
-           but some things should be referred to as plural */
-        if (otyp == LENSES || is_gloves(otmp) || is_boots(otmp))
-            what = "those";
-#endif
-/*JP
-        pline("Use the '%s' command to %s %s%s.", s1, s2, what, s3);
-*/
+        pline("Use the '%s' command to %s %s%s.", s1, s2,
+              !(is_plural(otmp) || pair_of(otmp)) ? "that" : "those", s3);
+#else
         pline("\82»\82ê\82ð%s\82É\82Í'%s'\83R\83}\83\93\83h\82ð\8eg\82¤\82±\82Æ\81D", s2, s1);
-    } else
+#endif
+    else
 #endif
         pline(silly_thing_to, word);
 }
@@ -1522,9 +1678,9 @@ static NEARDATA const char removeables[] = { ARMOR_CLASS, WEAPON_CLASS,
                                              RING_CLASS,  AMULET_CLASS,
                                              TOOL_CLASS,  0 };
 
-/* interactive version of getobj - used for Drop, Identify and */
-/* Takeoff (A). Return the number of times fn was called successfully */
-/* If combo is TRUE, we just use this to get a category list */
+/* Interactive version of getobj - used for Drop, Identify, and Takeoff (A).
+   Return the number of times fn was called successfully.
+   If combo is TRUE, we just use this to get a category list. */
 /*JP CHECK: 3.6.0 \82Ì\8cÄ\82Ñ\8fo\82µ\8c³
 do.c:962:        || (result = ggetobj("drop", drop, 0, FALSE, (unsigned *) 0)) < -1)
 do.c:1009:        i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
@@ -1540,13 +1696,13 @@ boolean combo; /* combination menu flag */
 unsigned *resultflags;
 {
     int FDECL((*ckfn), (OBJ_P)) = (int FDECL((*), (OBJ_P))) 0;
-    boolean FDECL((*filter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
+    boolean FDECL((*ofilter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
     boolean takeoff, ident, allflag, m_seen;
     int itemcount;
     int oletct, iletct, unpaid, oc_of_sym;
-    char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 5];
+    char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 10];
     char extra_removeables[3 + 1]; /* uwep,uswapwep,uquiver */
-    char buf[BUFSZ], qbuf[QBUFSZ];
+    char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
 #if 1 /*JP*/
     const char *joshi = "\82ð";
     const char *jword;
@@ -1556,46 +1712,45 @@ unsigned *resultflags;
     joshi = tv->particle;
 #endif
 
-    if (resultflags)
-        *resultflags = 0;
-    takeoff = ident = allflag = m_seen = FALSE;
     if (!invent) {
 /*JP
         You("have nothing to %s.", word);
 */
         You("%s\82à\82Ì\82Í\8e\9d\82Á\82Ä\82¢\82È\82¢\81D", jcan(jword));
+        if (resultflags)
+            *resultflags = ALL_FINISHED;
         return 0;
     }
+    if (resultflags)
+        *resultflags = 0;
+    takeoff = ident = allflag = m_seen = FALSE;
     add_valid_menu_class(0); /* reset */
     if (taking_off(word)) {
         takeoff = TRUE;
-        filter = is_worn;
+        ofilter = is_worn;
     } else if (!strcmp(word, "identify")) {
         ident = TRUE;
-        filter = not_fully_identified;
+        ofilter = not_fully_identified;
     }
 
-    iletct = collect_obj_classes(ilets, invent, FALSE, filter, &itemcount);
+    iletct = collect_obj_classes(ilets, invent, FALSE, ofilter, &itemcount);
     unpaid = count_unpaid(invent);
 
     if (ident && !iletct) {
         return -1; /* no further identifications */
-    } else if (!takeoff && (unpaid || invent)) {
+    } else if (invent) {
         ilets[iletct++] = ' ';
         if (unpaid)
             ilets[iletct++] = 'u';
-        if (count_buc(invent, BUC_BLESSED))
+        if (count_buc(invent, BUC_BLESSED, ofilter))
             ilets[iletct++] = 'B';
-        if (count_buc(invent, BUC_UNCURSED))
+        if (count_buc(invent, BUC_UNCURSED, ofilter))
             ilets[iletct++] = 'U';
-        if (count_buc(invent, BUC_CURSED))
+        if (count_buc(invent, BUC_CURSED, ofilter))
             ilets[iletct++] = 'C';
-        if (count_buc(invent, BUC_UNKNOWN))
+        if (count_buc(invent, BUC_UNKNOWN, ofilter))
             ilets[iletct++] = 'X';
-        if (invent)
-            ilets[iletct++] = 'a';
-    } else if (takeoff && invent) {
-        ilets[iletct++] = ' ';
+        ilets[iletct++] = 'a';
     }
     ilets[iletct++] = 'i';
     if (!combo)
@@ -1604,8 +1759,8 @@ unsigned *resultflags;
 
     for (;;) {
 #if 0 /*JP*/
-        Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]", word,
-                ilets);
+        Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]",
+                word, ilets);
 #else
         Sprintf(qbuf,"\82Ç\82Ì\8eí\97Þ\82Ì\82à\82Ì%s%s\82©\81H[%s]", joshi,
                 jpolite(jword), ilets);
@@ -1614,7 +1769,17 @@ unsigned *resultflags;
         if (buf[0] == '\033')
             return 0;
         if (index(buf, 'i')) {
-            if (display_inventory((char *) 0, TRUE) == '\033')
+            char ailets[1+26+26+1+5+1]; /* $ + a-z + A-Z + # + slop + \0 */
+            struct obj *otmp;
+
+            /* applicable inventory letters; if empty, show entire invent */
+            ailets[0] = '\0';
+            if (ofilter)
+                for (otmp = invent; otmp; otmp = otmp->nobj)
+                    /* index() check: limit overflow items to one '#' */
+                    if ((*ofilter)(otmp) && !index(ailets, otmp->invlet))
+                        (void) strkitten(ailets, otmp->invlet);
+            if (display_inventory(ailets, TRUE) == '\033')
                 return 0;
         } else
             break;
@@ -1683,21 +1848,12 @@ unsigned *resultflags;
         } else if (sym == 'a') {
             allflag = TRUE;
         } else if (sym == 'A') {
-            /* same as the default */;
+            ; /* same as the default */
         } else if (sym == 'u') {
             add_valid_menu_class('u');
             ckfn = ckunpaid;
-        } else if (sym == 'B') {
-            add_valid_menu_class('B');
-            ckfn = ckvalidcat;
-        } else if (sym == 'U') {
-            add_valid_menu_class('U');
-            ckfn = ckvalidcat;
-        } else if (sym == 'C') {
-            add_valid_menu_class('C');
-            ckfn = ckvalidcat;
-        } else if (sym == 'X') {
-            add_valid_menu_class('X');
+        } else if (index("BUCX", sym)) {
+            add_valid_menu_class(sym); /* 'B','U','C',or 'X' */
             ckfn = ckvalidcat;
         } else if (sym == 'm') {
             m_seen = TRUE;
@@ -1716,7 +1872,9 @@ unsigned *resultflags;
     }
 
     if (m_seen) {
-        return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
+        return (allflag
+                || (!oletct && ckfn != ckunpaid && ckfn != ckvalidcat))
+               ? -2 : -3;
     } else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
         return 0;
 #if 0
@@ -1742,8 +1900,8 @@ unsigned *resultflags;
  * Walk through the chain starting at objchn and ask for all objects
  * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
  * whether the action in question (i.e., fn) has to be performed.
- * If allflag then no questions are asked. Max gives the max nr of
- * objects to be treated. Return the number of objects treated.
+ * If allflag then no questions are asked.  Mx gives the max number
+ * of objects to be treated.  Return the number of objects treated.
  */
 /*JP CHECK: 3.6.0 \82Å\82Ì\8cÄ\82Ñ\8fo\82µ\8c³
 invent.c:1728:        int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
@@ -1753,14 +1911,14 @@ pickup.c:2882:        if (askchain(objlist, (one_by_one ? (char *) 0 : selection
 int
 askchain(objchn, olets, allflag, fn, ckfn, mx, word)
 struct obj **objchn;
-register int allflag, mx;
-register const char *olets, *word; /* olets is an Obj Class char array */
-register int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
+int allflag, mx;
+const char *olets, *word; /* olets is an Obj Class char array */
+int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
 {
     struct obj *otmp, *otmpo;
     register char sym, ilet;
     register int cnt = 0, dud = 0, tmp;
-    boolean takeoff, nodot, ident, take_out, put_in, first, ininv;
+    boolean takeoff, nodot, ident, take_out, put_in, first, ininv, bycat;
     char qbuf[QBUFSZ], qpfx[QBUFSZ];
 
     takeoff = taking_off(word);
@@ -1770,11 +1928,20 @@ register int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
     nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
              || takeoff || take_out || put_in);
     ininv = (*objchn == invent);
+    bycat = (menu_class_present('u')
+             || menu_class_present('B') || menu_class_present('U')
+             || menu_class_present('C') || menu_class_present('X'));
+
+    /* someday maybe we'll sort by 'olets' too (temporarily replace
+       flags.packorder and pass SORTLOOT_PACK), but not yet... */
+    sortloot(objchn, SORTLOOT_INVLET, FALSE);
+
     first = TRUE;
-/* Changed so the askchain is interrogated in the order specified.
- * For example, if a person specifies =/ then first all rings will be
- * asked about followed by all wands -dgk
- */
+    /*
+     * Interrogate in the object class order specified.
+     * For example, if a person specifies =/ then first all rings
+     * will be asked about followed by all wands.  -dgk
+     */
 nextclass:
     ilet = 'a' - 1;
     if (*objchn && (*objchn)->oclass == COIN_CLASS)
@@ -1795,6 +1962,8 @@ nextclass:
     while ((otmp = nxt_unbypassed_obj(*objchn)) != 0) {
         if (ilet == 'z')
             ilet = 'A';
+        else if (ilet == 'Z')
+            ilet = NOINVSYM; /* '#' */
         else
             ilet++;
         if (olets && *olets && otmp->oclass != *olets)
@@ -1805,6 +1974,8 @@ nextclass:
             continue;
         if (ckfn && !(*ckfn)(otmp))
             continue;
+        if (bycat && !ckvalidcat(otmp))
+            continue;
         if (!allflag) {
             safeq_xprn_ctx.let = ilet;
             safeq_xprn_ctx.dot = !nodot;
@@ -1818,13 +1989,15 @@ nextclass:
                 first = FALSE;
             }
 #if 0 /*JP*/
-            (void) safe_qbuf(
-                qbuf, qpfx, "?", otmp, ininv ? safeq_xprname : doname,
-                ininv ? safeq_shortxprname : ansimpleoname, "item");
+            (void) safe_qbuf(qbuf, qpfx, "?", otmp,
+                             ininv ? safeq_xprname : doname,
+                             ininv ? safeq_shortxprname : ansimpleoname,
+                             "item");
 #else
-            (void) safe_qbuf(
-                qbuf, qpfx, "\81H", otmp, ininv ? safeq_xprname : doname,
-                ininv ? safeq_shortxprname : ansimpleoname, "\83A\83C\83e\83\80");
+            (void) safe_qbuf(qbuf, qpfx, "\81H", otmp,
+                             ininv ? safeq_xprname : doname,
+                             ininv ? safeq_shortxprname : ansimpleoname,
+                             "\83A\83C\83e\83\80");
 #endif
             sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf)
                                                         : nyNaq(qbuf);
@@ -1837,11 +2010,10 @@ nextclass:
                to 'none' or 'all'.  2 special cases: cursed loadstones and
                welded weapons (eg, multiple daggers) will remain as merged
                unit; done to avoid splitting an object that won't be
-               droppable (even if we're picking up rather than dropping).
-             */
-            if (!yn_number)
+               droppable (even if we're picking up rather than dropping). */
+            if (!yn_number) {
                 sym = 'n';
-            else {
+            else {
                 sym = 'y';
                 if (yn_number < otmp->quan && splittable(otmp))
                     otmp = splitobj(otmp, yn_number);
@@ -1850,6 +2022,7 @@ nextclass:
         switch (sym) {
         case 'a':
             allflag = 1;
+            /*FALLTHRU*/
         case 'y':
             tmp = (*fn)(otmp);
             if (tmp < 0) {
@@ -1866,6 +2039,7 @@ nextclass:
             cnt += tmp;
             if (--mx == 0)
                 goto ret;
+            /*FALLTHRU*/
         case 'n':
             if (nodot)
                 dud++;
@@ -1942,8 +2116,8 @@ int id_limit;
         Sprintf(buf, "\82Ç\82ê\82ð%s\82É\8e¯\95Ê\82µ\82Ü\82·\82©\81H",
                 first ? "\8dÅ\8f\89" : "\8e\9f");
 #endif
-        n = query_objlist(buf, invent, SIGNAL_NOMENU | SIGNAL_ESCAPE
-                                           | USE_INVLET | INVORDER_SORT,
+        n = query_objlist(buf, &invent, (SIGNAL_NOMENU | SIGNAL_ESCAPE
+                                         | USE_INVLET | INVORDER_SORT),
                           &pick_list, PICK_ANY, not_fully_identified);
 
         if (n > 0) {
@@ -2095,25 +2269,29 @@ long quan;       /* if non-0, print this quantity, not obj->quan */
 #else
     static char li[BUFSZ];
 #endif
-    boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM;
+    boolean use_invlet = (flags.invlet_constant
+                          && let != CONTAINED_SYM && let != HANDS_SYM);
     long savequan = 0;
 
     if (quan && obj) {
         savequan = obj->quan;
         obj->quan = quan;
     }
-
     /*
      * If let is:
+     *  -  Then obj == null and 'txt' refers to hands or fingers.
      *  *  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 == '*') {
         /* if dot is true, we're doing Iu, otherwise Ix */
+        Sprintf(li,
 #if 0 /*JP*/
-        Sprintf(li, "%c - %-45s %6ld %s",
+                iflags.menu_tab_sep ? "%c - %s\t%6ld %s"
+                                    : "%c - %-45s %6ld %s",
 #else
-        Sprintf(li, "%c - %-45s %6ld%s",
+                iflags.menu_tab_sep ? "%c - %s\t%6ld%s"
+                                    : "%c - %-45s %6ld%s",
 #endif
                 (dot && use_invlet ? obj->invlet : let),
                 (txt ? txt : doname(obj)), cost, currency(cost));
@@ -2192,21 +2370,29 @@ free_pickinv_cache()
  * any count returned from the menu selection is placed here.
  */
 STATIC_OVL char
-display_pickinv(lets, want_reply, out_cnt)
+display_pickinv(lets, xtra_choice, query, want_reply, out_cnt)
 register const char *lets;
+const char *xtra_choice; /* "fingers", pick hands rather than an object */
+const char *query;
 boolean want_reply;
 long *out_cnt;
 {
+/*JP
+    static const char not_carrying_anything[] = "Not carrying anything";
+*/
+    static const char not_carrying_anything[] = "\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢";
     struct obj *otmp;
     char ilet, ret;
     char *invlet = flags.inv_order;
-    int i, n, classcount;
+    int n, classcount;
     winid win;                        /* windows being used */
     anything any;
     menu_item *selected;
-    struct obj **oarray;
 
-    if (flags.perm_invent && lets && *lets) {
+    if (lets && !*lets)
+        lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
+
+    if (flags.perm_invent && (lets || xtra_choice)) {
         /* partial inventory in perm_invent setting; don't operate on
            full inventory window, use an alternate one instead; create
            the first time needed and keep it for re-use as needed later */
@@ -2226,12 +2412,25 @@ long *out_cnt;
      * don't know at this level if its up or not.  This may not be
      * an issue if empty checks are done before hand and the call
      * to here is short circuited away.
+     *
+     * 2: our count here is only to distinguish between 0 and 1 and
+     * more than 1; for the last one, we don't need a precise number.
+     * For perm_invent update we force 'more than 1'.
      */
-    if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
+    n = (flags.perm_invent && !lets && !want_reply) ? 2
+        : lets ? (int) strlen(lets)
+               : !invent ? 0 : !invent->nobj ? 1 : 2;
+    /* for xtra_choice, there's another 'item' not included in initial 'n';
+       for !lets (full invent) and for override_ID (wizard mode identify),
+       skip message_menu handling of single item even if item count was 1 */
+    if (xtra_choice || (n == 1 && (!lets || iflags.override_ID)))
+        ++n;
+
+    if (n == 0) {
 /*JP
-        pline("Not carrying anything.");
+        pline("%s.", not_carrying_anything);
 */
-        pline("\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢\81D");
+        pline("%s\81D", not_carrying_anything);
         return 0;
     }
 
@@ -2239,58 +2438,66 @@ long *out_cnt;
     if (!flags.invlet_constant)
         reassign();
 
-    if (lets && strlen(lets) == 1 && !iflags.override_ID) {
+    if (n == 1 && !iflags.force_invmenu) {
         /* when only one item of interest, use pline instead of menus;
            we actually use a fake message-line menu in order to allow
            the user to perform selection at the --More-- prompt for tty */
         ret = '\0';
-        for (otmp = invent; otmp; otmp = otmp->nobj) {
-            if (otmp->invlet == lets[0]) {
-                ret = message_menu(
-                    lets[0], want_reply ? PICK_ONE : PICK_NONE,
-                    xprname(otmp, (char *) 0, lets[0], TRUE, 0L, 0L));
-                if (out_cnt)
-                    *out_cnt = -1L; /* select all */
-                break;
-            }
+        if (xtra_choice) {
+            /* xtra_choice is "bare hands" (wield), "fingertip" (Engrave),
+               "nothing" (ready Quiver), or "fingers" (apply grease) */
+            ret = message_menu(HANDS_SYM, PICK_ONE,
+                               xprname((struct obj *) 0, xtra_choice,
+                                       HANDS_SYM, TRUE, 0L, 0L)); /* '-' */
+        } else {
+            for (otmp = invent; otmp; otmp = otmp->nobj)
+                if (!lets || otmp->invlet == lets[0])
+                    break;
+            if (otmp)
+                ret = message_menu(otmp->invlet,
+                                   want_reply ? PICK_ONE : PICK_NONE,
+                                   xprname(otmp, (char *) 0, lets[0],
+                                           TRUE, 0L, 0L));
         }
+        if (out_cnt)
+            *out_cnt = -1L; /* select all */
         return ret;
     }
 
-    /* count the number of items */
-    for (n = 0, otmp = invent; otmp; otmp = otmp->nobj)
-        if (!lets || !*lets || index(lets, otmp->invlet))
-            n++;
-
-    oarray = objarr_init(n);
-
-    /* Add objects to the array */
-    i = 0;
-    for (otmp = invent; otmp; otmp = otmp->nobj)
-        if (!lets || !*lets || index(lets, otmp->invlet)) {
-            objarr_set(otmp, i++, oarray, (flags.sortloot == 'f'));
-        }
+    sortloot(&invent,
+             (((flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET)
+              | (flags.sortpack ? SORTLOOT_PACK : 0)),
+             FALSE);
 
     start_menu(win);
     any = zeroany;
     if (wizard && iflags.override_ID) {
-        char prompt[BUFSZ];
+        char prompt[QBUFSZ];
+
         any.a_char = -1;
-        /* wiz_identify stuffed the wiz_identify cmd character
-           into iflags.override_ID */
+        /* wiz_identify stuffed the wiz_identify command character (^I)
+           into iflags.override_ID for our use as an accelerator */
         Sprintf(prompt, "Debug Identify (%s to permanently identify)",
                 visctrl(iflags.override_ID));
         add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
                  prompt, MENU_UNSELECTED);
+    } else if (xtra_choice) {
+        /* wizard override ID and xtra_choice are mutually exclusive */
+        if (flags.sortpack)
+            add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+                     "Miscellaneous", MENU_UNSELECTED);
+        any.a_char = HANDS_SYM; /* '-' */
+        add_menu(win, NO_GLYPH, &any, HANDS_SYM, 0, ATR_NONE,
+                 xtra_choice, MENU_UNSELECTED);
     }
 nextclass:
     classcount = 0;
-    any = zeroany; /* set all bits to zero */
-    for (i = 0; i < n; i++) {
-        otmp = oarray[i];
-        ilet = otmp->invlet;
-        any = zeroany; /* zero */
+    for (otmp = invent; otmp; otmp = otmp->nobj) {
+        if (lets && !index(lets, otmp->invlet))
+            continue;
         if (!flags.sortpack || otmp->oclass == *invlet) {
+            any = zeroany; /* all bits zero */
+            ilet = otmp->invlet;
             if (flags.sortpack && !classcount) {
                 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
                          let_to_name(*invlet, FALSE,
@@ -2311,8 +2518,25 @@ nextclass:
             goto nextclass;
         }
     }
-    free(oarray);
-    end_menu(win, (char *) 0);
+    if (iflags.force_invmenu && lets && want_reply) {
+        any = zeroany;
+        add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+                 "Special", MENU_UNSELECTED);
+        any.a_char = '*';
+        add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
+                 "(list everything)", MENU_UNSELECTED);
+    }
+    /* for permanent inventory where we intend to show everything but
+       nothing has been listed (because there isn't anyhing to list;
+       recognized via any.a_char still being zero; the n==0 case above
+       gets skipped for perm_invent), put something into the menu */
+    if (flags.perm_invent && !lets && !any.a_char) {
+        any = zeroany;
+        add_menu(win, NO_GLYPH, &any, 0, 0, 0,
+                 not_carrying_anything, MENU_UNSELECTED);
+        want_reply = FALSE;
+    }
+    end_menu(win, query && *query ? query : (char *) 0);
 
     n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
     if (n > 0) {
@@ -2338,7 +2562,8 @@ display_inventory(lets, want_reply)
 const char *lets;
 boolean want_reply;
 {
-    return display_pickinv(lets, want_reply, (long *) 0);
+    return display_pickinv(lets, (char *) 0, (char *) 0,
+                           want_reply, (long *) 0);
 }
 
 /*
@@ -2387,7 +2612,7 @@ char avoidlet;
         }
         end_menu(win, "Inventory letters used:");
 
-        n = select_menu(win, PICK_NONE, &selected);
+        n = select_menu(win, PICK_ONE, &selected);
         if (n > 0) {
             ret = selected[0].item.a_char;
             free((genericptr_t) selected);
@@ -2426,20 +2651,27 @@ struct obj *list;
  * at some point:  bknown is forced for priest[ess], like in xname().
  */
 int
-count_buc(list, type)
+count_buc(list, type, filterfunc)
 struct obj *list;
 int type;
+boolean FDECL((*filterfunc), (OBJ_P));
 {
     int count = 0;
 
     for (; list; list = list->nobj) {
-        /* coins are "none of the above" as far as BUCX filtering goes */
-        if (list->oclass == COIN_CLASS)
-            continue;
         /* priests always know bless/curse state */
         if (Role_if(PM_PRIEST))
-            list->bknown = 1;
+            list->bknown = (list->oclass != COIN_CLASS);
+        /* some actions exclude some or most items */
+        if (filterfunc && !(*filterfunc)(list))
+            continue;
 
+        /* coins are either uncursed or unknown based upon option setting */
+        if (list->oclass == COIN_CLASS) {
+            if (type == (iflags.goldX ? BUC_UNKNOWN : BUC_UNCURSED))
+                ++count;
+            continue;
+        }
         /* check whether this object matches the requested type */
         if (!list->bknown
                 ? (type == BUC_UNKNOWN)
@@ -2453,21 +2685,32 @@ int type;
 
 /* similar to count_buc(), but tallies all states at once
    rather than looking for a specific type */
-STATIC_OVL void
-tally_BUCX(list, bcp, ucp, ccp, xcp, ocp)
+void
+tally_BUCX(list, by_nexthere, bcp, ucp, ccp, xcp, ocp)
 struct obj *list;
+boolean by_nexthere;
 int *bcp, *ucp, *ccp, *xcp, *ocp;
 {
+    /* Future extensions:
+     *  Skip current_container when list is invent, uchain when
+     *  first object of list is located on the floor.  'ocp' will then
+     *  have a function again (it was a counter for having skipped gold,
+     *  but that's not skipped anymore).
+     */
     *bcp = *ucp = *ccp = *xcp = *ocp = 0;
-    for (; list; list = list->nobj) {
+    for ( ; list; list = (by_nexthere ? list->nexthere : list->nobj)) {
+        /* priests always know bless/curse state */
+        if (Role_if(PM_PRIEST))
+            list->bknown = (list->oclass != COIN_CLASS);
+        /* coins are either uncursed or unknown based upon option setting */
         if (list->oclass == COIN_CLASS) {
-            ++(*ocp); /* "other" */
+            if (iflags.goldX)
+                ++(*xcp);
+            else
+                ++(*ucp);
             continue;
         }
-        /* priests always know bless/curse state */
-        if (Role_if(PM_PRIEST))
-            list->bknown = 1;
-
+        /* ordinary items */
         if (!list->bknown)
             ++(*xcp);
         else if (list->blessed)
@@ -2502,22 +2745,26 @@ STATIC_OVL void
 dounpaid()
 {
     winid win;
-    struct obj *otmp, *marker;
+    struct obj *otmp, *marker, *contnr;
     register char ilet;
     char *invlet = flags.inv_order;
     int classcount, count, num_so_far;
     long cost, totcost;
 
     count = count_unpaid(invent);
+    otmp = marker = contnr = (struct obj *) 0;
 
     if (count == 1) {
-        marker = (struct obj *) 0;
         otmp = find_unpaid(invent, &marker);
+        contnr = unknwn_contnr_contents(otmp);
+    }
+    if  (otmp && !contnr) {
+        /* 1 item; use pline instead of popup menu */
         cost = unpaid_cost(otmp, FALSE);
         iflags.suppress_price++; /* suppress "(unpaid)" suffix */
         pline1(xprname(otmp, distant_name(otmp, doname),
-                       carried(otmp) ? otmp->invlet : CONTAINED_SYM, TRUE,
-                       cost, 0L));
+                       carried(otmp) ? otmp->invlet : CONTAINED_SYM,
+                       TRUE, cost, 0L));
         iflags.suppress_price--;
         return;
     }
@@ -2609,7 +2856,12 @@ struct obj *obj;
 {
     boolean res = (obj->oclass == this_type);
 
-    if (obj->oclass != COIN_CLASS) {
+    if (obj->oclass == COIN_CLASS) {
+        /* if filtering by bless/curse state, gold is classified as
+           either unknown or uncursed based on user option setting */
+        if (this_type && index("BUCX", this_type))
+            res = (this_type == (iflags.goldX ? 'X' : 'U'));
+    } else {
         switch (this_type) {
         case 'B':
             res = (obj->bknown && obj->blessed);
@@ -2655,7 +2907,7 @@ dotypeinv()
         return 0;
     }
     unpaid_count = count_unpaid(invent);
-    tally_BUCX(invent, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
+    tally_BUCX(invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
 
     if (flags.menu_style != MENU_TRADITIONAL) {
         if (flags.menu_style == MENU_FULL
@@ -2683,9 +2935,9 @@ dotypeinv()
         /* collect a list of classes of objects carried, for use as a prompt
          */
         types[0] = 0;
-        class_count =
-            collect_obj_classes(types, invent, FALSE,
-                                (boolean FDECL((*), (OBJ_P))) 0, &itemcount);
+        class_count = collect_obj_classes(types, invent, FALSE,
+                                          (boolean FDECL((*), (OBJ_P))) 0,
+                                          &itemcount);
         if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
             types[class_count++] = ' ';
         if (unpaid_count)
@@ -2773,54 +3025,57 @@ dotypeinv()
             return doprgold();
         if (index(types, c) > index(types, '\033')) {
             /* '> ESC' => hidden choice, something known not to be carried */
-            const char *which = 0;
+            const char *before = "", *after = "";
 
             switch (c) {
             case 'B':
 /*JP
-                which = "known to be blessed";
+                before = "known to be blessed ";
 */
-                which = "\8fj\95\9f\82³\82ê\82Ä\82¢\82é\82Æ\82í\82©\82Á\82Ä\82¢\82é";
+                before = "\8fj\95\9f\82³\82ê\82Ä\82¢\82é\82Æ\82í\82©\82Á\82Ä\82¢\82é";
                 break;
             case 'U':
 /*JP
-                which = "known to be uncursed";
+                before = "known to be uncursed ";
 */
-                which = "\8eô\82í\82ê\82Ä\82¢\82È\82¢\82Æ\82í\82©\82Á\82Ä\82¢\82é";
+                before = "\8eô\82í\82ê\82Ä\82¢\82È\82¢\82Æ\82í\82©\82Á\82Ä\82¢\82é";
                 break;
             case 'C':
 /*JP
-                which = "known to be cursed";
+                before = "known to be cursed ";
 */
-                which = "\8eô\82í\82ê\82Ä\82¢\82é\82Æ\82í\82©\82Á\82Ä\82¢\82é";
+                before = "\8eô\82í\82ê\82Ä\82¢\82é\82Æ\82í\82©\82Á\82Ä\82¢\82é";
                 break;
             case 'X':
-#if 0 /*JP*/
-                You(
-          "have no objects whose blessed/uncursed/cursed status is unknown.");
-#else
-                You("\8fj\95\9f\81^\8eô\82¢\82ª\82í\82©\82ç\82È\82¢\82à\82Ì\82Í\89½\82à\82à\82Á\82Ä\82¢\82È\82¢\81D");
-#endif
+/*JP
+                after = " whose blessed/uncursed/cursed status is unknown";
+*/
+                after = "\8fj\95\9f\81^\8eô\82¢\82ª\82í\82©\82ç\82È\82¢";
                 break; /* better phrasing is desirable */
             default:
+                /* 'c' is an object class, because we've already handled
+                   all the non-class letters which were put into 'types[]';
+                   could/should move object class names[] array from below
+                   to somewhere above so that we can access it here (via
+                   lcase(strcpy(classnamebuf, names[(int) c]))), but the
+                   game-play value of doing so is low... */
 /*JP
-                which = "such";
+                before = "such ";
 */
-                which = "\82»\82Ì\82æ\82¤\82È";
+                before = "\82»\82Ì\82æ\82¤\82È";
                 break;
             }
-            if (which)
 /*JP
-                You("have no %s objects.", which);
+            You("have no %sobjects%s.", before, after);
 */
-                You("%s\82à\82Ì\82Í\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢\81D", which);
+                You("%s%s\82à\82Ì\82Í\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢\81D", before, after);
             return 0;
         }
         this_type = oclass;
     }
-    if (query_objlist((char *) 0, invent,
-                      (flags.invlet_constant ? USE_INVLET : 0)
-                          | INVORDER_SORT,
+    if (query_objlist((char *) 0, &invent,
+                      ((flags.invlet_constant ? USE_INVLET : 0)
+                       | INVORDER_SORT),
                       &pick_list, PICK_NONE, this_type_only) > 0)
         free((genericptr_t) pick_list);
     return 0;
@@ -2951,6 +3206,7 @@ boolean picked_some;
     skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
     if (u.uswallow && u.ustuck) {
         struct monst *mtmp = u.ustuck;
+
 #if 0 /*JP:T*/
         Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
                 mbodypart(mtmp, STOMACH));
@@ -2982,9 +3238,9 @@ boolean picked_some;
 #else
             Sprintf(fbuf, "\82±\82±\82É\82 \82é%s\82à\82Ì\82Í\81F", Blind ? "\82ç\82µ\82¢" : "");
 #endif
-            (void) display_minventory(mtmp, MINV_ALL, fbuf);
+            (void) display_minventory(mtmp, MINV_ALL | PICK_NONE, fbuf);
         } else {
-#if 0 /*JP:C*/
+#if 0 /*JP*/
             You("%s no objects here.", verb);
 #else
             pline(Blind ? "\82 \82È\82½\82Í\89½\82à\82È\82¢\82æ\82¤\82È\8bC\82ª\82µ\82½\81D"
@@ -3182,7 +3438,16 @@ boolean picked_some;
 int
 dolook()
 {
-    return look_here(0, FALSE);
+    int res;
+
+    /* don't let
+       MSGTYPE={norep,noshow} "You see here"
+       interfere with feedback from the look-here command */
+    hide_unhide_msgtypes(TRUE, MSGTYP_MASK_REP_SHOW);
+    res = look_here(0, FALSE);
+    /* restore normal msgtype handling */
+    hide_unhide_msgtypes(FALSE, MSGTYP_MASK_REP_SHOW);
+    return res;
 }
 
 boolean
@@ -3242,30 +3507,45 @@ struct obj *obj;
     return;
 }
 
-/* returns TRUE if obj  & otmp can be merged */
-STATIC_OVL boolean
+/* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
+boolean
 mergable(otmp, obj)
 register struct obj *otmp, *obj;
 {
     int objnamelth = 0, otmpnamelth = 0;
+
     if (obj == otmp)
         return FALSE; /* already the same object */
     if (obj->otyp != otmp->otyp)
+        return FALSE; /* different types */
+    if (obj->nomerge) /* explicitly marked to prevent merge */
         return FALSE;
+
     /* coins of the same kind will always merge */
     if (obj->oclass == COIN_CLASS)
         return TRUE;
+
     if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
-        || obj->dknown != otmp->dknown
-        || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
         || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
         || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
         || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
-        || obj->greased != otmp->greased || obj->oeroded != otmp->oeroded
-        || obj->oeroded2 != otmp->oeroded2 || obj->bypass != otmp->bypass)
+        || obj->bypass != otmp->bypass)
         return FALSE;
 
-    if (obj->nomerge) /* explicitly marked to prevent merge */
+    if (obj->globby)
+        return TRUE;
+    /* Checks beyond this point either aren't applicable to globs
+     * or don't inhibit their merger.
+     */
+
+    if (obj->oclass == FOOD_CLASS
+        && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
+        return FALSE;
+
+    if (obj->dknown != otmp->dknown
+        || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
+        || obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
+        || obj->greased != otmp->greased)
         return FALSE;
 
     if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
@@ -3273,10 +3553,6 @@ register struct obj *otmp, *obj;
             || obj->rknown != otmp->rknown))
         return FALSE;
 
-    if (obj->oclass == FOOD_CLASS
-        && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
-        return FALSE;
-
     if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
         if (obj->corpsenm != otmp->corpsenm)
             return FALSE;
@@ -3569,16 +3845,14 @@ STATIC_VAR NEARDATA const char *names[] = {
     "\95ó\90Î", "\8aâ\82Ü\82½\82Í\92¤\91\9c", "\93S\8b\85", "\8d½", "\93Å"
 #endif
 };
-
-static NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
-
+STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
 /*JP
-static NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
+STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
 */
-static NEARDATA const char *oth_names[] = { "\8bl\82ß\82ç\82ê\82½\93¹\8bï" };
+STATIC_VAR NEARDATA const char *oth_names[] = { "\8bl\82ß\82ç\82ê\82½\93¹\8bï" };
 
-static NEARDATA char *invbuf = (char *) 0;
-static NEARDATA unsigned invbufsiz = 0;
+STATIC_VAR NEARDATA char *invbuf = (char *) 0;
+STATIC_VAR NEARDATA unsigned invbufsiz = 0;
 
 char *
 let_to_name(let, unpaid, showsym)
@@ -3679,10 +3953,18 @@ reassign()
  *      then a 'to' slot for its destination.  Open slots and those
  *      filled by compatible stacks are listed as likely candidates
  *      but user can pick any inventory letter (including 'from').
- *      All compatible items found are gathered into the 'from'
- *      stack as it is moved.  If the 'to' slot isn't empty and
- *      doesn't merge, then its stack is swapped to the 'from' slot.
  *
+ *  to == from, 'from' has a name
+ *      All compatible items (same name or no name) are gathered
+ *      into the 'from' stack.  No count is allowed.
+ *  to == from, 'from' does not have a name
+ *      All compatible items without a name are gathered into the
+ *      'from' stack.  No count is allowed.  Compatible stacks with
+ *      names are left as-is.
+ *  to != from, no count
+ *      Move 'from' to 'to'.  If 'to' is not empty, merge 'from'
+ *      into it if possible, otherwise swap it with the 'from' slot.
+ *  to != from, count given
  *      If the user specifies a count when choosing the 'from' slot,
  *      and that count is less than the full size of the stack,
  *      then the stack will be split.  The 'count' portion is moved
@@ -3692,21 +3974,35 @@ reassign()
  *      will be moved to an open slot; if there isn't any open slot
  *      available, the adjustment attempt fails.
  *
- *      Splitting has one special case:  if 'to' slot is non-empty
- *      and is compatible with 'from' in all respects except for
- *      user-assigned names, the 'count' portion being moved is
- *      effectively renamed so that it will merge with 'to' stack.
+ *      To minimize merging for 'from == to', unnamed stacks will
+ *      merge with named 'from' but named ones won't merge with
+ *      unnamed 'from'.  Otherwise attempting to collect all unnamed
+ *      stacks would lump the first compatible named stack with them
+ *      and give them its name.
+ *
+ *      To maximize merging for 'from != to', compatible stacks will
+ *      merge when either lacks a name (or they already have the same
+ *      name).  When no count is given and one stack has a name and
+ *      the other doesn't, the merged result will have that name.
+ *      However, when splitting results in a merger, the name of the
+ *      destination overrides that of the source, even if destination
+ *      is unnamed and source is named.
  */
 int
 doorganize() /* inventory organizer by Del Lamb */
 {
     struct obj *obj, *otmp, *splitting, *bumped;
-    int ix, cur, trycnt;
+    int ix, cur, trycnt, goldstacks;
     char let;
-    char alphabet[52 + 1], buf[52 + 1];
+#define GOLD_INDX   0
+#define GOLD_OFFSET 1
+#define OVRFLW_INDX (GOLD_OFFSET + 52) /* past gold and 2*26 letters */
+    char lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */
     char qbuf[QBUFSZ];
-    char allowall[3]; /* { ALLOW_COUNT, ALL_CLASSES, 0 } */
+    char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
+    char *objname, *otmpname;
     const char *adj_type;
+    boolean ever_mind = FALSE, collect;
 
     if (!invent) {
 /*JP
@@ -3722,6 +4018,20 @@ doorganize() /* inventory organizer by Del Lamb */
     allowall[0] = ALLOW_COUNT;
     allowall[1] = ALL_CLASSES;
     allowall[2] = '\0';
+    for (goldstacks = 0, otmp = invent; otmp; otmp = otmp->nobj) {
+        /* gold should never end up in a letter slot, nor should two '$'
+           slots occur, but if they ever do, allow #adjust to handle them
+           (in the past, things like this have happened, usually due to
+           bknown being erroneously set on one stack, clear on another;
+           object merger isn't fooled by that anymore) */
+        if (otmp->oclass == COIN_CLASS
+            && (otmp->invlet != GOLD_SYM || ++goldstacks > 1)) {
+            allowall[1] = COIN_CLASS;
+            allowall[2] = ALL_CLASSES;
+            allowall[3] = '\0';
+            break;
+        }
+    }
     if (!(obj = getobj(allowall, "adjust")))
         return 0;
 
@@ -3735,43 +4045,47 @@ doorganize() /* inventory organizer by Del Lamb */
         }
 
     /* initialize the list with all lower and upper case letters */
-    for (ix = 0, let = 'a'; let <= 'z';)
-        alphabet[ix++] = let++;
+    lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
+    for (ix = GOLD_OFFSET, let = 'a'; let <= 'z';)
+        lets[ix++] = let++;
     for (let = 'A'; let <= 'Z';)
-        alphabet[ix++] = let++;
-    alphabet[ix] = '\0';
+        lets[ix++] = let++;
+    lets[OVRFLW_INDX] = ' ';
+    lets[sizeof lets - 1] = '\0';
     /* for floating inv letters, truncate list after the first open slot */
     if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
-        alphabet[ix + (splitting ? 0 : 1)] = '\0';
+        lets[ix + (splitting ? 0 : 1)] = '\0';
 
-    /* blank out all the letters currently in use in the inventory */
-    /* except those that will be merged with the selected object   */
+    /* blank out all the letters currently in use in the inventory
+       except those that will be merged with the selected object */
     for (otmp = invent; otmp; otmp = otmp->nobj)
         if (otmp != obj && !mergable(otmp, obj)) {
             let = otmp->invlet;
             if (let >= 'a' && let <= 'z')
-                alphabet[let - 'a'] = ' ';
+                lets[GOLD_OFFSET + let - 'a'] = ' ';
             else if (let >= 'A' && let <= 'Z')
-                alphabet[let - 'A' + 26] = ' ';
+                lets[GOLD_OFFSET + let - 'A' + 26] = ' ';
+            /* overflow defaults to off, but it we find a stack using that
+               slot, switch to on -- the opposite of normal invlet handling */
+            else if (let == NOINVSYM)
+                lets[OVRFLW_INDX] = NOINVSYM;
         }
 
     /* compact the list by removing all the blanks */
-    for (ix = cur = 0; alphabet[ix]; ix++)
-        if (alphabet[ix] != ' ')
-            buf[cur++] = alphabet[ix];
-    if (!cur && obj->invlet == NOINVSYM)
-        buf[cur++] = NOINVSYM;
-    buf[cur] = '\0';
+    for (ix = cur = 0; lets[ix]; ix++)
+        if (lets[ix] != ' ' && cur++ < ix)
+            lets[cur - 1] = lets[ix];
+    lets[cur] = '\0';
     /* and by dashing runs of letters */
     if (cur > 5)
-        compactify(buf);
+        compactify(lets);
 
     /* get 'to' slot to use as destination */
 #if 0 /*JP:T*/
-    Sprintf(qbuf, "Adjust letter to what [%s]%s?", buf,
+    Sprintf(qbuf, "Adjust letter to what [%s]%s?", lets,
             invent ? " (? see used letters)" : "");
 #else
-    Sprintf(qbuf, "\82Ç\82Ì\95\8e\9a\82É\92²\90®\82µ\82Ü\82·\82©[%s]%s\81H", buf,
+    Sprintf(qbuf, "\82Ç\82Ì\95\8e\9a\82É\92²\90®\82µ\82Ü\82·\82©[%s]%s\81H", lets,
             invent ? " (? \82Å\8eg\82Á\82Ä\82¢\82é\95\8e\9a\82ð\95\\8e¦)" : "");
 #endif
     for (trycnt = 1; ; ++trycnt) {
@@ -3791,10 +4105,19 @@ doorganize() /* inventory organizer by Del Lamb */
         noadjust:
             if (splitting)
                 (void) merged(&splitting, &obj);
-            pline1(Never_mind);
+            if (!ever_mind)
+                pline1(Never_mind);
             return 0;
+        } else if (let == GOLD_SYM && obj->oclass != COIN_CLASS) {
+            pline("Only gold coins may be moved into the '%c' slot.",
+                  GOLD_SYM);
+            ever_mind = TRUE;
+            goto noadjust;
         }
-        if ((letter(let) && let != '@') || index(buf, let))
+        /* letter() classifies '@' as one; compactify() can put '-' in lets;
+           the only thing of interest that index() might find is '$' or '#'
+           since letter() catches everything else that we put into lets[] */
+        if ((letter(let) && let != '@') || (index(lets, let) && let != '-'))
             break; /* got one */
         if (trycnt == 5)
             goto noadjust;
@@ -3805,11 +4128,12 @@ doorganize() /* inventory organizer by Del Lamb */
 #endif
     }
 
+    collect = (let == obj->invlet);
     /* change the inventory and print the resulting item */
 /*JP
-    adj_type = !splitting ? "Moving:" : "Splitting:";
+    adj_type = collect ? "Collecting" : !splitting ? "Moving:" : "Splitting:";
 */
-    adj_type = !splitting ? "\82ð\88Ú\93®\82µ\82½\81D" : "\82ð\95ª\8a\84\82µ\82½\81D";
+    adj_type = collect ? "\82ð\8fW\82ß\82½\81D" : !splitting ? "\82ð\88Ú\93®\82µ\82½\81D" : "\82ð\95ª\8a\84\82µ\82½\81D";
 
     /*
      * don't use freeinv/addinv to avoid double-touching artifacts,
@@ -3818,8 +4142,20 @@ doorganize() /* inventory organizer by Del Lamb */
     extract_nobj(obj, &invent);
 
     for (otmp = invent; otmp;) {
-        if (!splitting) {
-            if (merged(&otmp, &obj)) {
+        /* it's tempting to pull this outside the loop, but merged() could
+           free ONAME(obj) [via obfree()] and replace it with ONAME(otmp) */
+        objname = has_oname(obj) ? ONAME(obj) : (char *) 0;
+
+        if (collect) {
+            /* Collecting: #adjust an inventory stack into its same slot;
+               keep it there and merge other compatible stacks into it.
+               Traditional inventory behavior is to merge unnamed stacks
+               with compatible named ones; we only want that if it is
+               the 'from' stack (obj) with a name and candidate (otmp)
+               without one, not unnamed 'from' with named candidate. */
+            otmpname = has_oname(otmp) ? ONAME(otmp) : (char *) 0;
+            if ((!otmpname || (objname && !strcmp(objname, otmpname)))
+                && merged(&otmp, &obj)) {
 /*JP
                 adj_type = "Merging:";
 */
@@ -3828,37 +4164,36 @@ doorganize() /* inventory organizer by Del Lamb */
                 otmp = otmp->nobj;
                 extract_nobj(obj, &invent);
                 continue; /* otmp has already been updated */
-            } else if (otmp->invlet == let) {
+            }
+        } else if (otmp->invlet == let) {
+            /* Moving or splitting: don't merge extra compatible stacks.
+               Found 'otmp' in destination slot; merge if compatible,
+               otherwise bump whatever is there to an open slot. */
+            if (!splitting) {
 /*JP
                 adj_type = "Swapping:";
 */
                 adj_type = "\82ð\8cð\8a·\82µ\82½\81D";
                 otmp->invlet = obj->invlet;
-            }
-        } else {
-            /* splitting: don't merge extra compatible stacks;
-               if destination is compatible, do merge with it,
-               otherwise bump whatever is there to an open slot */
-            if (otmp->invlet == let) {
-                int olth = 0;
-
-                if (has_oname(obj))
-                    olth = strlen(ONAME(obj));
-                /* ugly hack:  if these objects aren't going to merge
-                   solely because they have conflicting user-assigned
-                   names, strip off the name of the one being moved */
-                if (olth && !obj->oartifact && !mergable(otmp, obj)) {
-                    char *holdname = ONAME(obj);
+            } else {
+                /* strip 'from' name if it has one */
+                if (objname && !obj->oartifact)
                     ONAME(obj) = (char *) 0;
-                    /* restore name iff merging is still not possible */
-                    if (!mergable(otmp, obj)) {
-                        ONAME(obj) = holdname;
-                        holdname = (char *) 0;
-                    } else
-                        free((genericptr_t) holdname);
+                if (!mergable(otmp, obj)) {
+                    /* won't merge; put 'from' name back */
+                    if (objname)
+                        ONAME(obj) = objname;
+                } else {
+                    /* will merge; discard 'from' name */
+                    if (objname)
+                        free((genericptr_t) objname), objname = 0;
                 }
 
                 if (merged(&otmp, &obj)) {
+/*JP
+                    adj_type = "Splitting and merging:";
+*/
+                    adj_type = "\82ð\95ª\8a\84\82µ\82Ä\8d\87\82í\82¹\82½\81D";
                     obj = otmp;
                     extract_nobj(obj, &invent);
                 } else if (inv_cnt(FALSE) >= 52) {
@@ -3873,9 +4208,9 @@ doorganize() /* inventory organizer by Del Lamb */
                     bumped = otmp;
                     extract_nobj(bumped, &invent);
                 }
-                break;
-            } /* found 'to' slot */
-        }     /* splitting */
+            } /* moving vs splitting */
+            break; /* not collecting and found 'to' slot */
+        } /* collect */
         otmp = otmp->nobj;
     }
 
@@ -3961,8 +4296,10 @@ struct obj *obj;
  * By default, only worn and wielded items are displayed.  The caller
  * can pick one.  Modifier flags are:
  *
- *      MINV_NOLET      - nothing selectable
- *      MINV_ALL        - display all inventory
+ *      PICK_NONE, PICK_ONE - standard menu control
+ *      PICK_ANY            - allowed, but we only return a single object
+ *      MINV_NOLET          - nothing selectable
+ *      MINV_ALL            - display all inventory
  */
 struct obj *
 display_minventory(mon, dflags, title)
@@ -3976,7 +4313,8 @@ char *title;
     menu_item *selected = 0;
     int do_all = (dflags & MINV_ALL) != 0,
         incl_hero = (do_all && u.uswallow && mon == u.ustuck),
-        have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero);
+        have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
+        pickings = (dflags & MINV_PICKMASK);
 
 #if 0 /*JP*/
     Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
@@ -3992,12 +4330,10 @@ char *title;
          */
         youmonst.data = mon->data;
 
-        n = query_objlist(title ? title : tmp, mon->minvent,
-                          INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0),
-                          &selected,
-                          (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE,
+        n = query_objlist(title ? title : tmp, &(mon->minvent),
+                          (INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0)),
+                          &selected, pickings,
                           do_all ? allow_all : worn_wield_only);
-
         set_uasmon();
     } else {
 /*JP
@@ -4037,8 +4373,8 @@ register struct obj *obj;
 #endif
 
     if (obj->cobj) {
-        n = query_objlist(qbuf, obj->cobj, INVORDER_SORT, &selected,
-                          PICK_NONE, allow_all);
+        n = query_objlist(qbuf, &(obj->cobj), INVORDER_SORT,
+                          &selected, PICK_NONE, allow_all);
     } else {
 /*JP
         invdisp_nothing(qbuf, "(empty)");
@@ -4092,10 +4428,11 @@ boolean as_if_seen;
         only.x = x;
         only.y = y;
 /*JP
-        if (query_objlist("Things that are buried here:", level.buriedobjlist,
+        if (query_objlist("Things that are buried here:",
 */
-        if (query_objlist("\82±\82±\82É\96\84\82ß\82ç\82ê\82Ä\82¢\82é\82à\82Ì\81F", level.buriedobjlist,
-                          INVORDER_SORT, &selected, PICK_NONE, only_here) > 0)
+        if (query_objlist("\82±\82±\82É\96\84\82ß\82ç\82ê\82Ä\82¢\82é\82à\82Ì\81F",
+                          &level.buriedobjlist, INVORDER_SORT,
+                          &selected, PICK_NONE, only_here) > 0)
             free((genericptr_t) selected);
         only.x = only.y = 0;
     }
index 33aad10..f4ea097 100644 (file)
@@ -310,6 +310,23 @@ int fd;
     }
 }
 
+/* to support '#stats' wizard-mode command */
+void
+light_stats(hdrfmt, hdrbuf, count, size)
+const char *hdrfmt;
+char *hdrbuf;
+long *count, *size;
+{
+    light_source *ls;
+
+    Sprintf(hdrbuf, hdrfmt, (long) sizeof (light_source));
+    *count = *size = 0L;
+    for (ls = light_base; ls; ls = ls->next) {
+        ++*count;
+        *size += (long) sizeof *ls;
+    }
+}
+
 /* Relink all lights that are so marked. */
 void
 relink_light_sources(ghostly)
index 7527dcd..17c8112 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 lock.c  $NHDT-Date: 1446955300 2015/11/08 04:01:40 $  $NHDT-Branch: master $:$NHDT-Revision: 1.67 $ */
+/* NetHack 3.6 lock.c  $NHDT-Date: 1521499715 2018/03/19 22:48:35 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 
 #include "hack.h"
 
-STATIC_PTR int NDECL(picklock);
-STATIC_PTR int NDECL(forcelock);
-
 /* at most one of `door' and `box' should be non-null at any given time */
 STATIC_VAR NEARDATA struct xlock_s {
     struct rm *door;
     struct obj *box;
     int picktyp, /* key|pick|card for unlock, sharp vs blunt for #force */
         chance, usedtime;
+    boolean magic_key;
 } xlock;
 
+/* occupation callbacks */
+STATIC_PTR int NDECL(picklock);
+STATIC_PTR int NDECL(forcelock);
+
 STATIC_DCL const char *NDECL(lock_action);
 STATIC_DCL boolean FDECL(obstructed, (int, int, BOOLEAN_P));
 STATIC_DCL void FDECL(chest_shatter_msg, (struct obj *));
@@ -95,7 +98,8 @@ STATIC_PTR int
 picklock(VOID_ARGS)
 {
     if (xlock.box) {
-        if ((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) {
+        if (xlock.box->where != OBJ_FLOOR
+            || xlock.box->ox != u.ux || xlock.box->oy != u.uy) {
             return ((xlock.usedtime = 0)); /* you or it moved */
         }
     } else { /* door */
@@ -136,6 +140,40 @@ picklock(VOID_ARGS)
     if (rn2(100) >= xlock.chance)
         return 1; /* still busy */
 
+    /* using the Master Key of Thievery finds traps if its bless/curse
+       state is adequate (non-cursed for rogues, blessed for others;
+       checked when setting up 'xlock') */
+    if ((!xlock.door ? (int) xlock.box->otrapped
+                     : (xlock.door->doormask & D_TRAPPED) != 0)
+        && xlock.magic_key) {
+        xlock.chance += 20; /* less effort needed next time */
+        /* unfortunately we don't have a 'tknown' flag to record
+           "known to be trapped" so declining to disarm and then
+           retrying lock manipulation will find it all over again */
+        if (yn("You find a trap!  Do you want to try to disarm it?") == 'y') {
+            const char *what;
+            boolean alreadyunlocked;
+
+            /* disarming while using magic key always succeeds */
+            if (xlock.door) {
+                xlock.door->doormask &= ~D_TRAPPED;
+                what = "door";
+                alreadyunlocked = !(xlock.door->doormask & D_LOCKED);
+            } else {
+                xlock.box->otrapped = 0;
+                what = (xlock.box->otyp == CHEST) ? "chest" : "box";
+                alreadyunlocked = !xlock.box->olocked;
+            }
+            You("succeed in disarming the trap.  The %s is still %slocked.",
+                what, alreadyunlocked ? "un" : "");
+            exercise(A_WIS, TRUE);
+        } else {
+            You("stop %s.", lock_action());
+            exercise(A_WIS, FALSE);
+        }
+        return ((xlock.usedtime = 0));
+    }
+
 /*JP
     You("succeed in %s.", lock_action());
 */
@@ -149,7 +187,7 @@ picklock(VOID_ARGS)
             xlock.door->doormask = D_NODOOR;
             unblock_point(u.ux + u.dx, u.uy + u.dy);
             if (*in_rooms(u.ux + u.dx, u.uy + u.dy, SHOPBASE))
-                add_damage(u.ux + u.dx, u.uy + u.dy, 0L);
+                add_damage(u.ux + u.dx, u.uy + u.dy, SHOP_DOOR_COST);
             newsym(u.ux + u.dx, u.uy + u.dy);
         } else if (xlock.door->doormask & D_LOCKED)
             xlock.door->doormask = D_CLOSED;
@@ -281,10 +319,19 @@ void
 reset_pick()
 {
     xlock.usedtime = xlock.chance = xlock.picktyp = 0;
+    xlock.magic_key = FALSE;
     xlock.door = 0;
     xlock.box = 0;
 }
 
+/* level change; don't reset if hero is carrying xlock.box with him/her */
+void
+maybe_reset_pick()
+{
+    if (!xlock.box || !carried(xlock.box))
+        reset_pick();
+}
+
 /* for doapply(); if player gives a direction or resumes an interrupted
    previous attempt then it costs hero a move even if nothing ultimately
    happens; when told "can't do that" before being asked for direction
@@ -318,6 +365,7 @@ struct obj *pick;
             const char *what = (picktyp == LOCK_PICK) ? "pick" : "key";
 */
             const char *what = (picktyp == LOCK_PICK) ? "\8c®\8aJ\82¯\8aí\8bï" : "\8c®";
+
             if (picktyp == CREDIT_CARD)
 /*JP
                 what = "card";
@@ -343,6 +391,7 @@ struct obj *pick;
             You("resume your attempt at %s.", action);
 */
             pline("%s\82Ì\82ð\8dÄ\8aJ\82µ\82½\81D", action);
+            xlock.magic_key = is_magic_key(&youmonst, pick);
             set_occupation(picklock, action, 0);
             return PICKLOCK_DID_SOMETHING;
         }
@@ -365,8 +414,9 @@ struct obj *pick;
         return PICKLOCK_DID_NOTHING;
     }
 
-    if ((picktyp != LOCK_PICK && picktyp != CREDIT_CARD
-         && picktyp != SKELETON_KEY)) {
+    if (picktyp != LOCK_PICK
+        && picktyp != CREDIT_CARD
+        && picktyp != SKELETON_KEY) {
         impossible("picking lock with object %d?", picktyp);
         return PICKLOCK_DID_NOTHING;
     }
@@ -401,9 +451,9 @@ struct obj *pick;
             return PICKLOCK_LEARNED_SOMETHING;
         } else if (is_pool(u.ux, u.uy) && !Underwater) {
 /*JP
-            pline_The("water has no lock.");
+            pline_The("%s has no lock.", hliquid("water"));
 */
-            pline("\90\85\82É\8fù\91O\82Í\82È\82¢\81D");
+            pline_The("%s\82É\8fù\91O\82Í\82È\82¢\81D", hliquid("\90\85"));
             return PICKLOCK_LEARNED_SOMETHING;
         }
 
@@ -494,7 +544,6 @@ struct obj *pick;
                 if (otmp->cursed)
                     ch /= 2;
 
-                xlock.picktyp = picktyp;
                 xlock.box = otmp;
                 xlock.door = 0;
                 break;
@@ -539,7 +588,7 @@ struct obj *pick;
         } else if (mtmp && is_door_mappear(mtmp)) {
             /* "The door actually was a <mimic>!" */
             stumble_onto_mimic(mtmp);
-            /* mimic might keep the key (50% chance, 10% for PYEC) */
+            /* mimic might keep the key (50% chance, 10% for PYEC or MKoT) */
             maybe_absorb_item(mtmp, pick, 50, 10);
             return PICKLOCK_LEARNED_SOMETHING;
         }
@@ -617,6 +666,7 @@ struct obj *pick;
     context.move = 0;
     xlock.chance = ch;
     xlock.picktyp = picktyp;
+    xlock.magic_key = is_magic_key(&youmonst, pick);
     xlock.usedtime = 0;
     set_occupation(picklock, lock_action(), 0);
     return PICKLOCK_DID_SOMETHING;
@@ -681,11 +731,17 @@ doforce()
     for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere)
         if (Is_box(otmp)) {
             if (otmp->obroken || !otmp->olocked) {
+                /* force doname() to omit known "broken" or "unlocked"
+                   prefix so that the message isn't worded redundantly;
+                   since we're about to set lknown, there's no need to
+                   remember and then reset its current value */
+                otmp->lknown = 0;
 #if 0 /*JP*/
-                There("is %s here, but its lock is already %s.", doname(otmp),
-                      otmp->obroken ? "broken" : "unlocked");
+                There("is %s here, but its lock is already %s.",
+                      doname(otmp), otmp->obroken ? "broken" : "unlocked");
 #else
-                pline("\82±\82±\82É\82Í%s\82ª\82 \82é\81C\82µ\82©\82µ\82»\82Ì\8c®\82Í\82à\82¤%s\81D", doname(otmp),
+                pline("\82±\82±\82É\82Í%s\82ª\82 \82é\81D\82µ\82©\82µ\82»\82Ì\8c®\82Í\82à\82¤%s\81D",
+                      doname(otmp),
                       otmp->obroken ? "\89ó\82ê\82Ä\82¢\82é" : "\82Í\82¸\82³\82ê\82Ä\82¢\82é");
 #endif
                 otmp->lknown = 1;
@@ -695,7 +751,7 @@ doforce()
             (void) safe_qbuf(qbuf, "There is ", " here; force its lock?",
                              otmp, doname, ansimpleoname, "a box");
 #else
-            (void) safe_qbuf(qbuf, "\82±\82±\82É\82Í", "\82ª\82 \82é\81C\8c®\82ð\82±\82\8aJ\82¯\82Ü\82·\82©\81H",
+            (void) safe_qbuf(qbuf, "\82±\82±\82É\82Í", "\82ª\82 \82é\81D\8c®\82ð\82±\82\8aJ\82¯\82Ü\82·\82©\81H",
                              otmp, doname, ansimpleoname, "\94 ");
 #endif
             otmp->lknown = 1;
@@ -719,6 +775,7 @@ doforce()
             xlock.box = otmp;
             xlock.chance = objects[uwep->otyp].oc_wldam * 2;
             xlock.picktyp = picktyp;
+            xlock.magic_key = FALSE;
             xlock.usedtime = 0;
             break;
         }
@@ -789,8 +846,9 @@ int x, y;
     } else if (!get_adjacent_loc((char *) 0, (char *) 0, u.ux, u.uy, &cc))
         return 0;
 
+    /* open at yourself/up/down */
     if ((cc.x == u.ux) && (cc.y == u.uy))
-        return 0;
+        return doloot();
 
     if (stumble_on_door_mimic(cc.x, cc.y))
         return 1;
@@ -824,6 +882,9 @@ int x, y;
             pline_The("drawbridge is already open.");
 */
             pline_The("\92µ\82Ë\8b´\82Í\82à\82¤\8aJ\82¢\82Ä\82¢\82é\81D");
+        else if (container_at(cc.x, cc.y, TRUE))
+            pline("%s like something lootable over there.",
+                  Blind ? "Feels" : "Seems");
         else
 /*JP
             You("%s no door there.", Blind ? "feel" : "see");
@@ -889,7 +950,7 @@ int x, y;
             b_trapped("\94à", FINGER);
             door->doormask = D_NODOOR;
             if (*in_rooms(cc.x, cc.y, SHOPBASE))
-                add_damage(cc.x, cc.y, 0L);
+                add_damage(cc.x, cc.y, SHOP_DOOR_COST);
         } else
             door->doormask = D_ISOPEN;
         feel_newsym(cc.x, cc.y); /* the hero knows she opened it */
index 0c0f31e..0467096 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 mail.c  $NHDT-Date: 1436754892 2015/07/13 02:34:52 $  $NHDT-Branch: master $:$NHDT-Revision: 1.20 $ */
+/* NetHack 3.6 mail.c  $NHDT-Date: 1519070343 2018/02/19 19:59:03 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.31 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 #include "hack.h"
 
 #ifdef MAIL
+#ifdef SIMPLE_MAIL
+# include <fcntl.h>
+# include <errno.h>
+#endif /* SIMPLE_MAIL */
 #include "mail.h"
 
 /*
  * Notify user when new mail has arrived.  Idea by Merlyn Leroy.
  *
  * The mail daemon can move with less than usual restraint.  It can:
- *     - move diagonally from a door
- *     - use secret and closed doors
- *     - run through a monster ("Gangway!", etc.)
- *     - run over pools & traps
+ *      - move diagonally from a door
+ *      - use secret and closed doors
+ *      - run through a monster ("Gangway!", etc.)
+ *      - run over pools & traps
  *
  * Possible extensions:
- *     - Open the file MAIL and do fstat instead of stat for efficiency.
- *       (But sh uses stat, so this cannot be too bad.)
- *     - Examine the mail and produce a scroll of mail named "From somebody".
- *     - Invoke MAILREADER in such a way that only this single letter is
- *read.
- *     - Do something to the text when the scroll is enchanted or cancelled.
- *     - Make the daemon always appear at a stairwell, and have it find a
- *       path to the hero.
+ *      - Open the file MAIL and do fstat instead of stat for efficiency.
+ *        (But sh uses stat, so this cannot be too bad.)
+ *      - Examine the mail and produce a scroll of mail named "From somebody".
+ *      - Invoke MAILREADER in such a way that only this single mail is read.
+ *      - Do something to the text when the scroll is enchanted or cancelled.
+ *      - Make the daemon always appear at a stairwell, and have it find a
+ *        path to the hero.
  *
  * Note by Olaf Seibert: On the Amiga, we usually don't get mail.  So we go
- *                      through most of the effects at 'random' moments.
+ *                       through most of the effects at 'random' moments.
  * Note by Paul Winner:  The MSDOS port also 'fakes' the mail daemon at
- *                      random intervals.
+ *                       random intervals.
  */
 
 STATIC_DCL boolean FDECL(md_start, (coord *));
@@ -83,35 +87,53 @@ static long laststattime;
 #endif
 
 void
+free_maildata()
+{
+    if (mailbox)
+        free((genericptr_t) mailbox), mailbox = (char *) 0;
+}
+
+void
 getmailstatus()
 {
-    if (!mailbox && !(mailbox = nh_getenv("MAIL"))) {
+    if (mailbox) {
+        ; /* no need to repeat the setup */
+    } else if ((mailbox = nh_getenv("MAIL")) != 0) {
+        mailbox = dupstr(mailbox);
 #ifdef MAILPATH
+    } else  {
 #ifdef AMS
         struct passwd ppasswd;
 
-        (void) memcpy(&ppasswd, getpwuid(getuid()), sizeof(struct passwd));
+        (void) memcpy(&ppasswd, getpwuid(getuid()), sizeof (struct passwd));
         if (ppasswd.pw_dir) {
-            mailbox = (char *) alloc((unsigned) strlen(ppasswd.pw_dir)
-                                     + sizeof(AMS_MAILBOX));
+            /* note: 'sizeof "LITERAL"' includes +1 for terminating '\0' */
+            mailbox = (char *) alloc((unsigned) (strlen(ppasswd.pw_dir)
+                                                 + sizeof AMS_MAILBOX));
             Strcpy(mailbox, ppasswd.pw_dir);
             Strcat(mailbox, AMS_MAILBOX);
-        } else
-            return;
+        }
 #else
         const char *pw_name = getpwuid(getuid())->pw_name;
-        mailbox = (char *) alloc(sizeof(MAILPATH) + strlen(pw_name));
+
+        /* note: 'sizeof "LITERAL"' includes +1 for terminating '\0' */
+        mailbox = (char *) alloc((unsigned) (strlen(pw_name)
+                                             + sizeof MAILPATH));
         Strcpy(mailbox, MAILPATH);
         Strcat(mailbox, pw_name);
 #endif /* AMS */
-#else
-        return;
-#endif
+#endif /* MAILPATH */
     }
-    if (stat(mailbox, &omstat)) {
+
+    debugpline3("mailbox=%c%s%c",
+                mailbox ? '\"' : '<',
+                mailbox ? mailbox : "null",
+                mailbox ? '\"' : '>');
+
+    if (mailbox && stat(mailbox, &omstat)) {
 #ifdef PERMANENT_MAILBOX
         pline("Cannot get status of MAIL=\"%s\".", mailbox);
-        mailbox = 0;
+        free_maildata(); /* set 'mailbox' to Null */
 #else
         omstat.st_mtime = 0;
 #endif
@@ -449,12 +471,12 @@ ckmailstatus()
         return;
     }
     if (--mustgetmail <= 0) {
-        static struct mail_info deliver = { MSG_MAIL,
+        static struct mail_info deliver = {
 /*JP
-                                            "I have some mail for you", 0,
+            MSG_MAIL, "I have some mail for you", 0, 0
 */
-                                            "\83\81\81[\83\8b\82ð\8e\9d\82Á\82Ä\82«\82½\82æ", 0,
-                                            0 };
+            MSG_MAIL, "\83\81\81[\83\8b\82ð\8e\9d\82Á\82Ä\82«\82½\82æ", 0, 0
+        };
         newmail(&deliver);
         mustgetmail = -1;
     }
@@ -463,7 +485,7 @@ ckmailstatus()
 /*ARGSUSED*/
 void
 readmail(otmp)
-struct obj *otmp;
+struct obj *otmp UNUSED;
 {
     static char *junk[] = {
         NULL, /* placeholder for "Report bugs to <devteam@nethack.org>.", */
@@ -528,6 +550,8 @@ struct obj *otmp;
 void
 ckmailstatus()
 {
+    ck_server_admin_msg();
+
     if (!mailbox || u.uswallow || !flags.biff
 #ifdef MAILCKFREQ
         || moves < laststattime + MAILCKFREQ
@@ -539,7 +563,7 @@ ckmailstatus()
     if (stat(mailbox, &nmstat)) {
 #ifdef PERMANENT_MAILBOX
         pline("Cannot get status of MAIL=\"%s\" anymore.", mailbox);
-        mailbox = 0;
+        free_maildata();
 #else
         nmstat.st_mtime = 0;
 #endif
@@ -566,27 +590,138 @@ ckmailstatus()
     }
 }
 
+#if defined(SIMPLE_MAIL) || defined(SERVER_ADMIN_MSG)
+void
+read_simplemail(mbox, adminmsg)
+char *mbox;
+boolean adminmsg;
+{
+    FILE* mb = fopen(mbox, "r");
+    char curline[128], *msg;
+    boolean seen_one_already = FALSE;
+#ifdef SIMPLE_MAIL
+    struct flock fl = { 0 };
+#endif
+    const char *msgfrom = adminmsg
+        ? "The voice of %s booms through the caverns:"
+        : "This message is from '%s'.";
+
+    if (!mb)
+        goto bail;
+
+#ifdef SIMPLE_MAIL
+    fl.l_type = F_RDLCK;
+    fl.l_whence = SEEK_SET;
+    fl.l_start = 0;
+    fl.l_len = 0;
+    errno = 0;
+#endif
+
+    /* Allow this call to block. */
+    if (!adminmsg
+#ifdef SIMPLE_MAIL
+        && fcntl (fileno (mb), F_SETLKW, &fl) == -1
+#endif
+        )
+        goto bail;
+
+    while (fgets(curline, 128, mb) != NULL) {
+        if (!adminmsg) {
+#ifdef SIMPLE_MAIL
+            fl.l_type = F_UNLCK;
+            fcntl (fileno(mb), F_UNLCK, &fl);
+#endif
+            pline("There is a%s message on this scroll.",
+                  seen_one_already ? "nother" : "");
+        }
+        msg = strchr(curline, ':');
+
+        if (!msg)
+            goto bail;
+
+        *msg = '\0';
+        msg++;
+        msg[strlen(msg) - 1] = '\0'; /* kill newline */
+
+        pline(msgfrom, curline);
+        if (adminmsg)
+            verbalize(msg);
+        else
+            pline("It reads: \"%s\".", msg);
+
+        seen_one_already = TRUE;
+#ifdef SIMPLE_MAIL
+        errno = 0;
+        if (!adminmsg) {
+            fl.l_type = F_RDLCK;
+            fcntl(fileno(mb), F_SETLKW, &fl);
+        }
+#endif
+    }
+
+#ifdef SIMPLE_MAIL
+    if (!adminmsg) {
+        fl.l_type = F_UNLCK;
+        fcntl(fileno(mb), F_UNLCK, &fl);
+    }
+#endif
+    fclose(mb);
+    if (adminmsg)
+        display_nhwindow(WIN_MESSAGE, TRUE);
+    else
+        unlink(mailbox);
+    return;
+bail:
+    /* bail out _professionally_ */
+    if (!adminmsg)
+        pline("It appears to be all gibberish.");
+}
+#endif /* SIMPLE_MAIL */
+
+void
+ck_server_admin_msg()
+{
+#ifdef SERVER_ADMIN_MSG
+    static struct stat ost,nst;
+    static long lastchk = 0;
+
+    if (moves < lastchk + SERVER_ADMIN_MSG_CKFREQ) return;
+    lastchk = moves;
+
+    if (!stat(SERVER_ADMIN_MSG, &nst)) {
+        if (nst.st_mtime > ost.st_mtime)
+            read_simplemail(SERVER_ADMIN_MSG, TRUE);
+        ost.st_mtime = nst.st_mtime;
+    }
+#endif /* SERVER_ADMIN_MSG */
+}
+
 /*ARGSUSED*/
 void
 readmail(otmp)
-struct obj *otmp;
+struct obj *otmp UNUSED;
 {
 #ifdef DEF_MAILREADER /* This implies that UNIX is defined */
     register const char *mr = 0;
-
+#endif /* DEF_MAILREADER */
+#ifdef SIMPLE_MAIL
+    read_simplemail(mailbox, FALSE);
+    return;
+#endif /* SIMPLE_MAIL */
+#ifdef DEF_MAILREADER /* This implies that UNIX is defined */
     display_nhwindow(WIN_MESSAGE, FALSE);
     if (!(mr = nh_getenv("MAILREADER")))
         mr = DEF_MAILREADER;
 
     if (child(1)) {
         (void) execl(mr, mr, (char *) 0);
-        terminate(EXIT_FAILURE);
+        nh_terminate(EXIT_FAILURE);
     }
 #else
 #ifndef AMS /* AMS mailboxes are directories */
     display_file(mailbox, TRUE);
-#endif      /* AMS */
-#endif      /* DEF_MAILREADER */
+#endif /* AMS */
+#endif /* DEF_MAILREADER */
 
     /* get new stat; not entirely correct: there is a small time
        window where we do not see new mail */
@@ -624,7 +759,7 @@ struct obj *otmp;
 {
 #ifdef SHELL /* can't access mail reader without spawning subprocess */
     const char *txt, *cmd;
-    char *p, buf[BUFSZ], qbuf[BUFSZ];
+    char *p, buf[BUFSZ] = DUMMY, qbuf[BUFSZ];
     int len;
 
     /* there should be a command in OMAILCMD */
@@ -652,6 +787,8 @@ struct obj *otmp;
         vms_doshell(cmd, TRUE);
         (void) sleep(1);
     }
+#else
+    nhUse(otmp);
 #endif /* SHELL */
 }
 
index 4e6600d..488a3ee 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 makemon.c       $NHDT-Date: 1449269917 2015/12/04 22:58:37 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.105 $ */
+/* NetHack 3.6 makemon.c       $NHDT-Date: 1495237801 2017/05/19 23:50:01 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.116 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -11,8 +12,6 @@
 
 #include <ctype.h>
 
-STATIC_VAR NEARDATA struct monst zeromonst;
-
 /* this assumes that a human quest leader or nemesis is an archetype
    of the corresponding role; that isn't so for some roles (tourist
    for instance) but is for the priests and monks we use it for... */
@@ -28,7 +27,8 @@ STATIC_DCL void FDECL(m_initgrp, (struct monst *, int, int, int));
 STATIC_DCL void FDECL(m_initthrow, (struct monst *, int, int));
 STATIC_DCL void FDECL(m_initweap, (struct monst *));
 STATIC_DCL void FDECL(m_initinv, (struct monst *));
-STATIC_DCL boolean FDECL(makemon_rnd_goodpos, (struct monst *, unsigned, coord *));
+STATIC_DCL boolean FDECL(makemon_rnd_goodpos, (struct monst *,
+                                               unsigned, coord *));
 
 extern const int monstr[];
 
@@ -275,6 +275,58 @@ register struct monst *mtmp;
         } else if (mm == PM_NINJA) { /* extra quest villains */
             (void) mongets(mtmp, rn2(4) ? SHURIKEN : DART);
             (void) mongets(mtmp, rn2(4) ? SHORT_SWORD : AXE);
+        } else if (ptr->msound == MS_GUARDIAN) {
+            /* quest "guardians" */
+            switch (mm) {
+            case PM_STUDENT:
+            case PM_ATTENDANT:
+            case PM_ABBOT:
+            case PM_ACOLYTE:
+            case PM_GUIDE:
+            case PM_APPRENTICE:
+                if (rn2(2))
+                    (void) mongets(mtmp, rn2(3) ? DAGGER : KNIFE);
+                if (rn2(5))
+                    (void) mongets(mtmp, rn2(3) ? LEATHER_JACKET : LEATHER_CLOAK);
+                if (rn2(3))
+                    (void) mongets(mtmp, rn2(3) ? LOW_BOOTS : HIGH_BOOTS);
+                if (rn2(3))
+                    (void) mongets(mtmp, POT_HEALING);
+                break;
+            case PM_CHIEFTAIN:
+            case PM_PAGE:
+            case PM_ROSHI:
+            case PM_WARRIOR:
+                (void) mongets(mtmp, rn2(3) ? LONG_SWORD : SHORT_SWORD);
+                (void) mongets(mtmp, rn2(3) ? CHAIN_MAIL : LEATHER_ARMOR);
+                if (rn2(2))
+                    (void) mongets(mtmp, rn2(2) ? LOW_BOOTS : HIGH_BOOTS);
+                if (!rn2(3))
+                    (void) mongets(mtmp, LEATHER_CLOAK);
+                if (!rn2(3)) {
+                    (void) mongets(mtmp, BOW);
+                    m_initthrow(mtmp, ARROW, 12);
+                }
+                break;
+            case PM_HUNTER:
+                (void) mongets(mtmp, rn2(3) ? SHORT_SWORD : DAGGER);
+                if (rn2(2))
+                    (void) mongets(mtmp, rn2(2) ? LEATHER_JACKET : LEATHER_ARMOR);
+                (void) mongets(mtmp, BOW);
+                m_initthrow(mtmp, ARROW, 12);
+                break;
+            case PM_THUG:
+                (void) mongets(mtmp, CLUB);
+                (void) mongets(mtmp, rn2(3) ? DAGGER : KNIFE);
+                if (rn2(2))
+                    (void) mongets(mtmp, LEATHER_GLOVES);
+                (void) mongets(mtmp, rn2(2) ? LEATHER_JACKET : LEATHER_ARMOR);
+                break;
+            case PM_NEANDERTHAL:
+                (void) mongets(mtmp, CLUB);
+                (void) mongets(mtmp, LEATHER_ARMOR);
+                break;
+            }
         }
         break;
 
@@ -604,6 +656,8 @@ register struct monst *mtmp;
             else if (mac < 10 && rn2(2))
                 mac += 1 + mongets(mtmp, LEATHER_CLOAK);
 
+            nhUse(mac); /* suppress 'dead increment' from static analyzer */
+
             if (ptr != &mons[PM_GUARD] && ptr != &mons[PM_WATCHMAN]
                 && ptr != &mons[PM_WATCH_CAPTAIN]) {
                 if (!rn2(3))
@@ -620,10 +674,13 @@ register struct monst *mtmp;
             /* MAJOR fall through ... */
             case 0:
                 (void) mongets(mtmp, WAN_MAGIC_MISSILE);
+                /*FALLTHRU*/
             case 1:
                 (void) mongets(mtmp, POT_EXTRA_HEALING);
+                /*FALLTHRU*/
             case 2:
                 (void) mongets(mtmp, POT_HEALING);
+                /*FALLTHRU*/
             case 3:
                 (void) mongets(mtmp, WAN_STRIKING);
             }
@@ -774,6 +831,7 @@ xchar x, y; /* clone's preferred location or 0 (near mon) */
     /* Max HP the same, but current HP halved for both.  The caller
      * might want to override this by halving the max HP also.
      * When current HP is odd, the original keeps the extra point.
+     * We know original has more than 1 HP, so both end up with at least 1.
      */
     m2->mhpmax = mon->mhpmax;
     m2->mhp = mon->mhp / 2;
@@ -854,7 +912,7 @@ boolean ghostly;
     result = (((int) mvitals[mndx].born < lim) && !gone) ? TRUE : FALSE;
 
     /* if it's unique, don't ever make it again */
-    if (mons[mndx].geno & G_UNIQ)
+    if ((mons[mndx].geno & G_UNIQ) && mndx != PM_HIGH_PRIEST)
         mvitals[mndx].mvflags |= G_EXTINCT;
 
     if (mvitals[mndx].born < 255 && tally
@@ -1305,6 +1363,13 @@ int mmflags;
             m_initweap(mtmp); /* equip with weapons / armor */
         m_initinv(mtmp); /* add on a few special items incl. more armor */
         m_dowear(mtmp, TRUE);
+
+        if (!rn2(100) && is_domestic(ptr)
+            && can_saddle(mtmp) && !which_armor(mtmp, W_SADDLE)) {
+            struct obj *otmp = mksobj(SADDLE, TRUE, FALSE);
+            put_saddle_on_mon(otmp, mtmp);
+        }
+
     } else {
         /* no initial inventory is allowed */
         if (mtmp->minvent)
@@ -1330,6 +1395,11 @@ int
 mbirth_limit(mndx)
 int mndx;
 {
+    /* There is an implicit limit of 4 for "high priest of <deity>",
+     * but aligned priests can grow into high priests, thus they aren't
+     * really limited to 4, so leave the default amount in place for them.
+     */
+
     /* assert(MAXMONNO < 255); */
     return (mndx == PM_NAZGUL ? 9 : mndx == PM_ERINYS ? 3 : MAXMONNO);
 }
@@ -1466,7 +1536,7 @@ rndmonst()
             rndmonst_state.mchoices[mndx] = 0;
             if (tooweak(mndx, minmlev) || toostrong(mndx, maxmlev))
                 continue;
-            if (upper && !isupper(def_monsyms[(int) (ptr->mlet)].sym))
+            if (upper && !isupper((uchar) def_monsyms[(int) ptr->mlet].sym))
                 continue;
             if (elemlevel && wrong_elem_type(ptr))
                 continue;
@@ -1671,6 +1741,7 @@ grow_up(mtmp, victim)
 struct monst *mtmp, *victim;
 {
     int oldtype, newtype, max_increase, cur_increase, lev_limit, hp_threshold;
+    unsigned fem;
     struct permonst *ptr = mtmp->data;
 
     /* monster died after killing enemy but before calling this function */
@@ -1733,9 +1804,12 @@ struct monst *mtmp, *victim;
 
     if ((int) ++mtmp->m_lev >= mons[newtype].mlevel && newtype != oldtype) {
         ptr = &mons[newtype];
+        /* new form might force gender change */
+        fem = is_male(ptr) ? 0 : is_female(ptr) ? 1 : mtmp->female;
+
         if (mvitals[newtype].mvflags & G_GENOD) { /* allow G_EXTINCT */
             if (canspotmon(mtmp))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 pline("As %s grows up into %s, %s %s!", mon_nam(mtmp),
                       an(ptr->mname), mhe(mtmp),
                       nonliving(ptr) ? "expires" : "dies");
@@ -1748,11 +1822,26 @@ struct monst *mtmp, *victim;
             mondied(mtmp);
             return (struct permonst *) 0;
         } else if (canspotmon(mtmp)) {
+            char buf[BUFSZ];
+
+            /* 3.6.1:
+             * Temporary (?) hack to fix growing into opposite gender.
+             */
 #if 0 /*JP*/
+            Sprintf(buf, "%s%s",
+                    /* deal with female gnome becoming a gnome lord */
+                    (mtmp->female && !fem) ? "male "
+                        /* or a male gnome becoming a gnome lady
+                           (can't happen with 3.6.0 mons[], but perhaps
+                           slightly less sexist if prepared for it...) */
+                      : (fem && !mtmp->female) ? "female " : "",
+                    ptr->mname);
             pline("%s %s %s.", Monnam(mtmp),
-                  humanoid(ptr) ? "becomes" : "grows up into",
-                  an(ptr->mname));
-#else
+                  (fem != mtmp->female) ? "changes into"
+                                        : humanoid(ptr) ? "becomes"
+                                                        : "grows up into",
+                  an(buf));
+#else /* \93ú\96{\8cê\82Å\82Í\82Æ\82è\82 \82¦\82¸\82»\82±\82Ü\82Å\82Í\82µ\82È\82¢ */
             pline("%s\82Í%s\82É%s\81D", Monnam(mtmp),
                   ptr->mname,
                   humanoid(ptr) ? "\82È\82Á\82½" : "\90¬\92·\82µ\82½");
@@ -1761,7 +1850,10 @@ struct monst *mtmp, *victim;
         set_mon_data(mtmp, ptr, 1);    /* preserve intrinsics */
         newsym(mtmp->mx, mtmp->my);    /* color may change */
         lev_limit = (int) mtmp->m_lev; /* never undo increment */
+
+        mtmp->female = fem; /* gender might be changing */
     }
+
     /* sanity checks */
     if ((int) mtmp->m_lev > lev_limit) {
         mtmp->m_lev--; /* undo increment */
@@ -2003,7 +2095,7 @@ register struct monst *mtmp;
     struct obj *otmp;
     int mx, my;
 
-    if (!mtmp)
+    if (!mtmp || Protection_from_shape_changers)
         return;
     mx = mtmp->mx;
     my = mtmp->my;
index 45bb651..6455ec7 100644 (file)
@@ -59,6 +59,9 @@ static int explcolors[] = {
     (currentgraphics == ROGUESET && SYMHANDLING(H_IBM))
 #endif
 
+#define is_objpile(x,y) (!Hallucination && level.objects[(x)][(y)] \
+                         && level.objects[(x)][(y)]->nexthere)
+
 /*ARGSUSED*/
 int
 mapglyph(glyph, ochar, ocolor, ospecial, x, y)
@@ -88,7 +91,7 @@ unsigned *ospecial;
         else
             obj_color(STATUE);
         special |= MG_STATUE;
-        if (level.objects[x][y] && level.objects[x][y]->nexthere)
+        if (is_objpile(x,y))
             special |= MG_OBJPILE;
     } else if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) { /* warn flash */
         idx = offset + SYM_OFF_W;
@@ -129,11 +132,17 @@ unsigned *ospecial;
                 color = NO_COLOR;
 #ifdef TEXTCOLOR
         /* provide a visible difference if normal and lit corridor
-         * use the same symbol */
+           use the same symbol */
         } else if (iflags.use_color && offset == S_litcorr
                    && showsyms[idx] == showsyms[S_corr + SYM_OFF_P]) {
             color = CLR_WHITE;
 #endif
+        /* try to provide a visible difference between water and lava
+           if they use the same symbol and color is disabled */
+        } else if (!iflags.use_color && offset == S_lava
+                   && (showsyms[idx] == showsyms[S_pool + SYM_OFF_P]
+                       || showsyms[idx] == showsyms[S_water + SYM_OFF_P])) {
+            special |= MG_BW_LAVA;
         } else {
             cmap_color(offset);
         }
@@ -155,8 +164,7 @@ unsigned *ospecial;
             }
         } else
             obj_color(offset);
-        if (offset != BOULDER && level.objects[x][y]
-            && level.objects[x][y]->nexthere)
+        if (offset != BOULDER && is_objpile(x,y))
             special |= MG_OBJPILE;
     } else if ((offset = (glyph - GLYPH_RIDDEN_OFF)) >= 0) { /* mon ridden */
         idx = mons[offset].mlet + SYM_OFF_M;
@@ -175,7 +183,7 @@ unsigned *ospecial;
         else
             mon_color(offset);
         special |= MG_CORPSE;
-        if (level.objects[x][y] && level.objects[x][y]->nexthere)
+        if (is_objpile(x,y))
             special |= MG_OBJPILE;
     } else if ((offset = (glyph - GLYPH_DETECT_OFF)) >= 0) { /* mon detect */
         idx = mons[offset].mlet + SYM_OFF_M;
index 01712c8..4d52f09 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 mcastu.c        $NHDT-Date: 1436753517 2015/07/13 02:11:57 $  $NHDT-Branch: master $:$NHDT-Revision: 1.44 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 #include "hack.h"
 
 /* monster mage spells */
-#define MGC_PSI_BOLT 0
-#define MGC_CURE_SELF 1
-#define MGC_HASTE_SELF 2
-#define MGC_STUN_YOU 3
-#define MGC_DISAPPEAR 4
-#define MGC_WEAKEN_YOU 5
-#define MGC_DESTRY_ARMR 6
-#define MGC_CURSE_ITEMS 7
-#define MGC_AGGRAVATION 8
-#define MGC_SUMMON_MONS 9
-#define MGC_CLONE_WIZ 10
-#define MGC_DEATH_TOUCH 11
+enum mcast_mage_spells {
+    MGC_PSI_BOLT = 0,
+    MGC_CURE_SELF,
+    MGC_HASTE_SELF,
+    MGC_STUN_YOU,
+    MGC_DISAPPEAR,
+    MGC_WEAKEN_YOU,
+    MGC_DESTRY_ARMR,
+    MGC_CURSE_ITEMS,
+    MGC_AGGRAVATION,
+    MGC_SUMMON_MONS,
+    MGC_CLONE_WIZ,
+    MGC_DEATH_TOUCH
+};
 
 /* monster cleric spells */
-#define CLC_OPEN_WOUNDS 0
-#define CLC_CURE_SELF 1
-#define CLC_CONFUSE_YOU 2
-#define CLC_PARALYZE 3
-#define CLC_BLIND_YOU 4
-#define CLC_INSECTS 5
-#define CLC_CURSE_ITEMS 6
-#define CLC_LIGHTNING 7
-#define CLC_FIRE_PILLAR 8
-#define CLC_GEYSER 9
+enum mcast_cleric_spells {
+    CLC_OPEN_WOUNDS = 0,
+    CLC_CURE_SELF,
+    CLC_CONFUSE_YOU,
+    CLC_PARALYZE,
+    CLC_BLIND_YOU,
+    CLC_INSECTS,
+    CLC_CURSE_ITEMS,
+    CLC_LIGHTNING,
+    CLC_FIRE_PILLAR,
+    CLC_GEYSER
+};
 
 STATIC_DCL void FDECL(cursetxt, (struct monst *, BOOLEAN_P));
 STATIC_DCL int FDECL(choose_magic_spell, (int));
@@ -109,7 +114,7 @@ int spellval;
     case 23:
         if (Antimagic || Hallucination)
             return MGC_PSI_BOLT;
-    /* else FALL THROUGH */
+        /*FALLTHRU*/
     case 22:
     case 21:
     case 20:
@@ -164,7 +169,7 @@ int spellnum;
     case 14:
         if (rn2(3))
             return CLC_OPEN_WOUNDS;
-    /* else FALL THROUGH */
+        /*FALLTHRU*/
     case 13:
         return CLC_GEYSER;
     case 12:
@@ -317,8 +322,8 @@ boolean foundyou;
     }
 
     /*
-     * As these are spells, the damage is related to the level
-     * of the monster casting the spell.
+     * As these are spells, the damage is related to the level
+     * of the monster casting the spell.
      */
     if (!foundyou) {
         dmg = 0;
@@ -568,6 +573,8 @@ int spellnum;
                       !See_invisible ? "\8fÁ\82¦\82½" : "\93§\96¾\82É\82È\82Á\82½");
 #endif
             mon_set_minvis(mtmp);
+            if (cansee(mtmp->mx, mtmp->my) && !canspotmon(mtmp))
+                map_invisible(mtmp->mx, mtmp->my);
             dmg = 0;
         } else
             impossible("no reason for monster to cast disappear spell?");
@@ -1031,20 +1038,11 @@ int spellnum;
             return TRUE;
         /* aggravation (global wakeup) when everyone is already active */
         if (spellnum == MGC_AGGRAVATION) {
-            struct monst *nxtmon;
-
-            for (nxtmon = fmon; nxtmon; nxtmon = nxtmon->nmon) {
-                if (DEADMONSTER(nxtmon))
-                    continue;
-                if ((nxtmon->mstrategy & STRAT_WAITFORU) != 0
-                    || nxtmon->msleeping || !nxtmon->mcanmove)
-                    break;
-            }
             /* if nothing needs to be awakened then this spell is useless
                but caster might not realize that [chance to pick it then
                must be very small otherwise caller's many retry attempts
                will eventually end up picking it too often] */
-            if (!nxtmon)
+            if (!has_aggravatables(mtmp))
                 return rn2(100) ? TRUE : FALSE;
         }
     } else if (adtyp == AD_CLRC) {
index 087ade0..4703d36 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 mhitm.c $NHDT-Date: 1446854229 2015/11/06 23:57:09 $  $NHDT-Branch: master $:$NHDT-Revision: 1.83 $ */
+/* NetHack 3.6 mhitm.c $NHDT-Date: 1513297346 2017/12/15 00:22:26 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.99 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -335,7 +336,7 @@ register struct monst *magr, *mdef;
 {
     int i,          /* loop counter */
         tmp,        /* amour class difference */
-        strike,     /* hit this attack */
+        strike = 0, /* hit this attack */
         attk,       /* attack attempted this time */
         struck = 0, /* hit at least once */
         res[NATTK]; /* results of all attacks */
@@ -366,15 +367,20 @@ register struct monst *magr, *mdef;
         mdef->mundetected = 0;
         newsym(mdef->mx, mdef->my);
         if (canseemon(mdef) && !sensemon(mdef)) {
-            if (Unaware)
+            if (Unaware) {
 #if 0 /*JP*/
-                You("dream of %s.", (mdef->data->geno & G_UNIQ)
-                                        ? a_monnam(mdef)
-                                        : makeplural(m_monnam(mdef)));
+                boolean justone = (mdef->data->geno & G_UNIQ) != 0L;
+                const char *montype;
+
+                montype = noname_monnam(mdef, justone ? ARTICLE_THE
+                                                      : ARTICLE_NONE);
+                if (!justone)
+                    montype = makeplural(montype);
+                You("dream of %s.", montype);
 #else
                 You("%s\82Ì\96²\82ð\8c©\82½\81D", a_monnam(mdef));
 #endif
-            else
+            else
 /*JP
                 pline("Suddenly, you notice %s.", a_monnam(mdef));
 */
@@ -400,11 +406,20 @@ register struct monst *magr, *mdef;
     /* Now perform all attacks for the monster. */
     for (i = 0; i < NATTK; i++) {
         res[i] = MM_MISS;
-        mattk = getmattk(pa, i, res, &alt_attk);
+        mattk = getmattk(magr, mdef, i, res, &alt_attk);
         otmp = (struct obj *) 0;
         attk = 1;
         switch (mattk->aatyp) {
         case AT_WEAP: /* "hand to hand" attacks */
+            if (distmin(magr->mx, magr->my, mdef->mx, mdef->my) > 1) {
+                /* D: Do a ranged attack here! */
+                strike = thrwmm(magr, mdef);
+                if (DEADMONSTER(mdef))
+                    res[i] = MM_DEF_DIED;
+                if (DEADMONSTER(magr))
+                    res[i] |= MM_AGR_DIED;
+                break;
+            }
             if (magr->weapon_check == NEED_WEAPON || !MON_WEP(magr)) {
                 magr->weapon_check = NEED_HTH_WEAPON;
                 if (mon_wield_item(magr) != 0)
@@ -428,7 +443,8 @@ register struct monst *magr, *mdef;
         case AT_TENT:
             /* Nymph that teleported away on first attack? */
             if (distmin(magr->mx, magr->my, mdef->mx, mdef->my) > 1)
-                return MM_MISS;
+                /* Continue because the monster may have a ranged attack. */
+                continue;
             /* Monsters won't attack cockatrices physically if they
              * have a weapon instead.  This instinct doesn't work for
              * players, or under conflict or confusion.
@@ -446,12 +462,13 @@ register struct monst *magr, *mdef;
             if (strike) {
                 res[i] = hitmm(magr, mdef, mattk);
                 if ((mdef->data == &mons[PM_BLACK_PUDDING]
-                     || mdef->data == &mons[PM_BROWN_PUDDING]) && otmp
-                    && objects[otmp->otyp].oc_material == IRON
+                     || mdef->data == &mons[PM_BROWN_PUDDING])
+                    && (otmp && (objects[otmp->otyp].oc_material == IRON
+                                 || objects[otmp->otyp].oc_material == METAL))
                     && mdef->mhp > 1
                     && !mdef->mcan) {
                     if (clone_mon(mdef, 0, 0)) {
-                        if (vis) {
+                        if (vis && canspotmon(mdef)) {
                             char buf[BUFSZ];
 
                             Strcpy(buf, Monnam(mdef));
@@ -482,6 +499,10 @@ register struct monst *magr, *mdef;
             break;
 
         case AT_EXPL:
+            /* D: Prevent explosions from a distance */
+            if (distmin(magr->mx,magr->my,mdef->mx,mdef->my) > 1)
+                continue;
+
             res[i] = explmm(magr, mdef, mattk);
             if (res[i] == MM_MISS) { /* cancelled--no attack */
                 strike = 0;
@@ -491,20 +512,49 @@ register struct monst *magr, *mdef;
             break;
 
         case AT_ENGL:
-            if (u.usteed && (mdef == u.usteed)) {
+            if (u.usteed && mdef == u.usteed) {
                 strike = 0;
                 break;
             }
-            /* Engulfing attacks are directed at the hero if
-             * possible. -dlc
-             */
+            /* D: Prevent engulf from a distance */
+            if (distmin(magr->mx, magr->my, mdef->mx, mdef->my) > 1)
+                continue;
+            /* Engulfing attacks are directed at the hero if possible. -dlc */
             if (u.uswallow && magr == u.ustuck)
                 strike = 0;
-            else {
-                if ((strike = (tmp > rnd(20 + i))))
-                    res[i] = gulpmm(magr, mdef, mattk);
-                else
-                    missmm(magr, mdef, mattk);
+            else if ((strike = (tmp > rnd(20 + i))) != 0)
+                res[i] = gulpmm(magr, mdef, mattk);
+            else
+                missmm(magr, mdef, mattk);
+            break;
+
+        case AT_BREA:
+            if (!monnear(magr, mdef->mx, mdef->my)) {
+                strike = breamm(magr, mattk, mdef);
+
+                /* We don't really know if we hit or not; pretend we did. */
+                if (strike)
+                    res[i] |= MM_HIT;
+                if (DEADMONSTER(mdef))
+                    res[i] = MM_DEF_DIED;
+                if (DEADMONSTER(magr))
+                    res[i] |= MM_AGR_DIED;
+            }
+            else
+                strike = 0;
+            break;
+
+        case AT_SPIT:
+            if (!monnear(magr, mdef->mx, mdef->my)) {
+                strike = spitmm(magr, mattk, mdef);
+
+                /* We don't really know if we hit or not; pretend we did. */
+                if (strike)
+                    res[i] |= MM_HIT;
+                if (DEADMONSTER(mdef))
+                    res[i] = MM_DEF_DIED;
+                if (DEADMONSTER(magr))
+                    res[i] |= MM_AGR_DIED;
             }
             break;
 
@@ -514,12 +564,12 @@ register struct monst *magr, *mdef;
             break;
         }
 
-        if (attk && !(res[i] & MM_AGR_DIED))
+        if (attk && !(res[i] & MM_AGR_DIED)
+            && distmin(magr->mx, magr->my, mdef->mx, mdef->my) <= 1)
             res[i] = passivemm(magr, mdef, strike, res[i] & MM_DEF_DIED);
 
         if (res[i] & MM_DEF_DIED)
             return res[i];
-
         if (res[i] & MM_AGR_DIED)
             return res[i];
         /* return if aggressor can no longer attack */
@@ -595,7 +645,7 @@ struct attack *mattk;
 /*JP
                 Sprintf(buf, "%s tentacles suck", s_suffix(magr_name));
 */
-                Sprintf(buf, "%s\82Ì\90G\8eè\82ª%%s\82Ì\91Ì\89t\82ð\8bz\82¢\82Æ\82Á\82½\81D", s_suffix(magr_name));
+                Sprintf(buf, "%s\82Ì\90G\8eè\82ª%%s\82Ì\91Ì\89t\82ð\8bz\82¢\82Æ\82Á\82½\81D", magr_name);
                 break;
             case AT_HUGS:
                 if (magr != u.ustuck) {
@@ -605,6 +655,7 @@ struct attack *mattk;
                     Sprintf(buf,"%s\82Í%%s\82ð\8di\82ß\82½\81D", magr_name);
                     break;
                 }
+                /*FALLTHRU*/
             default:
 /*JP
                 Sprintf(buf, "%s hits", magr_name);
@@ -632,19 +683,22 @@ struct attack *mattk;
     char buf[BUFSZ];
 
     if (vis) {
+        if (mdef->data->mlet == S_MIMIC
+            && mdef->m_ap_type != M_AP_NOTHING)
+            seemimic(mdef);
 #if 0 /*JP*/
         Sprintf(buf, "%s gazes at", Monnam(magr));
-        pline("%s %s...", buf, mon_nam(mdef));
+        pline("%s %s...", buf,
+              canspotmon(mdef) ? mon_nam(mdef) : "something");
 #else
         Sprintf(buf, "%s\82Í%%s\82ð\82É\82ç\82Ý\82Â\82¯\82½\81D\81D\81D", Monnam(magr));
-        pline(buf, mon_nam(mdef));
+        pline(buf, canspotmon(mdef) ? mon_nam(mdef) : "\89½\82©");
 #endif
     }
 
-    if (magr->mcan || !magr->mcansee
-        || (magr->minvis && !perceives(mdef->data)) || !mdef->mcansee
-        || mdef->msleeping) {
-        if (vis)
+    if (magr->mcan || !magr->mcansee || !mdef->mcansee
+        || (magr->minvis && !perceives(mdef->data)) || mdef->msleeping) {
+        if (vis && canspotmon(mdef))
 /*JP
             pline("but nothing happens.");
 */
@@ -661,11 +715,13 @@ struct attack *mattk;
         if (mdef->mcansee) {
             if (mon_reflects(magr, (char *) 0)) {
                 if (canseemon(magr))
-                    (void) mon_reflects(
-/*JP
-                        magr, "The gaze is reflected away by %s %s.");
-*/
-                        magr, "\82É\82ç\82Ý\82Í%s\82Ì%s\82Å\94½\8eË\82µ\82½\81D");
+#if 0 /*JP*/
+                    (void) mon_reflects(magr,
+                                      "The gaze is reflected away by %s %s.");
+#else
+                    (void) mon_reflects(magr,
+                                      "\82É\82ç\82Ý\82Í%s\82Ì%s\82Å\94½\8eË\82µ\82½\81D");
+#endif
                 return MM_MISS;
             }
             if (mdef->minvis && !perceives(magr->data)) {
@@ -743,6 +799,9 @@ register struct attack *mattk;
         return MM_MISS;
 
     if (vis) {
+        /* [this two-part formatting dates back to when only one x_monnam
+           result could be included in an expression because the next one
+           would overwrite first's result -- that's no longer the case] */
 #if 0 /*JP*/
         Sprintf(buf, "%s swallows", Monnam(magr));
         pline("%s %s.", buf, mon_nam(mdef));
@@ -754,6 +813,19 @@ register struct attack *mattk;
     for (obj = mdef->minvent; obj; obj = obj->nobj)
         (void) snuff_lit(obj);
 
+    if (is_vampshifter(mdef)
+        && newcham(mdef, &mons[mdef->cham], FALSE, FALSE)) {
+        if (vis) {
+            /* 'it' -- previous form is no longer available and
+               using that would be excessively verbose */
+            pline("%s expels %s.", Monnam(magr),
+                  canspotmon(mdef) ? "it" : something);
+            if (canspotmon(mdef))
+                pline("It turns into %s.", a_monnam(mdef));
+        }
+        return MM_HIT; /* bypass mdamagem() */
+    }
+
     /*
      *  All of this manipulation is needed to keep the display correct.
      *  There is a flush at the next pline().
@@ -791,13 +863,14 @@ register struct attack *mattk;
     } else if (status & MM_AGR_DIED) { /* aggressor died */
         place_monster(mdef, dx, dy);
         newsym(dx, dy);
-    } else { /* both alive, put them back */
+    } else {                           /* both alive, put them back */
         if (cansee(dx, dy))
 /*JP
             pline("%s is regurgitated!", Monnam(mdef));
 */
             pline("%s\82Í\93f\82«\96ß\82³\82ê\82½\81I", Monnam(mdef));
 
+        remove_monster(dx,dy);
         place_monster(magr, ax, ay);
         place_monster(mdef, dx, dy);
         newsym(ax, ay);
@@ -874,7 +947,7 @@ register struct attack *mattk;
                 mon_to_stone(magr);
                 return MM_HIT; /* no damage during the polymorph */
             }
-            if (vis)
+            if (vis && canspotmon(magr))
 /*JP
                 pline("%s turns to stone!", Monnam(magr));
 */
@@ -899,8 +972,8 @@ register struct attack *mattk;
     case AD_DGST:
         /* eating a Rider or its corpse is fatal */
         if (is_rider(pd)) {
-            if (vis)
-#if 0 /*JP*/
+            if (vis && canseemon(magr))
+#if 0 /*JP:T*/
                 pline("%s %s!", Monnam(magr),
                       (pd == &mons[PM_FAMINE])
                           ? "belches feebly, shrivels up and dies"
@@ -910,10 +983,10 @@ register struct attack *mattk;
 #else
                 pline("%s%s\81I", Monnam(magr),
                       (pd == &mons[PM_FAMINE])
-                      ? "\8eã\81X\82µ\82­\93f\82«\82à\82Ç\82µ\82½\82©\82Æ\8ev\82¤\82Æ\81C\91Ì\82ª\82µ\82Ú\82Ý\8e\80\82ñ\82Å\82µ\82Ü\82Á\82½" :
-                      pd == &mons[PM_PESTILENCE]
-                      ? "áz\9d¹\82µ\82½\82æ\82¤\82É\82¹\82«\82±\82Ý\93|\82ê\82½"
-                      : "\8c\83\82µ\82­\9aq\93f\82µ\8e\80\82ñ\82¾");
+                          ? "\8eã\81X\82µ\82­\93f\82«\82à\82Ç\82µ\82½\82©\82Æ\8ev\82¤\82Æ\81C\91Ì\82ª\82µ\82Ú\82Ý\8e\80\82ñ\82Å\82µ\82Ü\82Á\82½"
+                          : (pd == &mons[PM_PESTILENCE])
+                                ? "áz\9d¹\82µ\82½\82æ\82¤\82É\82¹\82«\82±\82Ý\93|\82ê\82½"
+                                : "\8c\83\82µ\82­\9aq\93f\82µ\8e\80\82ñ\82¾");
 #endif
             mondied(magr);
             if (magr->mhp > 0)
@@ -988,10 +1061,17 @@ register struct attack *mattk;
             tmp = 0;
         } else if (mattk->aatyp == AT_WEAP) {
             if (otmp) {
+                struct obj *marmg;
+
                 if (otmp->otyp == CORPSE
                     && touch_petrifies(&mons[otmp->corpsenm]))
                     goto do_stone;
                 tmp += dmgval(otmp, mdef);
+                if ((marmg = which_armor(magr, W_ARMG)) != 0
+                    && marmg->otyp == GAUNTLETS_OF_POWER)
+                    tmp += rn1(4, 3); /* 3..6 */
+                if (tmp < 1) /* is this necessary?  mhitu.c has it... */
+                    tmp = 1;
                 if (otmp->oartifact) {
                     (void) artifact_hit(magr, mdef, otmp, &tmp, dieroll);
                     if (mdef->mhp <= 0)
@@ -1015,18 +1095,18 @@ register struct attack *mattk;
             tmp = 0;
             break;
         }
-        if (vis)
+        if (vis && canseemon(mdef))
 /*JP
             pline("%s is %s!", Monnam(mdef), on_fire(pd, mattk));
 */
             pline("%s\82Í%s\81I", Monnam(mdef), on_fire(pd, mattk));
-        if (pd == &mons[PM_STRAW_GOLEM] || pd == &mons[PM_PAPER_GOLEM]) {
-            if (vis)
+        if (completelyburns(pd)) { /* paper golem or straw golem */
+            if (vis && canseemon(mdef))
 /*JP
                 pline("%s burns completely!", Monnam(mdef));
 */
                 pline("%s\82Í\8aD\82É\82È\82Á\82½\81I", Monnam(mdef));
-            mondied(mdef);
+            mondead(mdef); /* was mondied() but that dropped paper scrolls */
             if (mdef->mhp > 0)
                 return 0;
             else if (mdef->mtame && !vis)
@@ -1039,7 +1119,7 @@ register struct attack *mattk;
         tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
         tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
         if (resists_fire(mdef)) {
-            if (vis)
+            if (vis && canseemon(mdef))
 /*JP
                 pline_The("fire doesn't seem to burn %s!", mon_nam(mdef));
 */
@@ -1056,13 +1136,13 @@ register struct attack *mattk;
             tmp = 0;
             break;
         }
-        if (vis)
+        if (vis && canseemon(mdef))
 /*JP
             pline("%s is covered in frost!", Monnam(mdef));
 */
             pline("%s\82Í\95X\82Å\95¢\82í\82ê\82½\81I", Monnam(mdef));
         if (resists_cold(mdef)) {
-            if (vis)
+            if (vis && canseemon(mdef))
 /*JP
                 pline_The("frost doesn't seem to chill %s!", mon_nam(mdef));
 */
@@ -1078,14 +1158,14 @@ register struct attack *mattk;
             tmp = 0;
             break;
         }
-        if (vis)
+        if (vis && canseemon(mdef))
 /*JP
             pline("%s gets zapped!", Monnam(mdef));
 */
             pline("%s\82Í\8fÕ\8c\82\82ð\82­\82ç\82Á\82½\81I", Monnam(mdef));
         tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
         if (resists_elec(mdef)) {
-            if (vis)
+            if (vis && canseemon(mdef))
 /*JP
                 pline_The("zap doesn't shock %s!", mon_nam(mdef));
 */
@@ -1103,18 +1183,20 @@ register struct attack *mattk;
             break;
         }
         if (resists_acid(mdef)) {
-            if (vis)
-/*JP
-                pline("%s is covered in acid, but it seems harmless.",
-*/
-                pline("%s\82Í\8e_\82É\82Â\82Â\82Ü\82ê\82½\81D\82µ\82©\82µ\82È\82ñ\82Æ\82à\82È\82¢\82æ\82¤\82¾\81D",
-                      Monnam(mdef));
+            if (vis && canseemon(mdef))
+#if 0 /*JP*/
+                pline("%s is covered in %s, but it seems harmless.",
+                      Monnam(mdef), hliquid("acid"));
+#else
+                pline("%s\82Í%s\82É\82Â\82Â\82Ü\82ê\82½\81D\82µ\82©\82µ\82È\82ñ\82Æ\82à\82È\82¢\82æ\82¤\82¾\81D",
+                      Monnam(mdef), hliquid("\8e_"));
+#endif
             tmp = 0;
-        } else if (vis) {
+        } else if (vis && canseemon(mdef)) {
 /*JP
-            pline("%s is covered in acid!", Monnam(mdef));
+            pline("%s is covered in %s!", Monnam(mdef), hliquid("acid"));
 */
-            pline("%s\82Í\8e_\82É\82Â\82Â\82Ü\82ê\82½\81I", Monnam(mdef));
+            pline("%s\82Í%s\82É\82Â\82Â\82Ü\82ê\82½\81I", Monnam(mdef), hliquid("\8e_"));
 /*JP
             pline("It burns %s!", mon_nam(mdef));
 */
@@ -1129,7 +1211,7 @@ register struct attack *mattk;
         if (magr->mcan)
             break;
         if (pd == &mons[PM_IRON_GOLEM]) {
-            if (vis)
+            if (vis && canseemon(mdef))
 /*JP
                 pline("%s falls to pieces!", Monnam(mdef));
 */
@@ -1159,7 +1241,7 @@ register struct attack *mattk;
         if (magr->mcan)
             break;
         if (pd == &mons[PM_WOOD_GOLEM] || pd == &mons[PM_LEATHER_GOLEM]) {
-            if (vis)
+            if (vis && canseemon(mdef))
 /*JP
                 pline("%s falls to pieces!", Monnam(mdef));
 */
@@ -1191,7 +1273,7 @@ register struct attack *mattk;
             break;
         }
         if (!resists_ston(mdef)) {
-            if (vis)
+            if (vis && canseemon(mdef))
 /*JP
                 pline("%s turns to stone!", Monnam(mdef));
 */
@@ -1212,13 +1294,14 @@ register struct attack *mattk;
     case AD_TLPT:
         if (!cancelled && tmp < mdef->mhp && !tele_restrict(mdef)) {
             char mdef_Monnam[BUFSZ];
+            boolean wasseen = canspotmon(mdef);
             /* save the name before monster teleports, otherwise
                we'll get "it" in the suddenly disappears message */
-            if (vis)
+            if (vis && wasseen)
                 Strcpy(mdef_Monnam, Monnam(mdef));
             mdef->mstrategy &= ~STRAT_WAITFORU;
             (void) rloc(mdef, TRUE);
-            if (vis && !canspotmon(mdef) && mdef != u.usteed)
+            if (vis && wasseen && !canspotmon(mdef) && mdef != u.usteed)
 /*JP
                 pline("%s suddenly disappears!", mdef_Monnam);
 */
@@ -1228,7 +1311,7 @@ register struct attack *mattk;
     case AD_SLEE:
         if (!cancelled && !mdef->msleeping
             && sleep_monst(mdef, rnd(10), -1)) {
-            if (vis) {
+            if (vis && canspotmon(mdef)) {
                 Strcpy(buf, Monnam(mdef));
 /*JP
                 pline("%s is put to sleep by %s.", buf, mon_nam(magr));
@@ -1241,7 +1324,7 @@ register struct attack *mattk;
         break;
     case AD_PLYS:
         if (!cancelled && mdef->mcanmove) {
-            if (vis) {
+            if (vis && canspotmon(mdef)) {
                 Strcpy(buf, Monnam(mdef));
 /*JP
                 pline("%s is frozen by %s.", buf, mon_nam(magr));
@@ -1257,7 +1340,7 @@ register struct attack *mattk;
 
             mon_adjust_speed(mdef, -1, (struct obj *) 0);
             mdef->mstrategy &= ~STRAT_WAITFORU;
-            if (mdef->mspeed != oldspeed && vis)
+            if (mdef->mspeed != oldspeed && vis && canspotmon(mdef))
 /*JP
                 pline("%s slows down.", Monnam(mdef));
 */
@@ -1270,7 +1353,7 @@ register struct attack *mattk;
          * we still should check for it).
          */
         if (!magr->mcan && !mdef->mconf && !magr->mspec_used) {
-            if (vis)
+            if (vis && canseemon(mdef))
 /*JP
                 pline("%s looks confused.", Monnam(mdef));
 */
@@ -1283,7 +1366,7 @@ register struct attack *mattk;
         if (can_blnd(magr, mdef, mattk->aatyp, (struct obj *) 0)) {
             register unsigned rnd_tmp;
 
-            if (vis && mdef->mcansee)
+            if (vis && mdef->mcansee && canspotmon(mdef))
 /*JP
                 pline("%s is blinded.", Monnam(mdef));
 */
@@ -1299,8 +1382,8 @@ register struct attack *mattk;
         break;
     case AD_HALU:
         if (!magr->mcan && haseyes(pd) && mdef->mcansee) {
-            if (vis)
-#if 0 /*JP*/
+            if (vis && canseemon(mdef))
+#if 0 /*JP:T*/
                 pline("%s looks %sconfused.", Monnam(mdef),
                       mdef->mconf ? "more " : "");
 #else
@@ -1321,12 +1404,14 @@ register struct attack *mattk;
             if (is_were(pd) && pd->mlet != S_HUMAN)
                 were_change(mdef);
             if (pd == &mons[PM_CLAY_GOLEM]) {
-                if (vis) {
-/*JP
+                if (vis && canseemon(mdef)) {
+#if 0 /*JP*/
                     pline("Some writing vanishes from %s head!",
-*/
-                    pline("\82¢\82­\82Â\82©\82Ì\95\8e\9a\82ª%s\82Ì\93ª\82©\82ç\8fÁ\82¦\82½\81I",
                           s_suffix(mon_nam(mdef)));
+#else
+                    pline("\82¢\82­\82Â\82©\82Ì\95\8e\9a\82ª%s\82Ì\93ª\82©\82ç\8fÁ\82¦\82½\81I",
+                          mon_nam(mdef));
+#endif
 /*JP
                     pline("%s is destroyed!", Monnam(mdef));
 */
@@ -1349,7 +1434,7 @@ register struct attack *mattk;
                     You_hear("laughter.");
 */
                     You_hear("\8fÎ\82¢\90º\82ð\95·\82¢\82½\81D");
-                else
+                else if (canseemon(magr))
 /*JP
                     pline("%s chuckles.", Monnam(magr));
 */
@@ -1366,13 +1451,14 @@ register struct attack *mattk;
          */
         {
             struct obj *gold = findgold(mdef->minvent);
+
             if (!gold)
                 break;
             obj_extract_self(gold);
             add_to_minv(magr, gold);
         }
         mdef->mstrategy &= ~STRAT_WAITFORU;
-        if (vis) {
+        if (vis && canseemon(mdef)) {
             Strcpy(buf, Monnam(magr));
 /*JP
             pline("%s steals some gold from %s.", buf, mon_nam(mdef));
@@ -1380,8 +1466,9 @@ register struct attack *mattk;
             pline("%s\82Í%s\82©\82ç\8bà\82ð\93\90\82ñ\82¾\81D", buf, mon_nam(mdef));
         }
         if (!tele_restrict(magr)) {
+            boolean couldspot = canspotmon(magr);
             (void) rloc(magr, TRUE);
-            if (vis && !canspotmon(magr))
+            if (vis && couldspot && !canspotmon(magr))
 /*JP
                 pline("%s suddenly disappears!", buf);
 */
@@ -1391,7 +1478,7 @@ register struct attack *mattk;
     case AD_DRLI:
         if (!cancelled && !rn2(3) && !resists_drli(mdef)) {
             tmp = d(2, 6);
-            if (vis)
+            if (vis && canspotmon(mdef))
 /*JP
                 pline("%s suddenly seems weaker!", Monnam(mdef));
 */
@@ -1438,7 +1525,7 @@ register struct attack *mattk;
             if (vis)
                 Strcpy(onambuf, doname(otmp));
             (void) add_to_minv(magr, otmp);
-            if (vis) {
+            if (vis && canseemon(mdef)) {
                 Strcpy(buf, Monnam(magr));
 /*JP
                 pline("%s steals %s from %s!", buf, onambuf, mdefnambuf);
@@ -1452,8 +1539,10 @@ register struct attack *mattk;
                 return (MM_DEF_DIED
                         | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
             if (pa->mlet == S_NYMPH && !tele_restrict(magr)) {
+                boolean couldspot = canspotmon(magr);
+
                 (void) rloc(magr, TRUE);
-                if (vis && !canspotmon(magr))
+                if (vis && couldspot && !canspotmon(magr))
 /*JP
                     pline("%s suddenly disappears!", buf);
 */
@@ -1464,15 +1553,16 @@ register struct attack *mattk;
         break;
     case AD_DREN:
         if (!cancelled && !rn2(4))
-            xdrainenergym(mdef, vis && mattk->aatyp != AT_ENGL);
+            xdrainenergym(mdef, (boolean) (vis && canspotmon(mdef)
+                                           && mattk->aatyp != AT_ENGL));
         tmp = 0;
         break;
     case AD_DRST:
     case AD_DRDX:
     case AD_DRCO:
         if (!cancelled && !rn2(8)) {
-            if (vis)
-#if 0 /*JP*/
+            if (vis && canspotmon(magr))
+#if 0 /*JP:T*/
                 pline("%s %s was poisoned!", s_suffix(Monnam(magr)),
                       mpoisons_subj(magr, mattk));
 #else
@@ -1480,7 +1570,7 @@ register struct attack *mattk;
                       mpoisons_subj(magr, mattk));
 #endif
             if (resists_poison(mdef)) {
-                if (vis)
+                if (vis && canspotmon(mdef) && canspotmon(magr))
 /*JP
                     pline_The("poison doesn't seem to affect %s.",
 */
@@ -1490,7 +1580,7 @@ register struct attack *mattk;
                 if (rn2(10))
                     tmp += rn1(10, 6);
                 else {
-                    if (vis)
+                    if (vis && canspotmon(mdef))
 /*JP
                         pline_The("poison was deadly...");
 */
@@ -1502,7 +1592,7 @@ register struct attack *mattk;
         break;
     case AD_DRIN:
         if (notonhead || !has_head(pd)) {
-            if (vis)
+            if (vis && canspotmon(mdef))
 /*JP
                 pline("%s doesn't seem harmed.", Monnam(mdef));
 */
@@ -1512,7 +1602,7 @@ register struct attack *mattk;
             break;
         }
         if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
-            if (vis) {
+            if (vis && canspotmon(magr) && canseemon(mdef)) {
                 Strcpy(buf, s_suffix(Monnam(mdef)));
 #if 0 /*JP*/
                 pline("%s helmet blocks %s attack to %s head.", buf,
@@ -1531,7 +1621,7 @@ register struct attack *mattk;
             break; /* physical damage only */
         if (!rn2(4) && !slimeproof(pd)) {
             if (!munslime(mdef, FALSE) && mdef->mhp > 0) {
-                if (newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, vis))
+                if (newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, vis && canseemon(mdef)))
                     pd = mdef->data;
                 mdef->mstrategy &= ~STRAT_WAITFORU;
                 res = MM_HIT;
@@ -1656,20 +1746,24 @@ rustm(mdef, obj)
 struct monst *mdef;
 struct obj *obj;
 {
-    int dmgtyp;
+    int dmgtyp = -1, chance = 1;
 
     if (!mdef || !obj)
         return; /* just in case */
-    /* AD_ACID is handled in passivemm */
-    if (dmgtype(mdef->data, AD_CORR))
+    /* AD_ACID and AD_ENCH are handled in passivemm() and passiveum() */
+    if (dmgtype(mdef->data, AD_CORR)) {
         dmgtyp = ERODE_CORRODE;
-    else if (dmgtype(mdef->data, AD_RUST))
+    } else if (dmgtype(mdef->data, AD_RUST)) {
         dmgtyp = ERODE_RUST;
-    else if (dmgtype(mdef->data, AD_FIRE))
+    } else if (dmgtype(mdef->data, AD_FIRE)
+               /* steam vortex: fire resist applies, fire damage doesn't */
+               && mdef->data != &mons[PM_STEAM_VORTEX]) {
         dmgtyp = ERODE_BURN;
-    else
-        return;
-    (void) erode_obj(obj, NULL, dmgtyp, EF_GREASE | EF_VERBOSE);
+        chance = 6;
+    }
+
+    if (dmgtyp >= 0 && !rn2(chance))
+        (void) erode_obj(obj, (char *) 0, dmgtyp, EF_GREASE | EF_VERBOSE);
 }
 
 STATIC_OVL void
@@ -1726,12 +1820,12 @@ int mdead;
         if (mhit && !rn2(2)) {
             Strcpy(buf, Monnam(magr));
             if (canseemon(magr))
-#if 0 /*JP*/
-                pline("%s is splashed by %s acid!", buf,
-                      s_suffix(mon_nam(mdef)));
+#if 0 /*JP:T*/
+                pline("%s is splashed by %s %s!", buf,
+                      s_suffix(mon_nam(mdef)), hliquid("acid"));
 #else
-                pline("%s\82Í%s\82Ì\8e_\82ð\97\81\82Ñ\82½\81I", buf,
-                      mon_nam(mdef));
+                pline("%s\82Í%s\82Ì%s\82ð\97\81\82Ñ\82½\81I", buf,
+                      mon_nam(mdef), hliquid("\8e_"));
 #endif
             if (resists_acid(magr)) {
                 if (canseemon(magr))
@@ -1750,7 +1844,7 @@ int mdead;
         goto assess_dmg;
     case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
         if (mhit && !mdef->mcan && otmp) {
-            (void) drain_item(otmp);
+            (void) drain_item(otmp, FALSE);
             /* No message */
         }
         break;
@@ -1771,11 +1865,17 @@ int mdead;
                     tmp = 127;
                 if (magr->mcansee && haseyes(madat) && mdef->mcansee
                     && (perceives(madat) || !mdef->minvis)) {
+                    /* construct format string; guard against '%' in Monnam */
+#if 0 /*JP*/
+                    Strcpy(buf, s_suffix(Monnam(mdef)));
+#else
+                    Strcpy(buf, Monnam(mdef));
+#endif
+                    (void) strNsubst(buf, "%", "%%", 0);
 /*JP
-                    Sprintf(buf, "%s gaze is reflected by %%s %%s.",
+                    Strcat(buf, " gaze is reflected by %s %s.");
 */
-                    Sprintf(buf, "%s\82Ì\82É\82ç\82Ý\82Í%%s\82É\82æ\82Á\82Ä%%s\81D",
-                            s_suffix(Monnam(mdef)));
+                    Strcat(buf, "\82Ì\82É\82ç\82Ý\82Í%s\82É\82æ\82Á\82Ä%s\81D");
                     if (mon_reflects(magr,
                                      canseemon(magr) ? buf : (char *) 0))
                         return (mdead | mhit);
index e89da79..9a79584 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 mhitu.c $NHDT-Date: 1446854230 2015/11/06 23:57:10 $  $NHDT-Branch: master $:$NHDT-Revision: 1.130 $ */
+/* NetHack 3.6 mhitu.c $NHDT-Date: 1513297347 2017/12/15 00:22:27 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.149 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 #include "hack.h"
 #include "artifact.h"
 
-STATIC_VAR NEARDATA struct obj *otmp;
+STATIC_VAR NEARDATA struct obj *mon_currwep = (struct obj *) 0;
 
 STATIC_DCL boolean FDECL(u_slip_free, (struct monst *, struct attack *));
-STATIC_DCL int FDECL(passiveum,
-                     (struct permonst *, struct monst *, struct attack *));
-
+STATIC_DCL int FDECL(passiveum, (struct permonst *, struct monst *,
+                                 struct attack *));
 STATIC_DCL void FDECL(mayberem, (struct obj *, const char *));
-
 STATIC_DCL boolean FDECL(diseasemu, (struct permonst *));
 STATIC_DCL int FDECL(hitmu, (struct monst *, struct attack *));
 STATIC_DCL int FDECL(gulpmu, (struct monst *, struct attack *));
@@ -25,7 +24,6 @@ STATIC_DCL int FDECL(explmu, (struct monst *, struct attack *, BOOLEAN_P));
 STATIC_DCL void FDECL(missmu, (struct monst *, BOOLEAN_P, struct attack *));
 STATIC_DCL void FDECL(mswings, (struct monst *, struct obj *));
 STATIC_DCL void FDECL(wildmiss, (struct monst *, struct attack *));
-
 STATIC_DCL void FDECL(hitmsg, (struct monst *, struct attack *));
 
 /* See comment in mhitm.c.  If we use this a lot it probably should be */
@@ -34,34 +32,37 @@ static int dieroll;
 
 STATIC_OVL void
 hitmsg(mtmp, mattk)
-register struct monst *mtmp;
-register struct attack *mattk;
+struct monst *mtmp;
+struct attack *mattk;
 {
     int compat;
+    const char *pfmt = 0;
+    char *Monst_name = Monnam(mtmp);
 
     /* Note: if opposite gender, "seductively" */
     /* If same gender, "engagingly" for nymph, normal msg for others */
-    if ((compat = could_seduce(mtmp, &youmonst, mattk)) && !mtmp->mcan
-        && !mtmp->mspec_used) {
-#if 0 /*JP*/
-        pline("%s %s you %s.", Monnam(mtmp), Blind ? "talks to" : "smiles at",
-              compat == 2 ? "engagingly" : "seductively");
-#else
-        pline("%s\82Í\82 \82È\82½%s%s\81D", Monnam(mtmp),
-              compat == 2 ? "\82ð\88ø\82«\82Â\82¯\82é\82æ\82¤\82É" : "\82É\8dD\88Ó\82ð\82æ\82¹\82é\82æ\82¤\82É",
+    if ((compat = could_seduce(mtmp, &youmonst, mattk)) != 0
+        && !mtmp->mcan && !mtmp->mspec_used) {
+#if 0 /*JP:T*/
+        pline("%s %s you %s.", Monst_name,
+              Blind ? "talks to" : "smiles at",
+              (compat == 2) ? "engagingly" : "seductively");
+#else
+        pline("%s\82Í\82 \82È\82½%s%s\81D", Monst_name,
+              (compat == 2) ? "\82ð\88ø\82«\82Â\82¯\82é\82æ\82¤\82É" : "\82É\8dD\88Ó\82ð\82æ\82¹\82é\82æ\82¤\82É",
               Blind ? "\98b\82µ\82©\82¯\82½" : "\94÷\8fÎ\82ñ\82¾");
 #endif
-    } else
+    } else {
         switch (mattk->aatyp) {
         case AT_BITE:
 /*JP
-            pline("%s bites!", Monnam(mtmp));
+            pfmt = "%s bites!";
 */
-            pline("%s\82Í\8a\9a\82Ý\82Â\82¢\82½\81I", Monnam(mtmp));
+            pfmt = "%s\82Í\8a\9a\82Ý\82Â\82¢\82½\81I";
             break;
         case AT_KICK:
-#if 0 /*JP*/
-            pline("%s kicks%c", Monnam(mtmp),
+#if 0 /*JP:T*/
+            pline("%s kicks%c", Monst_name,
                   thick_skinned(youmonst.data) ? '.' : '!');
 #else
             pline("%s\82Í\8fR\82Æ\82Î\82µ\82½%s",Monnam(mtmp), 
@@ -70,41 +71,47 @@ register struct attack *mattk;
             break;
         case AT_STNG:
 /*JP
-            pline("%s stings!", Monnam(mtmp));
+            pfmt = "%s stings!";
 */
-            pline("%s\82Í\93Ë\82«\82³\82µ\82½\81I", Monnam(mtmp));
+            pfmt = "%s\82Í\93Ë\82«\82³\82µ\82½\81I";
             break;
         case AT_BUTT:
 /*JP
-            pline("%s butts!", Monnam(mtmp));
+            pfmt = "%s butts!";
 */
-            pline("%s\82Í\93ª\93Ë\82«\82ð\82­\82ç\82í\82µ\82½\81I", Monnam(mtmp));
+            pfmt = "%s\82Í\93ª\93Ë\82«\82ð\82­\82ç\82í\82µ\82½\81I";
             break;
         case AT_TUCH:
 /*JP
-            pline("%s touches you!", Monnam(mtmp));
+            pfmt = "%s touches you!";
 */
-            pline("%s\82Í\82 \82È\82½\82É\90G\82ê\82½\81I", Monnam(mtmp));
+            pfmt = "%s\82Í\82 \82È\82½\82É\90G\82ê\82½\81I";
             break;
         case AT_TENT:
 /*JP
-            pline("%s tentacles suck you!", s_suffix(Monnam(mtmp)));
+            pfmt = "%s tentacles suck you!";
 */
-            pline("%s\82Ì\90G\8eè\82ª\82 \82È\82½\82Ì\91Ì\89t\82ð\8bz\82¢\82Æ\82Á\82½\81I", Monnam(mtmp));
+            pfmt = "%s\82Ì\90G\8eè\82ª\82 \82È\82½\82Ì\91Ì\89t\82ð\8bz\82¢\82Æ\82Á\82½\81I";
+#if 0 /*JP*/
+            Monst_name = s_suffix(Monst_name);
+#endif
             break;
         case AT_EXPL:
         case AT_BOOM:
 /*JP
-            pline("%s explodes!", Monnam(mtmp));
+            pfmt = "%s explodes!";
 */
-            pline("%s\82Í\94\9a\94­\82µ\82½\81I", Monnam(mtmp));
+            pfmt = "%s\82Í\94\9a\94­\82µ\82½\81I";
             break;
         default:
 /*JP
-            pline("%s hits!", Monnam(mtmp));
+            pfmt = "%s hits!";
 */
-            pline("%s\82Ì\8dU\8c\82\82Í\96½\92\86\82µ\82½\81I", Monnam(mtmp));
+            pfmt = "%s\82Ì\8dU\8c\82\82Í\96½\92\86\82µ\82½\81I";
         }
+        if (pfmt)
+            pline(pfmt, Monst_name);
+    }
 }
 
 /* monster missed you */
@@ -201,10 +208,11 @@ u_slow_down()
 /* monster attacked your displaced image */
 STATIC_OVL void
 wildmiss(mtmp, mattk)
-register struct monst *mtmp;
-register struct attack *mattk;
+struct monst *mtmp;
+struct attack *mattk;
 {
     int compat;
+    const char *Monst_name; /* Monnam(mtmp) */
 
     /* no map_invisible() -- no way to tell where _this_ is coming from */
 
@@ -216,78 +224,75 @@ register struct attack *mattk;
 
     compat = ((mattk->adtyp == AD_SEDU || mattk->adtyp == AD_SSEX)
               && could_seduce(mtmp, &youmonst, (struct attack *) 0));
+    Monst_name = Monnam(mtmp);
 
     if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) {
-#if 0 /*JP*/
-        const char *swings =
-            mattk->aatyp == AT_BITE
-                ? "snaps"
-                : mattk->aatyp == AT_KICK
-                      ? "kicks"
-                      : (mattk->aatyp == AT_STNG || mattk->aatyp == AT_BUTT
-                         || nolimbs(mtmp->data))
-                            ? "lunges"
-                            : "swings";
-#else
-        const char *swings =
-            mattk->aatyp == AT_BITE
-                ? "\8a\9a\82Ý\82Â\82­"
-                : mattk->aatyp == AT_KICK
-                      ? "\8fR\82Æ\82Î\82·"
-                      : (mattk->aatyp == AT_STNG || mattk->aatyp == AT_BUTT
-                         || nolimbs(mtmp->data))
-                            ? "\93Ë\90i\82·\82é"
-                            : "\90U\82è\89ñ\82·";
+#if 0 /*JP:T*/
+        const char *swings = (mattk->aatyp == AT_BITE) ? "snaps"
+                             : (mattk->aatyp == AT_KICK) ? "kicks"
+                               : (mattk->aatyp == AT_STNG
+                                  || mattk->aatyp == AT_BUTT
+                                  || nolimbs(mtmp->data)) ? "lunges"
+                                 : "swings";
+#else
+        const char *swings = (mattk->aatyp == AT_BITE) ? "\8a\9a\82Ý\82Â\82­"
+                             : (mattk->aatyp == AT_KICK) ? "\8fR\82Æ\82Î\82·"
+                               : (mattk->aatyp == AT_STNG
+                                  || mattk->aatyp == AT_BUTT
+                                  || nolimbs(mtmp->data)) ? "\93Ë\90i\82·\82é"
+                                 : "\90U\82è\89ñ\82·";
 #endif
 
         if (compat)
 /*JP
-            pline("%s tries to touch you and misses!", Monnam(mtmp));
+            pline("%s tries to touch you and misses!", Monst_name);
 */
-            pline("%s\82Í\82 \82È\82½\82É\90G\82ë\82¤\82Æ\82µ\82½\82ª\8e¸\94s\82µ\82½\81I", Monnam(mtmp));
+            pline("%s\82Í\82 \82È\82½\82É\90G\82ë\82¤\82Æ\82µ\82½\82ª\8e¸\94s\82µ\82½\81I", Monst_name);
         else
             switch (rn2(3)) {
             case 0:
 /*JP
-                pline("%s %s wildly and misses!", Monnam(mtmp), swings);
+                pline("%s %s wildly and misses!", Monst_name, swings);
 */
-                pline("%s\82Í\8c\83\82µ\82­%s\82ª\81C\82Í\82¸\82µ\82½\81D", Monnam(mtmp), jpast(swings));
+                pline("%s\82Í\8c\83\82µ\82­%s\82ª\81C\82Í\82¸\82µ\82½\81I", Monst_name, swings);
                 break;
             case 1:
 /*JP
-                pline("%s attacks a spot beside you.", Monnam(mtmp));
+                pline("%s attacks a spot beside you.", Monst_name);
 */
-                pline("%s\82Ì\8dU\8c\82\82Í\82 \82È\82½\82Ì\98e\95 \82ð\82©\82·\82ß\82½\81D", Monnam(mtmp));
+                pline("%s\82Ì\8dU\8c\82\82Í\82 \82È\82½\82Ì\98e\95 \82ð\82©\82·\82ß\82½\81D", Monst_name);
                 break;
             case 2:
 #if 0 /*JP*/
-                pline("%s strikes at %s!", Monnam(mtmp),
-                      levl[mtmp->mux][mtmp->muy].typ == WATER ? "empty water"
-                                                              : "thin air");
+                pline("%s strikes at %s!", Monst_name,
+                      (levl[mtmp->mux][mtmp->muy].typ == WATER)
+                        ? "empty water"
+                        : "thin air");
 #else
-                pline("%s\82Í%s\82ð\91Å\82¿\82Â\82¯\82½\81I", Monnam(mtmp),
-                      levl[mtmp->mux][mtmp->muy].typ == WATER ? "\90\85"
-                                                              : "\89½\82à\82È\82¢\82Æ\82±\82ë");
+                pline("%s\82Í%s\82ð\91Å\82¿\82Â\82¯\82½\81I", Monst_name,
+                      (levl[mtmp->mux][mtmp->muy].typ == WATER)
+                        ? "\90\85"
+                        : "\89½\82à\82È\82¢\82Æ\82±\82ë");
 #endif
                 break;
             default:
 /*JP
-                pline("%s %s wildly!", Monnam(mtmp), swings);
+                pline("%s %s wildly!", Monst_name, swings);
 */
-                pline("%s\82Í\8c\83\82µ\82­%s\81I", Monnam(mtmp), jpast(swings));
+                pline("%s\82Í\8c\83\82µ\82­%s\81I", Monst_name, swings);
                 break;
             }
 
     } else if (Displaced) {
         if (compat)
 #if 0 /*JP*/
-            pline("%s smiles %s at your %sdisplaced image...", Monnam(mtmp),
-                  compat == 2 ? "engagingly" : "seductively",
+            pline("%s smiles %s at your %sdisplaced image...", Monst_name,
+                  (compat == 2) ? "engagingly" : "seductively",
                   Invis ? "invisible " : "");
 #else
-            pline("%s\82Í%s\82 \82È\82½\82Ì\8c\89e\82É\91Î\82µ\82Ä%s\94÷\8fÎ\82ñ\82¾\81D\81D\81D", Monnam(mtmp),
+            pline("%s\82Í%s\82 \82È\82½\82Ì\8c\89e\82É\91Î\82µ\82Ä%s\94÷\8fÎ\82ñ\82¾\81D\81D\81D", Monst_name,
                   Invis ? "\93§\96¾\82È" : "",
-                  compat == 2 ? "\96£\97Í\93I\82É" : "\97U\98f\93I\82É");
+                  (compat == 2) ? "\96£\97Í\93I\82É" : "\97U\98f\93I\82É");
 #endif
         else
 #if 0 /*JP*/
@@ -297,10 +302,10 @@ register struct attack *mattk;
                    * displaced image, since the displaced image is also
                    * invisible.
                    */
-                  Monnam(mtmp), Invis ? "invisible " : "");
+                  Monst_name, Invis ? "invisible " : "");
 #else
             pline("%s\82Í\82 \82È\82½\82Ì%s\8c\89e\82ð\8dU\8c\82\82µ\81C\82Í\82¸\82µ\82½\81I",
-                  Monnam(mtmp), Invis ? "\93§\96¾\82È" : "");
+                  Monst_name, Invis ? "\93§\96¾\82È" : "");
 #endif
 
     } else if (Underwater) {
@@ -308,19 +313,19 @@ register struct attack *mattk;
            bubbles shake the player here and there */
         if (compat)
 /*JP
-            pline("%s reaches towards your distorted image.", Monnam(mtmp));
+            pline("%s reaches towards your distorted image.", Monst_name);
 */
-            pline("%s\82Í\82 \82È\82½\82Ì\98c\82ñ\82¾\8c\89e\82Ì\95û\82Ö\8cü\82©\82Á\82½\81D", Monnam(mtmp));
+            pline("%s\82Í\82 \82È\82½\82Ì\98c\82ñ\82¾\8c\89e\82Ì\95û\82Ö\8cü\82©\82Á\82½\81D", Monst_name);
         else
 /*JP
             pline("%s is fooled by water reflections and misses!",
 */
             pline("%s\82Í\90\85\82Ì\94½\8eË\82É\82¾\82Ü\82³\82ê\81C\82Í\82¸\82µ\82½\81I",
-                  Monnam(mtmp));
+                  Monst_name);
 
     } else
         impossible("%s attacks you without knowing your location?",
-                   Monnam(mtmp));
+                   Monst_name);
 }
 
 void
@@ -330,24 +335,21 @@ struct permonst *mdat; /* if mtmp is polymorphed, mdat != mtmp->data */
 boolean message;
 {
     if (message) {
-        if (is_animal(mdat))
+        if (is_animal(mdat)) {
 /*JP
             You("get regurgitated!");
 */
             You("\93f\82«\82¾\82³\82ê\82½\81I");
-        else {
+        else {
             char blast[40];
-            register int i;
+            struct attack *attk = attacktype_fordmg(mdat, AT_ENGL, AD_ANY);
 
             blast[0] = '\0';
-            for (i = 0; i < NATTK; i++)
-                if (mdat->mattk[i].aatyp == AT_ENGL)
-                    break;
-            if (mdat->mattk[i].aatyp != AT_ENGL)
+            if (!attk) {
                 impossible("Swallower has no engulfing attack?");
-            else {
+            else {
                 if (is_whirly(mdat)) {
-                    switch (mdat->mattk[i].adtyp) {
+                    switch (attk->adtyp) {
                     case AD_ELEC:
 /*JP
                         Strcpy(blast, " in a shower of sparks");
@@ -361,11 +363,12 @@ boolean message;
                         Strcpy(blast, "\82Ì\97â\8bC\82Ì\95\97\82Ì\92\86\82©\82ç");
                         break;
                     }
-                } else
+                } else {
 /*JP
                     Strcpy(blast, " with a squelch");
 */
                     Strcpy(blast, "\82©\82ç\93f\82«\8fo\82³\82ê\82é\82æ\82¤\82É");
+                }
 /*JP
                 You("get expelled from %s%s!", mon_nam(mtmp), blast);
 */
@@ -387,12 +390,14 @@ boolean message;
 
 /* select a monster's next attack, possibly substituting for its usual one */
 struct attack *
-getmattk(mptr, indx, prev_result, alt_attk_buf)
-struct permonst *mptr;
+getmattk(magr, mdef, indx, prev_result, alt_attk_buf)
+struct monst *magr, *mdef;
 int indx, prev_result[];
 struct attack *alt_attk_buf;
 {
+    struct permonst *mptr = magr->data;
     struct attack *attk = &mptr->mattk[indx];
+    struct obj *weap = (magr == &youmonst) ? uwep : MON_WEP(magr);
 
     /* prevent a monster with two consecutive disease or hunger attacks
        from hitting with both of them on the same turn; if the first has
@@ -404,6 +409,58 @@ struct attack *alt_attk_buf;
         *alt_attk_buf = *attk;
         attk = alt_attk_buf;
         attk->adtyp = AD_STUN;
+
+    /* make drain-energy damage be somewhat in proportion to energy */
+    } else if (attk->adtyp == AD_DREN && mdef == &youmonst) {
+        int ulev = max(u.ulevel, 6);
+
+        *alt_attk_buf = *attk;
+        attk = alt_attk_buf;
+        /* 3.6.0 used 4d6 but since energy drain came out of max energy
+           once current energy was gone, that tended to have a severe
+           effect on low energy characters; it's now 2d6 with ajustments */
+        if (u.uen <= 5 * ulev && attk->damn > 1) {
+            attk->damn -= 1; /* low energy: 2d6 -> 1d6 */
+            if (u.uenmax <= 2 * ulev && attk->damd > 3)
+                attk->damd -= 3; /* very low energy: 1d6 -> 1d3 */
+        } else if (u.uen > 12 * ulev) {
+            attk->damn += 1; /* high energy: 2d6 -> 3d6 */
+            if (u.uenmax > 20 * ulev)
+                attk->damd += 3; /* very high energy: 3d6 -> 3d9 */
+            /* note: 3d9 is slightly higher than previous 4d6 */
+        }
+
+    } else if (attk->aatyp == AT_ENGL && magr->mspec_used) {
+        /* can't re-engulf yet; switch to simpler attack */
+        *alt_attk_buf = *attk;
+        attk = alt_attk_buf;
+        if (attk->adtyp == AD_ACID || attk->adtyp == AD_ELEC
+            || attk->adtyp == AD_COLD || attk->adtyp == AD_FIRE) {
+            attk->aatyp = AT_TUCH;
+        } else {
+            attk->aatyp = AT_CLAW; /* attack message will be "<foo> hits" */
+            attk->adtyp = AD_PHYS;
+        }
+        attk->damn = 1; /* relatively weak: 1d6 */
+        attk->damd = 6;
+
+    /* barrow wight, Nazgul, erinys have weapon attack for non-physical
+       damage; force physical damage if attacker has been cancelled or
+       if weapon is sufficiently interesting; a few unique creatures
+       have two weapon attacks where one does physical damage and other
+       doesn't--avoid forcing physical damage for those */
+    } else if (indx == 0 && magr != &youmonst
+               && attk->aatyp == AT_WEAP && attk->adtyp != AD_PHYS
+               && !(mptr->mattk[1].aatyp == AT_WEAP
+                    && mptr->mattk[1].adtyp == AD_PHYS)
+               && (magr->mcan
+                   || (weap && ((weap->otyp == CORPSE
+                                 && touch_petrifies(&mons[weap->corpsenm]))
+                                || weap->oartifact == ART_STORMBRINGER
+                                || weap->oartifact == ART_VORPAL_BLADE)))) {
+        *alt_attk_buf = *attk;
+        attk = alt_attk_buf;
+        attk->adtyp = AD_PHYS;
     }
     return attk;
 }
@@ -422,7 +479,7 @@ mattacku(mtmp)
 register struct monst *mtmp;
 {
     struct attack *mattk, alt_attk;
-    int i, j, tmp, sum[NATTK];
+    int i, j = 0, tmp, sum[NATTK];
     struct permonst *mdat = mtmp->data;
     boolean ranged = (distu(mtmp->mx, mtmp->my) > 3);
     /* Is it near you?  Affects your actions */
@@ -579,6 +636,8 @@ register struct monst *mtmp;
                         if (obj->otyp == EGG)
                             obj->spe = 0;
                     }
+                    /* note that m_monnam() overrides hallucination, which is
+                       what we want when message is from mtmp's perspective */
                     if (youmonst.data->mlet == S_EEL
                         || u.umonnum == PM_TRAPPER)
                         pline(
@@ -622,7 +681,7 @@ register struct monst *mtmp;
             pline("It gets stuck on you.");
 */
             pline("\89½\8eÒ\82©\82ª\82 \82È\82½\82Ì\8fã\82É\82Ì\82µ\82©\82©\82Á\82½\81D");
-        else
+        else /* see note about m_monnam() above */
 #if 0 /*JP*/
             pline("Wait, %s!  That's a %s named %s!", m_monnam(mtmp),
                   youmonst.data->mname, plname);
@@ -650,12 +709,12 @@ register struct monst *mtmp;
                                            ? "tries to pick you up"
                                            : "disturbs you");
 #else
-                 pline("%s\82Í%s\81I", Something, (likes_gold(mtmp->data)
+            pline("%s\82Í%s\81I", Something, (likes_gold(mtmp->data)
                                         && youmonst.mappearance == GOLD_PIECE)
                                            ? "\82 \82È\82½\82ð\8fE\82¨\82¤\82Æ\82µ\82½"
                                            : "\96³\8e\8b\82µ\82½");
 #endif
-        else
+        else /* see note about m_monnam() above */
 #if 0 /*JP*/
             pline("Wait, %s!  That %s is really %s named %s!", m_monnam(mtmp),
                   mimic_obj_name(&youmonst), an(mons[u.umonnum].mname),
@@ -816,7 +875,8 @@ register struct monst *mtmp;
 
     for (i = 0; i < NATTK; i++) {
         sum[i] = 0;
-        mattk = getmattk(mdat, i, sum, &alt_attk);
+        mon_currwep = (struct obj *)0;
+        mattk = getmattk(mtmp, &youmonst, i, sum, &alt_attk);
         if ((u.uswallow && mattk->aatyp != AT_ENGL)
             || (skipnonmagc && mattk->aatyp != AT_MAGC))
             continue;
@@ -868,10 +928,10 @@ register struct monst *mtmp;
         case AT_ENGL:
             if (!range2) {
                 if (foundyou) {
-                    if (u.uswallow || tmp > (j = rnd(20 + i))) {
-                        /* Force swallowing monster to be
-                         * displayed even when player is
-                         * moving away */
+                    if (u.uswallow
+                        || (!mtmp->mspec_used && tmp > (j = rnd(20 + i)))) {
+                        /* force swallowing monster to be displayed
+                           even when hero is moving away */
                         flush_screen(1);
                         sum[i] = gulpmu(mtmp, mattk);
                     } else {
@@ -929,18 +989,18 @@ register struct monst *mtmp;
                         break;
                 }
                 if (foundyou) {
-                    otmp = MON_WEP(mtmp);
-                    if (otmp) {
-                        hittmp = hitval(otmp, &youmonst);
+                    mon_currwep = MON_WEP(mtmp);
+                    if (mon_currwep) {
+                        hittmp = hitval(mon_currwep, &youmonst);
                         tmp += hittmp;
-                        mswings(mtmp, otmp);
+                        mswings(mtmp, mon_currwep);
                     }
                     if (tmp > (j = dieroll = rnd(20 + i)))
                         sum[i] = hitmu(mtmp, mattk);
                     else
                         missmu(mtmp, (tmp == j), mattk);
                     /* KMH -- Don't accumulate to-hit bonuses */
-                    if (otmp)
+                    if (mon_currwep)
                         tmp -= hittmp;
                 } else {
                     wildmiss(mtmp, mattk);
@@ -1086,7 +1146,7 @@ struct monst *mon;
     } else if (mc < 1) {
         /* intrinsic Protection is weaker (play balance; obtaining divine
            protection is too easy); it confers minimum mc 1 instead of 0 */
-        if ((is_you && ((HProtection && u.ublessed) || u.uspellprot))
+        if ((is_you && ((HProtection && u.ublessed > 0) || u.uspellprot))
             /* aligned priests and angels have innate intrinsic Protection */
             || (mon->data == &mons[PM_ALIGNED_PRIEST] || is_minion(mon->data)))
             mc = 1;
@@ -1105,8 +1165,8 @@ hitmu(mtmp, mattk)
 register struct monst *mtmp;
 register struct attack *mattk;
 {
-    register struct permonst *mdat = mtmp->data;
-    register int uncancelled, ptmp;
+    struct permonst *mdat = mtmp->data;
+    int uncancelled, ptmp;
     int dmg, armpro, permdmg;
     char buf[BUFSZ];
     struct permonst *olduasmon = youmonst.data;
@@ -1189,7 +1249,10 @@ register struct attack *mattk;
 #endif
             }
         } else { /* hand to hand weapon */
+            struct obj *otmp = mon_currwep;
+
             if (mattk->aatyp == AT_WEAP && otmp) {
+                struct obj *marmg;
                 int tmp;
 
                 if (otmp->otyp == CORPSE
@@ -1206,6 +1269,9 @@ register struct attack *mattk;
                         goto do_stone;
                 }
                 dmg += dmgval(otmp, &youmonst);
+                if ((marmg = which_armor(mtmp, W_ARMG)) != 0
+                    && marmg->otyp == GAUNTLETS_OF_POWER)
+                    dmg += rn1(4, 3); /* 3..6 */
                 if (dmg <= 0)
                     dmg = 1;
                 if (!(otmp->oartifact
@@ -1229,7 +1295,10 @@ register struct attack *mattk;
                     tmp -= rnd(-u.uac);
                 if (tmp < 1)
                     tmp = 1;
-                if (u.mh - tmp > 1 && objects[otmp->otyp].oc_material == IRON
+                if (u.mh - tmp > 1
+                    && (objects[otmp->otyp].oc_material == IRON
+                        /* relevant 'metal' objects are scalpel and tsurugi */
+                        || objects[otmp->otyp].oc_material == METAL)
                     && (u.umonnum == PM_BLACK_PUDDING
                         || u.umonnum == PM_BROWN_PUDDING)) {
                     if (tmp > 1)
@@ -1262,12 +1331,11 @@ register struct attack *mattk;
             pline("You're %s!", on_fire(youmonst.data, mattk));
 */
             pline("\82 \82È\82½\82Í%s\81I", on_fire(youmonst.data, mattk));
-            if (youmonst.data == &mons[PM_STRAW_GOLEM]
-                || youmonst.data == &mons[PM_PAPER_GOLEM]) {
+            if (completelyburns(youmonst.data)) { /* paper or straw golem */
 /*JP
-                You("roast!");
+                You("go up in flames!");
 */
-                You("\8fÅ\82°\82½\81I");
+                You("\89\8a\82É\95ï\82Ü\82ê\82½\81I");
                 /* KMH -- this is okay with unchanging */
                 rehumanize();
                 break;
@@ -1402,9 +1470,11 @@ register struct attack *mattk;
                  helm_simple_name(uarmh));
             break;
         }
+        /* negative armor class doesn't reduce this damage */
         if (Half_physical_damage)
             dmg = (dmg + 1) / 2;
         mdamageu(mtmp, dmg);
+        dmg = 0; /* don't inflict a second dose below */
 
         if (!uarmh || uarmh->otyp != DUNCE_CAP) {
             /* eat_brains() will miss if target is mindless (won't
@@ -1459,11 +1529,12 @@ register struct attack *mattk;
         }
         break;
     case AD_LEGS: {
-        register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
+        long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
 /*JP
-        const char *sidestr = (side == RIGHT_SIDE) ? "right" : "left";
+        const char *sidestr = (side == RIGHT_SIDE) ? "right" : "left",
 */
-        const char *sidestr = (side == RIGHT_SIDE) ? "\89E" : "\8d¶";
+        const char *sidestr = (side == RIGHT_SIDE) ? "\89E" : "\8d¶",
+                   *Monst_name = Monnam(mtmp), *leg = body_part(LEG);
 
         /* This case is too obvious to ignore, but Nethack is not in
          * general very good at considering height--most short monsters
@@ -1471,61 +1542,56 @@ register struct attack *mattk;
          * [FIXME: why can't a flying attacker overcome this?]
          */
         if (u.usteed || Levitation || Flying) {
-#if 0 /*JP*/
-            pline("%s tries to reach your %s %s!", Monnam(mtmp), sidestr,
-                  body_part(LEG));
-#else
-            pline("%s\82Í\82 \82È\82½\82Ì%s%s\82É\8dU\8c\82\82µ\82æ\82¤\82Æ\82µ\82½\81I", Monnam(mtmp), sidestr,
-                  body_part(LEG));
-#endif
+/*JP
+            pline("%s tries to reach your %s %s!", Monst_name, sidestr, leg);
+*/
+            pline("%s\82Í\82 \82È\82½\82Ì%s%s\82É\8dU\8c\82\82µ\82æ\82¤\82Æ\82µ\82½\81I", Monst_name, sidestr, leg);
             dmg = 0;
         } else if (mtmp->mcan) {
-#if 0 /*JP*/
-            pline("%s nuzzles against your %s %s!", Monnam(mtmp), sidestr,
-                  body_part(LEG));
+#if 0 /*JP:T*/
+            pline("%s nuzzles against your %s %s!", Monnam(mtmp),
+                  sidestr, leg);
 #else
-            pline("%s\82Í\82 \82È\82½\82Ì%s%s\82É\95@\82ð\82·\82è\82æ\82¹\82½\81I", Monnam(mtmp), sidestr,
-                  body_part(LEG));
+            pline("%s\82Í\82 \82È\82½\82Ì%s%s\82É\95@\82ð\82·\82è\82æ\82¹\82½\81I", Monnam(mtmp),
+                  sidestr, leg);
 #endif
             dmg = 0;
         } else {
             if (uarmf) {
                 if (rn2(2) && (uarmf->otyp == LOW_BOOTS
-                               || uarmf->otyp == IRON_SHOES))
-#if 0 /*JP*/
+                               || uarmf->otyp == IRON_SHOES)) {
+#if 0 /*JP:T*/
                     pline("%s pricks the exposed part of your %s %s!",
-                          Monnam(mtmp), sidestr, body_part(LEG));
+                          Monst_name, sidestr, leg);
 #else
                     pline("%s\82Í\82 \82È\82½\82Ì%s%s\82ð\82¿\82­\82è\82Æ\8eh\82µ\82½\81I",
-                          Monnam(mtmp), sidestr, body_part(LEG));
+                          Monst_name, sidestr, leg);
 #endif
-                else if (!rn2(5))
+                } else if (!rn2(5)) {
 #if 0 /*JP*/
-                    pline("%s pricks through your %s boot!", Monnam(mtmp),
+                    pline("%s pricks through your %s boot!", Monst_name,
                           sidestr);
 #else
-                    pline("%s\82Í\82 \82È\82½\82Ì%s\82Ì\8cC\82²\82µ\82É\82¿\82­\82è\82Æ\8eh\82µ\82½\81I", Monnam(mtmp),
+                    pline("%s\82Í\82 \82È\82½\82Ì%s\82Ì\8cC\82²\82µ\82É\82¿\82­\82è\82Æ\8eh\82µ\82½\81I", Monst_name,
                           sidestr);
 #endif
-                else {
+                else {
 #if 0 /*JP*/
-                    pline("%s scratches your %s boot!", Monnam(mtmp),
+                    pline("%s scratches your %s boot!", Monst_name,
                           sidestr);
 #else
-                    pline("%s\82Í\82 \82È\82½\82Ì%s\82Ì\8cC\82ð\82Ð\82Á\82©\82¢\82½\81I", Monnam(mtmp),
+                    pline("%s\82Í\82 \82È\82½\82Ì%s\82Ì\8cC\82ð\82Ð\82Á\82©\82¢\82½\81I", Monst_name,
                           sidestr);
 #endif
                     dmg = 0;
                     break;
                 }
             } else
-#if 0 /*JP*/
-                pline("%s pricks your %s %s!", Monnam(mtmp), sidestr,
-                      body_part(LEG));
-#else
-                pline("%s\82Í\82 \82È\82½\82Ì%s%s\82ð\82¿\82­\82è\82Æ\8eh\82µ\82½\81I", Monnam(mtmp), sidestr,
-                      body_part(LEG));
-#endif
+/*JP
+                pline("%s pricks your %s %s!", Monst_name, sidestr, leg);
+*/
+                pline("%s\82Í\82 \82È\82½\82Ì%s%s\82ð\82¿\82­\82è\82Æ\8eh\82µ\82½\81I", Monst_name, sidestr, leg);
+
             set_wounded_legs(side, rnd(60 - ACURR(A_DEX)));
             exercise(A_STR, FALSE);
             exercise(A_DEX, FALSE);
@@ -1636,7 +1702,7 @@ register struct attack *mattk;
 */
             You("\94M\82ª\82 \82é\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
             exercise(A_CON, FALSE);
-            u.ulycn = monsndx(mdat);
+            set_ulycn(monsndx(mdat));
             retouch_equipment(2);
         }
         break;
@@ -1655,7 +1721,7 @@ register struct attack *mattk;
                     return 3;
             break;
         }
-    /* else FALLTHRU */
+        /*FALLTHRU*/
     case AD_SITM: /* for now these are the same */
     case AD_SEDU:
         if (is_animal(mtmp->data)) {
@@ -1665,7 +1731,7 @@ register struct attack *mattk;
             /* Continue below */
         } else if (dmgtype(youmonst.data, AD_SEDU)
                    || (SYSOPT_SEDUCE && dmgtype(youmonst.data, AD_SSEX))) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             pline("%s %s.", Monnam(mtmp),
                   mtmp->minvent
                       ? "brags about the goods some dungeon explorer provided"
@@ -1680,7 +1746,7 @@ register struct attack *mattk;
                 (void) rloc(mtmp, TRUE);
             return 3;
         } else if (mtmp->mcan) {
-            if (!Blind) {
+            if (!Blind)
 #if 0 /*JP*/
                 pline("%s tries to %s you, but you seem %s.",
                       Adjmonnam(mtmp, "plain"),
@@ -1692,7 +1758,6 @@ register struct attack *mattk;
                       flags.female ? "\96£\97¹" : "\97U\98f",
                       flags.female ? "\89e\8b¿\82ð\8eó\82¯\82È\82¢" : "\8b»\96¡\82ª\82È\82¢");
 #endif
-            }
             if (rn2(3)) {
                 if (!tele_restrict(mtmp))
                     (void) rloc(mtmp, TRUE);
@@ -1726,11 +1791,11 @@ register struct attack *mattk;
 
     case AD_SAMU:
         hitmsg(mtmp, mattk);
-        /* when the Wiz hits, 1/20 steals the amulet */
-        if (u.uhave.amulet || u.uhave.bell || u.uhave.book || u.uhave.menorah
-            || u.uhave.questart) /* carrying the Quest Artifact */
-            if (!rn2(20))
-                stealamulet(mtmp);
+        /* when the Wizard or quest nemesis hits, there's a 1/20 chance
+           to steal a quest artifact (any, not just the one for the hero's
+           own role) or the Amulet or one of the invocation tools */
+        if (!rn2(20))
+            stealamulet(mtmp);
         break;
 
     case AD_TLPT:
@@ -1787,9 +1852,10 @@ register struct attack *mattk;
             hitmsg(mtmp, mattk);
             break;
         }
-        if (!uwep && !uarmu && !uarm && !uarmh && !uarms && !uarmg && !uarmc
-            && !uarmf) {
+        if (!uwep && !uarmu && !uarm && !uarmc
+            && !uarms && !uarmg && !uarmf && !uarmh) {
             boolean goaway = FALSE;
+
 /*JP
             pline("%s hits!  (I hope you don't mind.)", Monnam(mtmp));
 */
@@ -1885,16 +1951,19 @@ register struct attack *mattk;
         hitmsg(mtmp, mattk);
         if (!mtmp->mcan && !rn2(3))
             if (Acid_resistance) {
-/*JP
-                pline("You're covered in acid, but it seems harmless.");
-*/
-                pline("\8e_\82Å\95¢\82í\82ê\82½\81D\82µ\82©\82µ\8f\9d\82Â\82©\82È\82¢\81D");
+#if 0 /*JP:T*/
+                pline("You're covered in %s, but it seems harmless.",
+                      hliquid("acid"));
+#else
+                pline("%s\82Å\95¢\82í\82ê\82½\81D\82µ\82©\82µ\8f\9d\82Â\82©\82È\82¢\81D",
+                      hliquid("\8e_"));
+#endif
                 dmg = 0;
             } else {
 /*JP
-                pline("You're covered in acid!  It burns!");
+                pline("You're covered in %s!  It burns!", hliquid("acid"));
 */
-                You("\8e_\82Å\95¢\82í\82ê\8fÄ\82¯\82½\81I");
+                pline("%s\82Å\95¢\82í\82ê\8fÄ\82¯\82½\81I", hliquid("\8e_"));
                 exercise(A_STR, FALSE);
             }
         else
@@ -1907,7 +1976,7 @@ register struct attack *mattk;
         break;
     case AD_DREN:
         hitmsg(mtmp, mattk);
-        if (uncancelled && !rn2(4))
+        if (uncancelled && !rn2(4)) /* 25% chance */
             drain_en(dmg);
         dmg = 0;
         break;
@@ -1955,7 +2024,8 @@ register struct attack *mattk;
                 done(DIED);
                 dmg = 0;
                 break;
-            }    /* else FALLTHRU */
+            }
+            /*FALLTHRU*/
         default: /* case 16: ... case 5: */
 /*JP
             You_feel("your life force draining away...");
@@ -2032,7 +2102,27 @@ register struct attack *mattk;
         if (uncancelled) {
             struct obj *obj = some_armor(&youmonst);
 
-            if (drain_item(obj)) {
+            if (!obj) {
+                /* some rings are susceptible;
+                   amulets and blindfolds aren't (at present) */
+                switch (rn2(5)) {
+                case 0:
+                    break;
+                case 1:
+                    obj = uright;
+                    break;
+                case 2:
+                    obj = uleft;
+                    break;
+                case 3:
+                    obj = uamul;
+                    break;
+                case 4:
+                    obj = ublindf;
+                    break;
+                }
+            }
+            if (drain_item(obj, FALSE)) {
 /*JP
                 pline("%s less effective.", Yobjnam2(obj, "seem"));
 */
@@ -2044,8 +2134,11 @@ register struct attack *mattk;
         dmg = 0;
         break;
     }
-    if (u.uhp < 1)
-        done_in_by(mtmp, DIED);
+    if ((Upolyd ? u.mh : u.uhp) < 1) {
+        /* already dead? call rehumanize() or done_in_by() as appropriate */
+        mdamageu(mtmp, 1);
+        dmg = 0;
+    }
 
     /*  Negative armor class reduces damage done instead of fully protecting
      *  against hits.
@@ -2132,13 +2225,13 @@ gulp_blnd_check()
 /* monster swallows you, or damage if u.uswallow */
 STATIC_OVL int
 gulpmu(mtmp, mattk)
-register struct monst *mtmp;
-register struct attack *mattk;
+struct monst *mtmp;
+struct attack *mattk;
 {
     struct trap *t = t_at(u.ux, u.uy);
     int tmp = d((int) mattk->damn, (int) mattk->damd);
     int tim_tmp;
-    register struct obj *otmp2;
+    struct obj *otmp2;
     int i;
     boolean physical_damage = FALSE;
 
@@ -2160,6 +2253,7 @@ register struct attack *mattk;
         newsym(mtmp->mx, mtmp->my);
         if (is_animal(mtmp->data) && u.usteed) {
             char buf[BUFSZ];
+
             /* Too many quirks presently if hero and steed
              * are swallowed. Pretend purple worms don't
              * like horses for now :-)
@@ -2182,7 +2276,7 @@ register struct attack *mattk;
         reset_occupations(); /* behave as if you had moved */
 
         if (u.utrap) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             You("are released from the %s!",
                 u.utraptype == TT_WEB ? "web" : "trap");
 #else
@@ -2196,9 +2290,10 @@ register struct attack *mattk;
         if (i > 0) {
 #if 0 /*JP*/
             const char *s = (i > 1) ? "leashes" : "leash";
+
             pline_The("%s %s loose.", s, vtense(s, "snap"));
 #else
-            pline("\95R\82Í\83p\83`\83\93\82Æ\90Ø\82ê\82½\81D");
+            pline("\95R\82Í\83p\83`\83\93\82Æ\82Í\82¸\82ê\82½\81D");
 #endif
             unleash_all();
         }
@@ -2408,7 +2503,7 @@ register struct attack *mattk;
         break;
     case AD_DREN:
         /* AC magic cancellation doesn't help when engulfed */
-        if (!mtmp->mcan && rn2(4))
+        if (!mtmp->mcan && rn2(4)) /* 75% chance */
             drain_en(tmp);
         tmp = 0;
         break;
@@ -2454,8 +2549,8 @@ register struct attack *mattk;
 /* monster explodes in your face */
 STATIC_OVL int
 explmu(mtmp, mattk, ufound)
-register struct monst *mtmp;
-register struct attack *mattk;
+struct monst *mtmp;
+struct attack *mattk;
 boolean ufound;
 {
     boolean physical_damage = TRUE, kill_agr = TRUE;
@@ -2476,8 +2571,8 @@ boolean ufound;
                                                       : "\8bó\8aÔ");
 #endif
     else {
-        register int tmp = d((int) mattk->damn, (int) mattk->damd);
-        register boolean not_affected = defends((int) mattk->adtyp, uwep);
+        int tmp = d((int) mattk->damn, (int) mattk->damd);
+        boolean not_affected = defends((int) mattk->adtyp, uwep);
 
         hitmsg(mtmp, mattk);
 
@@ -2580,8 +2675,8 @@ boolean ufound;
 /* monster gazes at you */
 int
 gazemu(mtmp, mattk)
-register struct monst *mtmp;
-register struct attack *mattk;
+struct monst *mtmp;
+struct attack *mattk;
 {
     static const char *const reactions[] = {
 #if 0 /*JP*/
@@ -2638,11 +2733,13 @@ register struct attack *mattk;
             boolean useeit = canseemon(mtmp);
 
             if (useeit)
-/*JP
+#if 0 /*JP:T*/
                 (void) ureflects("%s gaze is reflected by your %s.",
-*/
-                (void) ureflects("%s\82Ì\82É\82ç\82Ý\82Í%s\82Å\94½\8eË\82³\82ê\82½\81D",
                                  s_suffix(Monnam(mtmp)));
+#else
+                (void) ureflects("%s\82Ì\82É\82ç\82Ý\82Í%s\82Å\94½\8eË\82³\82ê\82½\81D",
+                                 Monnam(mtmp));
+#endif
             if (mon_reflects(
                     mtmp, !useeit ? (char *) 0
 /*JP
@@ -2679,7 +2776,7 @@ register struct attack *mattk;
 /*JP
             You("meet %s gaze.", s_suffix(mon_nam(mtmp)));
 */
-            You("%s\82É\82É\82ç\82Ü\82ê\82½\81D", s_suffix(mon_nam(mtmp)));
+            You("%s\82É\82É\82ç\82Ü\82ê\82½\81D", mon_nam(mtmp));
             stop_occupation();
             if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
                 break;
@@ -2706,7 +2803,7 @@ register struct attack *mattk;
 /*JP
                     pline("%s gaze confuses you!", s_suffix(Monnam(mtmp)));
 */
-                    pline("%s\82Ì\82É\82ç\82Ý\82Å\82 \82È\82½\82Í\8d¬\97\90\82µ\82½\81I", s_suffix(Monnam(mtmp)));
+                    pline("%s\82Ì\82É\82ç\82Ý\82Å\82 \82È\82½\82Í\8d¬\97\90\82µ\82½\81I", Monnam(mtmp));
                 else
 /*JP
                     You("are getting more and more confused.");
@@ -2758,10 +2855,15 @@ register struct attack *mattk;
                 /* not blind at this point implies you're wearing
                    the Eyes of the Overworld; make them block this
                    particular stun attack too */
-                if (!Blind)
+                if (!Blind) {
                     Your1(vision_clears);
-                else
-                    make_stunned((long) d(1, 3), TRUE);
+                } else {
+                    long oldstun = (HStun & TIMEOUT), newstun = (long) rnd(3);
+
+                    /* we don't want to increment stun duration every time
+                       or sighted hero will become incapacitated */
+                    make_stunned(max(oldstun, newstun), TRUE);
+                }
             }
         }
         break;
@@ -2806,11 +2908,13 @@ register struct attack *mattk;
                 already = (mtmp->mfrozen != 0); /* can't happen... */
             } else {
                 fall_asleep(-rnd(10), TRUE);
-/*JP
+#if 0 /*JP:T*/
                 pline("%s gaze makes you very sleepy...",
-*/
-                pline("%s\82Ì\82É\82ç\82Ý\82Å\82 \82È\82½\82Í\96°\82­\82È\82Á\82½\81D\81D\81D",
                       s_suffix(Monnam(mtmp)));
+#else
+                pline("%s\82Ì\82É\82ç\82Ý\82Å\82 \82È\82½\82Í\96°\82­\82È\82Á\82½\81D\81D\81D",
+                      Monnam(mtmp));
+#endif
             }
         }
         break;
@@ -2855,8 +2959,8 @@ register struct attack *mattk;
 /* mtmp hits you for n points damage */
 void
 mdamageu(mtmp, n)
-register struct monst *mtmp;
-register int n;
+struct monst *mtmp;
+int n;
 {
     context.botl = 1;
     if (Upolyd) {
@@ -2879,7 +2983,7 @@ could_seduce(magr, mdef, mattk)
 struct monst *magr, *mdef;
 struct attack *mattk;
 {
-    register struct permonst *pagr;
+    struct permonst *pagr;
     boolean agrinvis, defperc;
     xchar genagr, gendef;
 
@@ -2920,11 +3024,11 @@ struct attack *mattk;
 /* Returns 1 if monster teleported */
 int
 doseduce(mon)
-register struct monst *mon;
+struct monst *mon;
 {
-    register struct obj *ring, *nring;
+    struct obj *ring, *nring;
     boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */
-    int tried_gloves = 0;
+    int attr_tot, tried_gloves = 0;
     char qbuf[QBUFSZ];
 
     if (mon->mcan || mon->mspec_used) {
@@ -3165,7 +3269,12 @@ register struct monst *mon;
 */
     pline("\82 \82È\82½\82Æ%s\82ª\95ø\82«\8d\87\82¤\82Æ\81C\8e\9e\82ª\8e~\82Ü\82Á\82½\82æ\82¤\82É\8a´\82\82½\81D\81D\81D",
           noit_mon_nam(mon));
-    if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) {
+    /* 3.6.1: a combined total for charisma plus intelligence of 35-1
+       used to guarantee successful outcome; now total maxes out at 32
+       as far as deciding what will happen; chance for bad outcome when
+       Cha+Int is 32 or more is 2/35, a bit over 5.7% */
+    attr_tot = ACURR(A_CHA) + ACURR(A_INT);
+    if (rn2(35) > min(attr_tot, 32)) {
         /* Don't bother with mspec_used here... it didn't get tired! */
 /*JP
         pline("%s seems to have enjoyed it more than you...",
@@ -3218,9 +3327,13 @@ register struct monst *mon;
 */
                 You("\95Ï\82È\8a´\82\82ª\82µ\82½\81D\81D\81D");
             }
+            exercise(A_CON, FALSE);
+            exercise(A_DEX, FALSE);
+            exercise(A_WIS, FALSE);
             break;
         case 4: {
             int tmp;
+
 /*JP
             You_feel("exhausted.");
 */
@@ -3232,8 +3345,8 @@ register struct monst *mon;
 */
             losehp(Maybe_Half_Phys(tmp), "\90¸\97Í\82Ì\8eg\82¢\82·\82¬\82Å", KILLED_BY);
             break;
-        }
-        }
+        } /* case 4 */
+        } /* switch */
     } else {
         mon->mspec_used = rnd(100); /* monster is worn out */
 /*JP
@@ -3289,22 +3402,22 @@ register struct monst *mon;
         }
     }
 
-    if (mon->mtame) /* don't charge */
+    if (mon->mtame) /* don't charge */
         ;
-    else if (rn2(20) < ACURR(A_CHA)) {
+    else if (rn2(20) < ACURR(A_CHA)) {
 #if 0 /*JP*/
         pline("%s demands that you pay %s, but you refuse...",
               noit_Monnam(mon), Blind ? (fem ? "her" : "him") : mhim(mon));
 #else
         pline("%s\82Í\82 \82È\82½\82É\8bà\82ð\95¥\82¤\82æ\82¤\97v\8b\81\82µ\82½\82ª\81C\82 \82È\82½\82Í\8b\91\82ñ\82¾\81D\81D\81D",
-              Monnam(mon));
+              noit_Monnam(mon));
 #endif
-    } else if (u.umonnum == PM_LEPRECHAUN)
+    } else if (u.umonnum == PM_LEPRECHAUN) {
 /*JP
         pline("%s tries to take your money, but fails...", noit_Monnam(mon));
 */
         pline("%s\82Í\8bà\82ð\8eæ\82ë\82¤\82Æ\82µ\82½\82ª\81C\8e¸\94s\82µ\82½\81D\81D\81D", noit_Monnam(mon));
-    else {
+    else {
         long cost;
         long umoney = money_cnt(invent);
 
@@ -3319,12 +3432,12 @@ register struct monst *mon;
         }
         if (cost > umoney)
             cost = umoney;
-        if (!cost)
+        if (!cost) {
 /*JP
             verbalize("It's on the house!");
 */
             verbalize("\82±\82ê\82Í\82¨\82²\82è%s\81I", fem ? "\82æ" : "\82³");
-        else {
+        else {
 #if 0 /*JP*/
             pline("%s takes %ld %s for services rendered!", noit_Monnam(mon),
                   cost, currency(cost));
@@ -3345,7 +3458,7 @@ register struct monst *mon;
 
 STATIC_OVL void
 mayberem(obj, str)
-register struct obj *obj;
+struct obj *obj;
 const char *str;
 {
     char qbuf[QBUFSZ];
@@ -3407,37 +3520,58 @@ const char *str;
     remove_worn_item(obj, TRUE);
 }
 
+/* FIXME:
+ *  sequencing issue:  a monster's attack might cause poly'd hero
+ *  to revert to normal form.  The messages for passive counterattack
+ *  would look better if they came before reverting form, but we need
+ *  to know whether hero reverted in order to decide whether passive
+ *  damage applies.
+ */
 STATIC_OVL int
 passiveum(olduasmon, mtmp, mattk)
 struct permonst *olduasmon;
-register struct monst *mtmp;
-register struct attack *mattk;
+struct monst *mtmp;
+struct attack *mattk;
 {
     int i, tmp;
+    struct attack *oldu_mattk = 0;
 
-    for (i = 0;; i++) {
+    /*
+     * mattk      == mtmp's attack that hit you;
+     * oldu_mattk == your passive counterattack (even if mtmp's attack
+     *               has already caused you to revert to normal form).
+     */
+    for (i = 0; !oldu_mattk; i++) {
         if (i >= NATTK)
             return 1;
         if (olduasmon->mattk[i].aatyp == AT_NONE
             || olduasmon->mattk[i].aatyp == AT_BOOM)
-            break;
+            oldu_mattk = &olduasmon->mattk[i];
     }
-    if (olduasmon->mattk[i].damn)
-        tmp =
-            d((int) olduasmon->mattk[i].damn, (int) olduasmon->mattk[i].damd);
-    else if (olduasmon->mattk[i].damd)
-        tmp = d((int) olduasmon->mlevel + 1, (int) olduasmon->mattk[i].damd);
+    if (oldu_mattk->damn)
+        tmp = d((int) oldu_mattk->damn, (int) oldu_mattk->damd);
+    else if (oldu_mattk->damd)
+        tmp = d((int) olduasmon->mlevel + 1, (int) oldu_mattk->damd);
     else
         tmp = 0;
 
     /* These affect the enemy even if you were "killed" (rehumanized) */
-    switch (olduasmon->mattk[i].adtyp) {
+    switch (oldu_mattk->adtyp) {
     case AD_ACID:
         if (!rn2(2)) {
-/*JP
-            pline("%s is splashed by your acid!", Monnam(mtmp));
-*/
-            pline("%s\82Í\82 \82È\82½\82Ì\8e_\82ð\82­\82ç\82Á\82½\81I", Monnam(mtmp));
+#if 0 /*JP*/
+            pline("%s is splashed by %s%s!", Monnam(mtmp),
+                  /* temporary? hack for sequencing issue:  "your acid"
+                     looks strange coming immediately after player has
+                     been told that hero has reverted to normal form */
+                  !Upolyd ? "" : "your ", hliquid("acid"));
+#else
+            pline("%s\82Í%s%s\82ð\90H\82ç\82Á\82½\81I", Monnam(mtmp),
+                  /* temporary? hack for sequencing issue:  "your acid"
+                     looks strange coming immediately after player has
+                     been told that hero has reverted to normal form */
+                  !Upolyd ? "" : "\82 \82È\82½\82Ì", hliquid("\8e_"));
+#endif
             if (resists_acid(mtmp)) {
 /*JP
                 pline("%s is not affected.", Monnam(mtmp));
@@ -3474,7 +3608,7 @@ register struct attack *mattk;
 */
             pline("%s\82Í\90Î\82É\82È\82Á\82½\81I", Monnam(mtmp));
             stoned = 1;
-            xkilled(mtmp, 0);
+            xkilled(mtmp, XKILL_NOMSG);
             if (mtmp->mhp > 0)
                 return 1;
             return 2;
@@ -3482,8 +3616,10 @@ register struct attack *mattk;
         return 1;
     }
     case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
-        if (otmp) {
-            (void) drain_item(otmp);
+        if (mon_currwep) {
+            /* by_you==True: passive counterattack to hero's action
+               is hero's fault */
+            (void) drain_item(mon_currwep, TRUE);
             /* No message */
         }
         return 1;
@@ -3495,9 +3631,9 @@ register struct attack *mattk;
 
     /* These affect the enemy only if you are still a monster */
     if (rn2(3))
-        switch (youmonst.data->mattk[i].adtyp) {
+        switch (oldu_mattk->adtyp) {
         case AD_PHYS:
-            if (youmonst.data->mattk[i].aatyp == AT_BOOM) {
+            if (oldu_mattk->aatyp == AT_BOOM) {
 /*JP
                 You("explode!");
 */
@@ -3628,7 +3764,7 @@ assess_dmg:
         pline("%s dies!", Monnam(mtmp));
 */
         pline("%s\82Í\8e\80\82ñ\82¾\81I", Monnam(mtmp));
-        xkilled(mtmp, 0);
+        xkilled(mtmp, XKILL_NOMSG);
         if (mtmp->mhp > 0)
             return 1;
         return 2;
@@ -3639,7 +3775,7 @@ assess_dmg:
 struct monst *
 cloneu()
 {
-    register struct monst *mon;
+    struct monst *mon;
     int mndx = monsndx(youmonst.data);
 
     if (u.mh <= 1)
index 1d22b72..c28556e 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 minion.c        $NHDT-Date: 1432512773 2015/05/25 00:12:53 $  $NHDT-Branch: master $:$NHDT-Revision: 1.33 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2008. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -62,6 +63,13 @@ struct monst *mon;
 
     if (mon) {
         ptr = mon->data;
+
+        if (uwep && uwep->oartifact == ART_DEMONBANE && is_demon(ptr)) {
+            if (canseemon(mon))
+                pline("%s looks puzzled for a moment.", Monnam(mon));
+            return 0;
+        }
+
         atyp = mon->ispriest ? EPRI(mon)->shralign
                              : mon->isminion ? EMIN(mon)->min_align
                                              : (ptr->maligntyp == A_NONE)
@@ -305,7 +313,8 @@ register struct monst *mtmp;
 */
             pline("\89°\95a\82È\92è\96½\82Ì\82à\82Ì\82ð\8fÎ\82¢\82È\82ª\82ç\81C%s\82Í\8fÁ\82¦\82½\81D",
                   Amonnam(mtmp));
-        } else if (offer > 0L && (long) rnd(40) > (demand - offer)) {
+        } else if (offer > 0L
+                   && (long) rnd(5 * ACURR(A_CHA)) > (demand - offer)) {
 /*JP
             pline("%s scowls at you menacingly, then vanishes.",
 */
@@ -329,7 +338,7 @@ long
 bribe(mtmp)
 struct monst *mtmp;
 {
-    char buf[BUFSZ];
+    char buf[BUFSZ] = DUMMY;
     long offer;
     long umoney = money_cnt(invent);
 
index ed78589..a984426 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 mklev.c $NHDT-Date: 1446191876 2015/10/30 07:57:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.44 $ */
+/* NetHack 3.6 mklev.c $NHDT-Date: 1511681724 2017/11/26 07:35:24 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.47 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Alex Smith, 2017. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -1261,6 +1262,7 @@ struct mkroom *croom;
 coord *tm;
 {
     register int kind;
+    unsigned lvl = level_difficulty();
     coord m;
 
     /* no traps in pools */
@@ -1297,8 +1299,6 @@ coord *tm;
         /* bias the frequency of fire traps in Gehennom */
         kind = FIRE_TRAP;
     } else {
-        unsigned lvl = level_difficulty();
-
         do {
             kind = rnd(TRAPNUM - 1);
             /* reject "too hard" traps */
@@ -1353,9 +1353,9 @@ coord *tm;
     if ((kind == TRAPDOOR || kind == HOLE) && !Can_fall_thru(&u.uz))
         kind = ROCKTRAP;
 
-    if (tm)
+    if (tm) {
         m = *tm;
-    else {
+    else {
         register int tryct = 0;
         boolean avoid_boulder = (kind == PIT || kind == SPIKED_PIT
                                  || kind == TRAPDOOR || kind == HOLE);
@@ -1374,6 +1374,139 @@ coord *tm;
     (void) maketrap(m.x, m.y, kind);
     if (kind == WEB)
         (void) makemon(&mons[PM_GIANT_SPIDER], m.x, m.y, NO_MM_FLAGS);
+
+    /* The hero isn't the only person who's entered the dungeon in
+       search of treasure. On the very shallowest levels, there's a
+       chance that a created trap will have killed something already
+       (and this is guaranteed on the first level).
+
+       This isn't meant to give any meaningful treasure (in fact, any
+       items we drop here are typically cursed, other than ammo fired
+       by the trap). Rather, it's mostly just for flavour and to give
+       players on very early levels a sufficient chance to avoid traps
+       that may end up killing them before they have a fair chance to
+       build max HP. Including cursed items gives the same fair chance
+       to the starting pet, and fits the rule that possessions of the
+       dead are normally cursed.
+
+       Some types of traps are excluded because they're entirely
+       nonlethal, even indirectly. We also exclude all of the
+       later/fancier traps because they tend to have special
+       considerations (e.g. webs, portals), often are indirectly
+       lethal, and tend not to generate on shallower levels anyway.
+       Finally, pits are excluded because it's weird to see an item
+       in a pit and yet not be able to identify that the pit is there. */
+    if (lvl <= (unsigned) rnd(4)
+        && kind != SQKY_BOARD && kind != RUST_TRAP
+        && kind != PIT && kind != SPIKED_PIT && kind < HOLE) {
+        /* Object generated by the trap; initially NULL, stays NULL if
+           we fail to generate an object or if the trap doesn't
+           generate objects. */
+        struct obj *otmp = NULL;
+        int victim_mnum; /* race of the victim */
+
+        /* Not all trap types have special handling here; only the ones
+           that kill in a specific way that's obvious after the fact. */
+        switch (kind) {
+        case ARROW_TRAP:
+            otmp = mksobj(ARROW, TRUE, FALSE);
+            otmp->opoisoned = 0;
+            /* don't adjust the quantity; maybe the trap shot multiple
+               times, there was an untrapping attempt, etc... */
+            break;
+        case DART_TRAP:
+            otmp = mksobj(DART, TRUE, FALSE);
+            break;
+        case ROCKTRAP:
+            otmp = mksobj(ROCK, TRUE, FALSE);
+            break;
+        default:
+            /* no item dropped by the trap */
+            break;
+        }
+        if (otmp) {
+            place_object(otmp, m.x, m.y);
+        }
+
+        /* now otmp is reused for other items we're placing */
+
+        /* Place a random possession. This could be a weapon, tool,
+           food, or gem, i.e. the item classes that are typically
+           nonmagical and not worthless. */
+        do {
+            int poss_class = RANDOM_CLASS; /* init => lint suppression */
+
+            switch (rn2(4)) {
+            case 0:
+                poss_class = WEAPON_CLASS;
+                break;
+            case 1:
+                poss_class = TOOL_CLASS;
+                break;
+            case 2:
+                poss_class = FOOD_CLASS;
+                break;
+            case 3:
+                poss_class = GEM_CLASS;
+                break;
+            }
+
+            otmp = mkobj(poss_class, FALSE);
+            /* these items are always cursed, both for flavour (owned
+               by a dead adventurer, bones-pile-style) and for balance
+               (less useful to use, and encourage pets to avoid the trap) */
+            if (otmp) {
+                otmp->blessed = 0;
+                otmp->cursed = 1;
+                otmp->owt = weight(otmp);
+                place_object(otmp, m.x, m.y);
+            }
+
+            /* 20% chance of placing an additional item, recursively */
+        } while (!rn2(5));
+
+        /* Place a corpse. */
+        switch (rn2(15)) {
+        case 0:
+            /* elf corpses are the rarest as they're the most useful */
+            victim_mnum = PM_ELF;
+            /* elven adventurers get sleep resistance early; so don't
+               generate elf corpses on sleeping gas traps unless a)
+               we're on dlvl 2 (1 is impossible) and b) we pass a coin
+               flip */
+            if (kind == SLP_GAS_TRAP && !(lvl <= 2 && rn2(2)))
+                victim_mnum = PM_HUMAN;
+            break;
+        case 1: case 2:
+            victim_mnum = PM_DWARF;
+            break;
+        case 3: case 4: case 5:
+            victim_mnum = PM_ORC;
+            break;
+        case 6: case 7: case 8: case 9:
+            /* more common as they could have come from the Mines */
+            victim_mnum = PM_GNOME;
+            /* 10% chance of a candle too */
+            if (!rn2(10)) {
+                otmp = mksobj(rn2(4) ? TALLOW_CANDLE : WAX_CANDLE,
+                              TRUE, FALSE);
+                otmp->quan = 1;
+                otmp->blessed = 0;
+                otmp->cursed = 1;
+                otmp->owt = weight(otmp);
+                place_object(otmp, m.x, m.y);
+            }
+            break;
+        default:
+            /* the most common race */
+            victim_mnum = PM_HUMAN;
+            break;
+        }
+        otmp = mkcorpstat(CORPSE, NULL, &mons[victim_mnum], m.x, m.y,
+                          CORPSTAT_INIT);
+        if (otmp)
+            otmp->age -= 51; /* died too long ago to eat */
+    }
 }
 
 void
index 3ed4fd9..df2e371 100644 (file)
@@ -247,8 +247,8 @@ boolean anyroom;
 }
 
 /*
- *     If we have drawn a map without walls, this allows us to
- *     auto-magically wallify it.  Taken from lev_main.c.
+ * If we have drawn a map without walls, this allows us to
+ * auto-magically wallify it.  Taken from lev_main.c.
  */
 STATIC_OVL void
 wallify_map()
index 4de113e..7471641 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 mkmaze.c        $NHDT-Date: 1449269918 2015/12/04 22:58:38 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.42 $ */
+/* NetHack 3.6 mkmaze.c        $NHDT-Date: 1518718417 2018/02/15 18:13:37 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.55 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 /* from sp_lev.c, for fixup_special() */
 extern lev_region *lregions;
 extern int num_lregions;
+/* for preserving the insect legs when wallifying baalz level */
+static lev_region bughack = { {COLNO, ROWNO, 0, 0}, {COLNO, ROWNO, 0, 0} };
 
-STATIC_DCL boolean FDECL(iswall, (int, int));
-STATIC_DCL boolean FDECL(iswall_or_stone, (int, int));
+STATIC_DCL int FDECL(iswall, (int, int));
+STATIC_DCL int FDECL(iswall_or_stone, (int, int));
 STATIC_DCL boolean FDECL(is_solid, (int, int));
 STATIC_DCL int FDECL(extend_spine, (int[3][3], int, int, int));
 STATIC_DCL boolean FDECL(okay, (int, int, int));
@@ -24,7 +27,7 @@ STATIC_DCL void FDECL(maze0xy, (coord *));
 STATIC_DCL boolean FDECL(put_lregion_here, (XCHAR_P, XCHAR_P, XCHAR_P,
                                             XCHAR_P, XCHAR_P, XCHAR_P,
                                             XCHAR_P, BOOLEAN_P, d_level *));
-STATIC_DCL void NDECL(fixup_special);
+STATIC_DCL void NDECL(baalz_fixup);
 STATIC_DCL void NDECL(setup_waterlevel);
 STATIC_DCL void NDECL(unsetup_waterlevel);
 
@@ -40,33 +43,28 @@ STATIC_DCL void NDECL(unsetup_waterlevel);
         }                                                        \
     } while (0)
 
-STATIC_OVL boolean
+STATIC_OVL int
 iswall(x, y)
 int x, y;
 {
-    register int type;
+    int type;
 
     if (!isok(x, y))
-        return FALSE;
+        return 0;
     type = levl[x][y].typ;
-    return (boolean) (IS_WALL(type) || IS_DOOR(type)
-                      || type == SDOOR || type == IRONBARS);
+    return (IS_WALL(type) || IS_DOOR(type)
+            || type == SDOOR || type == IRONBARS);
 }
 
-STATIC_OVL boolean
+STATIC_OVL int
 iswall_or_stone(x, y)
 int x, y;
 {
-    register int type;
-
     /* out of bounds = stone */
     if (!isok(x, y))
-        return TRUE;
+        return 1;
 
-    type = levl[x][y].typ;
-    return (boolean) (type == STONE
-                      || IS_WALL(type) || IS_DOOR(type)
-                      || type == SDOOR || type == IRONBARS);
+    return (levl[x][y].typ == STONE || iswall(x, y));
 }
 
 /* return TRUE if out of bounds, wall or rock */
@@ -128,37 +126,26 @@ int wall_there, dx, dy;
     return spine;
 }
 
-/*
- * Wall cleanup.  This function has two purposes: (1) remove walls that
- * are totally surrounded by stone - they are redundant.  (2) correct
- * the types so that they extend and connect to each other.
- */
+/* Remove walls totally surrounded by stone */
 void
-wallification(x1, y1, x2, y2)
+wall_cleanup(x1, y1, x2, y2)
 int x1, y1, x2, y2;
 {
     uchar type;
-    register int x, y;
+    int x, y;
     struct rm *lev;
-    int bits;
-    int locale[3][3]; /* rock or wall status surrounding positions */
-    /*
-     * Value 0 represents a free-standing wall.  It could be anything,
-     * so even though this table says VWALL, we actually leave whatever
-     * typ was there alone.
-     */
-    static xchar spine_array[16] = { VWALL, HWALL,    HWALL,    HWALL,
-                                     VWALL, TRCORNER, TLCORNER, TDWALL,
-                                     VWALL, BRCORNER, BLCORNER, TUWALL,
-                                     VWALL, TLWALL,   TRWALL,   CROSSWALL };
 
     /* sanity check on incoming variables */
     if (x1 < 0 || x2 >= COLNO || x1 > x2 || y1 < 0 || y2 >= ROWNO || y1 > y2)
-        panic("wallification: bad bounds (%d,%d) to (%d,%d)", x1, y1, x2, y2);
+        panic("wall_cleanup: bad bounds (%d,%d) to (%d,%d)", x1, y1, x2, y2);
 
-    /* Step 1: change walls surrounded by rock to rock. */
+    /* change walls surrounded by rock to rock. */
     for (x = x1; x <= x2; x++)
         for (y = y1; y <= y2; y++) {
+            if (within_bounded_area(x, y,
+                                    bughack.inarea.x1, bughack.inarea.y1,
+                                    bughack.inarea.x2, bughack.inarea.y2))
+                continue;
             lev = &levl[x][y];
             type = lev->typ;
             if (IS_WALL(type) && type != DBWALL) {
@@ -169,12 +156,35 @@ int x1, y1, x2, y2;
                     lev->typ = STONE;
             }
         }
+}
+
+/* Correct wall types so they extend and connect to each other */
+void
+fix_wall_spines(x1, y1, x2, y2)
+int x1, y1, x2, y2;
+{
+    uchar type;
+    int x, y;
+    struct rm *lev;
+    int FDECL((*loc_f), (int, int));
+    int bits;
+    int locale[3][3]; /* rock or wall status surrounding positions */
 
     /*
-     * Step 2: set the correct wall type.  We can't combine steps
-     * 1 and 2 into a single sweep because we depend on knowing if
-     * the surrounding positions are stone.
+     * Value 0 represents a free-standing wall.  It could be anything,
+     * so even though this table says VWALL, we actually leave whatever
+     * typ was there alone.
      */
+    static xchar spine_array[16] = { VWALL, HWALL,    HWALL,    HWALL,
+                                     VWALL, TRCORNER, TLCORNER, TDWALL,
+                                     VWALL, BRCORNER, BLCORNER, TUWALL,
+                                     VWALL, TLWALL,   TRWALL,   CROSSWALL };
+
+    /* sanity check on incoming variables */
+    if (x1 < 0 || x2 >= COLNO || x1 > x2 || y1 < 0 || y2 >= ROWNO || y1 > y2)
+        panic("wall_extends: bad bounds (%d,%d) to (%d,%d)", x1, y1, x2, y2);
+
+    /* set the correct wall type. */
     for (x = x1; x <= x2; x++)
         for (y = y1; y <= y2; y++) {
             lev = &levl[x][y];
@@ -183,16 +193,21 @@ int x1, y1, x2, y2;
                 continue;
 
             /* set the locations TRUE if rock or wall or out of bounds */
-            locale[0][0] = iswall_or_stone(x - 1, y - 1);
-            locale[1][0] = iswall_or_stone(x, y - 1);
-            locale[2][0] = iswall_or_stone(x + 1, y - 1);
-
-            locale[0][1] = iswall_or_stone(x - 1, y);
-            locale[2][1] = iswall_or_stone(x + 1, y);
-
-            locale[0][2] = iswall_or_stone(x - 1, y + 1);
-            locale[1][2] = iswall_or_stone(x, y + 1);
-            locale[2][2] = iswall_or_stone(x + 1, y + 1);
+            loc_f = within_bounded_area(x, y, /* for baalz insect */
+                                        bughack.inarea.x1, bughack.inarea.y1,
+                                        bughack.inarea.x2, bughack.inarea.y2)
+                       ? iswall
+                       : iswall_or_stone;
+            locale[0][0] = (*loc_f)(x - 1, y - 1);
+            locale[1][0] = (*loc_f)(x, y - 1);
+            locale[2][0] = (*loc_f)(x + 1, y - 1);
+
+            locale[0][1] = (*loc_f)(x - 1, y);
+            locale[2][1] = (*loc_f)(x + 1, y);
+
+            locale[0][2] = (*loc_f)(x - 1, y + 1);
+            locale[1][2] = (*loc_f)(x, y + 1);
+            locale[2][2] = (*loc_f)(x + 1, y + 1);
 
             /* determine if wall should extend to each direction NSEW */
             bits = (extend_spine(locale, iswall(x, y - 1), 0, -1) << 3)
@@ -206,15 +221,23 @@ int x1, y1, x2, y2;
         }
 }
 
+void
+wallification(x1, y1, x2, y2)
+int x1, y1, x2, y2;
+{
+    wall_cleanup(x1, y1, x2, y2);
+    fix_wall_spines(x1, y1, x2, y2);
+}
+
 STATIC_OVL boolean
 okay(x, y, dir)
 int x, y;
-register int dir;
+int dir;
 {
     mz_move(x, y, dir);
     mz_move(x, y, dir);
     if (x < 3 || y < 3 || x > x_maze_max || y > y_maze_max
-        || levl[x][y].typ != 0)
+        || levl[x][y].typ != STONE)
         return FALSE;
     return TRUE;
 }
@@ -270,9 +293,9 @@ d_level *lev;
             return;
         }
 
-        lx = 1;
+        lx = 1; /* column 0 is not used */
         hx = COLNO - 1;
-        ly = 1;
+        ly = 0; /* 3.6.0 and earlier erroneously had 1 here */
         hy = ROWNO - 1;
     }
 
@@ -288,11 +311,9 @@ d_level *lev;
 
     /* then a deterministic one */
 
-    oneshot = TRUE;
     for (x = lx; x <= hx; x++)
         for (y = ly; y <= hy; y++)
-            if (put_lregion_here(x, y, nlx, nly, nhx, nhy, rtype, oneshot,
-                                 lev))
+            if (put_lregion_here(x, y, nlx, nly, nhx, nhy, rtype, TRUE, lev))
                 return;
 
     impossible("Couldn't place lregion type %d!", rtype);
@@ -349,15 +370,103 @@ d_level *lev;
     return TRUE;
 }
 
+/* fix up Baalzebub's lair, which depicts a level-sized beetle;
+   its legs are walls within solid rock--regular wallification
+   classifies them as superfluous and gets rid of them */
+STATIC_OVL void
+baalz_fixup()
+{
+    struct monst *mtmp;
+    int x, y, lastx, lasty;
+
+    /*
+     * baalz level's nondiggable region surrounds the "insect" and rooms.
+     * The outermost perimeter of that region is subject to wall cleanup
+     * (hence 'x + 1' and 'y + 1' for starting don't-clean column and row,
+     * 'lastx - 1' and 'lasty - 1' for ending don't-clean column and row)
+     * and the interior is protected against that (in wall_cleanup()).
+     *
+     * Assumes level.flags.corrmaze is True, otherwise the bug legs will
+     * have already been "cleaned" away by general wallification.
+     */
+
+    /* find low and high x for to-be-wallified portion of level */
+    y = ROWNO / 2;
+    for (lastx = x = 0; x < COLNO; ++x)
+        if ((levl[x][y].wall_info & W_NONDIGGABLE) != 0) {
+            if (!lastx)
+                bughack.inarea.x1 = x + 1;
+            lastx = x;
+        }
+    bughack.inarea.x2 = ((lastx > bughack.inarea.x1) ? lastx : x) - 1;
+    /* find low and high y for to-be-wallified portion of level */
+    x = bughack.inarea.x1;
+    for (lasty = y = 0; y < ROWNO; ++y)
+        if ((levl[x][y].wall_info & W_NONDIGGABLE) != 0) {
+            if (!lasty)
+                bughack.inarea.y1 = y + 1;
+            lasty = y;
+        }
+    bughack.inarea.y2 = ((lasty > bughack.inarea.y1) ? lasty : y) - 1;
+    /* two pools mark where special post-wallify fix-ups are needed */
+    for (x = bughack.inarea.x1; x <= bughack.inarea.x2; ++x)
+        for (y = bughack.inarea.y1; y <= bughack.inarea.y2; ++y)
+            if (levl[x][y].typ == POOL) {
+                levl[x][y].typ = HWALL;
+                if (bughack.delarea.x1 == COLNO)
+                    bughack.delarea.x1 = x, bughack.delarea.y1 = y;
+                else
+                    bughack.delarea.x2 = x, bughack.delarea.y2 = y;
+            } else if (levl[x][y].typ == IRONBARS) {
+                /* novelty effect; allowing digging in front of 'eyes' */
+                levl[x - 1][y].wall_info &= ~W_NONDIGGABLE;
+                if (isok(x - 2, y))
+                    levl[x - 2][y].wall_info &= ~W_NONDIGGABLE;
+            }
+
+    wallification(max(bughack.inarea.x1 - 2, 1),
+                  max(bughack.inarea.y1 - 2, 0),
+                  min(bughack.inarea.x2 + 2, COLNO - 1),
+                  min(bughack.inarea.y2 + 2, ROWNO - 1));
+
+    /* bughack hack for rear-most legs on baalz level; first joint on
+       both top and bottom gets a bogus extra connection to room area,
+       producing unwanted rectangles; change back to separated legs */
+    x = bughack.delarea.x1, y = bughack.delarea.y1;
+    if (isok(x, y) && levl[x][y].typ == TLWALL
+        && isok(x, y + 1) && levl[x][y + 1].typ == TUWALL) {
+        levl[x][y].typ = BRCORNER;
+        levl[x][y + 1].typ = HWALL;
+        if ((mtmp = m_at(x, y)) != 0) /* something at temporary pool... */
+            (void) rloc(mtmp, FALSE);
+    }
+    x = bughack.delarea.x2, y = bughack.delarea.y2;
+    if (isok(x, y) && levl[x][y].typ == TLWALL
+        && isok(x, y - 1) && levl[x][y - 1].typ == TDWALL) {
+        levl[x][y].typ = TRCORNER;
+        levl[x][y - 1].typ = HWALL;
+        if ((mtmp = m_at(x, y)) != 0) /* something at temporary pool... */
+            (void) rloc(mtmp, FALSE);
+    }
+
+    /* reset bughack region; set low end to <COLNO,ROWNO> so that
+       within_bounded_region() in fix_wall_spines() will fail
+       most quickly--on its first test--when loading other levels */
+    bughack.inarea.x1 = bughack.delarea.x1 = COLNO;
+    bughack.inarea.y1 = bughack.delarea.y1 = ROWNO;
+    bughack.inarea.x2 = bughack.delarea.x2 = 0;
+    bughack.inarea.y2 = bughack.delarea.y2 = 0;
+}
+
 static boolean was_waterlevel; /* ugh... this shouldn't be needed */
 
 /* this is special stuff that the level compiler cannot (yet) handle */
-STATIC_OVL void
+void
 fixup_special()
 {
-    register lev_region *r = lregions;
+    lev_region *r = lregions;
     struct d_level lev;
-    register int x, y;
+    int x, y;
     struct mkroom *croom;
     boolean added_branch = FALSE;
 
@@ -388,7 +497,7 @@ fixup_special()
                 s_level *sp = find_level(r->rname.str);
                 lev = sp->dlevel;
             }
-        /* fall into... */
+            /*FALLTHRU*/
 
         case LR_UPSTAIR:
         case LR_DOWNSTAIR:
@@ -495,7 +604,7 @@ fixup_special()
 
         create_secret_door(croom, W_ANY);
     } else if (on_level(&u.uz, &orcus_level)) {
-        register struct monst *mtmp, *mtmp2;
+        struct monst *mtmp, *mtmp2;
 
         /* it's a ghost town, get rid of shopkeepers */
         for (mtmp = fmon; mtmp; mtmp = mtmp2) {
@@ -503,6 +612,9 @@ fixup_special()
             if (mtmp->isshk)
                 mongone(mtmp);
         }
+    } else if (on_level(&u.uz, &baalzebub_level)) {
+        /* custom wallify the "beetle" potion of the level */
+        baalz_fixup();
     }
 
     if (lregions)
@@ -510,9 +622,156 @@ fixup_special()
     num_lregions = 0;
 }
 
+boolean
+maze_inbounds(x, y)
+int x, y;
+{
+    return (x >= 2 && y >= 2
+            && x < x_maze_max && y < y_maze_max && isok(x, y));
+}
+
+void
+maze_remove_deadends(typ)
+xchar typ;
+{
+    char dirok[4];
+    int x, y, dir, idx, idx2, dx, dy, dx2, dy2;
+
+    dirok[0] = 0; /* lint suppression */
+    for (x = 2; x < x_maze_max; x++)
+        for (y = 2; y < y_maze_max; y++)
+            if (ACCESSIBLE(levl[x][y].typ) && (x % 2) && (y % 2)) {
+                idx = idx2 = 0;
+                for (dir = 0; dir < 4; dir++) {
+                    /* note: mz_move() is a macro which modifies
+                       one of its first two parameters */
+                    dx = dx2 = x;
+                    dy = dy2 = y;
+                    mz_move(dx, dy, dir);
+                    if (!maze_inbounds(dx, dy)) {
+                        idx2++;
+                        continue;
+                    }
+                    mz_move(dx2, dy2, dir);
+                    mz_move(dx2, dy2, dir);
+                    if (!maze_inbounds(dx2, dy2)) {
+                        idx2++;
+                        continue;
+                    }
+                    if (!ACCESSIBLE(levl[dx][dy].typ)
+                        && ACCESSIBLE(levl[dx2][dy2].typ)) {
+                        dirok[idx++] = dir;
+                        idx2++;
+                    }
+                }
+                if (idx2 >= 3 && idx > 0) {
+                    dx = x;
+                    dy = y;
+                    dir = dirok[rn2(idx)];
+                    mz_move(dx, dy, dir);
+                    levl[dx][dy].typ = typ;
+                }
+            }
+}
+
+/* Create a maze with specified corridor width and wall thickness
+ * TODO: rewrite walkfrom so it works on temp space, not levl
+ */
+void
+create_maze(corrwid, wallthick)
+int corrwid;
+int wallthick;
+{
+    int x,y;
+    coord mm;
+    int tmp_xmax = x_maze_max;
+    int tmp_ymax = y_maze_max;
+    int rdx = 0;
+    int rdy = 0;
+    int scale;
+
+    if (wallthick < 1)
+        wallthick = 1;
+    else if (wallthick > 5)
+        wallthick = 5;
+
+    if (corrwid < 1)
+        corrwid = 1;
+    else if (corrwid > 5)
+        corrwid = 5;
+
+    scale = corrwid + wallthick;
+    rdx = (x_maze_max / scale);
+    rdy = (y_maze_max / scale);
+
+    if (level.flags.corrmaze)
+        for (x = 2; x < (rdx * 2); x++)
+            for (y = 2; y < (rdy * 2); y++)
+                levl[x][y].typ = STONE;
+    else
+        for (x = 2; x <= (rdx * 2); x++)
+            for (y = 2; y <= (rdy * 2); y++)
+                levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
+
+    /* set upper bounds for maze0xy and walkfrom */
+    x_maze_max = (rdx * 2);
+    y_maze_max = (rdy * 2);
+
+    /* create maze */
+    maze0xy(&mm);
+    walkfrom((int) mm.x, (int) mm.y, 0);
+
+    if (!rn2(5))
+        maze_remove_deadends((level.flags.corrmaze) ? CORR : ROOM);
+
+    /* restore bounds */
+    x_maze_max = tmp_xmax;
+    y_maze_max = tmp_ymax;
+
+    /* scale maze up if needed */
+    if (scale > 2) {
+        char tmpmap[COLNO][ROWNO];
+        int rx = 1, ry = 1;
+
+        /* back up the existing smaller maze */
+        for (x = 1; x < x_maze_max; x++)
+            for (y = 1; y < y_maze_max; y++) {
+                tmpmap[x][y] = levl[x][y].typ;
+            }
+
+        /* do the scaling */
+        rx = x = 2;
+        while (rx < x_maze_max) {
+            int mx = (x % 2) ? corrwid
+                             : ((x == 2 || x == (rdx * 2)) ? 1
+                                                           : wallthick);
+            ry = y = 2;
+            while (ry < y_maze_max) {
+                int dx = 0, dy = 0;
+                int my = (y % 2) ? corrwid
+                                 : ((y == 2 || y == (rdy * 2)) ? 1
+                                                               : wallthick);
+                for (dx = 0; dx < mx; dx++)
+                    for (dy = 0; dy < my; dy++) {
+                        if (rx+dx >= x_maze_max
+                            || ry+dy >= y_maze_max)
+                            break;
+                        levl[rx + dx][ry + dy].typ = tmpmap[x][y];
+                    }
+                ry += my;
+                y++;
+            }
+            rx += mx;
+            x++;
+        }
+
+    }
+}
+
+
 void
 makemaz(s)
-register const char *s;
+const char *s;
 {
     int x, y;
     char protofile[20];
@@ -567,7 +826,6 @@ register const char *s;
     if (*protofile) {
         Strcat(protofile, LEV_EXT);
         if (load_special(protofile)) {
-            fixup_special();
             /* some levels can end up with monsters
                on dead mon list, including light source monsters */
             dmonsfree();
@@ -579,19 +837,12 @@ register const char *s;
     level.flags.is_maze_lev = TRUE;
     level.flags.corrmaze = !rn2(3);
 
-    if (level.flags.corrmaze)
-        for (x = 2; x < x_maze_max; x++)
-            for (y = 2; y < y_maze_max; y++)
-                levl[x][y].typ = STONE;
-    else
-        for (x = 2; x <= x_maze_max; x++)
-            for (y = 2; y <= y_maze_max; y++)
-                levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
-
-    maze0xy(&mm);
-    walkfrom((int) mm.x, (int) mm.y, 0);
-    /* put a boulder at the maze center */
-    (void) mksobj_at(BOULDER, (int) mm.x, (int) mm.y, TRUE, FALSE);
+    if (!Invocation_lev(&u.uz) && rn2(2)) {
+        int corrscale = rnd(4);
+        create_maze(corrscale,rnd(4)-corrscale);
+    } else {
+        create_maze(1,1);
+    }
 
     if (!level.flags.corrmaze)
         wallification(2, 2, x_maze_max, y_maze_max);
@@ -732,7 +983,7 @@ walkfrom(x, y, typ)
 int x, y;
 schar typ;
 {
-    register int q, a, dir;
+    int q, a, dir;
     int dirs[4];
 
     if (!typ) {
@@ -773,19 +1024,20 @@ coord *cc;
     int cpt = 0;
 
     do {
-        cc->x = 3 + 2 * rn2((x_maze_max >> 1) - 1);
-        cc->y = 3 + 2 * rn2((y_maze_max >> 1) - 1);
+        cc->x = 1 + rn2(x_maze_max);
+        cc->y = 1 + rn2(y_maze_max);
         cpt++;
     } while (cpt < 100
              && levl[cc->x][cc->y].typ
                     != (level.flags.corrmaze ? CORR : ROOM));
     if (cpt >= 100) {
-        register int x, y;
+        int x, y;
+
         /* last try */
-        for (x = 0; x < (x_maze_max >> 1) - 1; x++)
-            for (y = 0; y < (y_maze_max >> 1) - 1; y++) {
-                cc->x = 3 + 2 * x;
-                cc->y = 3 + 2 * y;
+        for (x = 1; x < x_maze_max; x++)
+            for (y = 1; y < y_maze_max; y++) {
+                cc->x = x;
+                cc->y = y;
                 if (levl[cc->x][cc->y].typ
                     == (level.flags.corrmaze ? CORR : ROOM))
                     return;
@@ -808,9 +1060,9 @@ coord *cc;
 void
 bound_digging()
 {
-    register int x, y;
-    register unsigned typ;
-    register struct rm *lev;
+    int x, y;
+    unsigned typ;
+    struct rm *lev;
     boolean found, nonwall;
     int xmin, xmax, ymin, ymax;
 
@@ -917,8 +1169,10 @@ fumaroles()
     for (n = rn2(3) + 2; n; n--) {
         xchar x = rn1(COLNO - 4, 3);
         xchar y = rn1(ROWNO - 4, 3);
+
         if (levl[x][y].typ == LAVAPOOL) {
             NhRegion *r = create_gas_cloud(x, y, 4 + rn2(5), rn1(10, 5));
+
             clear_heros_fault(r);
             snd = TRUE;
             if (distu(x, y) < 15)
@@ -936,16 +1190,6 @@ fumaroles()
  * other source files, but they are all so nicely encapsulated here.
  */
 
-#ifdef DEBUG
-/* to ease the work of debuggers at this stage */
-#define register
-#endif
-
-#define CONS_OBJ 0
-#define CONS_MON 1
-#define CONS_HERO 2
-#define CONS_TRAP 3
-
 static struct bubble *bbubbles, *ebubbles;
 
 static struct trap *wportal;
@@ -964,8 +1208,8 @@ void
 movebubbles()
 {
     static boolean up;
-    register struct bubble *b;
-    register int x, y, i, j;
+    struct bubble *b;
+    int x, y, i, j;
     struct trap *btrap;
     static const struct rm water_pos = { cmap_to_glyph(S_water), WATER, 0, 0,
                                          0, 0, 0, 0, 0, 0 };
@@ -1087,7 +1331,7 @@ movebubbles()
      */
     up = !up;
     for (b = up ? bbubbles : ebubbles; b; b = up ? b->next : b->prev) {
-        register int rx = rn2(3), ry = rn2(3);
+        int rx = rn2(3), ry = rn2(3);
 
         mv_bubble(b, b->dx + 1 - (!b->dx ? rx : (rx ? 1 : 0)),
                   b->dy + 1 - (!b->dy ? ry : (ry ? 1 : 0)), FALSE);
@@ -1103,8 +1347,8 @@ movebubbles()
 void
 water_friction()
 {
-    register int x, y, dx, dy;
-    register boolean eff = FALSE;
+    int x, y, dx, dy;
+    boolean eff = FALSE;
 
     if (Swimming && rn2(4))
         return; /* natural swimmers have advantage */
@@ -1141,7 +1385,7 @@ void
 save_waterlevel(fd, mode)
 int fd, mode;
 {
-    register struct bubble *b;
+    struct bubble *b;
 
     if (!Is_waterlevel(&u.uz) && !Is_airlevel(&u.uz))
         return;
@@ -1164,11 +1408,10 @@ int fd, mode;
 
 void
 restore_waterlevel(fd)
-register int fd;
+int fd;
 {
-    register struct bubble *b = (struct bubble *) 0, *btmp;
-    register int i;
-    int n;
+    struct bubble *b = (struct bubble *) 0, *btmp;
+    int i, n;
 
     if (!Is_waterlevel(&u.uz) && !Is_airlevel(&u.uz))
         return;
@@ -1201,7 +1444,7 @@ const char *
 waterbody_name(x, y)
 xchar x, y;
 {
-    register struct rm *lev;
+    struct rm *lev;
     schar ltyp;
 
     if (!isok(x, y))
@@ -1213,9 +1456,9 @@ xchar x, y;
 
     if (ltyp == LAVAPOOL)
 /*JP
-        return "lava";
+        return hliquid("lava");
 */
-        return "\97n\8aâ";
+        return hliquid("\97n\8aâ");
     else if (ltyp == ICE)
 /*JP
         return "ice";
@@ -1240,9 +1483,9 @@ xchar x, y;
         return "\96x";
 
 /*JP
-    return "water";
+    return hliquid("water");
 */
-    return "\90\85\92\86";
+    return hliquid("\90\85\92\86");
 }
 
 STATIC_OVL void
@@ -1258,10 +1501,10 @@ set_wportal()
 STATIC_OVL void
 setup_waterlevel()
 {
-    register int x, y;
-    register int xskip, yskip;
-    register int water_glyph = cmap_to_glyph(S_water);
-    register int air_glyph = cmap_to_glyph(S_air);
+    int x, y;
+    int xskip, yskip;
+    int water_glyph = cmap_to_glyph(S_water),
+        air_glyph = cmap_to_glyph(S_air);
 
     /* ouch, hardcoded... */
 
@@ -1294,7 +1537,7 @@ setup_waterlevel()
 STATIC_OVL void
 unsetup_waterlevel()
 {
-    register struct bubble *b, *bb;
+    struct bubble *b, *bb;
 
     /* free bubbles */
 
@@ -1307,7 +1550,7 @@ unsetup_waterlevel()
 
 STATIC_OVL void
 mk_bubble(x, y, n)
-register int x, y, n;
+int x, y, n;
 {
     /*
      * These bit masks make visually pleasing bubbles on a normal aspect
@@ -1316,14 +1559,15 @@ register int x, y, n;
      * in situ, either.  The first two elements tell the dimensions of
      * the bubble's bounding box.
      */
-    static uchar bm2[] = { 2, 1, 0x3 }, bm3[] = { 3, 2, 0x7, 0x7 },
+    static uchar bm2[] = { 2, 1, 0x3 },
+                 bm3[] = { 3, 2, 0x7, 0x7 },
                  bm4[] = { 4, 3, 0x6, 0xf, 0x6 },
                  bm5[] = { 5, 3, 0xe, 0x1f, 0xe },
                  bm6[] = { 6, 4, 0x1e, 0x3f, 0x3f, 0x1e },
                  bm7[] = { 7, 4, 0x3e, 0x7f, 0x7f, 0x3e },
                  bm8[] = { 8, 4, 0x7e, 0xff, 0xff, 0x7e },
                  *bmask[] = { bm2, bm3, bm4, bm5, bm6, bm7, bm8 };
-    register struct bubble *b;
+    struct bubble *b;
 
     if (x >= bxmax || y >= bymax)
         return;
@@ -1369,11 +1613,11 @@ register int x, y, n;
  */
 STATIC_OVL void
 mv_bubble(b, dx, dy, ini)
-register struct bubble *b;
-register int dx, dy;
-register boolean ini;
+struct bubble *b;
+int dx, dy;
+boolean ini;
 {
-    register int x, y, i, j, colli = 0;
+    int x, y, i, j, colli = 0;
     struct container *cons, *ctemp;
 
     /* clouds move slowly */
index dfe380b..274b3bc 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 mkobj.c $NHDT-Date: 1447475943 2015/11/14 04:39:03 $  $NHDT-Branch: master $:$NHDT-Revision: 1.113 $ */
+/* NetHack 3.6 mkobj.c $NHDT-Date: 1518053380 2018/02/08 01:29:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.130 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
@@ -107,13 +108,11 @@ struct obj *otmp;
 {
     if (!otmp->oextra)
         otmp->oextra = newoextra();
+
     if (!OMONST(otmp)) {
         struct monst *m = newmonst();
 
-        /* newmonst() allocates memory but doesn't initialize anything */
-        (void) memset((genericptr_t) m, 0, sizeof (struct monst));
-        m->mextra = (struct mextra *) 0;
-        m->nmon = (struct monst *) 0;
+        *m = zeromonst;
         OMONST(otmp) = m;
     }
 }
@@ -225,6 +224,7 @@ boolean init, artif;
     return otmp;
 }
 
+/* mkobj(): select a type of item from a class, use mksobj() to create it */
 struct obj *
 mkobj(oclass, artif)
 char oclass;
@@ -267,10 +267,10 @@ struct obj *box;
         n = 20;
         break;
     case CHEST:
-        n = 5;
+        n = box->olocked ? 7 : 5;
         break;
     case LARGE_BOX:
-        n = 3;
+        n = box->olocked ? 5 : 3;
         break;
     case SACK:
     case OILSKIN_SACK:
@@ -279,7 +279,7 @@ struct obj *box;
             n = 0;
             break;
         }
-    /*else FALLTHRU*/
+        /*FALLTHRU*/
     case BAG_OF_HOLDING:
         n = 1;
         break;
@@ -580,6 +580,23 @@ struct obj *otmp;
     }
 }
 
+/* is 'obj' inside a container whose contents aren't known?
+   if so, return the outermost container meeting that criterium */
+struct obj *
+unknwn_contnr_contents(obj)
+struct obj *obj;
+{
+    struct obj *result = 0, *parent;
+
+    while (obj->where == OBJ_CONTAINED) {
+        parent = obj->ocontainer;
+        if (!parent->cknown)
+            result = parent;
+        obj = parent;
+    }
+    return result;
+}
+
 /*
  * Create a dummy duplicate to put on shop bill.  The duplicate exists
  * only in the billobjs chain.  This function is used when a shop object
@@ -734,6 +751,7 @@ static const char dknowns[] = { WAND_CLASS,   RING_CLASS, POTION_CLASS,
                                 SCROLL_CLASS, GEM_CLASS,  SPBOOK_CLASS,
                                 WEAPON_CLASS, TOOL_CLASS, 0 };
 
+/* mksobj(): create a specific type of object */
 struct obj *
 mksobj(otyp, init, artif)
 int otyp;
@@ -756,7 +774,8 @@ boolean artif;
     otmp->where = OBJ_FREE;
     otmp->dknown = index(dknowns, let) ? 0 : 1;
     if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD)
-        || otmp->otyp == SHIELD_OF_REFLECTION)
+        || otmp->otyp == SHIELD_OF_REFLECTION
+        || objects[otmp->otyp].oc_merge)
         otmp->dknown = 0;
     if (!objects[otmp->otyp].oc_uses_known)
         otmp->known = 1;
@@ -764,7 +783,7 @@ boolean artif;
     otmp->cknown = 0;
     otmp->corpsenm = NON_PM;
 
-    if (init)
+    if (init) {
         switch (let) {
         case WEAPON_CLASS:
             otmp->quan = is_multigen(otmp) ? (long) rn1(6, 6) : 1L;
@@ -794,9 +813,8 @@ boolean artif;
                        && (--tryct > 0));
                 if (tryct == 0) {
                     /* perhaps rndmonnum() only wants to make G_NOCORPSE
-                       monsters on
-                       this level; let's create an adventurer's corpse
-                       instead, then */
+                       monsters on this level; create an adventurer's
+                       corpse instead, then */
                     otmp->corpsenm = PM_HUMAN;
                 }
                 /* timer set below */
@@ -839,11 +857,9 @@ boolean artif;
             }
             if (Is_pudding(otmp)) {
                 otmp->globby = 1;
-                otmp->known = otmp->bknown = otmp->rknown = otmp->dknown = 1;
-                otmp->corpsenm =
-                    PM_GRAY_OOZE + (otmp->otyp - GLOB_OF_GRAY_OOZE);
-                /* this ensures that they don't fail merging because of
-                 * BUC status or other irrelevancies */
+                otmp->known = otmp->dknown = 1;
+                otmp->corpsenm = PM_GRAY_OOZE
+                                 + (otmp->otyp - GLOB_OF_GRAY_OOZE);
             } else {
                 if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING
                     && otmp->otyp != KELP_FROND && !rn2(6)) {
@@ -889,15 +905,13 @@ boolean artif;
             case LARGE_BOX:
                 otmp->olocked = !!(rn2(5));
                 otmp->otrapped = !(rn2(10));
+                /*FALLTHRU*/
             case ICE_BOX:
             case SACK:
             case OILSKIN_SACK:
             case BAG_OF_HOLDING:
                 mkbox_cnts(otmp);
                 break;
-            case LEASH:
-                otmp->leashmon = 0;
-                break;
             case EXPENSIVE_CAMERA:
             case TINNING_KIT:
             case MAGIC_MARKER:
@@ -915,14 +929,13 @@ boolean artif;
             case BAG_OF_TRICKS:
                 otmp->spe = rnd(20);
                 break;
-            case FIGURINE: {
-                int tryct2 = 0;
+            case FIGURINE:
+                tryct = 0;
                 do
                     otmp->corpsenm = rndmonnum();
-                while (is_human(&mons[otmp->corpsenm]) && tryct2++ < 30);
+                while (is_human(&mons[otmp->corpsenm]) && tryct++ < 30);
                 blessorcurse(otmp, 4);
                 break;
-            }
             case BELL_OF_OPENING:
                 otmp->spe = 3;
                 break;
@@ -944,15 +957,12 @@ boolean artif;
                 curse(otmp);
             } else
                 blessorcurse(otmp, 10);
+            break;
         case VENOM_CLASS:
         case CHAIN_CLASS:
         case BALL_CLASS:
             break;
-        case POTION_CLASS:
-            otmp->fromsink = 0;
-            if (otmp->otyp == POT_OIL)
-                otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */
-        /* fall through */
+        case POTION_CLASS: /* note: potions get some additional init below */
         case SCROLL_CLASS:
 #ifdef MAIL
             if (otmp->otyp != SCR_MAIL)
@@ -1038,25 +1048,37 @@ boolean artif;
                        objects[otmp->otyp].oc_class);
             return (struct obj *) 0;
         }
+    }
 
     /* some things must get done (corpsenm, timers) even if init = 0 */
-    switch (otmp->otyp) {
+    switch ((otmp->oclass == POTION_CLASS && otmp->otyp != POT_OIL)
+            ? POT_WATER
+            : otmp->otyp) {
     case CORPSE:
         if (otmp->corpsenm == NON_PM) {
             otmp->corpsenm = undead_to_corpse(rndmonnum());
             if (mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE | G_GONE))
                 otmp->corpsenm = urole.malenum;
         }
-    /*FALLTHRU*/
+        /*FALLTHRU*/
     case STATUE:
     case FIGURINE:
         if (otmp->corpsenm == NON_PM)
             otmp->corpsenm = rndmonnum();
-    /*FALLTHRU*/
+        /*FALLTHRU*/
     case EGG:
-        /* case TIN: */
+    /* case TIN: */
         set_corpsenm(otmp, otmp->corpsenm);
         break;
+    case POT_OIL:
+        otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */
+        /*FALLTHRU*/
+    case POT_WATER: /* POTION_CLASS */
+        otmp->fromsink = 0; /* overloads corpsenm, which was set to NON_PM */
+        break;
+    case LEASH:
+        otmp->leashmon = 0; /* overloads corpsenm, which was set to NON_PM */
+        break;
     case SPE_NOVEL:
         otmp->novelidx = -1; /* "none of the above"; will be changed */
         otmp = oname(otmp, noveltitle(&otmp->novelidx));
@@ -1269,12 +1291,14 @@ void
 curse(otmp)
 register struct obj *otmp;
 {
+    unsigned already_cursed;
     int old_light = 0;
 
     if (otmp->oclass == COIN_CLASS)
         return;
     if (otmp->lamplit)
         old_light = arti_light_radius(otmp);
+    already_cursed = otmp->cursed;
     otmp->blessed = 0;
     otmp->cursed = 1;
     /* welded two-handed weapon interferes with some armor removal */
@@ -1285,14 +1309,18 @@ register struct obj *otmp;
     if (otmp == uswapwep && u.twoweap)
         drop_uswapwep();
     /* some cursed items need immediate updating */
-    if (carried(otmp) && confers_luck(otmp))
+    if (carried(otmp) && confers_luck(otmp)) {
         set_moreluck();
-    else if (otmp->otyp == BAG_OF_HOLDING)
+    } else if (otmp->otyp == BAG_OF_HOLDING) {
         otmp->owt = weight(otmp);
-    else if (otmp->otyp == FIGURINE) {
+    else if (otmp->otyp == FIGURINE) {
         if (otmp->corpsenm != NON_PM && !dead_species(otmp->corpsenm, TRUE)
             && (carried(otmp) || mcarried(otmp)))
             attach_fig_transform_timeout(otmp);
+    } else if (otmp->oclass == SPBOOK_CLASS) {
+        /* if book hero is reading becomes cursed, interrupt */
+        if (!already_cursed)
+            book_cursed(otmp);
     }
     if (otmp->lamplit)
         maybe_adjust_light(otmp, old_light);
@@ -1356,8 +1384,13 @@ int
 weight(obj)
 register struct obj *obj;
 {
-    int wt = objects[obj->otyp].oc_weight;
+    int wt = (int) objects[obj->otyp].oc_weight;
 
+    /* glob absorpsion means that merging globs accumulates weight while
+       quantity stays 1, so update 'wt' to reflect that, unless owt is 0,
+       when we assume this is a brand new glob so use objects[].oc_weight */
+    if (obj->globby && obj->owt > 0)
+        wt = obj->owt;
     if (SchroedingersBox(obj))
         wt += mons[PM_HOUSECAT].cwt;
     if (Is_container(obj) || obj->otyp == STATUE) {
@@ -1402,6 +1435,8 @@ register struct obj *obj;
         return (int) ((obj->quan + 50L) / 100L);
     } else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0) {
         return (int) obj->owt; /* kludge for "very" heavy iron ball */
+    } else if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->spe) {
+        return wt + obj->spe * (int) objects[TALLOW_CANDLE].oc_weight;
     }
     return (wt ? wt * (int) obj->quan : ((int) obj->quan + 1) >> 1);
 }
@@ -1422,8 +1457,10 @@ int x, y;
 {
     register struct obj *gold = g_at(x, y);
 
-    if (amount <= 0L)
-        amount = (long) (1 + rnd(level_difficulty() + 2) * rnd(30));
+    if (amount <= 0L) {
+        long mul = rnd(30 / max(12-depth(&u.uz), 2));
+        amount = (long) (1 + rnd(level_difficulty() + 2) * mul);
+    }
     if (gold) {
         gold->quan += amount;
     } else {
@@ -2195,7 +2232,8 @@ static const char NEARDATA /* pline formats for insane_object() */
     ofmt0[] = "%s obj %s %s: %s",
     ofmt3[] = "%s [not null] %s %s: %s",
     /* " held by mon %p (%s)" will be appended, filled by M,mon_nam(M) */
-    mfmt1[] = "%s obj %s %s (%s)", mfmt2[] = "%s obj %s %s (%s) *not*";
+    mfmt1[] = "%s obj %s %s (%s)",
+    mfmt2[] = "%s obj %s %s (%s) *not*";
 
 /* Check all object lists for consistency. */
 void
@@ -2204,6 +2242,13 @@ obj_sanity_check()
     int x, y;
     struct obj *obj;
 
+    /*
+     * TODO:
+     *  Should check whether the obj->bypass and/or obj->nomerge bits
+     *  are set.  Those are both used for temporary purposes and should
+     *  be clear between moves.
+     */
+
     objlist_sanity(fobj, OBJ_FLOOR, "floor sanity");
 
     /* check that the map's record of floor objects is consistent;
@@ -2213,12 +2258,12 @@ obj_sanity_check()
         for (y = 0; y < ROWNO; y++)
             for (obj = level.objects[x][y]; obj; obj = obj->nexthere) {
                 /* <ox,oy> should match <x,y>; <0,*> should always be empty */
-                if (obj->where != OBJ_FLOOR || x == 0 || obj->ox != x
-                    || obj->oy != y) {
+                if (obj->where != OBJ_FLOOR || x == 0
+                    || obj->ox != x || obj->oy != y) {
                     char at_fmt[BUFSZ];
 
-                    Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>", x,
-                            y, obj->ox, obj->oy);
+                    Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>",
+                            x, y, obj->ox, obj->oy);
                     insane_object(obj, at_fmt, "location sanity",
                                   (struct monst *) 0);
                 }
@@ -2246,7 +2291,11 @@ obj_sanity_check()
     if (kickedobj)
         insane_object(kickedobj, ofmt3, "kickedobj sanity",
                       (struct monst *) 0);
-    /* [how about current_wand too?] */
+    /* current_wand isn't removed from invent while in use, but should
+       be Null between moves when we're called */
+    if (current_wand)
+        insane_object(current_wand, ofmt3, "current_wand sanity",
+                      (struct monst *) 0);
 }
 
 /* sanity check for objects on specified list (fobj, &c) */
@@ -2625,15 +2674,11 @@ struct obj *
 obj_nexto(otmp)
 struct obj *otmp;
 {
-    struct obj *otmp2 = (struct obj *) 0;
-
-    if (otmp) {
-        otmp2 = obj_nexto_xy(otmp->otyp, otmp->ox, otmp->oy, otmp->o_id);
-    } else {
+    if (!otmp) {
         impossible("obj_nexto: wasn't given an object to check");
+        return (struct obj *) 0;
     }
-
-    return otmp2;
+    return obj_nexto_xy(otmp, otmp->ox, otmp->oy, TRUE);
 }
 
 /*
@@ -2645,24 +2690,27 @@ struct obj *otmp;
  * reliably predict which one we want to 'find' first
  */
 struct obj *
-obj_nexto_xy(otyp, x, y, oid)
-int otyp, x, y;
-unsigned oid;
+obj_nexto_xy(obj, x, y, recurs)
+struct obj *obj;
+int x, y;
+boolean recurs;
 {
     struct obj *otmp;
-    int fx, fy, ex, ey;
+    int fx, fy, ex, ey, otyp = obj->otyp;
     short dx, dy;
 
     /* check under our "feet" first */
     otmp = sobj_at(otyp, x, y);
     while (otmp) {
         /* don't be clever and find ourselves */
-        if (otmp->o_id != oid) {
+        if (otmp != obj && mergable(otmp, obj))
             return otmp;
-        }
         otmp = nxtobj(otmp, otyp, TRUE);
     }
 
+    if (!recurs)
+        return (struct obj *) 0;
+
     /* search in a random order */
     dx = (rn2(2) ? -1 : 1);
     dy = (rn2(2) ? -1 : 1);
@@ -2673,9 +2721,8 @@ unsigned oid;
         for (fy = ey; abs(fy - ey) < 3; fy += dy) {
             /* 0, 0 was checked above */
             if (isok(fx, fy) && (fx != x || fy != y)) {
-                if ((otmp = sobj_at(otyp, fx, fy)) != 0) {
+                if ((otmp = obj_nexto_xy(obj, fx, fy, FALSE)) != 0)
                     return otmp;
-                }
             }
         }
     }
@@ -2691,18 +2738,35 @@ struct obj *
 obj_absorb(obj1, obj2)
 struct obj **obj1, **obj2;
 {
-    struct obj *otmp1 = (struct obj *) 0, *otmp2 = (struct obj *) 0;
-    int extrawt = 0;
+    struct obj *otmp1, *otmp2;
+    int o1wt, o2wt;
+    long agetmp;
 
     /* don't let people dumb it up */
     if (obj1 && obj2) {
         otmp1 = *obj1;
         otmp2 = *obj2;
-        if (otmp1 && otmp2) {
-            extrawt = otmp2->oeaten ? otmp2->oeaten : otmp2->owt;
-            otmp1->owt += extrawt;
-            otmp1->oeaten += otmp1->oeaten ? extrawt : 0;
-            otmp1->quan = 1;
+        if (otmp1 && otmp2 && otmp1 != otmp2) {
+            if (otmp1->bknown != otmp2->bknown)
+                otmp1->bknown = otmp2->bknown = 0;
+            if (otmp1->rknown != otmp2->rknown)
+                otmp1->rknown = otmp2->rknown = 0;
+            if (otmp1->greased != otmp2->greased)
+                otmp1->greased = otmp2->greased = 0;
+            if (otmp1->orotten || otmp2->orotten)
+                otmp1->orotten = otmp2->orotten = 1;
+            o1wt = otmp1->oeaten ? otmp1->oeaten : otmp1->owt;
+            o2wt = otmp2->oeaten ? otmp2->oeaten : otmp2->owt;
+            /* averaging the relative ages is less likely to overflow
+               than averaging the absolute ages directly */
+            agetmp = (((moves - otmp1->age) * o1wt
+                       + (moves - otmp2->age) * o2wt)
+                      / (o1wt + o2wt));
+            otmp1->age = moves - agetmp; /* conv. relative back to absolute */
+            otmp1->owt += o2wt;
+            if (otmp1->oeaten)
+                otmp1->oeaten += o2wt;
+            otmp1->quan = 1L;
             obj_extract_self(otmp2);
             newsym(otmp2->ox, otmp2->oy); /* in case of floor */
             dealloc_obj(otmp2);
@@ -2724,13 +2788,14 @@ struct obj *
 obj_meld(obj1, obj2)
 struct obj **obj1, **obj2;
 {
-    struct obj *otmp1 = (struct obj *) 0, *otmp2 = (struct obj *) 0;
+    struct obj *otmp1, *otmp2;
 
     if (obj1 && obj2) {
         otmp1 = *obj1;
         otmp2 = *obj2;
-        if (otmp1 && otmp2) {
-            if (otmp1->owt > otmp2->owt || rn2(2)) {
+        if (otmp1 && otmp2 && otmp1 != otmp2) {
+            if (otmp1->owt > otmp2->owt
+                || (otmp1->owt == otmp2->owt && rn2(2))) {
                 return obj_absorb(obj1, obj2);
             }
             return obj_absorb(obj2, obj1);
@@ -2741,4 +2806,49 @@ struct obj **obj1, **obj2;
     return (struct obj *) 0;
 }
 
+/* give a message if hero notices two globs merging [used to be in pline.c] */
+void
+pudding_merge_message(otmp, otmp2)
+struct obj *otmp;
+struct obj *otmp2;
+{
+    boolean visible = (cansee(otmp->ox, otmp->oy)
+                       || cansee(otmp2->ox, otmp2->oy)),
+            onfloor = (otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR),
+            inpack = (carried(otmp) || carried(otmp2));
+
+    /* the player will know something happened inside his own inventory */
+    if ((!Blind && visible) || inpack) {
+        if (Hallucination) {
+            if (onfloor) {
+/*JP
+                You_see("parts of the floor melting!");
+*/
+                You_see("\8f°\82Ì\88ê\95\94\82ª\97n\82¯\82Ä\82¢\82é\82Ì\82ð\8c©\82½\81I");
+            } else if (inpack) {
+/*JP
+                Your("pack reaches out and grabs something!");
+*/
+                Your("\82©\82Î\82ñ\82ª\8eè\82ð\90L\82Î\82µ\82Ä\89½\82©\82ð\82Â\82©\82ñ\82¾\81I");
+            }
+            /* even though we can see where they should be,
+             * they'll be out of our view (minvent or container)
+             * so don't actually show anything */
+        } else if (onfloor || inpack) {
+#if 0 /*JP*/
+            pline("The %s coalesce%s.", makeplural(obj_typename(otmp->otyp)),
+                  inpack ? " inside your pack" : "");
+#else
+            pline("%s\82ª%s\8d\87\91Ì\82µ\82½\81D", obj_typename(otmp->otyp),
+                  inpack ? "\82 \82È\82½\82Ì\82©\82Î\82ñ\82Ì\92\86\82Å" : "");
+#endif
+        }
+    } else {
+/*JP
+        You_hear("a faint sloshing sound.");
+*/
+        You_hear("\82©\82·\82©\82È\83o\83V\83\83\83o\83V\83\83\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
+    }
+}
+
 /*mkobj.c*/
index c7f6196..15cffdc 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 mkroom.c        $NHDT-Date: 1446887530 2015/11/07 09:12:10 $  $NHDT-Branch: master $:$NHDT-Revision: 1.24 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -240,6 +241,26 @@ int type;
 }
 
 void
+mk_zoo_thronemon(x,y)
+int x,y;
+{
+    int i = rnd(level_difficulty());
+    int pm = (i > 9) ? PM_OGRE_KING
+        : (i > 5) ? PM_ELVENKING
+        : (i > 2) ? PM_DWARF_KING
+        : PM_GNOME_KING;
+    struct monst *mon = makemon(&mons[pm], x, y, NO_MM_FLAGS);
+
+    if (mon) {
+        mon->msleeping = 1;
+        mon->mpeaceful = 0;
+        set_malign(mon);
+        /* Give him a sceptre to pound in judgment */
+        (void) mongets(mon, MACE);
+    }
+}
+
+void
 fill_zoo(sroom)
 struct mkroom *sroom;
 {
@@ -265,7 +286,7 @@ struct mkroom *sroom;
             ty = mm.y;
         } while (occupied((xchar) tx, (xchar) ty) && --i > 0);
     throne_placed:
-        /* TODO: try to ensure the enthroned monster is an M2_PRINCE */
+        mk_zoo_thronemon(tx, ty);
         break;
     case BEEHIVE:
         tx = sroom->lx + (sroom->hx - sroom->lx + 1) / 2;
@@ -380,12 +401,16 @@ struct mkroom *sroom;
         }
     switch (type) {
     case COURT: {
-        struct obj *chest;
+        struct obj *chest, *gold;
         levl[tx][ty].typ = THRONE;
         (void) somexy(sroom, &mm);
-        (void) mkgold((long) rn1(50 * level_difficulty(), 10), mm.x, mm.y);
+        gold = mksobj(GOLD_PIECE, TRUE, FALSE);
+        gold->quan = (long) rn1(50 * level_difficulty(), 10);
+        gold->owt = weight(gold);
         /* the royal coffers */
         chest = mksobj_at(CHEST, mm.x, mm.y, TRUE, FALSE);
+        add_to_container(chest, gold);
+        chest->owt = weight(chest);
         chest->spe = 2; /* so it can be found later */
         level.flags.has_court = 1;
         break;
@@ -684,9 +709,9 @@ coord *c;
 
 /*
  * Search for a special room given its type (zoo, court, etc...)
- *     Special values :
- *             - ANY_SHOP
- *             - ANY_TYPE
+ *      Special values :
+ *              - ANY_SHOP
+ *              - ANY_TYPE
  */
 struct mkroom *
 search_special(type)
index 39aefdb..dbfb6d8 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 mon.c   $NHDT-Date: 1449269918 2015/12/04 22:58:38 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.199 $ */
+/* NetHack 3.6 mon.c   $NHDT-Date: 1522540516 2018/03/31 23:55:16 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.250 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 #include "mfndpos.h"
 #include <ctype.h>
 
-STATIC_VAR boolean vamp_rise_msg;
+STATIC_VAR boolean vamp_rise_msg, disintegested;
 
-STATIC_DCL void FDECL(sanity_check_single_mon, (struct monst *, const char *));
+STATIC_DCL void FDECL(sanity_check_single_mon, (struct monst *, BOOLEAN_P,
+                                                const char *));
 STATIC_DCL boolean FDECL(restrap, (struct monst *));
 STATIC_DCL long FDECL(mm_aggression, (struct monst *, struct monst *));
 STATIC_DCL long FDECL(mm_displacement, (struct monst *, struct monst *));
@@ -27,7 +29,6 @@ STATIC_DCL void FDECL(kill_eggs, (struct obj *));
 STATIC_DCL int FDECL(pickvampshape, (struct monst *));
 STATIC_DCL boolean FDECL(isspecmon, (struct monst *));
 STATIC_DCL boolean FDECL(validspecmon, (struct monst *, int));
-STATIC_DCL boolean FDECL(validvamp, (struct monst *, int *, int));
 STATIC_DCL struct permonst *FDECL(accept_newcham_form, (int));
 STATIC_DCL struct obj *FDECL(make_corpse, (struct monst *, unsigned));
 STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *));
@@ -49,35 +50,89 @@ const char *warnings[] = {
 
 
 void
-sanity_check_single_mon(mtmp, msg)
+sanity_check_single_mon(mtmp, chk_geno, msg)
 struct monst *mtmp;
+boolean chk_geno;
 const char *msg;
 {
     if (DEADMONSTER(mtmp))
         return;
-    if (mtmp->data < &mons[LOW_PM] || mtmp->data >= &mons[NUMMONS])
-        impossible("illegal mon data (%s)", msg);
+    if (mtmp->data < &mons[LOW_PM] || mtmp->data >= &mons[NUMMONS]) {
+        impossible("illegal mon data %s; mnum=%d (%s)",
+                   fmt_ptr((genericptr_t) mtmp->data), mtmp->mnum, msg);
+    } else {
+        int mndx = monsndx(mtmp->data);
+
+        if (mtmp->mnum != mndx) {
+            impossible("monster mnum=%d, monsndx=%d (%s)",
+                       mtmp->mnum, mndx, msg);
+            mtmp->mnum = mndx;
+        }
+        if (chk_geno && (mvitals[mndx].mvflags & G_GENOD) != 0)
+            impossible("genocided %s in play (%s)", mons[mndx].mname, msg);
+    }
+    if (mtmp->isshk && !has_eshk(mtmp))
+        impossible("shk without eshk (%s)", msg);
+    if (mtmp->ispriest && !has_epri(mtmp))
+        impossible("priest without epri (%s)", msg);
+    if (mtmp->isgd && !has_egd(mtmp))
+        impossible("guard without egd (%s)", msg);
+    if (mtmp->isminion && !has_emin(mtmp))
+        impossible("minion without emin (%s)", msg);
+    /* guardian angel on astral level is tame but has emin rather than edog */
+    if (mtmp->mtame && !has_edog(mtmp) && !mtmp->isminion)
+        impossible("pet without edog (%s)", msg);
 }
 
 void
 mon_sanity_check()
 {
-    int x,y;
-    struct monst *mtmp = fmon;
+    int x, y;
+    struct monst *mtmp, *m;
 
-    while (mtmp) {
-        sanity_check_single_mon(mtmp, "fmon");
-        mtmp = mtmp->nmon;
+    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+        sanity_check_single_mon(mtmp, TRUE, "fmon");
+        if (DEADMONSTER(mtmp))
+            continue;
+        x = mtmp->mx, y = mtmp->my;
+        if (!isok(x, y) && !(mtmp->isgd && x == 0 && y == 0)) {
+            impossible("mon (%s) claims to be at <%d,%d>?",
+                       fmt_ptr((genericptr_t) mtmp), x, y);
+        } else if (mtmp == u.usteed) {
+            /* steed is in fmon list but not on the map; its
+               <mx,my> coordinates should match hero's location */
+            if (x != u.ux || y != u.uy)
+                impossible("steed (%s) claims to be at <%d,%d>?",
+                           fmt_ptr((genericptr_t) mtmp), x, y);
+        } else if (level.monsters[x][y] != mtmp) {
+            impossible("mon (%s) at <%d,%d> is not there!",
+                       fmt_ptr((genericptr_t) mtmp), x, y);
+        } else if (mtmp->wormno) {
+            sanity_check_worm(mtmp);
+        }
     }
+
     for (x = 0; x < COLNO; x++)
         for (y = 0; y < ROWNO; y++)
-            if ((mtmp = m_at(x,y)) != 0)
-                sanity_check_single_mon(mtmp, "m_at");
+            if ((mtmp = level.monsters[x][y]) != 0) {
+                for (m = fmon; m; m = m->nmon)
+                    if (m == mtmp)
+                        break;
+                if (!m)
+                    impossible("map mon (%s) at <%d,%d> not in fmon list!",
+                               fmt_ptr((genericptr_t) mtmp), x, y);
+                else if (mtmp == u.usteed)
+                    impossible("steed (%s) is on the map at <%d,%d>!",
+                               fmt_ptr((genericptr_t) mtmp), x, y);
+                else if ((mtmp->mx != x || mtmp->my != y)
+                         && mtmp->data != &mons[PM_LONG_WORM])
+                    impossible("map mon (%s) at <%d,%d> is found at <%d,%d>?",
+                               fmt_ptr((genericptr_t) mtmp),
+                               mtmp->mx, mtmp->my, x, y);
+            }
 
-    mtmp = migrating_mons;
-    while (mtmp) {
-        sanity_check_single_mon(mtmp, "migr");
-        mtmp = mtmp->nmon;
+    for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
+        sanity_check_single_mon(mtmp, FALSE, "migr");
     }
 }
 
@@ -274,11 +329,13 @@ unsigned corpseflags;
     case PM_BLACK_UNICORN:
         if (mtmp->mrevived && rn2(2)) {
             if (canseemon(mtmp))
-/*JP
+#if 0 /*JP*/
                 pline("%s recently regrown horn crumbles to dust.",
-*/
-                pline("\8dÅ\8bß\8dÄ\90\82µ\82½%s\82Ì\8ap\82Í\95²\81X\82É\82È\82Á\82½\81D",
                       s_suffix(Monnam(mtmp)));
+#else
+                pline("\8dÅ\8bß\8dÄ\90\82µ\82½%s\82Ì\8ap\82Í\95²\81X\82É\82È\82Á\82½\81D",
+                      Monnam(mtmp));
+#endif
         } else {
             obj = mksobj_at(UNICORN_HORN, x, y, TRUE, FALSE);
             if (obj && mtmp->mrevived)
@@ -381,7 +438,6 @@ unsigned corpseflags;
         }
         free_mname(mtmp);
         return obj;
-        break;
     default_1:
     default:
         if (mvitals[mndx].mvflags & G_NOCORPSE) {
@@ -486,21 +542,26 @@ register struct monst *mtmp;
          */
         if (!is_clinger(mtmp->data) && !likes_lava(mtmp->data)) {
             if (!resists_fire(mtmp)) {
-                if (cansee(mtmp->mx, mtmp->my))
+                if (cansee(mtmp->mx, mtmp->my)) {
+                    struct attack *dummy = &mtmp->data->mattk[0];
+                    const char *how = on_fire(mtmp->data, dummy);
+
 #if 0 /*JP*/
                     pline("%s %s.", Monnam(mtmp),
-                          mtmp->data == &mons[PM_WATER_ELEMENTAL]
-                              ? "boils away"
-                              : "burns to a crisp");
-#else
+                          !strcmp(how, "boiling") ? "boils away"
+                             : !strcmp(how, "melting") ? "melts away"
+                                : "burns to a crisp");
+#else /*mon.c:on_fire()\82Ì\95Ô\82è\92l*/
                     pline("%s\82Í%s\82½\81D", Monnam(mtmp),
-                          mtmp->data == &mons[PM_WATER_ELEMENTAL]
-                              ? "\95¦\93«\82µ"
-                              : "\94R\82¦\82Ä\83p\83\8a\83p\83\8a\82É\82È\82Á");
+                          !strcmp(how, "\95¦\93«\82µ\82½") ? "\95¦\93«\82µ"
+                             : !strcmp(how, "\97n\82¯\82½") ? "\97n\82¯\82½"
+                                : "\94R\82¦\82Ä\83p\83\8a\83p\83\8a\82É\82È\82Á");
 #endif
+                }
                 mondead(mtmp);
             } else {
-                if (--mtmp->mhp < 1) {
+                mtmp->mhp -= 1;
+                if (mtmp->mhp < 1) {
                     if (cansee(mtmp->mx, mtmp->my))
 /*JP
                         pline("%s surrenders to the fire.", Monnam(mtmp));
@@ -537,11 +598,13 @@ register struct monst *mtmp;
             if (u.ustuck && u.uswallow && u.ustuck == mtmp) {
                 /* This can happen after a purple worm plucks you off a
                 flying steed while you are over water. */
-/*JP
-                pline("%s sinks as water rushes in and flushes you out.",
-*/
+#if 0 /*JP*/
+                pline("%s sinks as %s rushes in and flushes you out.",
+                      Monnam(mtmp), hliquid("water"));
+#else /*hliquid\82Í\95s\8e©\91R\82É\82È\82é\82Ì\82Å\82Æ\82è\82 \82¦\82¸\8eg\82í\82È\82¢*/
                 pline("%s\82Í\90\85\97¬\82É\92¾\82Ý\81D\82 \82È\82½\82ð\93f\82«\8fo\82µ\82½\81D",
                       Monnam(mtmp));
+#endif
             }
             mondead(mtmp);
             if (mtmp->mhp > 0) {
@@ -568,6 +631,7 @@ mcalcmove(mon)
 struct monst *mon;
 {
     int mmove = mon->data->mmove;
+    int mmove_adj;
 
     /* Note: MSLOW's `+ 1' prevents slowed speed 1 getting reduced to 0;
      *       MFAST's `+ 2' prevents hasted speed 1 from becoming a no-op;
@@ -578,21 +642,24 @@ struct monst *mon;
     else if (mon->mspeed == MFAST)
         mmove = (4 * mmove + 2) / 3;
 
-    if (mon == u.usteed) {
-        if (u.ugallop && context.mv) {
-            /* average movement is 1.50 times normal */
-            mmove = ((rn2(2) ? 4 : 5) * mmove) / 3;
-        }
-    } else if (mmove) {
-        /* vary movement points allocated to slightly reduce predictability;
-           random increment (avg +2) exceeds random decrement (avg +1) by
-           a small amount; normal speed monsters will occasionally get an
-           extra move and slow ones won't be quite as slow */
-        mmove += rn2(5) - rn2(3); /* + 0..4 - 0..2, average net +1 */
-        if (mmove < 1)
-            mmove = 1;
+    if (mon == u.usteed && u.ugallop && context.mv) {
+        /* increase movement by a factor of 1.5; also increase variance of
+           movement speed (if it's naturally 24, we don't want it to always
+           become 36) */
+        mmove = ((rn2(2) ? 4 : 5) * mmove) / 3;
     }
 
+    /* Randomly round the monster's speed to a multiple of NORMAL_SPEED. This
+       makes it impossible for the player to predict when they'll get a free
+       turn (thus preventing exploits like "melee kiting"), while retaining
+       guarantees about shopkeepers not being outsped by a normal-speed player,
+       normal-speed players being unable to open up a gap when fleeing a
+       normal-speed monster, etc.*/
+    mmove_adj = mmove % NORMAL_SPEED;
+    mmove -= mmove_adj;
+    if (rn2(NORMAL_SPEED) < mmove_adj)
+        mmove += NORMAL_SPEED;
+
     return mmove;
 }
 
@@ -621,12 +688,10 @@ mcalcdistress()
         mon_regen(mtmp, FALSE);
 
         /* possibly polymorph shapechangers and lycanthropes */
-        if (mtmp->cham >= LOW_PM) {
-            if (is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE)
-                decide_to_shapeshift(mtmp, 0);
-            else if (!rn2(6))
-                (void) newcham(mtmp, (struct permonst *) 0, FALSE, FALSE);
-        }
+        if (mtmp->cham >= LOW_PM)
+            decide_to_shapeshift(mtmp, (canspotmon(mtmp)
+                                        || (u.uswallow && mtmp == u.ustuck))
+                                          ? SHIFT_MSG : 0);
         were_change(mtmp);
 
         /* gradually time out temporary problems */
@@ -889,9 +954,9 @@ int
 meatobj(mtmp) /* for gelatinous cubes */
 struct monst *mtmp;
 {
-    register struct obj *otmp, *otmp2;
+    struct obj *otmp, *otmp2;
     struct permonst *ptr, *original_ptr = mtmp->data;
-    int poly, grow, heal, count = 0, ecount = 0;
+    int poly, grow, heal, eyes, count = 0, ecount = 0;
     char buf[BUFSZ];
 
     buf[0] = '\0';
@@ -916,7 +981,12 @@ struct monst *mtmp;
                     && !resists_ston(mtmp))
                    /* don't engulf boulders and statues or ball&chain */
                    || otmp->oclass == ROCK_CLASS
-                   || otmp == uball || otmp == uchain) {
+                   || otmp == uball || otmp == uchain
+                   /* normally mtmp won't have stepped onto scare monster
+                      scroll, but if it does, don't eat or engulf that
+                      (note: scrolls inside eaten containers will still
+                      become engulfed) */
+                   || otmp->otyp == SCR_SCARE_MONSTER) {
             /* do nothing--neither eaten nor engulfed */
             continue;
 
@@ -929,7 +999,8 @@ struct monst *mtmp;
                        || otmp->otyp == RIN_SLOW_DIGESTION)
                    /* cockatrice corpses handled above; this
                       touch_petrifies() check catches eggs */
-                   || ((otmp->otyp == CORPSE || otmp->otyp == EGG)
+                   || ((otmp->otyp == CORPSE || otmp->otyp == EGG
+                        || otmp->globby)
                        && ((touch_petrifies(&mons[otmp->corpsenm])
                             && !resists_ston(mtmp))
                            || (otmp->corpsenm == PM_GREEN_SLIME
@@ -956,19 +1027,26 @@ struct monst *mtmp;
         } else {
             /* devour */
             ++count;
-            if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
+            if (cansee(mtmp->mx, mtmp->my)) {
+                if (flags.verbose)
 #if 0 /*JP*/
-                pline("%s eats %s!", Monnam(mtmp),
-                      distant_name(otmp, doname));
+                    pline("%s eats %s!", Monnam(mtmp),
+                          distant_name(otmp, doname));
 #else
-                pline("%s\82Í%s\82ð\90H\82×\82Ä\82¢\82é\81I", Monnam(mtmp),
-                      distant_name(otmp, doname));
+                    pline("%s\82Í%s\82ð\90H\82×\82Ä\82¢\82é\81I", Monnam(mtmp),
+                          distant_name(otmp, doname));
 #endif
-            else if (flags.verbose)
+                /* give this one even if !verbose */
+                if (otmp->oclass == SCROLL_CLASS
+                    && !strcmpi(OBJ_DESCR(objects[otmp->otyp]), "YUM YUM"))
+                    pline("Yum%c", otmp->blessed ? '!' : '.');
+            } else {
+                if (flags.verbose)
 /*JP
                 You_hear("a slurping sound.");
 */
                 You_hear("\82²\82­\82ñ\82Æ\88ù\82Ý\8d\9e\82Þ\89¹\82ð\95·\82¢\82½\81D");
+            }
             /* Heal up to the object's weight in hp */
             if (mtmp->mhp < mtmp->mhpmax) {
                 mtmp->mhp += objects[otmp->otyp].oc_weight;
@@ -992,6 +1070,7 @@ struct monst *mtmp;
             poly = polyfodder(otmp);
             grow = mlevelgain(otmp);
             heal = mhealup(otmp);
+            eyes = (otmp->otyp == CARROT);
             delobj(otmp); /* munch */
             ptr = mtmp->data;
             if (poly) {
@@ -1002,6 +1081,8 @@ struct monst *mtmp;
             } else if (heal) {
                 mtmp->mhp = mtmp->mhpmax;
             }
+            if ((eyes || heal) && !mtmp->mcansee)
+                mcureblindness(mtmp, canseemon(mtmp));
             /* in case it polymorphed or died */
             if (ptr != original_ptr)
                 return !ptr ? 2 : 1;
@@ -1257,6 +1338,9 @@ long flag;
     boolean wantpool, poolok, lavaok, nodiag;
     boolean rockok = FALSE, treeok = FALSE, thrudoor;
     int maxx, maxy;
+    boolean poisongas_ok, in_poisongas;
+    NhRegion *gas_reg;
+    int gas_glyph = cmap_to_glyph(S_poisoncloud);
 
     x = mon->mx;
     y = mon->my;
@@ -1268,6 +1352,11 @@ long flag;
               || (is_swimmer(mdat) && !wantpool));
     lavaok = (is_flyer(mdat) || is_clinger(mdat) || likes_lava(mdat));
     thrudoor = ((flag & (ALLOW_WALL | BUSTDOOR)) != 0L);
+    poisongas_ok = ((nonliving(mdat) || is_vampshifter(mon)
+                     || breathless(mdat)) || resists_poison(mon));
+    in_poisongas = ((gas_reg = visible_region_at(x,y)) != 0
+                    && gas_reg->glyph == gas_glyph);
+
     if (flag & ALLOW_DIG) {
         struct obj *mw_tmp;
 
@@ -1316,6 +1405,11 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
                     || ((levl[nx][ny].doormask & D_LOCKED)
                         && !(flag & UNLOCKDOOR))) && !thrudoor)
                 continue;
+            /* avoid poison gas? */
+            if (!poisongas_ok && !in_poisongas
+                && (gas_reg = visible_region_at(nx,ny)) != 0
+                && gas_reg->glyph == gas_glyph)
+                continue;
             /* first diagonal checks (tight squeezes handled below) */
             if (nx != x && ny != y
                 && (nodiag
@@ -1442,7 +1536,8 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
                         && (ttmp->ttyp != FIRE_TRAP || !resists_fire(mon))
                         && (ttmp->ttyp != SQKY_BOARD || !is_flyer(mdat))
                         && (ttmp->ttyp != WEB
-                            || (!amorphous(mdat) && !webmaker(mdat)))
+                            || (!amorphous(mdat) && !webmaker(mdat)
+                                && !is_whirly(mdat) && !unsolid(mdat)))
                         && (ttmp->ttyp != ANTI_MAGIC || !resists_magm(mon))) {
                         if (!(flag & ALLOW_TRAPS)) {
                             if (mon->mtrapseen & (1L << (ttmp->ttyp - 1)))
@@ -1611,7 +1706,10 @@ struct monst **monst_list; /* &migrating_mons or &mydogs or null */
             seemimic(mon);
     }
 
-    remove_monster(mx, my);
+    if (mon->wormno)
+        remove_worm(mon);
+    else
+        remove_monster(mx, my);
 
     if (mon == fmon) {
         fmon = fmon->nmon;
@@ -1653,32 +1751,27 @@ struct monst *mtmp2, *mtmp1;
     if (EGD(mtmp1)) {
         if (!EGD(mtmp2))
             newegd(mtmp2);
-        (void) memcpy((genericptr_t) EGD(mtmp2), (genericptr_t) EGD(mtmp1),
-                      sizeof (struct egd));
+        *EGD(mtmp2) = *EGD(mtmp1);
     }
     if (EPRI(mtmp1)) {
         if (!EPRI(mtmp2))
             newepri(mtmp2);
-        (void) memcpy((genericptr_t) EPRI(mtmp2), (genericptr_t) EPRI(mtmp1),
-                      sizeof (struct epri));
+        *EPRI(mtmp2) = *EPRI(mtmp1);
     }
     if (ESHK(mtmp1)) {
         if (!ESHK(mtmp2))
             neweshk(mtmp2);
-        (void) memcpy((genericptr_t) ESHK(mtmp2), (genericptr_t) ESHK(mtmp1),
-                      sizeof (struct eshk));
+        *ESHK(mtmp2) = *ESHK(mtmp1);
     }
     if (EMIN(mtmp1)) {
         if (!EMIN(mtmp2))
             newemin(mtmp2);
-        (void) memcpy((genericptr_t) EMIN(mtmp2), (genericptr_t) EMIN(mtmp1),
-                      sizeof (struct emin));
+        *EMIN(mtmp2) = *EMIN(mtmp1);
     }
     if (EDOG(mtmp1)) {
         if (!EDOG(mtmp2))
             newedog(mtmp2);
-        (void) memcpy((genericptr_t) EDOG(mtmp2), (genericptr_t) EDOG(mtmp1),
-                      sizeof (struct edog));
+        *EDOG(mtmp2) = *EDOG(mtmp1);
     }
     if (has_mcorpsenm(mtmp1))
         MCORPSENM(mtmp2) = MCORPSENM(mtmp1);
@@ -1738,6 +1831,8 @@ struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */
     remove_monster(mtmp->mx, mtmp->my);
     if (emits_light(mptr))
         del_light_source(LS_MONSTER, monst_to_any(mtmp));
+    if (mtmp->m_ap_type)
+        seemimic(mtmp);
     newsym(mtmp->mx, mtmp->my);
     unstuck(mtmp);
     fill_pit(mtmp->mx, mtmp->my);
@@ -1824,8 +1919,8 @@ struct monst *mtmp;
             pline("Unfortunately, %s is still genocided...", mon_nam(mtmp));
 */
             pline("\8ec\94O\82È\82ª\82ç%s\82Í\8bs\8eE\82³\82ê\82Ä\82¢\82é\81D\81D\81D", mon_nam(mtmp));
+        mtmp->mhp = 0;
     }
-    mtmp->mhp = 0;
 }
 
 void
@@ -1835,6 +1930,7 @@ register struct monst *mtmp;
     struct permonst *mptr;
     int tmp;
 
+    mtmp->mhp = 0; /* in case caller hasn't done this */
     lifesaved_monster(mtmp);
     if (mtmp->mhp > 0)
         return;
@@ -1844,32 +1940,37 @@ register struct monst *mtmp;
         int x = mtmp->mx, y = mtmp->my;
 
         /* this only happens if shapeshifted */
-        if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)) {
+        if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)
+            && !(mvitals[mndx].mvflags & G_GENOD)) {
             char buf[BUFSZ];
             boolean in_door = (amorphous(mtmp->data)
                                && closed_door(mtmp->mx, mtmp->my)),
                 /* alternate message phrasing for some monster types */
                 spec_mon = (nonliving(mtmp->data)
                             || noncorporeal(mtmp->data)
-                            || amorphous(mtmp->data));
+                            || amorphous(mtmp->data)),
+                spec_death = (disintegested /* disintegrated or digested */
+                              || noncorporeal(mtmp->data)
+                              || amorphous(mtmp->data));
 
-            /* construct a format string before transformation */
+            /* construct a format string before transformation;
+               will be capitalized when used, expects one %s arg */
 #if 0 /*JP*/
-            Sprintf(buf, "The %s%s suddenly %s and rises as %%s!",
-                    spec_mon ? "" : "seemingly dead ",
-                    x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
+            Sprintf(buf, "%s suddenly %s and rises as %%s!",
+                    x_monnam(mtmp, ARTICLE_THE,
+                             spec_mon ? (char *) 0 : "seemingly dead",
                              SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION
                                  | SUPPRESS_INVISIBLE | SUPPRESS_IT,
                              FALSE),
-                    spec_mon ? "reconstitutes" : "transforms");
+                    spec_death ? "reconstitutes" : "transforms");
 #else
             Sprintf(buf, "%s%s\82Í\93Ë\91R%s\81C%%s\82Æ\82µ\82Ä\91h\82Á\82½\81I",
-                    spec_mon ? "" : "\8e\80\82ñ\82¾\82æ\82¤\82É\8ev\82í\82ê\82½",
+                    spec_death ? "" : "\8e\80\82ñ\82¾\82æ\82¤\82É\8ev\82í\82ê\82½",
                     x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
                              SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION
                                  | SUPPRESS_INVISIBLE | SUPPRESS_IT,
                              FALSE),
-                    spec_mon ? "\8dÄ\8d\\90¬\82³\82ê" : "\95Ï\89»\82µ");
+                    spec_death ? "\8dÄ\8d\\90¬\82³\82ê" : "\95Ï\89»\82µ");
 #endif
             mtmp->mcanmove = 1;
             mtmp->mfrozen = 0;
@@ -1892,7 +1993,9 @@ register struct monst *mtmp;
             else
                 mtmp->cham = mndx;
             if (canspotmon(mtmp)) {
-                pline(buf, a_monnam(mtmp));
+                /* was using a_monnam(mtmp) but that's weird if mtmp is named:
+                   "Dracula suddenly transforms and rises as Dracula" */
+                pline(upstart(buf), an(mtmp->data->mname));
                 vamp_rise_msg = TRUE;
             }
             newsym(x, y);
@@ -1922,9 +2025,7 @@ register struct monst *mtmp;
     else if (mtmp->data == &mons[PM_WERERAT])
         set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT], -1);
 
-    /* if MAXMONNO monsters of a given type have died, and it
-     * can be done, extinguish that monster.
-     *
+    /*
      * mvitals[].died does double duty as total number of dead monsters
      * and as experience factor for the player killing more monsters.
      * this means that a dragon dying by other means reduces the
@@ -2042,6 +2143,8 @@ boolean was_swallowed; /* digestion */
             Sprintf(killer.name, "%s\82Ì\94\9a\94­\82Å", mdat->mname);
             killer.format = KILLED_BY_AN;
             explode(mon->mx, mon->my, -1, tmp, MON_EXPLODE, EXPL_NOXIOUS);
+            killer.name[0] = '\0';
+            killer.format = 0;
             return FALSE;
         }
     }
@@ -2053,7 +2156,7 @@ boolean was_swallowed; /* digestion */
         return FALSE;
 
     if (((bigmonst(mdat) || mdat == &mons[PM_LIZARD]) && !mon->mcloned)
-        || is_golem(mdat) || is_mplayer(mdat) || is_rider(mdat))
+        || is_golem(mdat) || is_mplayer(mdat) || is_rider(mdat) || mon->isshk)
         return TRUE;
     tmp = 2 + ((mdat->geno & G_FREQ) < 2) + verysmall(mdat);
     return (boolean) !rn2(tmp);
@@ -2087,6 +2190,8 @@ struct monst *mdef;
     /* hero is thrown from his steed when it disappears */
     if (mdef == u.usteed)
         dismount_steed(DISMOUNT_GENERIC);
+    /* stuck to you? release */
+    unstuck(mdef);
     /* drop special items like the Amulet so that a dismissed Kop or nurse
        can't remove them from the game */
     mdrop_special_objs(mdef);
@@ -2104,10 +2209,14 @@ struct monst *mdef;
     xchar x = mdef->mx, y = mdef->my;
     boolean wasinside = FALSE;
 
+    if (!vamp_stone(mdef)) /* vampshifter reverts to vampire */
+        return;
+
     /* we have to make the statue before calling mondead, to be able to
      * put inventory in it, and we have to check for lifesaving before
      * making the statue....
      */
+    mdef->mhp = 0; /* in case caller hasn't done this */
     lifesaved_monster(mdef);
     if (mdef->mhp > 0)
         return;
@@ -2215,7 +2324,8 @@ int how;
         be_sad = (mdef->mtame != 0);
 
     /* no corpses if digested or disintegrated */
-    if (how == AD_DGST || how == -AD_RBRE)
+    disintegested = (how == AD_DGST || how == -AD_RBRE);
+    if (disintegested)
         mondead(mdef);
     else
         mondied(mdef);
@@ -2241,6 +2351,10 @@ struct monst *mtmp;
                 placebc();
             vision_full_recalc = 1;
             docrt();
+            /* prevent swallower (mtmp might have just poly'd into something
+               without an engulf attack) from immediately re-engulfing */
+            if (attacktype(mtmp->data, AT_ENGL) && !mtmp->mspec_used)
+                mtmp->mspec_used = rnd(2);
         }
         u.ustuck = 0;
     }
@@ -2250,63 +2364,54 @@ void
 killed(mtmp)
 struct monst *mtmp;
 {
-    xkilled(mtmp, 1);
+    xkilled(mtmp, XKILL_GIVEMSG);
 }
 
 /* the player has killed the monster mtmp */
 void
-xkilled(mtmp, dest)
+xkilled(mtmp, xkill_flags)
 struct monst *mtmp;
-int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
-             drop corpse either; dest==3, message but no corpse */
+int xkill_flags; /* 1: suppress message, 2: suppress corpse, 4: pacifist */
 {
     int tmp, mndx, x = mtmp->mx, y = mtmp->my;
     struct permonst *mdat;
     struct obj *otmp;
     struct trap *t;
-    boolean wasinside = u.uswallow && (u.ustuck == mtmp);
-    boolean burycorpse = FALSE;
+    boolean wasinside = u.uswallow && (u.ustuck == mtmp),
+            burycorpse = FALSE,
+            nomsg = (xkill_flags & XKILL_NOMSG) != 0,
+            nocorpse = (xkill_flags & XKILL_NOCORPSE) != 0,
+            noconduct = (xkill_flags & XKILL_NOCONDUCT) != 0;
 
-    /* KMH, conduct */
-    u.uconduct.killer++;
+    mtmp->mhp = 0; /* caller will usually have already done this */
+    if (!noconduct) /* KMH, conduct */
+        u.uconduct.killer++;
 
-    if (dest & 1) {
-#if 0 /*JP*/
-        const char *verb = nonliving(mtmp->data) ? "destroy" : "kill";
-#endif
+    if (!nomsg) {
+        boolean namedpet = has_mname(mtmp) && !Hallucination;
 
-        if (!wasinside && !canspotmon(mtmp))
-/*JP
-            You("%s it!", verb);
-*/
-            You("\89½\8eÒ\82©\82ð\93|\82µ\82½\81I");
-        else {
 #if 0 /*JP*/
-            You("%s %s!", verb,
-                !mtmp->mtame
-                    ? mon_nam(mtmp)
-                    : x_monnam(mtmp,
-                               (has_mname(mtmp)) ? ARTICLE_NONE : ARTICLE_THE,
-                               "poor",
-                               (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0,
-                               FALSE));
+        You("%s %s!",
+            nonliving(mtmp->data) ? "destroy" : "kill",
+            !(wasinside || canspotmon(mtmp)) ? "it"
+              : !mtmp->mtame ? mon_nam(mtmp)
+                : x_monnam(mtmp, namedpet ? ARTICLE_NONE : ARTICLE_THE,
+                           "poor", namedpet ? SUPPRESS_SADDLE : 0, FALSE));
 #else
-            You("%s%s\82ð\93|\82µ\82½\81I",
-                mtmp->mtame ? "\82©\82í\82¢\82»\82¤\82È" : "",
+        You("%s%s\82ð\93|\82µ\82½\81I",
+            !(wasinside || canspotmon(mtmp)) ? "\82»\82ê"
+              : mtmp->mtame ? "\82©\82í\82¢\82»\82¤\82È" : "",
                 mon_nam(mtmp));
 #endif
-        }
     }
 
     if (mtmp->mtrapped && (t = t_at(x, y)) != 0
         && (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) {
         if (sobj_at(BOULDER, x, y))
-            dest |= 2; /*
-        * Prevent corpses/treasure being created "on top"
-        * of the boulder that is about to fall in. This is
-        * out of order, but cannot be helped unless this
-        * whole routine is rearranged.
-        */
+            nocorpse = TRUE; /* Prevent corpses/treasure being created
+                                "on top" of boulder that is about to fall in.
+                                This is out of order, but cannot be helped
+                                unless this whole routine is rearranged. */
         if (m_carrying(mtmp, BOULDER))
             burycorpse = TRUE;
     }
@@ -2326,18 +2431,19 @@ int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
         thrownobj = 0;
     }
 
-    vamp_rise_msg = FALSE; /* might get set in mondead() */
+    vamp_rise_msg = FALSE; /* might get set in mondead(); only checked below */
+    disintegested = nocorpse; /* alternate vamp_rise message needed if true */
     /* dispose of monster and make cadaver */
     if (stoned)
         monstone(mtmp);
     else
         mondead(mtmp);
+    disintegested = FALSE; /* reset */
 
     if (mtmp->mhp > 0) { /* monster lifesaved */
         /* Cannot put the non-visible lifesaving message in
-         * lifesaved_monster() since the message appears only when you
-         * kill it (as opposed to visible lifesaving which always
-         * appears).
+         * lifesaved_monster() since the message appears only when _you_
+         * kill it (as opposed to visible lifesaving which always appears).
          */
         stoned = FALSE;
         if (!cansee(x, y) && !vamp_rise_msg)
@@ -2356,7 +2462,7 @@ int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
         goto cleanup;
     }
 
-    if ((dest & 2) || LEVEL_SPECIFIC_NOCORPSE(mdat))
+    if (nocorpse || LEVEL_SPECIFIC_NOCORPSE(mdat))
         goto cleanup;
 
 #ifdef MAIL
@@ -2384,9 +2490,9 @@ int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
                 && (otmp->owt > 30 || objects[otyp].oc_big)) {
                 delobj(otmp);
 #if 0 /*JP*/
-            } else if (!flooreffects(otmp, x, y, (dest & 1) ? "fall" : "")) {
+            } else if (!flooreffects(otmp, x, y, nomsg ? "" : "fall")) {
 #else
-            } else if (!flooreffects(otmp, x, y, (dest & 1) ? "\97\8e\82¿\82é" : "")) {
+            } else if (!flooreffects(otmp, x, y, nomsg ? "" : "\97\8e\82¿\82é")) {
 #endif
                 place_object(otmp, x, y);
                 stackobj(otmp);
@@ -2397,11 +2503,11 @@ int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
             cadaver = make_corpse(mtmp, burycorpse ? CORPSTAT_BURIED
                                                    : CORPSTAT_NONE);
             if (burycorpse && cadaver && cansee(x, y) && !mtmp->minvis
-                && cadaver->where == OBJ_BURIED && (dest & 1)) {
+                && cadaver->where == OBJ_BURIED && !nomsg) {
 /*JP
                 pline("%s corpse ends up buried.", s_suffix(Monnam(mtmp)));
 */
-                pline("%s\82Ì\8e\80\91Ì\82Í\96\84\82Ü\82Á\82Ä\82µ\82Ü\82Á\82½\81D", s_suffix(Monnam(mtmp)));
+                pline("%s\82Ì\8e\80\91Ì\82Í\96\84\82Ü\82Á\82Ä\82µ\82Ü\82Á\82½\81D", Monnam(mtmp));
             }
         }
     }
@@ -2412,7 +2518,8 @@ int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
 
 cleanup:
     /* punish bad behaviour */
-    if (is_human(mdat) && (!always_hostile(mdat) && mtmp->malign <= 0)
+    if (is_human(mdat)
+        && (!always_hostile(mdat) && mtmp->malign <= 0)
         && (mndx < PM_ARCHEOLOGIST || mndx > PM_WIZARD)
         && u.ualign.type != A_CHAOTIC) {
         HTelepat &= ~INTRINSIC;
@@ -2520,6 +2627,75 @@ struct monst *mtmp;
         impossible("Can't polystone %s!", a_monnam(mtmp));
 }
 
+boolean
+vamp_stone(mtmp)
+struct monst *mtmp;
+{
+    if (is_vampshifter(mtmp)) {
+        int mndx = mtmp->cham;
+        int x = mtmp->mx, y = mtmp->my;
+
+        /* this only happens if shapeshifted */
+        if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)
+            && !(mvitals[mndx].mvflags & G_GENOD)) {
+            char buf[BUFSZ];
+            boolean in_door = (amorphous(mtmp->data)
+                               && closed_door(mtmp->mx, mtmp->my));
+
+            /* construct a format string before transformation */
+            Sprintf(buf, "The lapidifying %s %s %s",
+                    x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
+                             (SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION
+                              | SUPPRESS_INVISIBLE | SUPPRESS_IT), FALSE),
+                    amorphous(mtmp->data) ? "coalesces on the"
+                       : is_flyer(mtmp->data) ? "drops to the"
+                          : "writhes on the",
+                    surface(x,y));
+            mtmp->mcanmove = 1;
+            mtmp->mfrozen = 0;
+            if (mtmp->mhpmax <= 0)
+                mtmp->mhpmax = 10;
+            mtmp->mhp = mtmp->mhpmax;
+            /* this can happen if previously a fog cloud */
+            if (u.uswallow && (mtmp == u.ustuck))
+                expels(mtmp, mtmp->data, FALSE);
+            if (in_door) {
+                coord new_xy;
+
+                if (enexto(&new_xy, mtmp->mx, mtmp->my, &mons[mndx])) {
+                    rloc_to(mtmp, new_xy.x, new_xy.y);
+                }
+            }
+            if (canspotmon(mtmp)) {
+                pline("%s!", buf);
+                display_nhwindow(WIN_MESSAGE, FALSE);
+            }
+            newcham(mtmp, &mons[mndx], FALSE, FALSE);
+            if (mtmp->data == &mons[mndx])
+                mtmp->cham = NON_PM;
+            else
+                mtmp->cham = mndx;
+            if (canspotmon(mtmp)) {
+                pline("%s rises from the %s with renewed agility!",
+                      Amonnam(mtmp), surface(mtmp->mx, mtmp->my));
+            }
+            newsym(mtmp->mx, mtmp->my);
+            return FALSE;   /* didn't petrify */
+        }
+    }
+    return TRUE;
+}
+
+/* drop monster into "limbo" - that is, migrate to the current level */
+void
+m_into_limbo(mtmp)
+struct monst *mtmp;
+{
+    unstuck(mtmp);
+    mdrop_special_objs(mtmp);
+    migrate_to_level(mtmp, ledger_no(&u.uz), MIGR_APPROX_XY, NULL);
+}
+
 /* make monster mtmp next to you (if possible);
    might place monst on far side of a wall or boulder */
 void
@@ -2536,7 +2712,11 @@ struct monst *mtmp;
         return;
     }
 
-    if (!enexto(&mm, u.ux, u.uy, mtmp->data))
+    if (!enexto(&mm, u.ux, u.uy, mtmp->data)) {
+        m_into_limbo(mtmp);
+        return;
+    }
+    if (!isok(mm.x, mm.y))
         return;
     rloc_to(mtmp, mm.x, mm.y);
     if (!in_mklev && (mtmp->mstrategy & STRAT_APPEARMSG)) {
@@ -2577,8 +2757,8 @@ struct monst *mtmp;
 /* mnearto()
  * Put monster near (or at) location if possible.
  * Returns:
- *      1 - if a monster was moved from x, y to put mtmp at x, y.
- *      0 - in most cases.
+ *  true if relocation was successful
+ *  false otherwise
  */
 boolean
 mnearto(mtmp, x, y, move_other)
@@ -2591,7 +2771,7 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
     coord mm;
 
     if (mtmp->mx == x && mtmp->my == y)
-        return FALSE;
+        return TRUE;
 
     if (move_other && (othermon = m_at(x, y)) != 0) {
         if (othermon->wormno)
@@ -2609,6 +2789,8 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
          */
         if (!enexto(&mm, newx, newy, mtmp->data))
             return FALSE;
+        if (!isok(mm.x,mm.y))
+            return FALSE;
         newx = mm.x;
         newy = mm.y;
     }
@@ -2620,16 +2802,14 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
         othermon->mx = othermon->my = 0;
         (void) mnearto(othermon, x, y, FALSE);
         if (othermon->mx == 0 && othermon->my == 0) {
-            /* reloc failed, dump monster into "limbo"
-               (aka migrate to current level) */
+            /* reloc failed */
             othermon->mx = oldx;
             othermon->my = oldy;
-            mdrop_special_objs(othermon);
-            migrate_to_level(othermon, ledger_no(&u.uz), MIGR_APPROX_XY, NULL);
+            m_into_limbo(othermon);
         }
     }
 
-    return FALSE;
+    return TRUE;
 }
 
 /* monster responds to player action; not the same as a passive attack;
@@ -2665,10 +2845,33 @@ struct monst *mtmp;
     }
 }
 
+/* Called whenever the player attacks mtmp; also called in other situations
+   where mtmp gets annoyed at the player. Handles mtmp getting annoyed at the
+   attack and any ramifications that might have. Useful also in situations
+   where mtmp was already hostile; it checks for situations where the player
+   shouldn't be attacking and any ramifications /that/ might have. */
 void
-setmangry(mtmp)
+setmangry(mtmp, via_attack)
 struct monst *mtmp;
+boolean via_attack;
 {
+    if (via_attack && sengr_at("Elbereth", u.ux, u.uy, TRUE)) {
+        You_feel("like a hypocrite.");
+        /* AIS: Yes, I know alignment penalties and bonuses aren't balanced
+           at the moment. This is about correct relative to other "small"
+           penalties; it should be fairly large, as attacking while standing
+           on an Elbereth means that you're requesting peace and then
+           violating your own request. I know 5 isn't actually large, but
+           it's intentionally larger than the 1s and 2s that are normally
+           given for this sort of thing. */
+        adjalign(-5);
+
+        if (!Blind)
+            pline("The engraving beneath you fades.");
+        del_engr_at(u.ux, u.uy);
+    }
+
+    /* AIS: Should this be in both places, or just in wakeup()? */
     mtmp->mstrategy &= ~STRAT_WAITMASK;
     if (!mtmp->mpeaceful)
         return;
@@ -2709,26 +2912,89 @@ struct monst *mtmp;
                     ++got_mad;
             }
         }
-        if (got_mad && !Hallucination)
+        if (got_mad && !Hallucination) {
+            const char *who = q_guardian->mname;
+
 #if 0 /*JP*/
-            pline_The("%s appear%s to be angry too...",
-                      got_mad == 1 ? q_guardian->mname
-                                   : makeplural(q_guardian->mname),
-                      got_mad == 1 ? "s" : "");
+            if (got_mad > 1)
+                who = makeplural(who);
+            pline_The("%s %s to be angry too...",
+                      who, vtense(who, "appear"));
 #else
-            pline("%s\82à\93{\82Á\82½\81D\81D\81D", q_guardian->mname);
+            pline("%s\82à\93{\82Á\82½\82æ\82¤\82¾\81D\81D\81D", who);
 #endif
+        }
+    }
+
+    /* make other peaceful monsters react */
+    if (!context.mon_moving) {
+        static const char *const Exclam[] = {
+            "Gasp!", "Uh-oh.", "Oh my!", "What?", "Why?",
+        };
+        struct monst *mon;
+        int mndx = monsndx(mtmp->data);
+
+        for (mon = fmon; mon; mon = mon->nmon) {
+            if (DEADMONSTER(mon))
+                continue;
+            if (mon == mtmp) /* the mpeaceful test catches this since mtmp */
+                continue;    /* is no longer peaceful, but be explicit...  */
+
+            if (!mindless(mon->data) && mon->mpeaceful
+                && couldsee(mon->mx, mon->my) && !mon->msleeping
+                && mon->mcansee && m_canseeu(mon)) {
+                boolean exclaimed = FALSE;
+
+                if (humanoid(mon->data) || mon->isshk || mon->ispriest) {
+                    if (is_watch(mon->data)) {
+                        verbalize("Halt!  You're under arrest!");
+                        (void) angry_guards(!!Deaf);
+                    } else {
+                        if (!rn2(5)) {
+                            verbalize("%s", Exclam[mon->m_id % SIZE(Exclam)]);
+                            exclaimed = TRUE;
+                        }
+                        /* shopkeepers and temple priests might gasp in
+                           surprise, but they won't become angry here */
+                        if (mon->isshk || mon->ispriest)
+                            continue;
+
+                        if (mon->data->mlevel < rn2(10)) {
+                            monflee(mon, rn2(50) + 25, TRUE, !exclaimed);
+                            exclaimed = TRUE;
+                        }
+                        if (mon->mtame) {
+                            /* mustn't set mpeaceful to 0 as below;
+                               perhaps reduce tameness? */
+                        } else {
+                            mon->mpeaceful = 0;
+                            adjalign(-1);
+                            if (!exclaimed)
+                                pline("%s gets angry!", Monnam(mon));
+                        }
+                    }
+                } else if (mon->data->mlet == mtmp->data->mlet
+                           && big_little_match(mndx, monsndx(mon->data))
+                           && !rn2(3)) {
+                    if (!rn2(4)) {
+                        growl(mon);
+                        exclaimed = TRUE;
+                    }
+                    if (rn2(6))
+                        monflee(mon, rn2(25) + 15, TRUE, !exclaimed);
+                }
+            }
+        }
     }
 }
 
-/* wake up a monster, usually making it angry in the process */
+/* wake up a monster, possibly making it angry in the process */
 void
-wakeup(mtmp)
+wakeup(mtmp, via_attack)
 register struct monst *mtmp;
+boolean via_attack;
 {
     mtmp->msleeping = 0;
-    finish_meating(mtmp);
-    setmangry(mtmp);
     if (mtmp->m_ap_type) {
         seemimic(mtmp);
     } else if (context.forcefight && !context.mon_moving
@@ -2736,6 +3002,9 @@ register struct monst *mtmp;
         mtmp->mundetected = 0;
         newsym(mtmp->mx, mtmp->my);
     }
+    finish_meating(mtmp);
+    if (via_attack)
+        setmangry(mtmp, TRUE);
 }
 
 /* Wake up nearby monsters without angering them. */
@@ -2751,8 +3020,13 @@ wake_nearby()
             mtmp->msleeping = 0;
             if (!unique_corpstat(mtmp->data))
                 mtmp->mstrategy &= ~STRAT_WAITMASK;
-            if (mtmp->mtame && !mtmp->isminion)
-                EDOG(mtmp)->whistletime = moves;
+            if (mtmp->mtame) {
+                if (!mtmp->isminion)
+                    EDOG(mtmp)->whistletime = moves;
+                /* Clear mtrack. This is to fix up a pet who is
+                   stuck "fleeing" its master. */
+                memset(mtmp->mtrack, 0, sizeof(mtmp->mtrack));
+            }
         }
     }
 }
@@ -2780,8 +3054,7 @@ void
 seemimic(mtmp)
 register struct monst *mtmp;
 {
-    boolean is_blocker_appear = (is_door_mappear(mtmp)
-                                 || is_obj_mappear(mtmp, BOULDER));
+    boolean is_blocker_appear = (is_lightblocker_mappear(mtmp));
 
     if (has_mcorpsenm(mtmp))
         freemcorpsenm(mtmp);
@@ -3001,38 +3274,68 @@ decide_to_shapeshift(mon, shiftflags)
 struct monst *mon;
 int shiftflags;
 {
-    struct permonst *ptr;
+    struct permonst *ptr = 0;
+    int mndx;
     unsigned was_female = mon->female;
-    boolean msg = FALSE;
+    boolean msg = FALSE, dochng = FALSE;
 
     if ((shiftflags & SHIFT_MSG)
         || ((shiftflags & SHIFT_SEENMSG) && sensemon(mon)))
         msg = TRUE;
 
-    if (is_vampshifter(mon)) {
+    if (!is_vampshifter(mon)) {
+        /* regular shapeshifter */
+        if (!rn2(6))
+            dochng = TRUE;
+    } else {
         /* The vampire has to be in good health (mhp) to maintain
          * its shifted form.
-             *
-         * If we're shifted and getting low on hp, maybe shift back.
+         *
+         * If we're shifted and getting low on hp, maybe shift back, or
+         * if we're a fog cloud at full hp, maybe pick a different shape.
          * If we're not already shifted and in good health, maybe shift.
          */
-        if ((mon->mhp <= mon->mhpmax / 6) && rn2(4) && (mon->cham >= LOW_PM))
-            (void) newcham(mon, &mons[mon->cham], FALSE, msg);
-    } else if (mon->data->mlet == S_VAMPIRE && mon->cham == NON_PM && !rn2(6)
-               && (mon->mhp > mon->mhpmax - ((mon->mhpmax / 10) + 1))) {
-        (void) newcham(mon, (struct permonst *) 0, FALSE, msg);
+        if (mon->data->mlet != S_VAMPIRE) {
+            if ((mon->mhp <= (mon->mhpmax + 5) / 6) && rn2(4)
+                && mon->cham >= LOW_PM) {
+                ptr = &mons[mon->cham];
+                dochng = TRUE;
+            } else if (mon->data == &mons[PM_FOG_CLOUD]
+                     && mon->mhp == mon->mhpmax && !rn2(4)
+                     && (!canseemon(mon)
+                         || distu(mon->mx, mon->my) > BOLT_LIM * BOLT_LIM)) {
+                /* if a fog cloud, maybe change to wolf or vampire bat;
+                   those are more likely to take damage--at least when
+                   tame--and then switch back to vampire; they'll also
+                   switch to fog cloud if they encounter a closed door */
+                mndx = pickvampshape(mon);
+                if (mndx >= LOW_PM) {
+                    ptr = &mons[mndx];
+                    dochng = (ptr != mon->data);
+                }
+            }
+        } else {
+            if (mon->mhp >= 9 * mon->mhpmax / 10 && !rn2(6)
+                && (!canseemon(mon)
+                    || distu(mon->mx, mon->my) > BOLT_LIM * BOLT_LIM))
+                dochng = TRUE; /* 'ptr' stays Null */
+        }
+    }
+    if (dochng) {
+        if (newcham(mon, ptr, FALSE, msg) && is_vampshifter(mon)) {
+            /* for vampshift, override the 10% chance for sex change */
+            ptr = mon->data;
+            if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
+                mon->female = was_female;
+        }
     }
-    /* override the 10% chance for sex change */
-    ptr = mon->data;
-    if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
-        mon->female = was_female;
 }
 
 STATIC_OVL int
 pickvampshape(mon)
 struct monst *mon;
 {
-    int mndx = mon->cham;
+    int mndx = mon->cham, wolfchance = 10;
     /* avoid picking monsters with lowercase display symbols ('d' for wolf
        and 'v' for fog cloud) on rogue level*/
     boolean uppercase_only = Is_rogue_level(&u.uz);
@@ -3042,9 +3345,10 @@ struct monst *mon;
         /* ensure Vlad can keep carrying the Candelabrum */
         if (mon_has_special(mon))
             break; /* leave mndx as is */
+        wolfchance = 3;
     /*FALLTHRU*/
     case PM_VAMPIRE_LORD: /* vampire lord or Vlad can become wolf */
-        if (!rn2(10) && !uppercase_only) {
+        if (!rn2(wolfchance) && !uppercase_only) {
             mndx = PM_WOLF;
             break;
         }
@@ -3092,7 +3396,7 @@ int mndx;
 }
 
 /* prevent wizard mode user from specifying invalid vampshifter shape */
-STATIC_OVL boolean
+boolean
 validvamp(mon, mndx_p, monclass)
 struct monst *mon;
 int *mndx_p, monclass;
@@ -3195,13 +3499,17 @@ struct monst *mon;
       }
         break;
     }
+
     /* for debugging: allow control of polymorphed monster */
     if (wizard && iflags.mon_polycontrol) {
-        char pprompt[BUFSZ], buf[BUFSZ];
+        char pprompt[BUFSZ], buf[BUFSZ] = DUMMY;
         int monclass;
 
-        Sprintf(pprompt, "Change %s @ <%d,%d> into what kind of monster?",
-                noit_mon_nam(mon), (int) mon->mx, (int) mon->my);
+        Sprintf(pprompt, "Change %s @ %s into what kind of monster?",
+                noit_mon_nam(mon),
+                coord_desc((int) mon->mx, (int) mon->my, buf,
+                           (iflags.getpos_coords != GPCOORDS_NONE)
+                              ? iflags.getpos_coords : GPCOORDS_MAP));
         tryct = 5;
         do {
             monclass = 0;
@@ -3305,11 +3613,18 @@ boolean msg;      /* "The oldmon turns into a newmon!" */
     int hpn, hpd;
     int mndx, tryct;
     struct permonst *olddata = mtmp->data;
-    char oldname[BUFSZ], newname[BUFSZ];
+    char *p, oldname[BUFSZ], l_oldname[BUFSZ], newname[BUFSZ];
 
-    /* Riders are immune to polymorph and green slime */
-    if (is_rider(mtmp->data))
-        return 0;
+    /* Riders are immune to polymorph and green slime
+       (but apparent Rider might actually be a doppelganger) */
+    if (mtmp->cham == NON_PM) { /* not a shapechanger */
+        if (is_rider(olddata))
+            return 0;
+        /* make Nazgul and erinyes immune too, to reduce chance of
+           anomalous extinction feedback during final disclsoure */
+        if (mbirth_limit(monsndx(olddata)) < MAXMONNO)
+            return 0;
+    }
 
     if (msg) {
         /* like Monnam() but never mention saddle */
@@ -3317,6 +3632,9 @@ boolean msg;      /* "The oldmon turns into a newmon!" */
                                  SUPPRESS_SADDLE, FALSE));
         oldname[0] = highc(oldname[0]);
     }
+    /* we need this one whether msg is true or not */
+    Strcpy(l_oldname, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
+                               has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE));
 
     /* mdat = 0 -> caller wants a random monster shape */
     if (mdat == 0) {
@@ -3339,24 +3657,19 @@ boolean msg;      /* "The oldmon turns into a newmon!" */
     } else if (mvitals[monsndx(mdat)].mvflags & G_GENOD)
         return 0; /* passed in mdat is genocided */
 
-    mgender_from_permonst(mtmp, mdat);
-
-    if (In_endgame(&u.uz) && is_mplayer(olddata) && has_mname(mtmp)) {
-        /* mplayers start out as "Foo the Bar", but some of the
-         * titles are inappropriate when polymorphed, particularly
-         * into the opposite sex.  players don't use ranks when
-         * polymorphed, so dropping the rank for mplayers seems
-         * reasonable.
-         */
-        char *p = index(MNAME(mtmp), ' ');
-
-        if (p)
-            *p = '\0';
-    }
-
-    if (mdat == mtmp->data)
+    if (mdat == olddata)
         return 0; /* still the same monster */
 
+    mgender_from_permonst(mtmp, mdat);
+    /* Endgame mplayers start out as "Foo the Bar", but some of the
+     * titles are inappropriate when polymorphed, particularly into
+     * the opposite sex.  Player characters don't use ranks when
+     * polymorphed, so dropping rank for mplayers seems reasonable.
+     */
+    if (In_endgame(&u.uz) && is_mplayer(olddata)
+        && has_mname(mtmp) && (p = strstr(MNAME(mtmp), " the ")) != 0)
+        *p = '\0';
+
     if (mtmp->wormno) { /* throw tail away */
         wormgone(mtmp);
         place_monster(mtmp, mtmp->mx, mtmp->my);
@@ -3407,13 +3720,33 @@ boolean msg;      /* "The oldmon turns into a newmon!" */
                 /* Does mdat care? */
                 if (!noncorporeal(mdat) && !amorphous(mdat)
                     && !is_whirly(mdat) && (mdat != &mons[PM_YELLOW_LIGHT])) {
+                    char msgtrail[BUFSZ];
+
+                    if (is_vampshifter(mtmp)) {
+                        Sprintf(msgtrail, " which was a shapeshifted %s",
+                                noname_monnam(mtmp, ARTICLE_NONE));
+                    } else if (is_animal(mdat)) {
+/*JP
+                        Strcpy(msgtrail, "'s stomach");
+*/
+                        Strcpy(msgtrail, "\82Ì\88Ý");
+                    } else {
+                        msgtrail[0] = '\0';
+                    }
+
+                    /* Do this even if msg is FALSE */
 #if 0 /*JP*/
-                    You("break out of %s%s!", mon_nam(mtmp),
-                        (is_animal(mdat) ? "'s stomach" : ""));
+                    You("%s %s%s!",
+                        (amorphous(olddata) || is_whirly(olddata))
+                            ? "emerge from" : "break out of",
+                        l_oldname, msgtrail);
 #else
-                    You("%s%s\82ð\94j\82è\8fo\82½\81I", mon_nam(mtmp),
-                        (is_animal(mdat) ? "\82Ì\88Ý\91Ü" : ""));
+                    You("%s%s%s\81I", l_oldname, msgtrail,
+                        (amorphous(olddata) || is_whirly(olddata))
+                            ? "\82©\82ç\94ò\82Ñ\8fo\82µ\82½" : "\82ð\94j\82è\8fo\82½"
+                        );
 #endif
+                    msg = FALSE; /* message has been given */
                     mtmp->mhp = 1; /* almost dead */
                 }
                 expels(mtmp, olddata, FALSE);
@@ -3443,37 +3776,41 @@ boolean msg;      /* "The oldmon turns into a newmon!" */
     newsym(mtmp->mx, mtmp->my);
 
     if (msg) {
-        char *save_mname = 0;
-
-        if (has_mname(mtmp)) {
-            save_mname = MNAME(mtmp);
-            MNAME(mtmp) = (char *) 0;
-        }
+        Strcpy(newname, noname_monnam(mtmp, ARTICLE_A));
+        /* oldname was capitalized above; newname will be lower case */
 #if 0 /*JP*/
-        Strcpy(newname, (mdat == &mons[PM_GREEN_SLIME])
-                            ? "slime"
-                            : x_monnam(mtmp, ARTICLE_A, (char *) 0,
-                                       SUPPRESS_SADDLE, FALSE));
+        if (!strcmpi(newname, "it")) { /* can't see or sense it now */
 #else
-        Strcpy(newname, (mdat == &mons[PM_GREEN_SLIME])
-                            ? "\83X\83\89\83C\83\80"
-                            : x_monnam(mtmp, ARTICLE_A, (char *) 0,
-                                       SUPPRESS_SADDLE, FALSE));
+        if (!strcmpi(newname, "\89½\8eÒ\82©")) { /* can't see or sense it now */
 #endif
-/*JP
-        if (!strcmpi(oldname, "it") && !strcmpi(newname, "it"))
-*/
-        if (!strcmpi(oldname, "\89½\8eÒ\82©") && !strcmpi(newname, "\89½\8eÒ\82©"))
+#if 0 /*JP*/
+            if (!!strcmpi(oldname, "it")) /* could see or sense it before */
+#else
+            if (!!strcmpi(oldname, "\89½\8eÒ\82©")) /* could see or sense it before */
+#endif
+                pline("%s disappears!", oldname);
             (void) usmellmon(mdat);
-        else
+        } else { /* can see or sense it now */
+#if 0 /*JP*/
+            if (!strcmpi(oldname, "it")) /* couldn't see or sense it before */
+#else
+            if (!strcmpi(oldname, "\89½\8eÒ\82©")) /* couldn't see or sense it before */
+#endif
+                pline("%s appears!", upstart(newname));
+            else
 /*JP
             pline("%s turns into %s!", oldname, newname);
 */
             pline("%s\82Í%s\82É\82È\82Á\82½\81I", oldname, newname);
-        if (save_mname)
-            MNAME(mtmp) = save_mname;
+        }
     }
 
+    /* when polymorph trap/wand/potion produces a vampire, turn in into
+       a full-fledged vampshifter unless shape-changing is blocked */
+    if (mtmp->cham == NON_PM && mdat->mlet == S_VAMPIRE
+        && !Protection_from_shape_changers)
+        mtmp->cham = pm_to_cham(monsndx(mdat));
+
     possibly_unwield(mtmp, polyspot); /* might lose use of weapon */
     mon_break_armor(mtmp, polyspot);
     if (!(mtmp->misc_worn_check & W_ARMG))
index 8498643..34a586f 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 mondata.c       $NHDT-Date: 1446604115 2015/11/04 02:28:35 $  $NHDT-Branch: master $:$NHDT-Revision: 1.58 $ */
+/* NetHack 3.6 mondata.c       $NHDT-Date: 1508479720 2017/10/20 06:08:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.63 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -8,8 +9,9 @@
 /* JNetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
-
-/*      These routines provide basic data for any type of monster. */
+/*
+ *      These routines provide basic data for any type of monster.
+ */
 
 /* set up an individual monster's base type (initial creation, shapechange) */
 void
@@ -18,7 +20,10 @@ struct monst *mon;
 struct permonst *ptr;
 int flag;
 {
+    int new_speed, old_speed = mon->data ? mon->data->mmove : 0;
+
     mon->data = ptr;
+    mon->mnum = (short) monsndx(ptr);
     if (flag == -1)
         return; /* "don't care" */
 
@@ -26,6 +31,15 @@ int flag;
         mon->mintrinsics |= (ptr->mresists & 0x00FF);
     else
         mon->mintrinsics = (ptr->mresists & 0x00FF);
+
+    if (mon->movement) { /* same adjustment as poly'd hero undergoes */
+        new_speed = ptr->mmove;
+        /* prorate unused movement if new form is slower so that
+           it doesn't get extra moves leftover from previous form;
+           if new form is faster, leave unused movement as is */
+        if (new_speed < old_speed)
+            mon->movement = new_speed * mon->movement / old_speed;
+    }
     return;
 }
 
@@ -323,7 +337,7 @@ struct permonst *mptr;
 /* returns True if monster can blow (whistle, etc) */
 boolean
 can_blow(mtmp)
-register struct monst *mtmp;
+struct monst *mtmp;
 {
     if ((is_silent(mtmp->data) || mtmp->data->msound == MS_BUZZ)
         && (breathless(mtmp->data) || verysmall(mtmp->data)
@@ -334,6 +348,18 @@ register struct monst *mtmp;
     return TRUE;
 }
 
+/* for casting spells and reading scrolls while blind */
+boolean
+can_chant(mtmp)
+struct monst *mtmp;
+{
+    if ((mtmp == &youmonst && Strangled)
+        || is_silent(mtmp->data) || !has_head(mtmp->data)
+        || mtmp->data->msound == MS_BUZZ || mtmp->data->msound == MS_BURBLE)
+        return FALSE;
+    return TRUE;
+}
+
 /* True if mon is vulnerable to strangulation */
 boolean
 can_be_strangled(mon)
@@ -857,16 +883,12 @@ int *mndx_p;
             if ((p = strstri(x, in_str)) != 0 && (p == x || *(p - 1) == ' '))
                 return i;
         }
-        /* check individual species names; not as thorough as mon_to_name()
-           but our caller can call that directly if desired */
-        for (i = LOW_PM; i < NUMMONS; i++) {
-            x = mons[i].mname;
-            if ((p = strstri(x, in_str)) != 0
-                && (p == x || *(p - 1) == ' ')) {
-                if (mndx_p)
-                    *mndx_p = i;
-                return mons[i].mlet;
-            }
+        /* check individual species names */
+        i = name_to_mon(in_str);
+        if (i != NON_PM) {
+            if (mndx_p)
+                *mndx_p = i;
+            return mons[i].mlet;
         }
     }
     return 0;
@@ -1015,6 +1037,32 @@ int montype;
     return montype;
 }
 
+/* determine whether two permonst indices are part of the same progression;
+   existence of progressions with more than one step makes it a bit tricky */
+boolean
+big_little_match(montyp1, montyp2)
+int montyp1, montyp2;
+{
+    int l, b;
+
+    /* simplest case: both are same pm */
+    if (montyp1 == montyp2)
+        return TRUE;
+    /* assume it isn't possible to grow from one class letter to another */
+    if (mons[montyp1].mlet != mons[montyp2].mlet)
+        return FALSE;
+    /* check whether montyp1 can grow up into montyp2 */
+    for (l = montyp1; (b = little_to_big(l)) != l; l = b)
+        if (b == montyp2)
+            return TRUE;
+    /* check whether montyp2 can grow up into montyp1 */
+    for (l = montyp2; (b = little_to_big(l)) != l; l = b)
+        if (b == montyp1)
+            return TRUE;
+    /* neither grows up to become the other; no match */
+    return FALSE;
+}
+
 /*
  * Return the permonst ptr for the race of the monster.
  * Returns correct pointer for non-polymorphed and polymorphed
index 8a74c06..bf15359 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 monmove.c       $NHDT-Date: 1446808446 2015/11/06 11:14:06 $  $NHDT-Branch: master $:$NHDT-Revision: 1.78 $ */
+/* NetHack 3.6 monmove.c       $NHDT-Date: 1517877380 2018/02/06 00:36:20 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.96 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -19,7 +20,7 @@ STATIC_DCL void FDECL(release_hero, (struct monst *));
 STATIC_DCL void FDECL(distfleeck, (struct monst *, int *, int *, int *));
 STATIC_DCL int FDECL(m_arrival, (struct monst *));
 STATIC_DCL boolean FDECL(stuff_prevents_passage, (struct monst *));
-STATIC_DCL int FDECL(vamp_shift, (struct monst *, struct permonst *));
+STATIC_DCL int FDECL(vamp_shift, (struct monst *, struct permonst *, BOOLEAN_P));
 
 /* True if mtmp died */
 boolean
@@ -67,17 +68,30 @@ mon_yells(mon, shout)
 struct monst *mon;
 const char *shout;
 {
-    if (canspotmon(mon))
+    if (Deaf) {
+        if (canspotmon(mon))
+            /* Sidenote on "A watchman angrily waves her arms!"
+             * Female being called watchman is correct (career name).
+             */
+            pline("%s angrily %s %s %s!",
+                Amonnam(mon),
+                nolimbs(mon->data) ? "shakes" : "waves",
+                mhis(mon),
+                nolimbs(mon->data) ? mbodypart(mon, HEAD)
+                                   : makeplural(mbodypart(mon, ARM)));
+    } else {
+        if (canspotmon(mon))
 /*JP
         pline("%s yells:", Amonnam(mon));
 */
         pline("%s\82Í\8b©\82ñ\82¾\81F", Amonnam(mon));
-    else
+        else
 /*JP
         You_hear("someone yell:");
 */
         pline("\89½\8eÒ\82©\82Í\8b©\82ñ\82¾\81F");
-    verbalize1(shout);
+        verbalize1(shout);
+    }
 }
 
 STATIC_OVL void
@@ -144,14 +158,20 @@ onscary(x, y, mtmp)
 int x, y;
 struct monst *mtmp;
 {
-    boolean epresent = sengr_at("Elbereth", x, y, TRUE);
-
     /* creatures who are directly resistant to magical scaring:
-     * Rodney, lawful minions, angels, the Riders */
+     * Rodney, lawful minions, Angels, the Riders, shopkeepers
+     * inside their own shop, priests inside their own temple */
     if (mtmp->iswiz || is_lminion(mtmp) || mtmp->data == &mons[PM_ANGEL]
-        || is_rider(mtmp->data))
+        || is_rider(mtmp->data)
+        || (mtmp->isshk && inhishop(mtmp))
+        || (mtmp->ispriest && inhistemple(mtmp)))
         return FALSE;
 
+    /* <0,0> is used by musical scaring to check for the above;
+     * it doesn't care about scrolls or engravings or dungeon branch */
+    if (x == 0 && y == 0)
+        return TRUE;
+
     /* should this still be true for defiled/molochian altars? */
     if (IS_ALTAR(levl[x][y].typ)
         && (mtmp->data->mlet == S_VAMPIRE || is_vampshifter(mtmp)))
@@ -162,16 +182,19 @@ struct monst *mtmp;
     if (sobj_at(SCR_SCARE_MONSTER, x, y))
         return TRUE;
 
-    /* creatures who don't (or can't) fear a written Elbereth:
-     * all the above plus shopkeepers, guards, blind or
-     * peaceful monsters, humans, and minotaurs.
+    /*
+     * Creatures who don't (or can't) fear a written Elbereth:
+     * all the above plus shopkeepers (even if poly'd into non-human),
+     * vault guards (also even if poly'd), blind or peaceful monsters,
+     * humans and elves, and minotaurs.
      *
-     * if the player isn't actually on the square OR the player's image
-     * isn't displaced to the square, no protection is being granted
+     * If the player isn't actually on the square OR the player's image
+     * isn't displaced to the square, no protection is being granted.
      *
      * Elbereth doesn't work in Gehennom, the Elemental Planes, or the
-     * Astral Plane; the influence of the Valar only reaches so far.  */
-    return (epresent
+     * Astral Plane; the influence of the Valar only reaches so far.
+     */
+    return (sengr_at("Elbereth", x, y, TRUE)
             && ((u.ux == x && u.uy == y)
                 || (Displaced && mtmp->mux == x && mtmp->muy == y))
             && !(mtmp->isshk || mtmp->isgd || !mtmp->mcansee
@@ -303,6 +326,8 @@ boolean fleemsg;
         }
         mtmp->mflee = 1;
     }
+    /* ignore recently-stepped spaces when made to flee */
+    memset(mtmp->mtrack, 0, sizeof(mtmp->mtrack));
 }
 
 STATIC_OVL void
@@ -337,12 +362,6 @@ int *inrange, *nearby, *scared;
                     || (!mtmp->mpeaceful && in_your_sanctuary(mtmp, 0, 0)))) {
         *scared = 1;
         monflee(mtmp, rnd(rn2(7) ? 10 : 100), TRUE, TRUE);
-
-        /* magical protection won't last forever, so there'll be a
-         * chance of the magic being used up regardless of type */
-        if (sawscary) {
-            wipe_engr_at(seescaryx, seescaryy, 1, TRUE);
-        }
     } else
         *scared = 0;
 }
@@ -635,7 +654,7 @@ toofar:
         case 0: /* no movement, but it can still attack you */
         case 3: /* absolutely no movement */
             /* vault guard might have vanished */
-            if (mtmp->isgd && (mtmp->mhp < 1 || !mtmp->mx == 0))
+            if (mtmp->isgd && (mtmp->mhp < 1 || mtmp->mx == 0))
                 return 1; /* behave as if it died */
             /* During hallucination, monster appearance should
              * still change - even if it doesn't move.
@@ -672,7 +691,8 @@ toofar:
      */
 
     if (!mtmp->mpeaceful || (Conflict && !resist(mtmp, RING_CLASS, 0, 0))) {
-        if (inrange && !noattacks(mdat) && u.uhp > 0 && !scared && tmp != 3)
+        if (inrange && !noattacks(mdat)
+            && (Upolyd ? u.mh : u.uhp) > 0 && !scared && tmp != 3)
             if (mattacku(mtmp))
                 return 1; /* monster died (e.g. exploded) */
 
@@ -757,6 +777,38 @@ xchar gx, gy;
     return FALSE;
 }
 
+boolean
+m_digweapon_check(mtmp, nix, niy)
+struct monst *mtmp;
+xchar nix,niy;
+{
+    boolean can_tunnel = 0;
+    struct obj *mw_tmp;
+
+    if (!Is_rogue_level(&u.uz))
+        can_tunnel = tunnels(mtmp->data);
+
+    if (can_tunnel && needspick(mtmp->data)
+        && mtmp->weapon_check != NO_WEAPON_WANTED
+        && ((IS_ROCK(levl[nix][niy].typ) && may_dig(nix, niy))
+            || closed_door(nix, niy))) {
+        if (closed_door(nix, niy)) {
+            if (!(mw_tmp = MON_WEP(mtmp))
+                || !is_pick(mw_tmp)
+                || !is_axe(mw_tmp))
+                mtmp->weapon_check = NEED_PICK_OR_AXE;
+        } else if (IS_TREE(levl[nix][niy].typ)) {
+            if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
+                mtmp->weapon_check = NEED_AXE;
+        } else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
+            mtmp->weapon_check = NEED_PICK_AXE;
+        }
+        if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
+            return TRUE;
+    }
+    return FALSE;
+}
+
 /* Return values:
  * 0: did not move, but can still attack and do other stuff.
  * 1: moved, possibly can attack.
@@ -778,16 +830,17 @@ register int after;
     boolean uses_items = 0, setlikes = 0;
     boolean avoid = FALSE;
     boolean better_with_displacing = FALSE;
+    boolean sawmon = canspotmon(mtmp); /* before it moved */
     struct permonst *ptr;
     struct monst *mtoo;
     schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */
     long info[9];
     long flag;
     int omx = mtmp->mx, omy = mtmp->my;
-    struct obj *mw_tmp;
 
     if (mtmp->mtrapped) {
         int i = mintrap(mtmp);
+
         if (i >= 2) {
             newsym(mtmp->mx, mtmp->my);
             return 2;
@@ -1002,15 +1055,21 @@ not_special:
                  * mpickstuff() as well.
                  */
                 if (xx >= lmx && xx <= oomx && yy >= lmy && yy <= oomy) {
-                    /* don't get stuck circling around an object that's
-                       underneath
-                       an immobile or hidden monster; paralysis victims
-                       excluded */
+                    /* don't get stuck circling around object that's
+                       underneath an immobile or hidden monster;
+                       paralysis victims excluded */
                     if ((mtoo = m_at(xx, yy)) != 0
                         && (mtoo->msleeping || mtoo->mundetected
                             || (mtoo->mappearance && !mtoo->iswiz)
                             || !mtoo->data->mmove))
                         continue;
+                    /* the mfndpos() test for whether to allow a move to a
+                       water location accepts flyers, but they can't reach
+                       underwater objects, so being able to move to a spot
+                       is insufficient for deciding whether to do so */
+                    if ((is_pool(xx, yy) && !is_swimmer(ptr))
+                        || (is_lava(xx, yy) && !likes_lava(ptr)))
+                        continue;
 
                     if (((likegold && otmp->oclass == COIN_CLASS)
                          || (likeobjs && index(practical, otmp->oclass)
@@ -1091,9 +1150,7 @@ not_special:
         flag |= ALLOW_DIG;
     if (is_human(ptr) || ptr == &mons[PM_MINOTAUR])
         flag |= ALLOW_SSM;
-    if (is_undead(ptr) && ptr->mlet != S_GHOST)
-        flag |= NOGARLIC;
-    if (is_vampshifter(mtmp))
+    if ((is_undead(ptr) && ptr->mlet != S_GHOST) || is_vampshifter(mtmp))
         flag |= NOGARLIC;
     if (throws_rocks(ptr))
         flag |= ALLOW_ROCK;
@@ -1165,22 +1222,9 @@ not_special:
         if (mmoved == 1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
             return 3;
 
-        if (mmoved == 1 && can_tunnel && needspick(ptr)
-            && ((IS_ROCK(levl[nix][niy].typ) && may_dig(nix, niy))
-                || closed_door(nix, niy))) {
-            if (closed_door(nix, niy)) {
-                if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)
-                    || !is_axe(mw_tmp))
-                    mtmp->weapon_check = NEED_PICK_OR_AXE;
-            } else if (IS_TREE(levl[nix][niy].typ)) {
-                if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
-                    mtmp->weapon_check = NEED_AXE;
-            } else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
-                mtmp->weapon_check = NEED_PICK_AXE;
-            }
-            if (mtmp->weapon_check >= NEED_PICK_AXE && mon_wield_item(mtmp))
-                return 3;
-        }
+        if (mmoved == 1 && m_digweapon_check(mtmp, nix,niy))
+            return 3;
+
         /* If ALLOW_U is set, either it's trying to attack you, or it
          * thinks it is.  In either case, attack this spot in preference to
          * all others.
@@ -1275,29 +1319,42 @@ postmov:
             }
             ptr = mtmp->data;
 
-            /* open a door, or crash through it, if you can */
+            /* open a door, or crash through it, if 'mtmp' can */
             if (IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
                 && !passes_walls(ptr) /* doesn't need to open doors */
                 && !can_tunnel) {     /* taken care of below */
                 struct rm *here = &levl[mtmp->mx][mtmp->my];
-                boolean btrapped = (here->doormask & D_TRAPPED),
+                boolean btrapped = (here->doormask & D_TRAPPED) != 0,
                         observeit = canseeit && canspotmon(mtmp);
 
-                if (here->doormask & (D_LOCKED | D_CLOSED)
+                /* if mon has MKoT, disarm door trap; no message given */
+                if (btrapped && has_magic_key(mtmp)) {
+                    /* BUG: this lets a vampire or blob or a doorbuster
+                       holding the Key disarm the trap even though it isn't
+                       using that Key when squeezing under or smashing the
+                       door.  Not significant enough to worry about; perhaps
+                       the Key's magic is more powerful for monsters? */
+                    here->doormask &= ~D_TRAPPED;
+                    btrapped = FALSE;
+                }
+                if ((here->doormask & (D_LOCKED | D_CLOSED)) != 0
                     && (amorphous(ptr)
-                        || (!amorphous(ptr) && can_fog(mtmp)
-                            && vamp_shift(mtmp, &mons[PM_FOG_CLOUD])))) {
+                        || (can_fog(mtmp)
+                            && vamp_shift(mtmp, &mons[PM_FOG_CLOUD],
+                                          sawmon)))) {
+                    /* update cached value for vamp_shift() case */
+                    ptr = mtmp->data;
                     if (flags.verbose && canseemon(mtmp))
 #if 0 /*JP*/
                         pline("%s %s under the door.", Monnam(mtmp),
                               (ptr == &mons[PM_FOG_CLOUD]
-                               || ptr == &mons[PM_YELLOW_LIGHT])
+                               || ptr->mlet == S_LIGHT)
                                   ? "flows"
                                   : "oozes");
 #else
                         pline("%s\82Í\94à\82Ì\89º\82©\82ç%s\81D", Monnam(mtmp),
                               (ptr == &mons[PM_FOG_CLOUD]
-                               || ptr == &mons[PM_YELLOW_LIGHT])
+                               || ptr->mlet == S_LIGHT)
                                   ? "\97¬\82ê\82Å\82½"
                                   : "\82É\82\82Ý\82Å\82½");
 #endif
@@ -1387,7 +1444,7 @@ postmov:
 */
                                 You_hear("\94à\82ª\94j\89ó\82³\82ê\82é\89¹\82ð\95·\82¢\82½\81D");
                         }
-                        if (here->doormask & D_LOCKED && !rn2(2))
+                        if ((here->doormask & D_LOCKED) != 0 && !rn2(2))
                             here->doormask = D_NODOOR;
                         else
                             here->doormask = D_BROKEN;
@@ -1692,27 +1749,38 @@ boolean
 can_fog(mtmp)
 struct monst *mtmp;
 {
-    if ((is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE)
+    if (!(mvitals[PM_FOG_CLOUD].mvflags & G_GENOD) && is_vampshifter(mtmp)
         && !Protection_from_shape_changers && !stuff_prevents_passage(mtmp))
         return TRUE;
     return FALSE;
 }
 
 STATIC_OVL int
-vamp_shift(mon, ptr)
+vamp_shift(mon, ptr, domsg)
 struct monst *mon;
 struct permonst *ptr;
+boolean domsg;
 {
     int reslt = 0;
+    char oldmtype[BUFSZ];
 
-    if (mon->cham >= LOW_PM) {
-        if (ptr == &mons[mon->cham])
-            mon->cham = NON_PM;
-        reslt = newcham(mon, ptr, FALSE, FALSE);
-    } else if (mon->cham == NON_PM && ptr != mon->data) {
-        mon->cham = monsndx(mon->data);
+    /* remember current monster type before shapechange */
+    Strcpy(oldmtype, domsg ? noname_monnam(mon, ARTICLE_THE) : "");
+
+    if (mon->data == ptr) {
+        /* already right shape */
+        reslt = 1;
+        domsg = FALSE;
+    } else if (is_vampshifter(mon)) {
         reslt = newcham(mon, ptr, FALSE, FALSE);
     }
+
+    if (reslt && domsg) {
+        pline("You %s %s where %s was.",
+              !canseemon(mon) ? "now detect" : "observe",
+              noname_monnam(mon, ARTICLE_A), oldmtype);
+    }
+
     return reslt;
 }
 
index cf14f9e..7f998c0 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 monst.c $NHDT-Date: 1445556875 2015/10/22 23:34:35 $  $NHDT-Branch: master $:$NHDT-Revision: 1.53 $ */
+/* NetHack 3.6 monst.c $NHDT-Date: 1510531569 2017/11/13 00:06:09 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.59 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "config.h"
 
 void NDECL(monst_init);
 /*
- *     Entry Format:           (from permonst.h)
+ *      Entry Format:   (from permonst.h)
  *
- *     name, symbol (S_* defines),
- *     difficulty level, move rate, armor class, magic resistance,
- *     alignment, creation/geno flags (G_* defines),
- *     6 * attack structs ( type , damage-type, # dice, # sides ),
- *     weight (WT_* defines), nutritional value, extension length,
- *     sounds made (MS_* defines), physical size (MZ_* defines),
- *     resistances, resistances conferred (both MR_* defines),
- *     3 * flag bitmaps (M1_*, M2_*, and M3_* defines respectively)
- *     symbol color (C(x) macro)
+ *      name, symbol (S_* defines),
+ *      difficulty level, move rate, armor class, magic resistance,
+ *      alignment, creation/geno flags (G_* defines),
+ *      6 * attack structs ( type , damage-type, # dice, # sides ),
+ *      weight (WT_* defines), nutritional value, extension length,
+ *      sounds made (MS_* defines), physical size (MZ_* defines),
+ *      resistances, resistances conferred (both MR_* defines),
+ *      3 * flag bitmaps (M1_*, M2_*, and M3_* defines respectively)
+ *      symbol color (C(x) macro)
+ *
+ *      For AT_BREA attacks, '# sides' is ignored; 6 is used for most
+ *      damage types, 25 for sleep, not applicable for death or poison.
  */
 #define MON(nam, sym, lvl, gen, atk, siz, mr1, mr2, flg1, flg2, flg3, col) \
     {                                                                      \
@@ -59,37 +63,37 @@ void NDECL(monst_init);
     }
 
 /*
- *     Rule #1:        monsters of a given class are contiguous in the
- *                     mons[] array.
+ *      Rule #1:        monsters of a given class are contiguous in the
+ *                      mons[] array.
  *
- *     Rule #2:        monsters of a given class are presented in ascending
- *                     order of strength.
+ *      Rule #2:        monsters of a given class are presented in ascending
+ *                      order of strength.
  *
- *     Rule #3:        monster frequency is included in the geno mask;
- *                     the frequency can be from 0 to 7.  0's will also
- *                     be skipped during generation.
+ *      Rule #3:        monster frequency is included in the geno mask;
+ *                      the frequency can be from 0 to 7.  0's will also
+ *                      be skipped during generation.
  *
- *     Rule #4:        monster subclasses (e.g. giants) should be kept
- *                     together, unless it violates Rule 2.  NOGEN monsters
- *                     won't violate Rule 2.
+ *      Rule #4:        monster subclasses (e.g. giants) should be kept
+ *                      together, unless it violates Rule 2.  NOGEN monsters
+ *                      won't violate Rule 2.
  *
  * Guidelines for color assignment:
  *
- *     * Use the same color for all `growth stages' of a monster (ex.
- *       little dog/big dog, baby naga/full-grown naga.
+ *      * Use the same color for all `growth stages' of a monster (ex.
+ *        little dog/big dog, baby naga/full-grown naga.
  *
- *     * Use colors given in names wherever possible. If the class has `real'
- *       members with strong color associations, use those.
+ *      * Use colors given in names wherever possible. If the class has `real'
+ *        members with strong color associations, use those.
  *
- *     * Favor `cool' colors for cold-resistant monsters, `warm' ones for
- *       fire-resistant ones.
+ *      * Favor `cool' colors for cold-resistant monsters, `warm' ones for
+ *        fire-resistant ones.
  *
- *     * Try to reserve purple (magenta) for powerful `ruler' monsters (queen
- *       bee, kobold lord, &c.).
+ *      * Try to reserve purple (magenta) for powerful `ruler' monsters (queen
+ *        bee, kobold lord, &c.).
  *
- *     * Subject to all these constraints, try to use color to make as many
- *       distinctions as the / command (that is, within a monster letter
- *       distinct names should map to distinct colors).
+ *      * Subject to all these constraints, try to use color to make as many
+ *        distinctions as the / command (that is, within a monster letter
+ *        distinct names should map to distinct colors).
  *
  * The aim in assigning colors is to be consistent enough so a player can
  * become `intuitive' about them, deducing some or all of these rules
@@ -253,7 +257,7 @@ NEARDATA struct permonst mons[] = {
         M2_NOPOLY | M2_WERE | M2_HOSTILE, M3_INFRAVISIBLE, CLR_BROWN),
     MON("winter wolf cub", S_DOG, LVL(5, 12, 4, 0, -5),
         (G_NOHELL | G_GENO | G_SGROUP | 2),
-        A(ATTK(AT_BITE, AD_PHYS, 1, 8), ATTK(AT_BREA, AD_COLD, 1, 8), NO_ATTK,
+        A(ATTK(AT_BITE, AD_PHYS, 1, 8), ATTK(AT_BREA, AD_COLD, 1, 6), NO_ATTK,
           NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(250, 200, MS_BARK, MZ_SMALL), MR_COLD, MR_COLD,
         M1_ANIMAL | M1_NOHANDS | M1_CARNIVORE, M2_HOSTILE, 0, CLR_CYAN),
@@ -331,13 +335,13 @@ NEARDATA struct permonst mons[] = {
         M2_HOSTILE | M2_NEUTER, M3_INFRAVISIBLE, HI_ZAP),
 #if 0 /* not yet implemented */
     MON("beholder", S_EYE,
-       LVL(6, 3, 4, 0, -10), (G_GENO | 2),
-       A(ATTK(AT_GAZE, AD_SLOW, 0, 0), ATTK(AT_GAZE, AD_SLEE, 2,25),
-         ATTK(AT_GAZE, AD_DISN, 0, 0), ATTK(AT_GAZE, AD_STON, 0, 0),
-         ATTK(AT_GAZE, AD_CNCL, 2, 4), ATTK(AT_BITE, AD_PHYS, 2, 4)),
-       SIZ(10, 10, MS_SILENT, MZ_SMALL), MR_COLD, 0,
-       M1_FLY | M1_BREATHLESS | M1_NOLIMBS | M1_NOHEAD | M1_MINDLESS,
-       M2_NOPOLY | M2_HOSTILE | M2_NEUTER, M3_INFRAVISIBLE, CLR_BROWN),
+        LVL(6, 3, 4, 0, -10), (G_GENO | 2),
+        A(ATTK(AT_GAZE, AD_SLOW, 0, 0), ATTK(AT_GAZE, AD_SLEE, 2,25),
+          ATTK(AT_GAZE, AD_DISN, 0, 0), ATTK(AT_GAZE, AD_STON, 0, 0),
+          ATTK(AT_GAZE, AD_CNCL, 2, 4), ATTK(AT_BITE, AD_PHYS, 2, 4)),
+        SIZ(10, 10, MS_SILENT, MZ_SMALL), MR_COLD, 0,
+        M1_FLY | M1_BREATHLESS | M1_NOLIMBS | M1_NOHEAD | M1_MINDLESS,
+        M2_NOPOLY | M2_HOSTILE | M2_NEUTER, M3_INFRAVISIBLE, CLR_BROWN),
 #endif
     /*
      * felines
@@ -878,7 +882,7 @@ NEARDATA struct permonst mons[] = {
         M2_HOSTILE | M2_NEUTER, M3_INFRAVISIBLE, CLR_CYAN),
     MON("energy vortex", S_VORTEX, LVL(6, 20, 2, 30, 0),
         (G_GENO | G_NOCORPSE | 1),
-        A(ATTK(AT_ENGL, AD_ELEC, 1, 6), ATTK(AT_ENGL, AD_DREN, 4, 6),
+        A(ATTK(AT_ENGL, AD_ELEC, 1, 6), ATTK(AT_ENGL, AD_DREN, 2, 6),
           ATTK(AT_NONE, AD_ELEC, 0, 4), NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(0, 0, MS_SILENT, MZ_HUGE),
         MR_ELEC | MR_SLEEP | MR_DISINT | MR_POISON | MR_STONE, 0,
@@ -1104,12 +1108,12 @@ NEARDATA struct permonst mons[] = {
         M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0, DRAGON_SILVER),
 #if 0 /* DEFERRED */
     MON("baby shimmering dragon", S_DRAGON,
-       LVL(12, 9, 2, 10, 0), G_GENO,
-       A(ATTK(AT_BITE, AD_PHYS, 2, 6),
-         NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-       SIZ(1500, 500, MS_ROAR, MZ_HUGE), 0, 0,
-       M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
-       M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0, CLR_CYAN),
+        LVL(12, 9, 2, 10, 0), G_GENO,
+        A(ATTK(AT_BITE, AD_PHYS, 2, 6),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+        SIZ(1500, 500, MS_ROAR, MZ_HUGE), 0, 0,
+        M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE,
+        M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0, CLR_CYAN),
 #endif
     MON("baby red dragon", S_DRAGON, LVL(12, 9, 2, 10, 0), G_GENO,
         A(ATTK(AT_BITE, AD_PHYS, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
@@ -1174,15 +1178,15 @@ NEARDATA struct permonst mons[] = {
         0, DRAGON_SILVER),
 #if 0 /* DEFERRED */
     MON("shimmering dragon", S_DRAGON,
-       LVL(15, 9, -1, 20, 4), (G_GENO | 1),
-       A(ATTK(AT_BREA, AD_MAGM, 4, 6), ATTK(AT_BITE, AD_PHYS, 3, 8),
-         ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_CLAW, AD_PHYS, 1, 4),
-         NO_ATTK, NO_ATTK),
-       SIZ(WT_DRAGON, 1500, MS_ROAR, MZ_GIGANTIC), 0, 0,
-       M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_SEE_INVIS | M1_OVIPAROUS
-         | M1_CARNIVORE,
-       M2_HOSTILE | M2_STRONG | M2_NASTY | M2_GREEDY | M2_JEWELS | M2_MAGIC,
-       0, CLR_CYAN),
+        LVL(15, 9, -1, 20, 4), (G_GENO | 1),
+        A(ATTK(AT_BREA, AD_MAGM, 4, 6), ATTK(AT_BITE, AD_PHYS, 3, 8),
+          ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_CLAW, AD_PHYS, 1, 4),
+          NO_ATTK, NO_ATTK),
+        SIZ(WT_DRAGON, 1500, MS_ROAR, MZ_GIGANTIC), 0, 0,
+        M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_SEE_INVIS | M1_OVIPAROUS
+          | M1_CARNIVORE,
+        M2_HOSTILE | M2_STRONG | M2_NASTY | M2_GREEDY | M2_JEWELS | M2_MAGIC,
+        0, CLR_CYAN),
 #endif
     MON("red dragon", S_DRAGON, LVL(15, 9, -1, 20, -4), (G_GENO | 1),
         A(ATTK(AT_BREA, AD_FIRE, 6, 6), ATTK(AT_BITE, AD_PHYS, 3, 8),
@@ -1211,8 +1215,9 @@ NEARDATA struct permonst mons[] = {
             | M1_CARNIVORE,
         M2_HOSTILE | M2_STRONG | M2_NASTY | M2_GREEDY | M2_JEWELS | M2_MAGIC,
         0, CLR_ORANGE),
+    /* disintegration breath is actually all or nothing, not 1d255 */
     MON("black dragon", S_DRAGON, LVL(15, 9, -1, 20, -6), (G_GENO | 1),
-        A(ATTK(AT_BREA, AD_DISN, 4, 10), ATTK(AT_BITE, AD_PHYS, 3, 8),
+        A(ATTK(AT_BREA, AD_DISN, 1, 255), ATTK(AT_BITE, AD_PHYS, 3, 8),
           ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_CLAW, AD_PHYS, 1, 4), NO_ATTK,
           NO_ATTK),
         SIZ(WT_DRAGON, 1500, MS_ROAR, MZ_GIGANTIC), MR_DISINT, MR_DISINT,
@@ -1465,13 +1470,13 @@ struct permonst _mons2[] = {
         CLR_ORANGE),
 #if 0 /* DEFERRED */
     MON("vorpal jabberwock", S_JABBERWOCK,
-       LVL(20, 12, -2, 50, 0), (G_GENO | 1),
-       A(ATTK(AT_BITE, AD_PHYS, 3, 10), ATTK(AT_BITE, AD_PHYS, 3, 10),
-         ATTK(AT_CLAW, AD_PHYS, 3, 10), ATTK(AT_CLAW, AD_PHYS, 3, 10),
-         NO_ATTK, NO_ATTK),
-       SIZ(1300, 600, MS_BURBLE, MZ_LARGE), 0, 0,
-       M1_ANIMAL | M1_FLY | M1_CARNIVORE,
-       M2_HOSTILE | M2_STRONG | M2_NASTY | M2_COLLECT, M3_INFRAVISIBLE,
+        LVL(20, 12, -2, 50, 0), (G_GENO | 1),
+        A(ATTK(AT_BITE, AD_PHYS, 3, 10), ATTK(AT_BITE, AD_PHYS, 3, 10),
+          ATTK(AT_CLAW, AD_PHYS, 3, 10), ATTK(AT_CLAW, AD_PHYS, 3, 10),
+          NO_ATTK, NO_ATTK),
+        SIZ(1300, 600, MS_BURBLE, MZ_LARGE), 0, 0,
+        M1_ANIMAL | M1_FLY | M1_CARNIVORE,
+        M2_HOSTILE | M2_STRONG | M2_NASTY | M2_COLLECT, M3_INFRAVISIBLE,
         HI_LORD),
 #endif
     /*
@@ -1857,18 +1862,18 @@ struct permonst _mons2[] = {
         M3_INFRAVISIBLE, CLR_BLUE),
 #if 0 /* DEFERRED */
     MON("vampire mage", S_VAMPIRE,
-       LVL(20, 14, -4, 50, -9), (G_GENO | G_NOCORPSE | 1),
-       A(ATTK(AT_CLAW, AD_DRLI, 2, 8), ATTK(AT_BITE, AD_DRLI, 1, 8),
-         ATTK(AT_MAGC, AD_SPEL, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK),
-       SIZ(WT_HUMAN, 400, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP | MR_POISON, 0,
-       M1_FLY | M1_BREATHLESS | M1_HUMANOID | M1_POIS | M1_REGEN,
-       M2_UNDEAD | M2_STALK | M2_HOSTILE | M2_STRONG | M2_NASTY | M2_LORD
+        LVL(20, 14, -4, 50, -9), (G_GENO | G_NOCORPSE | 1),
+        A(ATTK(AT_CLAW, AD_DRLI, 2, 8), ATTK(AT_BITE, AD_DRLI, 1, 8),
+          ATTK(AT_MAGC, AD_SPEL, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK),
+        SIZ(WT_HUMAN, 400, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP | MR_POISON, 0,
+        M1_FLY | M1_BREATHLESS | M1_HUMANOID | M1_POIS | M1_REGEN,
+        M2_UNDEAD | M2_STALK | M2_HOSTILE | M2_STRONG | M2_NASTY | M2_LORD
           | M2_MALE | M2_MAGIC | M2_SHAPESHIFTER,
         M3_INFRAVISIBLE, HI_ZAP),
 #endif
-    MON("Vlad the Impaler", S_VAMPIRE, LVL(14, 18, -3, 80, -10),
+    MON("Vlad the Impaler", S_VAMPIRE, LVL(28, 26, -6, 80, -10),
         (G_NOGEN | G_NOCORPSE | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 1, 10), ATTK(AT_BITE, AD_DRLI, 1, 10),
+        A(ATTK(AT_WEAP, AD_PHYS, 2, 10), ATTK(AT_BITE, AD_DRLI, 1, 12),
           NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(WT_HUMAN, 400, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP | MR_POISON, 0,
         M1_FLY | M1_BREATHLESS | M1_HUMANOID | M1_POIS | M1_REGEN,
@@ -1915,16 +1920,18 @@ struct permonst _mons2[] = {
     /*
      * Apelike beasts
      */
+    /* tameable via banana; does not grow up into ape...
+       not flagged as domestic, so no guilt penalty for eating non-pet one */
     MON("monkey", S_YETI, LVL(2, 12, 6, 0, 0), (G_GENO | 1),
         A(ATTK(AT_CLAW, AD_SITM, 0, 0), ATTK(AT_BITE, AD_PHYS, 1, 3), NO_ATTK,
           NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(100, 50, MS_GROWL, MZ_SMALL), 0, 0,
-        M1_ANIMAL | M1_HUMANOID | M1_CARNIVORE, 0, M3_INFRAVISIBLE, CLR_GRAY),
+        M1_ANIMAL | M1_HUMANOID | M1_OMNIVORE, 0, M3_INFRAVISIBLE, CLR_GRAY),
     MON("ape", S_YETI, LVL(4, 12, 6, 0, 0), (G_GENO | G_SGROUP | 2),
         A(ATTK(AT_CLAW, AD_PHYS, 1, 3), ATTK(AT_CLAW, AD_PHYS, 1, 3),
           ATTK(AT_BITE, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(1100, 500, MS_GROWL, MZ_LARGE), 0, 0,
-        M1_ANIMAL | M1_HUMANOID | M1_CARNIVORE, M2_STRONG, M3_INFRAVISIBLE,
+        M1_ANIMAL | M1_HUMANOID | M1_OMNIVORE, M2_STRONG, M3_INFRAVISIBLE,
         CLR_BROWN),
     MON("owlbear", S_YETI, LVL(5, 12, 5, 0, 0), (G_GENO | 3),
         A(ATTK(AT_CLAW, AD_PHYS, 1, 6), ATTK(AT_CLAW, AD_PHYS, 1, 6),
@@ -2355,8 +2362,8 @@ struct permonst _mons2[] = {
         M1_HUMANOID | M1_POIS | M1_SWIM,
         M2_NOPOLY | M2_DEMON | M2_STALK | M2_HOSTILE | M2_NASTY | M2_COLLECT,
         M3_INFRAVISIBLE | M3_INFRAVISION, CLR_BLUE),
-/* standard demons & devils
- */
+    /* standard demons & devils
    */
 #define SEDUCTION_ATTACKS_YES                                     \
     A(ATTK(AT_BITE, AD_SSEX, 0, 0), ATTK(AT_CLAW, AD_PHYS, 1, 3), \
       ATTK(AT_CLAW, AD_PHYS, 1, 3), NO_ATTK, NO_ATTK, NO_ATTK)
@@ -2381,8 +2388,8 @@ struct permonst _mons2[] = {
         MR_FIRE | MR_POISON, 0, M1_HUMANOID | M1_FLY | M1_POIS,
         M2_DEMON | M2_STALK | M2_HOSTILE | M2_NASTY | M2_MALE,
         M3_INFRAVISIBLE | M3_INFRAVISION, CLR_GRAY),
-    /* Used by AD&D for a type of demon, originally one of the Furies */
-    /* and spelled this way */
+    /* Used by AD&D for a type of demon, originally one of the Furies
+       and spelled this way */
     MON("erinys", S_DEMON, LVL(7, 12, 2, 30, 10),
         (G_HELL | G_NOCORPSE | G_SGROUP | 2),
         A(ATTK(AT_WEAP, AD_DRST, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
@@ -2553,7 +2560,8 @@ struct permonst _mons2[] = {
         M2_NOPOLY | M2_DEMON | M2_STALK | M2_HOSTILE | M2_PNAME | M2_NASTY
             | M2_PRINCE | M2_MALE,
         M3_WANTSAMUL | M3_INFRAVISIBLE | M3_INFRAVISION, HI_LORD),
-    /* Riders -- the Four Horsemen of the Apocalypse ("War" == player)
+    /* Riders -- the Four Horsemen of the Apocalypse ("War" == player);
+     * depicted with '&' but do not have M2_DEMON set.
      */
     MON("Death", S_DEMON, LVL(30, 12, -5, 100, 0), (G_UNIQ | G_NOGEN),
         A(ATTK(AT_TUCH, AD_DETH, 8, 8), ATTK(AT_TUCH, AD_DETH, 8, 8), NO_ATTK,
@@ -2579,8 +2587,8 @@ struct permonst _mons2[] = {
         M1_FLY | M1_HUMANOID | M1_REGEN | M1_SEE_INVIS | M1_TPORT_CNTRL,
         M2_NOPOLY | M2_STALK | M2_HOSTILE | M2_PNAME | M2_STRONG | M2_NASTY,
         M3_INFRAVISIBLE | M3_INFRAVISION | M3_DISPLACES, HI_LORD),
-/* other demons
- */
+    /* other demons
    */
 #ifdef MAIL
     MON("mail daemon", S_DEMON, LVL(56, 24, 10, 127, 0),
         (G_NOGEN | G_NOCORPSE),
@@ -2697,14 +2705,12 @@ struct permonst _mons2[] = {
 
     /*
      * dummy monster needed for visual interface
-     */
-    /* (marking it unique prevents figurines)
+     * (marking it unique prevents figurines)
      */
     MON("long worm tail", S_WORM_TAIL, LVL(0, 0, 0, 0, 0),
         (G_NOGEN | G_NOCORPSE | G_UNIQ),
         A(NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(0, 0, 0, 0), 0, 0, 0L, M2_NOPOLY, 0, CLR_BROWN),
-
     /* Note:
      * Worm tail must be between the normal monsters and the special
      * quest & pseudo-character ones because an optimization in the
@@ -2848,26 +2854,26 @@ struct permonst _mons2[] = {
             | M2_COLLECT | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, HI_LORD),
 #if 0 /* OBSOLETE */
-       /* Two for elves - one of each sex.
-        */
+    /* Two for elves - one of each sex.
+     */
     MON("Earendil", S_HUMAN,
-       LVL(20, 12, 0, 50, -20), (G_NOGEN | G_UNIQ),
-       A(ATTK(AT_WEAP, AD_PHYS, 1, 8),
-         NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-       SIZ(WT_ELF, 350, MS_LEADER, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
-       M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE,
-       M2_NOPOLY | M2_ELF | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG
+        LVL(20, 12, 0, 50, -20), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 1, 8),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+        SIZ(WT_ELF, 350, MS_LEADER, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
+        M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE,
+        M2_NOPOLY | M2_ELF | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG
           | M2_MALE | M2_COLLECT | M2_MAGIC,
-       M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, HI_LORD),
+        M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, HI_LORD),
     MON("Elwing", S_HUMAN,
-       LVL(20, 12, 0, 50, -20), (G_NOGEN | G_UNIQ),
-       A(ATTK(AT_WEAP, AD_PHYS, 1, 8),
-         NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-       SIZ(WT_ELF, 350, MS_LEADER, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
-       M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE,
-       M2_NOPOLY | M2_ELF | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG
+        LVL(20, 12, 0, 50, -20), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 1, 8),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+        SIZ(WT_ELF, 350, MS_LEADER, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
+        M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE,
+        M2_NOPOLY | M2_ELF | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG
           | M2_FEMALE | M2_COLLECT | M2_MAGIC,
-       M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, HI_LORD),
+        M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, HI_LORD),
 #endif
     MON("Hippocrates", S_HUMAN, LVL(20, 12, 0, 40, 0), (G_NOGEN | G_UNIQ),
         A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
@@ -2986,7 +2992,7 @@ struct permonst _mons2[] = {
      */
     MON("Chromatic Dragon", S_DRAGON, LVL(16, 12, 0, 30, -14),
         (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_BREA, AD_RBRE, 6, 8), ATTK(AT_MAGC, AD_SPEL, 0, 0),
+        A(ATTK(AT_BREA, AD_RBRE, 6, 6), ATTK(AT_MAGC, AD_SPEL, 0, 0),
           ATTK(AT_CLAW, AD_SAMU, 2, 8), ATTK(AT_BITE, AD_PHYS, 4, 8),
           ATTK(AT_BITE, AD_PHYS, 4, 8), ATTK(AT_STNG, AD_PHYS, 1, 6)),
         SIZ(WT_DRAGON, 1700, MS_NEMESIS, MZ_GIGANTIC),
@@ -3000,14 +3006,14 @@ struct permonst _mons2[] = {
         M3_WANTSARTI | M3_WAITFORU | M3_INFRAVISIBLE, HI_LORD),
 #if 0 /* OBSOLETE */
     MON("Goblin King", S_ORC,
-       LVL(15, 12, 10, 0, -15), (G_NOGEN | G_UNIQ),
-       A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6),
-         ATTK(AT_CLAW, AD_SAMU, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK),
-       SIZ(750, 350, MS_NEMESIS, MZ_HUMAN), 0, 0,
-       M1_HUMANOID | M1_OMNIVORE,
-       M2_NOPOLY | M2_ORC | M2_HOSTILE | M2_STRONG | M2_STALK | M2_NASTY
+        LVL(15, 12, 10, 0, -15), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6),
+          ATTK(AT_CLAW, AD_SAMU, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK),
+        SIZ(750, 350, MS_NEMESIS, MZ_HUMAN), 0, 0,
+        M1_HUMANOID | M1_OMNIVORE,
+        M2_NOPOLY | M2_ORC | M2_HOSTILE | M2_STRONG | M2_STALK | M2_NASTY
           | M2_MALE | M2_GREEDY | M2_JEWELS | M2_COLLECT | M2_MAGIC,
-       M3_WANTSARTI | M3_WAITFORU | M3_INFRAVISION | M3_INFRAVISIBLE,
+        M3_WANTSARTI | M3_WAITFORU | M3_INFRAVISION | M3_INFRAVISIBLE,
         HI_LORD),
 #endif
     MON("Cyclops", S_GIANT, LVL(18, 12, 0, 0, -15), (G_NOGEN | G_UNIQ),
@@ -3126,13 +3132,13 @@ struct permonst _mons2[] = {
         M3_INFRAVISIBLE, HI_DOMESTIC),
 #if 0 /* OBSOLETE */
     MON("High-elf", S_HUMAN,
-       LVL(5, 12, 10, 10, -7), G_NOGEN,
-       A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_MAGC, AD_CLRC, 0, 0),
-         NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-       SIZ(WT_ELF, 350, MS_GUARDIAN, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
-       M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE,
-       M2_NOPOLY | M2_ELF | M2_PEACEFUL | M2_COLLECT,
-       M3_INFRAVISION | M3_INFRAVISIBLE, HI_DOMESTIC),
+        LVL(5, 12, 10, 10, -7), G_NOGEN,
+        A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_MAGC, AD_CLRC, 0, 0),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+        SIZ(WT_ELF, 350, MS_GUARDIAN, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
+        M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE,
+        M2_NOPOLY | M2_ELF | M2_PEACEFUL | M2_COLLECT,
+        M3_INFRAVISION | M3_INFRAVISIBLE, HI_DOMESTIC),
 #endif
     MON("attendant", S_HUMAN, LVL(5, 12, 10, 10, 3), G_NOGEN,
         A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
@@ -3230,7 +3236,6 @@ monst_init()
 
 struct attack sa_yes[NATTK] = SEDUCTION_ATTACKS_YES;
 struct attack sa_no[NATTK] = SEDUCTION_ATTACKS_NO;
-
 #endif
 
 /*monst.c*/
index fbe996b..1dd89eb 100644 (file)
@@ -1,5 +1,5 @@
-/* NetHack 3.6 mplayer.c       $NHDT-Date: 1432512774 2015/05/25 00:12:54 $  $NHDT-Branch: master $:$NHDT-Revision: 1.19 $ */
-/*     Copyright (c) Izchak Miller, 1992.                        */
+/* NetHack 3.6 mplayer.c       $NHDT-Date: 1458949461 2016/03/25 23:44:21 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */
+/*      Copyright (c) Izchak Miller, 1992.                        */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
@@ -16,9 +16,10 @@ STATIC_DCL void FDECL(mk_mplayer_armor, (struct monst *, SHORT_P));
  */
 static const char *developers[] = {
     /* devteam */
-    "Dave",    "Dean",   "Eric",    "Izchak", "Janet",    "Jessie",
-    "Ken",     "Kevin",  "Michael", "Mike",   "Pat",      "Paul",
-    "Steve",   "Timo",   "Warwick",
+    "Alex",    "Dave",   "Dean",    "Derek",   "Eric",    "Izchak",
+    "Janet",   "Jessie", "Ken",     "Kevin",   "Michael", "Mike",
+    "Pasi",    "Pat",    "Patric",  "Paul",    "Sean",    "Steve",
+    "Timo",    "Warwick",
     /* PC team */
     "Bill",    "Eric",   "Keizo",   "Ken",    "Kevin",    "Michael",
     "Mike",    "Paul",   "Stephen", "Steve",  "Timo",     "Yitzhak",
@@ -145,23 +146,13 @@ register boolean special;
         special = FALSE;
 
     if ((mtmp = makemon(ptr, x, y, NO_MM_FLAGS)) != 0) {
-        short weapon = rn2(2) ? LONG_SWORD : rnd_class(SPEAR, BULLWHIP);
-        short armor =
-            rnd_class(GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL);
-        short cloak = !rn2(8)
-                          ? STRANGE_OBJECT
-                          : rnd_class(OILSKIN_CLOAK, CLOAK_OF_DISPLACEMENT);
-        short helm = !rn2(8) ? STRANGE_OBJECT : rnd_class(ELVEN_LEATHER_HELM,
-                                                          HELM_OF_TELEPATHY);
-        short shield = !rn2(8)
-                           ? STRANGE_OBJECT
-                           : rnd_class(ELVEN_SHIELD, SHIELD_OF_REFLECTION);
+        short weapon, armor, cloak, helm, shield;
         int quan;
         struct obj *otmp;
 
         mtmp->m_lev = (special ? rn1(16, 15) : rnd(16));
-        mtmp->mhp = mtmp->mhpmax =
-            d((int) mtmp->m_lev, 10) + (special ? (30 + rnd(30)) : 30);
+        mtmp->mhp = mtmp->mhpmax = d((int) mtmp->m_lev, 10)
+                                   + (special ? (30 + rnd(30)) : 30);
         if (special) {
             get_mplname(mtmp, nam);
             mtmp = christen_monst(mtmp, nam);
@@ -171,6 +162,16 @@ register boolean special;
         mtmp->mpeaceful = 0;
         set_malign(mtmp); /* peaceful may have changed again */
 
+        /* default equipment; much of it will be overridden below */
+        weapon = !rn2(2) ? LONG_SWORD : rnd_class(SPEAR, BULLWHIP);
+        armor  = rnd_class(GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL);
+        cloak  = !rn2(8) ? STRANGE_OBJECT
+                         : rnd_class(OILSKIN_CLOAK, CLOAK_OF_DISPLACEMENT);
+        helm   = !rn2(8) ? STRANGE_OBJECT
+                         : rnd_class(ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY);
+        shield = !rn2(8) ? STRANGE_OBJECT
+                         : rnd_class(ELVEN_SHIELD, SHIELD_OF_REFLECTION);
+
         switch (monsndx(ptr)) {
         case PM_ARCHEOLOGIST:
             if (rn2(2))
@@ -295,19 +296,21 @@ register boolean special;
             mk_mplayer_armor(mtmp, cloak);
             mk_mplayer_armor(mtmp, helm);
             mk_mplayer_armor(mtmp, shield);
+            if (weapon == WAR_HAMMER) /* valkyrie: wimpy weapon or Mjollnir */
+                mk_mplayer_armor(mtmp, GAUNTLETS_OF_POWER);
+            else if (rn2(8))
+                mk_mplayer_armor(mtmp, rnd_class(LEATHER_GLOVES,
+                                                 GAUNTLETS_OF_DEXTERITY));
             if (rn2(8))
-                mk_mplayer_armor(
-                    mtmp, rnd_class(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY));
-            if (rn2(8))
-                mk_mplayer_armor(mtmp,
-                                 rnd_class(LOW_BOOTS, LEVITATION_BOOTS));
+                mk_mplayer_armor(mtmp, rnd_class(LOW_BOOTS,
+                                                 LEVITATION_BOOTS));
             m_dowear(mtmp, TRUE);
 
             quan = rn2(3) ? rn2(3) : rn2(16);
             while (quan--)
                 (void) mongets(mtmp, rnd_class(DILITHIUM_CRYSTAL, JADE));
-            /* To get the gold "right" would mean a player can double his */
-            /* gold supply by killing one mplayer.  Not good. */
+            /* To get the gold "right" would mean a player can double his
+               gold supply by killing one mplayer.  Not good. */
             mkmonmoney(mtmp, rn2(1000));
             quan = rn2(10);
             while (quan--)
@@ -342,12 +345,13 @@ boolean special;
     int pm, x, y;
     struct monst fakemon;
 
+    fakemon = zeromonst;
     while (num) {
         int tryct = 0;
 
         /* roll for character class */
-        pm = PM_ARCHEOLOGIST + rn2(PM_WIZARD - PM_ARCHEOLOGIST + 1);
-        fakemon.data = &mons[pm];
+        pm = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1, PM_ARCHEOLOGIST);
+        set_mon_data(&fakemon, &mons[pm], -1);
 
         /* roll for an available location */
         do {
@@ -368,18 +372,15 @@ void
 mplayer_talk(mtmp)
 register struct monst *mtmp;
 {
+    static const char
 #if 0 /*JP*/
-    static const char *same_class_msg[3] =
-        {
-          "I can't win, and neither will you!", "You don't deserve to win!",
-          "Mine should be the honor, not yours!",
+        *same_class_msg[3] = {
+            "I can't win, and neither will you!",
+            "You don't deserve to win!",
+            "Mine should be the honor, not yours!",
         },
-                      *other_class_msg[3] = {
-                          "The low-life wants to talk, eh?", "Fight, scum!",
-                          "Here is what I have to say!",
-                      };
-#else
-    static const char *same_class_msg[2][3] = {
+#else /* \93ú\96{\8cê\82Å\82Í\92j\8f\97\82Å\91ä\8e\8c\82ð\95Ï\82¦\82½\95û\82ª\8e©\91R */
+        *same_class_msg[2][3] = {
         {
             "\8e\84\82Å\82·\82ç\92B\90¬\82Å\82«\82È\82¢\82Ì\82É\81C\82¨\91O\82É\92B\90¬\82Å\82«\82é\82Ì\82©\81H",
             "\82¨\91O\82ª\90¬\8c÷\82·\82é\82È\82ñ\82Ä\82±\82Æ\82Í\82È\82¢\82È\81D",
@@ -390,8 +391,16 @@ register struct monst *mtmp;
             "\82 \82È\82½\82ª\90¬\8c÷\82·\82é\82È\82ñ\82Ä\82 \82è\82¦\82Ü\82¹\82ñ\82í\81D",
             "\96¼\97_\82Í\8e\84\82É\81I\82 \82È\82½\82É\82È\82ñ\82Ä\82Æ\82ñ\82Å\82à\82È\82¢\81D",
         }
-    },
-    *other_class_msg[2][3] = {
+        },
+#endif
+#if 0 /*JP*/
+        *other_class_msg[3] = {
+            "The low-life wants to talk, eh?",
+            "Fight, scum!",
+            "Here is what I have to say!",
+        };
+#else
+        *other_class_msg[2][3] = {
         {
             "\89º\8fO\82ª\98b\82µ\82©\82¯\82é\82©\81H\82Í\82Í\81[\82ñ\81H",
             "\90í\82¦\81I\82±\82Ì\96ì\98Y\81I",
@@ -402,7 +411,9 @@ register struct monst *mtmp;
             "\8c\95\82ð\8eæ\82è\82È\82³\82¢\81I",
             "\82 \82È\82½\82Æ\98b\82·\82±\82Æ\82È\82Ç\82 \82è\82Ü\82¹\82ñ\82í\81I",
         }
-    };
+        };
+#endif
+#if 1 /*JP*/
     int female;
 #endif
 
index 34d69df..64fad35 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 mthrowu.c       $NHDT-Date: 1446887531 2015/11/07 09:12:11 $  $NHDT-Branch: master $:$NHDT-Revision: 1.63 $ */
+/* NetHack 3.6 mthrowu.c       $NHDT-Date: 1514152830 2017/12/24 22:00:30 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.73 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2016. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 
 #include "hack.h"
 
+STATIC_DCL int FDECL(monmulti, (struct monst *, struct obj *, struct obj *));
+STATIC_DCL void FDECL(monshoot, (struct monst *, struct obj *, struct obj *));
 STATIC_DCL int FDECL(drop_throw, (struct obj *, BOOLEAN_P, int, int));
+STATIC_DCL boolean FDECL(m_lined_up, (struct monst *, struct monst *));
 
 #define URETREATING(x, y) \
     (distmin(u.ux, u.uy, x, y) > distmin(u.ux0, u.uy0, x, y))
 
 #define POLE_LIM 5 /* How far monsters can use pole-weapons */
 
+#define PET_MISSILE_RANGE2 36 /* Square of distance within which pets shoot */
+
 /*
  * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h.
  */
@@ -32,52 +38,59 @@ STATIC_OVL NEARDATA const char *breathwep[] = {
 };
 
 extern boolean notonhead; /* for long worms */
+STATIC_VAR int mesg_given; /* for m_throw()/thitu() 'miss' message */
 
 /* hero is hit by something other than a monster */
 int
-thitu(tlev, dam, obj, name)
+thitu(tlev, dam, objp, name)
 int tlev, dam;
-struct obj *obj;
-const char *name; /* if null, then format `obj' */
+struct obj **objp;
+const char *name; /* if null, then format `*objp' */
 {
+    struct obj *obj = objp ? *objp : 0;
     const char *onm, *knm;
     boolean is_acid;
-    int kprefix = KILLED_BY_AN;
+    int kprefix = KILLED_BY_AN, dieroll;
     char onmbuf[BUFSZ], knmbuf[BUFSZ];
 
     if (!name) {
         if (!obj)
             panic("thitu: name & obj both null?");
-        name =
-            strcpy(onmbuf, (obj->quan > 1L) ? doname(obj) : mshot_xname(obj));
+        name = strcpy(onmbuf,
+                      (obj->quan > 1L) ? doname(obj) : mshot_xname(obj));
         knm = strcpy(knmbuf, killer_xname(obj));
         kprefix = KILLED_BY; /* killer_name supplies "an" if warranted */
     } else {
-#if 0 /*JP*/
         knm = name;
+#if 0 /*JP*/
         /* [perhaps ought to check for plural here to] */
         if (!strncmpi(name, "the ", 4) || !strncmpi(name, "an ", 3)
             || !strncmpi(name, "a ", 2))
             kprefix = KILLED_BY;
-#else
+#else /* \93ú\96{\8cê\82Å\82Í\82»\82Ì\82Ü\82Ü */
         knm = strcpy(knmbuf, name);
 #endif
     }
 #if 1 /*JP*/
     strcat(knmbuf, "\82É\93\96\82½\82Á\82Ä");
 #endif
-    onm = (obj && obj_is_pname(obj)) ? the(name) : (obj && obj->quan > 1L)
-                                                       ? name
-                                                       : an(name);
+    onm = (obj && obj_is_pname(obj)) ? the(name)
+          : (obj && obj->quan > 1L) ? name
+            : an(name);
     is_acid = (obj && obj->otyp == ACID_VENOM);
 
-    if (u.uac + tlev <= rnd(20)) {
-        if (Blind || !flags.verbose)
+    if (u.uac + tlev <= (dieroll = rnd(20))) {
+        ++mesg_given;
+        if (Blind || !flags.verbose) {
 /*JP
             pline("It misses.");
 */
             pline("\82»\82ê\82Í\82Í\82¸\82ê\82½\81D");
-        else
+        } else if (u.uac + tlev <= dieroll - 2) {
+            if (onm != onmbuf)
+                Strcpy(onmbuf, onm); /* [modifiable buffer for upstart()] */
+            pline("%s %s you.", upstart(onmbuf), vtense(onmbuf, "miss"));
+        } else
 /*JP
             You("are almost hit by %s.", onm);
 */
@@ -95,20 +108,26 @@ const char *name; /* if null, then format `obj' */
 */
             pline("%s\82ª\82 \82È\82½\82É\96½\92\86\82µ\82½\81I", onm);
 
-        if (obj && objects[obj->otyp].oc_material == SILVER && Hate_silver) {
-            /* extra damage already applied by dmgval() */
-/*JP
-            pline_The("silver sears your flesh!");
-*/
-            pline("\82 \82È\82½\82Ì\91Ì\82Í\8bâ\82Å\8fÄ\82©\82ê\82½\81I");
-            exercise(A_CON, FALSE);
-        }
-        if (is_acid && Acid_resistance)
+        if (is_acid && Acid_resistance) {
 /*JP
             pline("It doesn't seem to hurt you.");
 */
             pline("\82 \82È\82½\82Í\8f\9d\82Â\82©\82È\82©\82Á\82½\81D");
-        else {
+        } else if (obj && obj->oclass == POTION_CLASS) {
+            /* an explosion which scatters objects might hit hero with one
+               (potions deliberately thrown at hero are handled by m_throw) */
+            potionhit(&youmonst, obj, POTHIT_OTHER_THROW);
+            *objp = obj = 0; /* potionhit() uses up the potion */
+        } else {
+            if (obj && objects[obj->otyp].oc_material == SILVER
+                && Hate_silver) {
+                /* extra damage already applied by dmgval() */
+/*JP
+            pline_The("silver sears your flesh!");
+*/
+            pline("\82 \82È\82½\82Ì\91Ì\82Í\8bâ\82Å\8fÄ\82©\82ê\82½\81I");
+                exercise(A_CON, FALSE);
+            }
             if (is_acid)
 /*JP
                 pline("It burns!");
@@ -144,20 +163,18 @@ int x, y;
     else
         create = 1;
 
-    if (create
-        && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) && (t = t_at(x, y))
-             && ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT)))) {
+    if (create && !((mtmp = m_at(x, y)) != 0 && mtmp->mtrapped
+                    && (t = t_at(x, y)) != 0
+                    && (t->ttyp == PIT || t->ttyp == SPIKED_PIT))) {
         int objgone = 0;
 
         if (down_gate(x, y) != -1)
             objgone = ship_object(obj, x, y, FALSE);
         if (!objgone) {
-#if 0 /*JP*/
-            if (!flooreffects(obj, x, y,
-                              "fall")) { /* don't double-dip on damage */
+#if 0 /*JP:T*/
+            if (!flooreffects(obj, x, y, "fall")) {
 #else
-            if (!flooreffects(obj, x, y,
-                              "\97\8e\82¿\82é")) { /* don't double-dip on damage */
+            if (!flooreffects(obj, x, y, "\97\8e\82¿\82é")) {
 #endif
                 place_object(obj, x, y);
                 if (!mtmp && x == u.ux && y == u.uy)
@@ -173,6 +190,165 @@ int x, y;
     return retvalu;
 }
 
+/* The monster that's being shot at when one monster shoots at another */
+STATIC_OVL struct monst *target = 0;
+/* The monster that's doing the shooting/throwing */
+STATIC_OVL struct monst *archer = 0;
+
+/* calculate multishot volley count for mtmp throwing otmp (if not ammo) or
+   shooting otmp with mwep (if otmp is ammo and mwep appropriate launcher) */
+STATIC_OVL int
+monmulti(mtmp, otmp, mwep)
+struct monst *mtmp;
+struct obj *otmp, *mwep;
+{
+    int skill = (int) objects[otmp->otyp].oc_skill;
+    int multishot = 1;
+
+    if (otmp->quan > 1L /* no point checking if there's only 1 */
+        /* ammo requires corresponding launcher be wielded */
+        && (is_ammo(otmp)
+               ? matching_launcher(otmp, mwep)
+               /* otherwise any stackable (non-ammo) weapon */
+               : otmp->oclass == WEAPON_CLASS)
+        && !mtmp->mconf) {
+        /* Assumes lords are skilled, princes are expert */
+        if (is_prince(mtmp->data))
+            multishot += 2;
+        else if (is_lord(mtmp->data))
+            multishot++;
+        /* fake players treated as skilled (regardless of role limits) */
+        else if (is_mplayer(mtmp->data))
+            multishot++;
+
+        /* this portion is different from hero multishot; from slash'em?
+         */
+        /* Elven Craftsmanship makes for light, quick bows */
+        if (otmp->otyp == ELVEN_ARROW && !otmp->cursed)
+            multishot++;
+        if (ammo_and_launcher(otmp, uwep) && mwep->otyp == ELVEN_BOW
+            && !mwep->cursed)
+            multishot++;
+        /* 1/3 of launcher enchantment */
+        if (ammo_and_launcher(otmp, mwep) && mwep->spe > 1)
+            multishot += (long) rounddiv(mwep->spe, 3);
+        /* Some randomness */
+        multishot = (long) rnd((int) multishot);
+
+        /* class bonus */
+        switch (monsndx(mtmp->data)) {
+        case PM_CAVEMAN: /* give bonus for low-tech gear */
+            if (skill == -P_SLING || skill == P_SPEAR)
+                multishot++;
+            break;
+        case PM_MONK: /* allow higher volley count */
+            if (skill == -P_SHURIKEN)
+                multishot++;
+            break;
+        case PM_RANGER:
+            if (skill != P_DAGGER)
+                multishot++;
+            break;
+        case PM_ROGUE:
+            if (skill == P_DAGGER)
+                multishot++;
+            break;
+        case PM_NINJA:
+            if (skill == -P_SHURIKEN || skill == -P_DART)
+                multishot++;
+            /*FALLTHRU*/
+        case PM_SAMURAI:
+            if (otmp->otyp == YA && mwep->otyp == YUMI)
+                multishot++;
+            break;
+        default:
+            break;
+        }
+        /* racial bonus */
+        if ((is_elf(mtmp->data) && otmp->otyp == ELVEN_ARROW
+            && mwep->otyp == ELVEN_BOW)
+            || (is_orc(mtmp->data) && otmp->otyp == ORCISH_ARROW
+                && mwep->otyp == ORCISH_BOW)
+            || (is_gnome(mtmp->data) && otmp->otyp == CROSSBOW_BOLT
+                && mwep->otyp == CROSSBOW))
+            multishot++;
+    }
+
+    if (otmp->quan < multishot)
+        multishot = (int) otmp->quan;
+    if (multishot < 1)
+        multishot = 1;
+    return multishot;
+}
+
+/* mtmp throws otmp, or shoots otmp with mwep, at hero or at monster mtarg */
+STATIC_OVL void
+monshoot(mtmp, otmp, mwep)
+struct monst *mtmp;
+struct obj *otmp, *mwep;
+{
+    struct monst *mtarg = target;
+    int dm = distmin(mtmp->mx, mtmp->my,
+                     mtarg ? mtarg->mx : mtmp->mux,
+                     mtarg ? mtarg->my : mtmp->muy),
+        multishot = monmulti(mtmp, otmp, mwep);
+        /*
+         * Caller must have called linedup() to set up tbx, tby.
+         */
+
+    if (canseemon(mtmp)) {
+        const char *onm;
+        char onmbuf[BUFSZ], trgbuf[BUFSZ];
+
+        if (multishot > 1) {
+            /* "N arrows"; multishot > 1 implies otmp->quan > 1, so
+               xname()'s result will already be pluralized */
+/*JP
+            Sprintf(onmbuf, "%d %s", multishot, xname(otmp));
+*/
+            Sprintf(onmbuf, "%d%s\82Ì%s", multishot, numeral(otmp), xname(otmp));
+            onm = onmbuf;
+        } else {
+            /* "an arrow" */
+            onm = singular(otmp, xname);
+            onm = obj_is_pname(otmp) ? the(onm) : an(onm);
+        }
+        m_shot.s = ammo_and_launcher(otmp, mwep) ? TRUE : FALSE;
+        Strcpy(trgbuf, mtarg ? mon_nam(mtarg) : "");
+        if (!strcmp(trgbuf, "it"))
+            Strcpy(trgbuf, humanoid(mtmp->data) ? "someone" : something);
+#if 0 /*JP*/
+        pline("%s %s %s%s%s!", Monnam(mtmp),
+              m_shot.s ? "shoots" : "throws", onm,
+              mtarg ? " at " : "", trgbuf);
+#else
+        pline("%s\82Í%s\82ð%s\82É%s\81I", Monnam(mtmp),
+              onm,
+              trgbuf,
+              m_shot.s ? "\8c\82\82Á\82½" : "\93\8a\82°\82½");
+#endif
+        m_shot.o = otmp->otyp;
+    } else {
+        m_shot.o = STRANGE_OBJECT; /* don't give multishot feedback */
+    }
+    m_shot.n = multishot;
+    for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) {
+        m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), dm, otmp);
+        /* conceptually all N missiles are in flight at once, but
+           if mtmp gets killed (shot kills adjacent gas spore and
+           triggers explosion, perhaps), inventory will be dropped
+           and otmp might go away via merging into another stack */
+        if (mtmp->mhp <= 0 && m_shot.i < m_shot.n)
+            /* cancel pending shots (perhaps ought to give a message here
+               since we gave one above about throwing/shooting N missiles) */
+            break; /* endmultishot(FALSE); */
+    }
+    /* reset 'm_shot' */
+    m_shot.n = m_shot.i = 0;
+    m_shot.o = STRANGE_OBJECT;
+    m_shot.s = FALSE;
+}
+
 /* an object launched by someone/thing other than player attacks a monster;
    return 1 if the object has stopped moving (hit or its range used up) */
 int
@@ -187,17 +363,27 @@ boolean verbose;    /* give message(s) even when you can't see what happened */
     int damage, tmp;
     boolean vis, ismimic;
     int objgone = 1;
+    struct obj *mon_launcher = archer ? MON_WEP(archer) : NULL;
 
     notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
     ismimic = mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER;
     vis = cansee(bhitpos.x, bhitpos.y);
 
     tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE);
+    /* High level monsters will be more likely to hit */
+    /* This check applies only if this monster is the target
+     * the archer was aiming at. */
+    if (archer && target == mtmp) {
+        if (archer->m_lev > 5)
+            tmp += archer->m_lev - 5;
+        if (mon_launcher && mon_launcher->oartifact)
+            tmp += spec_abon(mon_launcher, mtmp);
+    }
     if (tmp < rnd(20)) {
         if (!ismimic) {
             if (vis)
                 miss(distant_name(otmp, mshot_xname), mtmp);
-            else if (verbose)
+            else if (verbose && !target)
 /*JP
                 pline("It is missed.");
 */
@@ -213,7 +399,9 @@ boolean verbose;    /* give message(s) even when you can't see what happened */
         mtmp->msleeping = 0;
         if (vis)
             otmp->dknown = 1;
-        potionhit(mtmp, otmp, FALSE);
+        /* probably thrown by a monster rather than 'other', but the
+           distinction only matters when hitting the hero */
+        potionhit(mtmp, otmp, POTHIT_OTHER_THROW);
         return 1;
     } else {
         damage = dmgval(otmp, mtmp);
@@ -222,13 +410,20 @@ boolean verbose;    /* give message(s) even when you can't see what happened */
         if (ismimic)
             seemimic(mtmp);
         mtmp->msleeping = 0;
-        if (vis)
-            hit(distant_name(otmp, mshot_xname), mtmp, exclam(damage));
-        else if (verbose)
-/*JP
-            pline("%s is hit%s", Monnam(mtmp), exclam(damage));
-*/
-            pline("%s\82É\96½\92\86\82µ\82½%s", Monnam(mtmp), exclam(damage));
+        if (vis) {
+            if (otmp->otyp == EGG)
+                pline("Splat! %s is hit with %s egg!", Monnam(mtmp),
+                      otmp->known ? an(mons[otmp->corpsenm].mname) : "an");
+            else
+                hit(distant_name(otmp, mshot_xname), mtmp, exclam(damage));
+        } else if (verbose && !target)
+#if 0 /*JP:T*/
+            pline("%s%s is hit%s", (otmp->otyp == EGG) ? "Splat! " : "",
+                  Monnam(mtmp), exclam(damage));
+#else
+            pline("%s%s\82É\96½\92\86\82µ\82½%s", (otmp->otyp == EGG) ? "\83r\83`\83\83\83b\81I" : "",
+                  Monnam(mtmp), exclam(damage));
+#endif
 
         if (otmp->opoisoned && is_poisonable(otmp)) {
             if (resists_poison(mtmp)) {
@@ -257,8 +452,8 @@ boolean verbose;    /* give message(s) even when you can't see what happened */
 /*JP
                 pline_The("silver sears %s flesh!", s_suffix(mon_nam(mtmp)));
 */
-                pline("%s\82Ì\91Ì\82Í\8bâ\82Å\8fÄ\82©\82ê\82½\81I", s_suffix(mon_nam(mtmp)));
-            else if (verbose)
+                pline("%s\82Ì\91Ì\82Í\8bâ\82Å\8fÄ\82©\82ê\82½\81I", mon_nam(mtmp));
+            else if (verbose && !target)
 /*JP
                 pline("Its flesh is seared!");
 */
@@ -266,53 +461,60 @@ boolean verbose;    /* give message(s) even when you can't see what happened */
         }
         if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx, mtmp->my)) {
             if (resists_acid(mtmp)) {
-                if (vis || verbose)
+                if (vis || (verbose && !target))
 /*JP
                     pline("%s is unaffected.", Monnam(mtmp));
 */
                     pline("%s\82Í\89e\8b¿\82ð\8eó\82¯\82È\82¢\81D", Monnam(mtmp));
-                damage = 0;
             } else {
                 if (vis)
 /*JP
-                    pline_The("acid burns %s!", mon_nam(mtmp));
+                    pline_The("%s burns %s!", hliquid("acid"), mon_nam(mtmp));
 */
-                    pline("%s\82Í\8e_\82Å\8fÄ\82©\82ê\82½\81I", mon_nam(mtmp));
-                else if (verbose)
+                    pline_The("%s\82Í%s\82Å\8fÄ\82©\82ê\82½\81I", mon_nam(mtmp), hliquid("\8e_"));
+                else if (verbose && !target)
 /*JP
                     pline("It is burned!");
 */
                     pline("\89½\82©\82Í\8fÄ\82©\82ê\82½\81I");
             }
         }
-        mtmp->mhp -= damage;
-        if (mtmp->mhp < 1) {
-            if (vis || verbose)
-#if 0 /*JP*/
-                pline("%s is %s!", Monnam(mtmp),
-                      (nonliving(mtmp->data) || is_vampshifter(mtmp)
-                       || !canspotmon(mtmp))
-                          ? "destroyed"
-                          : "killed");
+        if (otmp->otyp == EGG && touch_petrifies(&mons[otmp->corpsenm])) {
+            if (!munstone(mtmp, TRUE))
+                minstapetrify(mtmp, TRUE);
+            if (resists_ston(mtmp))
+                damage = 0;
+        }
+
+        if (mtmp->mhp > 0) { /* might already be dead (if petrified) */
+            mtmp->mhp -= damage;
+            if (mtmp->mhp < 1) {
+                if (vis || (verbose && !target))
+#if 0 /*JP:T*/
+                    pline("%s is %s!", Monnam(mtmp),
+                          (nonliving(mtmp->data) || is_vampshifter(mtmp)
+                           || !canspotmon(mtmp)) ? "destroyed" : "killed");
 #else
-                pline("%s\82Í%s\81I", Monnam(mtmp),
-                      (nonliving(mtmp->data) || is_vampshifter(mtmp)
-                       || !canspotmon(mtmp))
-                          ? "\93|\82³\82ê\82½"
-                          : "\8e\80\82ñ\82¾");
+                    pline("%s\82Í%s\81I", Monnam(mtmp),
+                          (nonliving(mtmp->data) || is_vampshifter(mtmp)
+                           || !canspotmon(mtmp)) ? "\93|\82³\82ê\82½" : "\8e\80\82ñ\82¾");
 #endif
-            /* don't blame hero for unknown rolling boulder trap */
-            if (!context.mon_moving
-                && (otmp->otyp != BOULDER || range >= 0 || otmp->otrapped))
-                xkilled(mtmp, 0);
-            else
-                mondied(mtmp);
+                /* don't blame hero for unknown rolling boulder trap */
+                if (!context.mon_moving && (otmp->otyp != BOULDER
+                                            || range >= 0 || otmp->otrapped))
+                    xkilled(mtmp, XKILL_NOMSG);
+                else
+                    mondied(mtmp);
+            }
         }
 
-        if (can_blnd((struct monst *) 0, mtmp,
-                     (uchar) (otmp->otyp == BLINDING_VENOM ? AT_SPIT
-                                                           : AT_WEAP),
-                     otmp)) {
+        /* blinding venom and cream pie do 0 damage, but verify
+           that the target is still alive anyway */
+        if (mtmp->mhp > 0
+            && can_blnd((struct monst *) 0, mtmp,
+                        (uchar) ((otmp->otyp == BLINDING_VENOM) ? AT_SPIT
+                                                                : AT_WEAP),
+                        otmp)) {
             if (vis && mtmp->mcansee)
 /*JP
                 pline("%s is blinded by %s.", Monnam(mtmp), the(xname(otmp)));
@@ -335,6 +537,24 @@ boolean verbose;    /* give message(s) even when you can't see what happened */
     return 0;
 }
 
+#define MT_FLIGHTCHECK(pre)                                             \
+    (/* missile hits edge of screen */                                  \
+     !isok(bhitpos.x + dx, bhitpos.y + dy)                              \
+     /* missile hits the wall */                                        \
+     || IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ)               \
+     /* missile hit closed door */                                      \
+     || closed_door(bhitpos.x + dx, bhitpos.y + dy)                     \
+     /* missile might hit iron bars */                                  \
+     /* the random chance for small objects hitting bars is */          \
+     /* skipped when reaching them at point blank range */              \
+     || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS           \
+         && hits_bars(&singleobj,                                       \
+                      bhitpos.x, bhitpos.y,                             \
+                      bhitpos.x + dx, bhitpos.y + dy,                   \
+                      ((pre) ? 0 : !rn2(5)), 0))                        \
+     /* Thrown objects "sink" */                                        \
+     || (!(pre) && IS_SINK(levl[bhitpos.x][bhitpos.y].typ)))
+
 void
 m_throw(mon, x, y, dx, dy, range, obj)
 struct monst *mon;       /* launching monster */
@@ -344,7 +564,7 @@ struct obj *obj;         /* missile (or stack providing it) */
     struct monst *mtmp;
     struct obj *singleobj;
     char sym = obj->oclass;
-    int hitu, oldumort, blindinc = 0;
+    int hitu = 0, oldumort, blindinc = 0;
 
     bhitpos.x = x;
     bhitpos.y = y;
@@ -400,18 +620,11 @@ struct obj *obj;         /* missile (or stack providing it) */
         }
     }
 
-    /* pre-check for doors, walls and boundaries.
-       Also need to pre-check for bars regardless of direction;
-       the random chance for small objects hitting bars is
-       skipped when reaching them at point blank range */
-    if (!isok(bhitpos.x + dx, bhitpos.y + dy)
-        || IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ)
-        || closed_door(bhitpos.x + dx, bhitpos.y + dy)
-        || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS
-            && hits_bars(&singleobj, bhitpos.x, bhitpos.y, 0, 0))) {
+    if (MT_FLIGHTCHECK(TRUE)) {
         (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
         return;
     }
+    mesg_given = 0; /* a 'missile misses' message has not yet been shown */
 
     /* Note: drop_throw may destroy singleobj.  Since obj must be destroyed
      * early to avoid the dagger bug, anyone who modifies this code should
@@ -437,11 +650,13 @@ struct obj *obj;         /* missile (or stack providing it) */
                     You("catch the %s.", xname(singleobj));
 */
                     You("%s\82ð\82Â\82©\82Ü\82¦\82½\81D", xname(singleobj));
-/*JP
+#if 0 /*JP*/
                     You("are not interested in %s junk.",
-*/
-                    You("%s\82Ì\83K\83\89\83N\83^\82É\8b»\96¡\82Í\82È\82¢\81D",
                         s_suffix(mon_nam(mon)));
+#else
+                    You("%s\82Ì\83K\83\89\83N\83^\82É\8b»\96¡\82Í\82È\82¢\81D",
+                        mon_nam(mon));
+#endif
                     makeknown(singleobj->otyp);
                     dropy(singleobj);
                 } else {
@@ -452,13 +667,15 @@ struct obj *obj;         /* missile (or stack providing it) */
                      "\82±\82ê\82ª\97~\82µ\82©\82Á\82½\82ñ\82¾\82Æ\8ev\82¢\82È\82ª\82ç%s\82Ì\91¡\82è\95¨\82ð\8eó\82¯\82Æ\82Á\82½\81D",
                         s_suffix(mon_nam(mon)));
 #if 0 /*JP*/
-                    (void) hold_another_object(
-                        singleobj, "You catch, but drop, %s.",
-                        xname(singleobj), "You catch:");
+                    (void) hold_another_object(singleobj,
+                                               "You catch, but drop, %s.",
+                                               xname(singleobj),
+                                               "You catch:");
 #else
-                    (void) hold_another_object(
-                        singleobj, "\82 \82È\82½\82Í%s\82ð\82Â\82©\82Ü\82¦\82½\82ª\81C\97\8e\82µ\82½\81D",
-                        xname(singleobj), "\82ð\82Â\82©\82Ü\82¦\82½\81D");
+                    (void) hold_another_object(singleobj,
+                                     "\82 \82È\82½\82Í%s\82ð\82Â\82©\82Ü\82¦\82½\82ª\81C\97\8e\82µ\82½\81D",
+                                               xname(singleobj),
+                                               "\82ð\82Â\82©\82Ü\82¦\82½\81D");
 #endif
                 }
                 break;
@@ -466,7 +683,7 @@ struct obj *obj;         /* missile (or stack providing it) */
             if (singleobj->oclass == POTION_CLASS) {
                 if (!Blind)
                     singleobj->dknown = 1;
-                potionhit(&youmonst, singleobj, FALSE);
+                potionhit(&youmonst, singleobj, POTHIT_MONST_THROW);
                 break;
             }
             oldumort = u.umortality;
@@ -482,7 +699,7 @@ struct obj *obj;         /* missile (or stack providing it) */
             /* fall through */
             case CREAM_PIE:
             case BLINDING_VENOM:
-                hitu = thitu(8, 0, singleobj, (char *) 0);
+                hitu = thitu(8, 0, &singleobj, (char *) 0);
                 break;
             default:
                 dam = dmgval(singleobj, &youmonst);
@@ -502,7 +719,7 @@ struct obj *obj;         /* missile (or stack providing it) */
                 hitv += 8 + singleobj->spe;
                 if (dam < 1)
                     dam = 1;
-                hitu = thitu(hitv, dam, singleobj, (char *) 0);
+                hitu = thitu(hitv, dam, &singleobj, (char *) 0);
             }
             if (hitu && singleobj->opoisoned && is_poisonable(singleobj)) {
                 char onmbuf[BUFSZ], knmbuf[BUFSZ];
@@ -515,7 +732,7 @@ struct obj *obj;         /* missile (or stack providing it) */
                          (u.umortality > oldumort) ? 0 : 10, TRUE);
             }
             if (hitu && can_blnd((struct monst *) 0, &youmonst,
-                                 (uchar) (singleobj->otyp == BLINDING_VENOM
+                                 (uchar) ((singleobj->otyp == BLINDING_VENOM)
                                              ? AT_SPIT
                                              : AT_WEAP),
                                  singleobj)) {
@@ -561,25 +778,21 @@ struct obj *obj;         /* missile (or stack providing it) */
                 }
             }
             stop_occupation();
-            if (hitu || !range) {
+            if (hitu) {
                 (void) drop_throw(singleobj, hitu, u.ux, u.uy);
                 break;
             }
         }
         if (!range /* reached end of path */
-            /* missile hits edge of screen */
-            || !isok(bhitpos.x + dx, bhitpos.y + dy)
-            /* missile hits the wall */
-            || IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ)
-            /* missile hit closed door */
-            || closed_door(bhitpos.x + dx, bhitpos.y + dy)
-            /* missile might hit iron bars */
-            || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS
-                && hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(5), 0))
-            /* Thrown objects "sink" */
-            || IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) {
-            if (singleobj) /* hits_bars might have destroyed it */
+            || MT_FLIGHTCHECK(FALSE)) {
+            if (singleobj) { /* hits_bars might have destroyed it */
+                if (m_shot.n > 1
+                    && (!mesg_given || bhitpos.x != u.ux || bhitpos.y != u.uy)
+                    && (cansee(bhitpos.x, bhitpos.y)
+                        || (archer && canseemon(archer))))
+                    pline("%s misses.", The(mshot_xname(singleobj)));
                 (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
+            }
             break;
         }
         tmp_at(bhitpos.x, bhitpos.y);
@@ -588,6 +801,7 @@ struct obj *obj;         /* missile (or stack providing it) */
     tmp_at(bhitpos.x, bhitpos.y);
     delay_output();
     tmp_at(DISP_END, 0);
+    mesg_given = 0; /* reset */
 
     if (blindinc) {
         u.ucreamed += blindinc;
@@ -597,6 +811,171 @@ struct obj *obj;         /* missile (or stack providing it) */
     }
 }
 
+#undef MT_FLIGHTCHECK
+
+/* Monster throws item at another monster */
+int
+thrwmm(mtmp, mtarg)
+struct monst *mtmp, *mtarg;
+{
+    struct obj *otmp, *mwep;
+    register xchar x, y;
+    boolean ispole;
+
+    /* Polearms won't be applied by monsters against other monsters */
+    if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
+        mtmp->weapon_check = NEED_RANGED_WEAPON;
+        /* mon_wield_item resets weapon_check as appropriate */
+        if (mon_wield_item(mtmp) != 0)
+            return 0;
+    }
+
+    /* Pick a weapon */
+    otmp = select_rwep(mtmp);
+    if (!otmp)
+        return 0;
+    ispole = is_pole(otmp);
+
+    x = mtmp->mx;
+    y = mtmp->my;
+
+    mwep = MON_WEP(mtmp); /* wielded weapon */
+
+    if (!ispole && m_lined_up(mtarg, mtmp)) {
+        int chance = max(BOLT_LIM - distmin(x, y, mtarg->mx, mtarg->my), 1);
+
+        if (!mtarg->mflee || !rn2(chance)) {
+            if (ammo_and_launcher(otmp, mwep)
+                && dist2(mtmp->mx, mtmp->my, mtarg->mx, mtarg->my)
+                   > PET_MISSILE_RANGE2)
+                return 0; /* Out of range */
+            /* Set target monster */
+            target = mtarg;
+            archer = mtmp;
+            monshoot(mtmp, otmp, mwep); /* multishot shooting or throwing */
+            archer = target = (struct monst *) 0;
+            nomul(0);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/* monster spits substance at monster */
+int
+spitmm(mtmp, mattk, mtarg)
+struct monst *mtmp, *mtarg;
+struct attack *mattk;
+{
+    struct obj *otmp;
+
+    if (mtmp->mcan) {
+        if (!Deaf)
+#if 0 /*JP:T*/
+            pline("A dry rattle comes from %s throat.",
+                  s_suffix(mon_nam(mtmp)));
+#else
+            pline("%s\82Ì\8dA\82ª\83K\83\89\83K\83\89\82Æ\96Â\82Á\82½\81D",
+                  mon_nam(mtmp));
+#endif
+        return 0;
+    }
+    if (m_lined_up(mtarg, mtmp)) {
+        switch (mattk->adtyp) {
+        case AD_BLND:
+        case AD_DRST:
+            otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
+            break;
+        default:
+            impossible("bad attack type in spitmu");
+            /* fall through */
+        case AD_ACID:
+            otmp = mksobj(ACID_VENOM, TRUE, FALSE);
+            break;
+        }
+        if (!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtarg->mx,mtarg->my))) {
+            if (canseemon(mtmp))
+/*JP
+                pline("%s spits venom!", Monnam(mtmp));
+*/
+                pline("%s\82Í\93Å\82ð\93f\82¢\82½\81I", Monnam(mtmp));
+            target = mtarg;
+            m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
+                    distmin(mtmp->mx,mtmp->my,mtarg->mx,mtarg->my), otmp);
+            target = (struct monst *)0;
+            nomul(0);
+
+            /* If this is a pet, it'll get hungry. Minions and
+             * spell beings won't hunger */
+            if (mtmp->mtame && !mtmp->isminion) {
+                struct edog *dog = EDOG(mtmp);
+
+                /* Hunger effects will catch up next move */
+                if (dog->hungrytime > 1)
+                    dog->hungrytime -= 5;
+            }
+
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/* monster breathes at monster (ranged) */
+int
+breamm(mtmp, mattk, mtarg)
+struct monst *mtmp, *mtarg;
+struct attack  *mattk;
+{
+    /* if new breath types are added, change AD_ACID to max type */
+    int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ;
+
+    if (m_lined_up(mtarg, mtmp)) {
+        if (mtmp->mcan) {
+            if (!Deaf) {
+                if (canseemon(mtmp))
+/*JP
+                    pline("%s coughs.", Monnam(mtmp));
+*/
+                    pline("%s\82Í\82¹\82«\82ð\82µ\82½\81D", Monnam(mtmp));
+                else
+/*JP
+                    You_hear("a cough.");
+*/
+                    You_hear("\82¹\82«\82Ì\89¹\82ð\95·\82¢\82½\81D");
+            }
+            return 0;
+        }
+        if (!mtmp->mspec_used && rn2(3)) {
+            if ((typ >= AD_MAGM) && (typ <= AD_ACID)) {
+                if (canseemon(mtmp))
+                    pline("%s breathes %s!", Monnam(mtmp), breathwep[typ - 1]);
+                dobuzz((int) (-20 - (typ - 1)), (int)mattk->damn,
+                       mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), FALSE);
+                nomul(0);
+                /* breath runs out sometimes. Also, give monster some
+                 * cunning; don't breath if the target fell asleep.
+                 */
+                mtmp->mspec_used = 6 + rn2(18);
+
+                /* If this is a pet, it'll get hungry. Minions and
+                 * spell beings won't hunger */
+                if (mtmp->mtame && !mtmp->isminion) {
+                    struct edog *dog = EDOG(mtmp);
+
+                    /* Hunger effects will catch up next move */
+                    if (dog->hungrytime >= 10)
+                        dog->hungrytime -= 10;
+                }
+            } else impossible("Breath weapon %d used", typ-1);
+        } else
+            return 0;
+    }
+    return 1;
+}
+
+
+
 /* remove an entire item from a monster's inventory; destroy that item */
 void
 m_useupall(mon, obj)
@@ -635,7 +1014,6 @@ struct monst *mtmp;
 {
     struct obj *otmp, *mwep;
     xchar x, y;
-    int multishot;
     const char *onm;
 
     /* Rearranged beginning so monsters can use polearms not in a line */
@@ -680,7 +1058,7 @@ struct monst *mtmp;
         if (dam < 1)
             dam = 1;
 
-        (void) thitu(hitv, dam, otmp, (char *) 0);
+        (void) thitu(hitv, dam, &otmp, (char *) 0);
         stop_occupation();
         return;
     }
@@ -698,107 +1076,7 @@ struct monst *mtmp;
         return;
 
     mwep = MON_WEP(mtmp); /* wielded weapon */
-
-    /* Multishot calculations */
-    multishot = 1;
-    if (otmp->quan > 1L /* no point checking if there's only 1 */
-        /* ammo requires corresponding launcher be wielded */
-        && (is_ammo(otmp)
-               ? matching_launcher(otmp, mwep)
-               /* otherwise any stackable (non-ammo) weapon */
-               : otmp->oclass == WEAPON_CLASS)
-        && !mtmp->mconf) {
-        int skill = (int) objects[otmp->otyp].oc_skill;
-
-        /* Assumes lords are skilled, princes are expert */
-        if (is_prince(mtmp->data))
-            multishot += 2;
-        else if (is_lord(mtmp->data))
-            multishot++;
-        /* fake players treated as skilled (regardless of role limits) */
-        else if (is_mplayer(mtmp->data))
-            multishot++;
-
-        /* class bonus */
-        switch (monsndx(mtmp->data)) {
-        case PM_MONK:
-            if (skill == -P_SHURIKEN)
-                multishot++;
-            break;
-        case PM_RANGER:
-            multishot++;
-            break;
-        case PM_ROGUE:
-            if (skill == P_DAGGER)
-                multishot++;
-            break;
-        case PM_NINJA:
-            if (skill == -P_SHURIKEN || skill == -P_DART)
-                multishot++;
-            /*FALLTHRU*/
-        case PM_SAMURAI:
-            if (otmp->otyp == YA && mwep && mwep->otyp == YUMI)
-                multishot++;
-            break;
-        default:
-            break;
-        }
-        /* racial bonus */
-        if ((is_elf(mtmp->data) && otmp->otyp == ELVEN_ARROW && mwep
-             && mwep->otyp == ELVEN_BOW)
-            || (is_orc(mtmp->data) && otmp->otyp == ORCISH_ARROW && mwep
-                && mwep->otyp == ORCISH_BOW))
-            multishot++;
-
-        multishot = rnd(multishot);
-        if ((long) multishot > otmp->quan)
-            multishot = (int) otmp->quan;
-    }
-
-    if (canseemon(mtmp)) {
-        char onmbuf[BUFSZ];
-
-        if (multishot > 1) {
-            /* "N arrows"; multishot > 1 implies otmp->quan > 1, so
-               xname()'s result will already be pluralized */
-/*JP
-            Sprintf(onmbuf, "%d %s", multishot, xname(otmp));
-*/
-            Sprintf(onmbuf, "%d%s\82Ì%s", multishot, numeral(otmp), xname(otmp));
-            onm = onmbuf;
-        } else {
-            /* "an arrow" */
-            onm = singular(otmp, xname);
-            onm = obj_is_pname(otmp) ? the(onm) : an(onm);
-        }
-        m_shot.s = ammo_and_launcher(otmp, mwep) ? TRUE : FALSE;
-/*JP
-        pline("%s %s %s!", Monnam(mtmp), m_shot.s ? "shoots" : "throws", onm);
-*/
-        pline("%s\82Í%s\82ð%s!", Monnam(mtmp), onm, m_shot.s ? "\8c\82\82Á\82½" : "\93\8a\82°\82½");
-        m_shot.o = otmp->otyp;
-    } else {
-        m_shot.o = STRANGE_OBJECT; /* don't give multishot feedback */
-    }
-
-    m_shot.n = multishot;
-    for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) {
-        m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
-                distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp);
-        /* conceptually all N missiles are in flight at once, but
-           if mtmp gets killed (shot kills adjacent gas spore and
-           triggers explosion, perhaps), inventory will be dropped
-           and otmp might go away via merging into another stack */
-        if (mtmp->mhp <= 0 && m_shot.i < m_shot.n) {
-            /* cancel pending shots (ought to give a message here since
-               we gave one above about throwing/shooting N missiles) */
-            break; /* endmultishot(FALSE); */
-        }
-    }
-    m_shot.n = m_shot.i = 0;
-    m_shot.o = STRANGE_OBJECT;
-    m_shot.s = FALSE;
-
+    monshoot(mtmp, otmp, mwep); /* multishot shooting or throwing */
     nomul(0);
 }
 
@@ -812,10 +1090,7 @@ struct attack *mattk;
 
     if (mtmp->mcan) {
         if (!Deaf)
-/*JP
             pline("A dry rattle comes from %s throat.",
-*/
-            pline("%s\82Ì\8dA\82ª\83K\83\89\83K\83\89\82Æ\96Â\82Á\82½\81D",
                   s_suffix(mon_nam(mtmp)));
         return 0;
     }
@@ -835,10 +1110,7 @@ struct attack *mattk;
         if (!rn2(BOLT_LIM
                  - distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy))) {
             if (canseemon(mtmp))
-/*JP
                 pline("%s spits venom!", Monnam(mtmp));
-*/
-                pline("%s\82Í\93Å\82ð\93f\82¢\82½\81I", Monnam(mtmp));
             m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
                     distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp);
             nomul(0);
@@ -864,15 +1136,9 @@ struct attack *mattk;
         if (mtmp->mcan) {
             if (!Deaf) {
                 if (canseemon(mtmp))
-/*JP
                     pline("%s coughs.", Monnam(mtmp));
-*/
-                    pline("%s\82Í\82¹\82«\82ð\82µ\82½\81D", Monnam(mtmp));
                 else
-/*JP
                     You_hear("a cough.");
-*/
-                    You_hear("\82¹\82«\82Ì\89¹\82ð\95·\82¢\82½\81D");
             }
             return 0;
         }
@@ -945,6 +1211,14 @@ int boulderhandling; /* 0=block, 1=ignore, 2=conditionally block */
     return FALSE;
 }
 
+STATIC_OVL boolean
+m_lined_up(mtarg, mtmp)
+struct monst *mtarg, *mtmp;
+{
+    return (linedup(mtarg->mx, mtarg->my, mtmp->mx, mtmp->my, 0));
+}
+
+
 /* is mtmp in position to use ranged attack? */
 boolean
 lined_up(mtmp)
@@ -978,11 +1252,54 @@ int type;
     return (struct obj *) 0;
 }
 
+void
+hit_bars(objp, objx, objy, barsx, barsy, your_fault, from_invent)
+struct obj **objp;      /* *objp will be set to NULL if object breaks */
+int objx, objy, barsx, barsy;
+boolean your_fault, from_invent;
+{
+    struct obj *otmp = *objp;
+    int obj_type = otmp->otyp;
+    boolean unbreakable = (levl[barsx][barsy].wall_info & W_NONDIGGABLE) != 0;
+
+    if (your_fault
+        ? hero_breaks(otmp, objx, objy, from_invent)
+        : breaks(otmp, objx, objy)) {
+        *objp = 0; /* object is now gone */
+        /* breakage makes its own noises */
+        if (obj_type == POT_ACID) {
+            if (cansee(barsx, barsy) && !unbreakable)
+                pline_The("iron bars are dissolved!");
+            else
+                You_hear(Hallucination ? "angry snakes!" : "a hissing noise.");
+            if (!unbreakable)
+                dissolve_bars(barsx, barsy);
+        }
+    }
+    else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
+/*JP
+            pline("Whang!");
+*/
+            pline("\82®\82í\81[\82ñ\81I");
+    else if (otmp->oclass == COIN_CLASS
+             || objects[obj_type].oc_material == GOLD
+             || objects[obj_type].oc_material == SILVER)
+/*JP
+            pline("Clink!");
+*/
+            pline("\83`\83\83\83\8a\83\93\81I");
+    else
+/*JP
+            pline("Clonk!");
+*/
+            pline("\83S\83c\83\93\81I");
+}
+
 /* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */
 boolean
-hits_bars(obj_p, x, y, always_hit, whodidit)
+hits_bars(obj_p, x, y, barsx, barsy, always_hit, whodidit)
 struct obj **obj_p; /* *obj_p will be set to NULL if object breaks */
-int x, y;
+int x, y, barsx, barsy;
 int always_hit; /* caller can force a hit for items which would fit through */
 int whodidit;   /* 1==hero, 0=other, -1==just check whether it'll pass thru */
 {
@@ -1032,26 +1349,7 @@ int whodidit;   /* 1==hero, 0=other, -1==just check whether it'll pass thru */
         }
 
     if (hits && whodidit != -1) {
-        if (whodidit ? hero_breaks(otmp, x, y, FALSE) : breaks(otmp, x, y))
-            *obj_p = otmp = 0; /* object is now gone */
-        /* breakage makes its own noises */
-        else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
-/*JP
-            pline("Whang!");
-*/
-            pline("\82®\82í\81[\82ñ\81I");
-        else if (otmp->oclass == COIN_CLASS
-                 || objects[obj_type].oc_material == GOLD
-                 || objects[obj_type].oc_material == SILVER)
-/*JP
-            pline("Clink!");
-*/
-            pline("\83`\83\83\83\8a\83\93\81I");
-        else
-/*JP
-            pline("Clonk!");
-*/
-            pline("\83S\83c\83\93\81I");
+        hit_bars(obj_p, x,y, barsx,barsy, whodidit, FALSE);
     }
 
     return hits;
index b7f7a70..2d74c03 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 muse.c  $NHDT-Date: 1447987786 2015/11/20 02:49:46 $  $NHDT-Branch: master $:$NHDT-Revision: 1.68 $ */
+/* NetHack 3.6 muse.c  $NHDT-Date: 1505181522 2017/09/12 01:58:42 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */
 /*      Copyright (C) 1990 by Ken Arromdee                         */
 /* NetHack may be freely redistributed.  See license for details.  */
 
@@ -28,6 +28,7 @@ STATIC_DCL int FDECL(precheck, (struct monst *, struct obj *));
 STATIC_DCL void FDECL(mzapmsg, (struct monst *, struct obj *, BOOLEAN_P));
 STATIC_DCL void FDECL(mreadmsg, (struct monst *, struct obj *));
 STATIC_DCL void FDECL(mquaffmsg, (struct monst *, struct obj *));
+STATIC_DCL boolean FDECL(m_use_healing, (struct monst *));
 STATIC_PTR int FDECL(mbhitm, (struct monst *, struct obj *));
 STATIC_DCL void FDECL(mbhit, (struct monst *, int,
                               int FDECL((*), (MONST_P, OBJ_P)),
@@ -39,7 +40,7 @@ STATIC_DCL boolean FDECL(cures_stoning, (struct monst *, struct obj *,
                                          BOOLEAN_P));
 STATIC_DCL boolean FDECL(mcould_eat_tin, (struct monst *));
 STATIC_DCL boolean FDECL(muse_unslime, (struct monst *, struct obj *,
-                                        BOOLEAN_P));
+                                        struct trap *, BOOLEAN_P));
 STATIC_DCL int FDECL(cures_sliming, (struct monst *, struct obj *));
 STATIC_DCL boolean FDECL(green_mon, (struct monst *));
 
@@ -178,27 +179,37 @@ struct obj *obj;
         && !rn2(WAND_BACKFIRE_CHANCE)) {
         int dam = d(obj->spe + 2, 6);
 
-        if (!Deaf) {
-            if (vis)
+        /* 3.6.1: no Deaf filter; 'if' message doesn't warrant it, 'else'
+           message doesn't need it since You_hear() has one of its own */
+        if (vis) {
+#if 0 /*JP:T*/
+            pline("%s zaps %s, which suddenly explodes!", Monnam(mon),
+                  an(xname(obj)));
+#else
+            pline("%s\82ª%s\82ð\82Ó\82è\82©\82´\82·\82Æ\81C\82»\82ê\82Í\93Ë\91R\94\9a\94­\82µ\82½\81I", Monnam(mon),
+                  an(xname(obj)));
+#endif
+        } else {
+            /* same near/far threshold as mzapmsg() */
+            int range = couldsee(mon->mx, mon->my) /* 9 or 5 */
+                           ? (BOLT_LIM + 1) : (BOLT_LIM - 3);
+
 #if 0 /*JP*/
-                pline("%s zaps %s, which suddenly explodes!", Monnam(mon),
-                      an(xname(obj)));
+            You_hear("a zap and an explosion %s.",
+                     (distu(mon->mx, mon->my) <= range * range)
+                        ? "nearby" : "in the distance");
 #else
-                pline("%s\82Í%s\82ð\82Ó\82è\82©\82´\82µ\82½\81C\82»\82ê\82Í\93Ë\91R\94\9a\94­\82µ\82½\81I", Monnam(mon),
-                      an(xname(obj)));
+            You_hear("%s\82­\82Ì\8fñ\82Ì\89¹\82Æ\94\9a\94­\89¹\82ð\95·\82¢\82½\81D",
+                     (distu(mon->mx, mon->my) <= range * range)
+                        ? "\8bß" : "\89\93");
 #endif
-            else
-/*JP
-                You_hear("a zap and an explosion in the distance.");
-*/
-                You_hear("\89\93\95û\82Ì\8fñ\82Ì\89¹\82Æ\94\9a\94­\89¹\82ð\95·\82¢\82½\81D");
         }
         m_useup(mon, obj);
-        if (mon->mhp <= dam) {
+        mon->mhp -= dam;
+        if (mon->mhp <= 0) {
             monkilled(mon, "", AD_RBRE);
             return 1;
-        } else
-            mon->mhp -= dam;
+        }
         m.has_defense = m.has_offense = m.has_misc = 0;
         /* Only one needed to be set to 0 but the others are harmless */
     }
@@ -212,17 +223,16 @@ struct obj *otmp;
 boolean self;
 {
     if (!canseemon(mtmp)) {
-        if (!Deaf)
+        int range = couldsee(mtmp->mx, mtmp->my) /* 9 or 5 */
+                       ? (BOLT_LIM + 1) : (BOLT_LIM - 3);
+
 #if 0 /*JP*/
-            You_hear("a %s zap.", (distu(mtmp->mx, mtmp->my)
-                                   <= (BOLT_LIM + 1) * (BOLT_LIM + 1))
-                                      ? "nearby"
-                                      : "distant");
+        You_hear("a %s zap.", (distu(mtmp->mx, mtmp->my) <= range * range)
+                                 ? "nearby" : "distant");
 #else
-            You_hear("%s\82­\82Å\8fñ\82Ì\89¹\82ð\95·\82¢\82½\81D", (distu(mtmp->mx, mtmp->my)
-                                   <= (BOLT_LIM + 1) * (BOLT_LIM + 1))
-                                      ? "\8bß"
-                                      : "\89\93");
+        You_hear("%s\82­\82Å\8fñ\82Ì\89¹\82ð\95·\82¢\82½\81D",
+                              (distu(mtmp->mx, mtmp->my) <= range * range)
+                                 ? "\8bß" : "\89\93");
 #endif
     } else if (self) {
 #if 0 /*JP*/
@@ -345,6 +355,29 @@ struct obj *otmp;
  * that if you polymorph into one you teleport at will.
  */
 
+STATIC_OVL boolean
+m_use_healing(mtmp)
+struct monst *mtmp;
+{
+    struct obj *obj = 0;
+    if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
+        m.defensive = obj;
+        m.has_defense = MUSE_POT_FULL_HEALING;
+        return TRUE;
+    }
+    if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
+        m.defensive = obj;
+        m.has_defense = MUSE_POT_EXTRA_HEALING;
+        return TRUE;
+    }
+    if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
+        m.defensive = obj;
+        m.has_defense = MUSE_POT_HEALING;
+        return TRUE;
+    }
+    return FALSE;
+}
+
 /* Select a defensive item/action for a monster.  Returns TRUE iff one is
    found. */
 boolean
@@ -415,21 +448,8 @@ struct monst *mtmp;
      */
     if (!mtmp->mcansee && !nohands(mtmp->data)
         && mtmp->data != &mons[PM_PESTILENCE]) {
-        if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
-            m.defensive = obj;
-            m.has_defense = MUSE_POT_FULL_HEALING;
+        if (m_use_healing(mtmp))
             return TRUE;
-        }
-        if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
-            m.defensive = obj;
-            m.has_defense = MUSE_POT_EXTRA_HEALING;
-            return TRUE;
-        }
-        if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
-            m.defensive = obj;
-            m.has_defense = MUSE_POT_HEALING;
-            return TRUE;
-        }
     }
 
     fraction = u.ulevel < 10 ? 5 : u.ulevel < 14 ? 4 : 3;
@@ -439,21 +459,8 @@ struct monst *mtmp;
 
     if (mtmp->mpeaceful) {
         if (!nohands(mtmp->data)) {
-            if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
-                m.defensive = obj;
-                m.has_defense = MUSE_POT_FULL_HEALING;
-                return TRUE;
-            }
-            if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
-                m.defensive = obj;
-                m.has_defense = MUSE_POT_EXTRA_HEALING;
-                return TRUE;
-            }
-            if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
-                m.defensive = obj;
-                m.has_defense = MUSE_POT_HEALING;
+            if (m_use_healing(mtmp))
                 return TRUE;
-            }
         }
         return FALSE;
     }
@@ -465,9 +472,7 @@ struct monst *mtmp;
             if (!is_floater(mtmp->data))
                 m.has_defense = MUSE_DOWNSTAIRS;
         } else if (x == xupstair && y == yupstair) {
-            /* don't let monster leave the dungeon with the Amulet */
-            if (ledger_no(&u.uz) != 1)
-                m.has_defense = MUSE_UPSTAIRS;
+            m.has_defense = MUSE_UPSTAIRS;
         } else if (sstairs.sx && x == sstairs.sx && y == sstairs.sy) {
             if (sstairs.up || !is_floater(mtmp->data))
                 m.has_defense = MUSE_SSTAIRS;
@@ -683,10 +688,7 @@ struct monst *mtmp;
     int i, fleetim, how = 0;
     struct obj *otmp = m.defensive;
     boolean vis, vismon, oseen;
-/*JP
-    const char *mcsa = "%s can see again.";
-*/
-    const char *mcsa = "%s\82Í\82Ü\82½\8c©\82¦\82é\82æ\82¤\82É\82È\82Á\82½\81D";
+    const char *Mnam;
 
     if ((i = precheck(mtmp, otmp)) != 0)
         return i;
@@ -717,10 +719,7 @@ struct monst *mtmp;
                 pline("%s\82Ì\8ap\82Ì\90æ\92[\82ª\8bP\82¢\82½\81I", mon_nam(mtmp));
         }
         if (!mtmp->mcansee) {
-            mtmp->mcansee = 1;
-            mtmp->mblinded = 0;
-            if (vismon)
-                pline(mcsa, Monnam(mtmp));
+            mcureblindness(mtmp, vismon);
         } else if (mtmp->mconf || mtmp->mstun) {
             mtmp->mconf = mtmp->mstun = 0;
             if (vismon)
@@ -950,12 +949,13 @@ struct monst *mtmp;
         if (vis) {
             struct trap *t = t_at(trapx, trapy);
 
+            Mnam = Monnam(mtmp);
 #if 0 /*JP*/
-            pline("%s %s into a %s!", Monnam(mtmp),
-                  makeplural(locomotion(mtmp->data, "jump")),
-                  t->ttyp == TRAPDOOR ? "trap door" : "hole");
+            pline("%s %s into a %s!", Mnam,
+                  vtense(Mnam, locomotion(mtmp->data, "jump")),
+                  (t->ttyp == TRAPDOOR) ? "trap door" : "hole");
 #else
-            pline("%s\82Í%s\82É%s\93ü\82Á\82½\81I", Monnam(mtmp),
+            pline("%s\82Í%s\82É%s\93ü\82Á\82½\81I", Mnam,
                   t->ttyp == TRAPDOOR ? "\97\8e\82µ\94à" : "\8c\8a",
                   jconj(locomotion(mtmp->data, "\94ò\82Ô"), "\82Ä"));
 #endif
@@ -978,24 +978,9 @@ struct monst *mtmp;
                          (coord *) 0);
         return 2;
     case MUSE_UPSTAIRS:
-        /* Monsters without amulets escape the dungeon and are
-         * gone for good when they leave up the up stairs.
-         * Monsters with amulets would reach the endlevel,
-         * which we cannot allow since that would leave the
-         * player stranded.
-         */
-        if (ledger_no(&u.uz) == 1) {
-            if (mon_has_special(mtmp))
-                return 0;
-            if (vismon)
-/*JP
-                pline("%s escapes the dungeon!", Monnam(mtmp));
-*/
-                pline("%s\82Í\96À\8b{\82©\82ç\93¦\91\96\82µ\82½\81I", Monnam(mtmp));
-            mongone(mtmp);
-            return 2;
-        }
         m_flee(mtmp);
+        if (ledger_no(&u.uz) == 1)
+            goto escape; /* impossible; level 1 upstairs are SSTAIRS */
         if (Inhell && mon_has_amulet(mtmp) && !rn2(4)
             && (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz) - 3)) {
             if (vismon)
@@ -1056,6 +1041,25 @@ struct monst *mtmp;
         return 2;
     case MUSE_SSTAIRS:
         m_flee(mtmp);
+        if (ledger_no(&u.uz) == 1) {
+        escape:
+            /* Monsters without the Amulet escape the dungeon and
+             * are gone for good when they leave up the up stairs.
+             * A monster with the Amulet would leave it behind
+             * (mongone -> mdrop_special_objs) but we force any
+             * monster who manages to acquire it or the invocation
+             * tools to stick around instead of letting it escape.
+             */
+            if (mon_has_special(mtmp))
+                return 0;
+            if (vismon)
+/*JP
+                pline("%s escapes the dungeon!", Monnam(mtmp));
+*/
+                pline("%s\82Í\96À\8b{\82©\82ç\93¦\91\96\82µ\82½\81I", Monnam(mtmp));
+            mongone(mtmp);
+            return 2;
+        }
         if (vismon)
 #if 0 /*JP*/
             pline("%s escapes %sstairs!", Monnam(mtmp),
@@ -1074,11 +1078,12 @@ struct monst *mtmp;
     case MUSE_TELEPORT_TRAP:
         m_flee(mtmp);
         if (vis) {
-#if 0 /*JP*/
-            pline("%s %s onto a teleport trap!", Monnam(mtmp),
-                  makeplural(locomotion(mtmp->data, "jump")));
-#else
-            pline("%s\82Í\8fu\8aÔ\88Ú\93®\82Ìã©\82É\94ò\82Ñ\8d\9e\82ñ\82¾\81I", Monnam(mtmp));
+            Mnam = Monnam(mtmp);
+#if 0 /*JP:T*/
+            pline("%s %s onto a teleport trap!", Mnam,
+                  vtense(Mnam, locomotion(mtmp->data, "jump")));
+#else /* \93ú\96{\8cê\82Å\82Í\91S\82Ä\81u\94ò\82Ñ\8d\9e\82ñ\82¾\81v */
+            pline("%s\82Í\8fu\8aÔ\88Ú\93®\82Ìã©\82É\94ò\82Ñ\8d\9e\82ñ\82¾\81I", Mnam);
 #endif
             seetrap(t_at(trapx, trapy));
         }
@@ -1097,12 +1102,8 @@ struct monst *mtmp;
         mtmp->mhp += i;
         if (mtmp->mhp > mtmp->mhpmax)
             mtmp->mhp = ++mtmp->mhpmax;
-        if (!otmp->cursed && !mtmp->mcansee) {
-            mtmp->mcansee = 1;
-            mtmp->mblinded = 0;
-            if (vismon)
-                pline(mcsa, Monnam(mtmp));
-        }
+        if (!otmp->cursed && !mtmp->mcansee)
+            mcureblindness(mtmp, vismon);
         if (vismon)
 /*JP
             pline("%s looks better.", Monnam(mtmp));
@@ -1118,12 +1119,8 @@ struct monst *mtmp;
         mtmp->mhp += i;
         if (mtmp->mhp > mtmp->mhpmax)
             mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 5 : 2));
-        if (!mtmp->mcansee) {
-            mtmp->mcansee = 1;
-            mtmp->mblinded = 0;
-            if (vismon)
-                pline(mcsa, Monnam(mtmp));
-        }
+        if (!mtmp->mcansee)
+            mcureblindness(mtmp, vismon);
         if (vismon)
 /*JP
             pline("%s looks much better.", Monnam(mtmp));
@@ -1138,12 +1135,8 @@ struct monst *mtmp;
         if (otmp->otyp == POT_SICKNESS)
             unbless(otmp); /* Pestilence */
         mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 8 : 4));
-        if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS) {
-            mtmp->mcansee = 1;
-            mtmp->mblinded = 0;
-            if (vismon)
-                pline(mcsa, Monnam(mtmp));
-        }
+        if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS)
+            mcureblindness(mtmp, vismon);
         if (vismon)
 /*JP
             pline("%s looks completely healed.", Monnam(mtmp));
@@ -1187,7 +1180,7 @@ try_again:
             goto try_again;
         if (!rn2(3))
             return WAN_TELEPORTATION;
-    /* else FALLTHRU */
+        /*FALLTHRU*/
     case 0:
     case 1:
         return SCR_TELEPORTATION;
@@ -1195,7 +1188,7 @@ try_again:
     case 10:
         if (!rn2(3))
             return WAN_CREATE_MONSTER;
-    /* else FALLTHRU */
+        /*FALLTHRU*/
     case 2:
         return SCR_CREATE_MONSTER;
     case 3:
@@ -1281,7 +1274,7 @@ struct monst *mtmp;
                 m.has_offense = MUSE_WAN_FIRE;
             }
             nomore(MUSE_FIRE_HORN);
-            if (obj->otyp == FIRE_HORN && obj->spe > 0) {
+            if (obj->otyp == FIRE_HORN && obj->spe > 0 && can_blow(mtmp)) {
                 m.offensive = obj;
                 m.has_offense = MUSE_FIRE_HORN;
             }
@@ -1291,7 +1284,7 @@ struct monst *mtmp;
                 m.has_offense = MUSE_WAN_COLD;
             }
             nomore(MUSE_FROST_HORN);
-            if (obj->otyp == FROST_HORN && obj->spe > 0) {
+            if (obj->otyp == FROST_HORN && obj->spe > 0 && can_blow(mtmp)) {
                 m.offensive = obj;
                 m.has_offense = MUSE_FROST_HORN;
             }
@@ -1311,6 +1304,24 @@ struct monst *mtmp;
             m.offensive = obj;
             m.has_offense = MUSE_WAN_STRIKING;
         }
+#if 0   /* use_offensive() has had some code to support wand of teleportation
+         * for a long time, but find_offensive() never selected one;
+         * so for the time being, this is still disabled */
+        nomore(MUSE_WAN_TELEPORTATION);
+        if (obj->otyp == WAN_TELEPORTATION && obj->spe > 0
+            /* don't give controlled hero a free teleport */
+            && !Teleport_control
+            /* do try to move hero to a more vulnerable spot */
+            && (onscary(u.ux, u.uy, mtmp)
+                || (u.ux == xupstair && u.uy == yupstair)
+                || (u.ux == xdnstair && u.uy == ydnstair)
+                || (u.ux == sstairs.sx && u.uy == sstairs.sy)
+                || (u.ux == xupladder && u.uy == yupladder)
+                || (u.ux == xdnladder && u.uy == ydnladder))) {
+            m.offensive = obj;
+            m.has_offense = MUSE_WAN_TELEPORTATION;
+        }
+#endif
         nomore(MUSE_POT_PARALYSIS);
         if (obj->otyp == POT_PARALYSIS && multi >= 0) {
             m.offensive = obj;
@@ -1374,8 +1385,8 @@ register struct monst *mtmp;
 register struct obj *otmp;
 {
     int tmp;
-
     boolean reveal_invis = FALSE;
+
     if (mtmp != &youmonst) {
         mtmp->msleeping = 0;
         if (mtmp->m_ap_type)
@@ -1436,6 +1447,7 @@ register struct obj *otmp;
                 makeknown(WAN_STRIKING);
         }
         break;
+#if 0   /* disabled because find_offensive() never picks WAN_TELEPORTATION */
     case WAN_TELEPORTATION:
         if (mtmp == &youmonst) {
             if (zap_oseen)
@@ -1453,6 +1465,7 @@ register struct obj *otmp;
                 (void) rloc(mtmp, TRUE);
         }
         break;
+#endif
     case WAN_CANCELLATION:
     case SPE_CANCELLATION:
         (void) cancel_monst(mtmp, otmp, FALSE, TRUE, FALSE);
@@ -1720,10 +1733,13 @@ struct monst *mtmp;
 */
                 losehp(num, "\89\8a\82Ì\8aª\95¨\82Å", KILLED_BY_AN);
             for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
-                if (DEADMONSTER(mtmp2)) continue;
-                if (mtmp == mtmp2) continue;
+                if (DEADMONSTER(mtmp2))
+                    continue;
+                if (mtmp == mtmp2)
+                    continue;
                 if (dist2(mtmp2->mx, mtmp2->my, mtmp->mx, mtmp->my) < 3) {
-                    if (resists_fire(mtmp2)) continue;
+                    if (resists_fire(mtmp2))
+                        continue;
                     mtmp2->mhp -= num;
                     if (resists_cold(mtmp2))
                         mtmp2->mhp -= 3 * num;
@@ -2052,8 +2068,8 @@ struct monst *mtmp;
         Strcpy(nambuf, mon_nam(mtmp));
         mon_set_minvis(mtmp);
         if (vismon && mtmp->minvis) { /* was seen, now invisible */
-            if (canspotmon(mtmp))
-#if 0 /*JP*/
+            if (canspotmon(mtmp)) {
+#if 0 /*JP:T*/
                 pline("%s body takes on a %s transparency.",
                       upstart(s_suffix(nambuf)),
                       Hallucination ? "normal" : "strange");
@@ -2062,11 +2078,14 @@ struct monst *mtmp;
                       Hallucination ? "\82 \82½\82è\82Ü\82¦\82È\82±\82Æ\82¾\82ª" : "\8aï\96­\82È\82±\82Æ\82É",
                       nambuf);
 #endif
-            else
+            } else {
 /*JP
                 pline("Suddenly you cannot see %s.", nambuf);
 */
                 pline("%s\82Í\93Ë\91R\8c©\82¦\82È\82­\82È\82Á\82½\81D", nambuf);
+                if (vis)
+                    map_invisible(mtmp->mx, mtmp->my);
+            }
             if (oseen)
                 makeknown(otmp->otyp);
         }
@@ -2110,13 +2129,16 @@ struct monst *mtmp;
         m_useup(mtmp, otmp);
         return 2;
     case MUSE_POLY_TRAP:
-        if (vismon)
-#if 0 /*JP*/
-            pline("%s deliberately %s onto a polymorph trap!", Monnam(mtmp),
-                  makeplural(locomotion(mtmp->data, "jump")));
+        if (vismon) {
+            const char *Mnam = Monnam(mtmp);
+
+#if 0 /*JP:T*/
+            pline("%s deliberately %s onto a polymorph trap!", Mnam,
+                  vtense(Mnam, locomotion(mtmp->data, "jump")));
 #else
-            pline("%s\82Í\82í\82´\82Æ\95Ï\89»\82Ìã©\82É\94ò\82Ñ\82±\82ñ\82¾\81I", Monnam(mtmp));
+            pline("%s\82Í\82í\82´\82Æ\95Ï\89»\82Ìã©\82É\94ò\82Ñ\82±\82ñ\82¾\81I", Mnam);
 #endif
+        }
         if (vis)
             seetrap(t_at(trapx, trapy));
 
@@ -2249,11 +2271,13 @@ STATIC_OVL void
 you_aggravate(mtmp)
 struct monst *mtmp;
 {
-/*JP
+#if 0 /*JP:T*/
     pline("For some reason, %s presence is known to you.",
-*/
-    pline("\82È\82º\82©\81C\82 \82È\82½\82Í%s\82Ì\91\8dÝ\82É\8bC\82ª\82Â\82¢\82½\81D",
           s_suffix(noit_mon_nam(mtmp)));
+#else
+    pline("\82È\82º\82©\81C\82 \82È\82½\82Í%s\82Ì\91\8dÝ\82É\8bC\82ª\82Â\82¢\82½\81D",
+          noit_mon_nam(mtmp));
+#endif
     cls();
 #ifdef CLIPPING
     cliparound(mtmp->mx, mtmp->my);
@@ -2369,7 +2393,7 @@ struct obj *obj;
         if (typ == UNICORN_HORN)
             return (boolean) (!obj->cursed && !is_unicorn(mon->data));
         if (typ == FROST_HORN || typ == FIRE_HORN)
-            return (obj->spe > 0);
+            return (obj->spe > 0 && can_blow(mon));
         break;
     case FOOD_CLASS:
         if (typ == CORPSE)
@@ -2496,6 +2520,23 @@ const char *fmt, *str;
     return FALSE;
 }
 
+/* cure mon's blindness (use_defensive, dog_eat, meatobj) */
+void
+mcureblindness(mon, verbos)
+struct monst *mon;
+boolean verbos;
+{
+    if (!mon->mcansee) {
+        mon->mcansee = 1;
+        mon->mblinded = 0;
+        if (verbos && haseyes(mon->data))
+/*JP
+            pline("%s can see again.", Monnam(mon));
+*/
+            pline("%s\82Í\82Ü\82½\8c©\82¦\82é\82æ\82¤\82É\82È\82Á\82½\81D", Monnam(mon));
+    }
+}
+
 /* TRUE if the monster ate something */
 boolean
 munstone(mon, by_you)
@@ -2526,7 +2567,7 @@ mon_consume_unstone(mon, obj, by_you, stoning)
 struct monst *mon;
 struct obj *obj;
 boolean by_you;
-boolean stoning;
+boolean stoning; /* True: stop petrification, False: cure stun && confusion */
 {
     boolean vis = canseemon(mon), tinned = obj->otyp == TIN,
             food = obj->otyp == CORPSE || tinned,
@@ -2585,7 +2626,10 @@ boolean stoning;
 */
             pline("%s\82Í\8e\80\82ñ\82¾\81I", Monnam(mon));
             if (by_you)
-                xkilled(mon, 0);
+                /* hero gets credit (experience) and blame (possible loss
+                   of alignment and/or luck and/or telepathy depending on
+                   mon) for the kill but does not break pacifism conduct */
+                xkilled(mon, XKILL_NOMSG | XKILL_NOCONDUCT);
             else
                 mondead(mon);
             return;
@@ -2681,6 +2725,7 @@ struct monst *mon;
 boolean by_you;
 {
     struct obj *obj, odummy;
+    struct permonst *mptr = mon->data;
 
     /*
      * muse_unslime() gives "mon starts turning green", "mon zaps
@@ -2689,7 +2734,7 @@ boolean by_you;
      * (via our caller) newcham()'s "mon turns into slime" feedback.
      */
 
-    if (slimeproof(mon->data))
+    if (slimeproof(mptr))
         return FALSE;
     if (mon->meating || !mon->mcanmove || mon->msleeping)
         return FALSE;
@@ -2701,29 +2746,63 @@ boolean by_you;
        [possible extension: monst capable of casting high level clerical
        spells could toss pillar of fire at self--probably too suicidal] */
     if (!mon->mcan && !mon->mspec_used
-        && attacktype_fordmg(mon->data, AT_BREA, AD_FIRE)) {
+        && attacktype_fordmg(mptr, AT_BREA, AD_FIRE)) {
         odummy = zeroobj; /* otyp == STRANGE_OBJECT */
-        return muse_unslime(mon, &odummy, by_you);
+        return muse_unslime(mon, &odummy, (struct trap *) 0, by_you);
     }
 
-    for (obj = mon->minvent; obj; obj = obj->nobj)
-        if (cures_sliming(mon, obj))
-            return muse_unslime(mon, obj, by_you);
+    /* same MUSE criteria as use_defensive() */
+    if (!is_animal(mptr) && !mindless(mptr)) {
+        struct trap *t;
 
-    /* TODO: check for and move onto an adjacent fire trap */
+        for (obj = mon->minvent; obj; obj = obj->nobj)
+            if (cures_sliming(mon, obj))
+                return muse_unslime(mon, obj, (struct trap *) 0, by_you);
+
+        if (((t = t_at(mon->mx, mon->my)) == 0 || t->ttyp != FIRE_TRAP)
+            && mptr->mmove && !mon->mtrapped) {
+            int xy[2][8], x, y, idx, ridx, nxy = 0;
+
+            for (x = mon->mx - 1; x <= mon->mx + 1; ++x)
+                for (y = mon->my - 1; y <= mon->my + 1; ++y)
+                    if (isok(x, y) && accessible(x, y)
+                        && !m_at(x, y) && (x != u.ux || y != u.uy)) {
+                        xy[0][nxy] = x, xy[1][nxy] = y;
+                        ++nxy;
+                    }
+            for (idx = 0; idx < nxy; ++idx) {
+                ridx = rn1(nxy - idx, idx);
+                if (ridx != idx) {
+                    x = xy[0][idx];
+                    xy[0][idx] = xy[0][ridx];
+                    xy[0][ridx] = x;
+                    y = xy[1][idx];
+                    xy[1][idx] = xy[1][ridx];
+                    xy[1][ridx] = y;
+                }
+                if ((t = t_at(xy[0][idx], xy[1][idx])) != 0
+                    && t->ttyp == FIRE_TRAP)
+                    break;
+            }
+        }
+        if (t && t->ttyp == FIRE_TRAP)
+            return muse_unslime(mon, &zeroobj, t, by_you);
+
+    } /* MUSE */
 
     return FALSE;
 }
 
 /* mon uses an item--selected by caller--to burn away incipient slime */
 STATIC_OVL boolean
-muse_unslime(mon, obj, by_you)
+muse_unslime(mon, obj, trap, by_you)
 struct monst *mon;
 struct obj *obj;
+struct trap *trap;
 boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
-{
+{               /* [by_you not honored if 'mon' triggers fire trap]. */
     struct obj *odummyp;
-    int otyp = obj->otyp, dmg;
+    int otyp = obj->otyp, dmg = 0;
     boolean vis = canseemon(mon), res = TRUE;
 
     if (vis)
@@ -2732,14 +2811,37 @@ boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
     /* -4 => sliming, causes quiet loss of enhanced speed */
     mon_adjust_speed(mon, -4, (struct obj *) 0);
 
-    if (otyp == STRANGE_OBJECT) {
+    if (trap) {
+        const char *Mnam = vis ? Monnam(mon) : 0;
+
+        if (mon->mx == trap->tx && mon->my == trap->ty) {
+            if (vis)
+                pline("%s triggers %s fire trap!", Mnam,
+                      trap->tseen ? "the" : "a");
+        } else {
+            remove_monster(mon->mx, mon->my);
+            newsym(mon->mx, mon->my);
+            place_monster(mon, trap->tx, trap->ty);
+            if (mon->wormno) /* won't happen; worms don't MUSE to unslime */
+                worm_move(mon);
+            newsym(mon->mx, mon->my);
+            if (vis)
+                pline("%s %s %s %s fire trap!", Mnam,
+                      vtense(Mnam, locomotion(mon->data, "move")),
+                      is_floater(mon->data) ? "over" : "onto",
+                      trap->tseen ? "the" : "a");
+        }
+        /* hack to avoid mintrap()'s chance of avoiding known trap */
+        mon->mtrapseen &= ~(1 << (FIRE_TRAP - 1));
+        mintrap(mon);
+    } else if (otyp == STRANGE_OBJECT) {
         /* monster is using fire breath on self */
         if (vis)
             pline("%s breathes fire on %sself.", Monnam(mon), mhim(mon));
         if (!rn2(3))
             mon->mspec_used = rn1(10, 5);
         /* -21 => monster's fire breath; 1 => # of damage dice */
-        (void) zhitm(mon, by_you ? 21 : -21, 1, &odummyp);
+        dmg = zhitm(mon, by_you ? 21 : -21, 1, &odummyp);
     } else if (otyp == SCR_FIRE) {
         mreadmsg(mon, obj);
         if (mon->mconf) {
@@ -2758,17 +2860,43 @@ boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
             explode(mon->mx, mon->my, -11, dmg, SCROLL_CLASS,
                     /* by_you: override -11 for mon but not others */
                     by_you ? -EXPL_FIERY : EXPL_FIERY);
+            dmg = 0; /* damage has been applied by explode() */
         }
     } else { /* wand/horn of fire w/ positive charge count */
         mzapmsg(mon, obj, TRUE);
         obj->spe--;
         /* -1 => monster's wand of fire; 2 => # of damage dice */
-        (void) zhitm(mon, by_you ? 1 : -1, 2, &odummyp);
+        dmg = zhitm(mon, by_you ? 1 : -1, 2, &odummyp);
     }
 
+    if (dmg) {
+        /* zhitm() applies damage but doesn't kill creature off;
+           for fire breath, dmg is going to be 0 (fire breathers are
+           immune to fire damage) but for wand of fire or fire horn,
+           'mon' could have taken damage so might die */
+        if (mon->mhp <= 0) {
+            if (by_you) {
+                /* mon killed self but hero gets credit and blame (except
+                   for pacifist conduct); xkilled()'s message would say
+                   "You killed/destroyed <mon>" so give our own message */
+                if (vis)
+                    pline("%s is %s by the fire!", Monnam(mon),
+                          nonliving(mon->data) ? "destroyed" : "killed");
+                xkilled(mon, XKILL_NOMSG | XKILL_NOCONDUCT);
+            } else
+                monkilled(mon, "fire", AD_FIRE);
+        } else {
+            /* non-fatal damage occurred */
+            if (vis)
+                pline("%s is burned%s", Monnam(mon), exclam(dmg));
+        }
+    }
     if (vis) {
         if (res && mon->mhp > 0)
+/*JP
             pline("%s slime is burned away!", s_suffix(Monnam(mon)));
+*/
+            pline("%s\82Ì\83X\83\89\83C\83\80\82Í\94R\82¦\82Â\82«\82½\81I", Monnam(mon));
         if (otyp != STRANGE_OBJECT)
             makeknown(otyp);
     }
@@ -2788,7 +2916,8 @@ struct obj *obj;
     if (obj->otyp == SCR_FIRE)
         return (haseyes(mon->data) && mon->mcansee);
     /* hero doesn't need hands or even limbs to zap, so mon doesn't either */
-    return ((obj->otyp == WAN_FIRE || obj->otyp == FIRE_HORN)
+    return ((obj->otyp == WAN_FIRE
+             || (obj->otyp == FIRE_HORN && can_blow(mon)))
             && obj->spe > 0);
 }
 
index a5d9f24..62832f1 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 music.c $NHDT-Date: 1446808448 2015/11/06 11:14:08 $  $NHDT-Branch: master $:$NHDT-Revision: 1.40 $ */
+/* NetHack 3.6 music.c $NHDT-Date: 1517877381 2018/02/06 00:36:21 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.47 $ */
 /*      Copyright (c) 1989 by Jean-Christophe Collet */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -11,7 +11,7 @@
  * This file contains the different functions designed to manipulate the
  * musical instruments and their various effects.
  *
- * Actually the list of instruments / effects is :
+ * The list of instruments / effects is :
  *
  * (wooden) flute       may calm snakes if player has enough dexterity
  * magic flute          may put monsters to sleep:  area of effect depends
@@ -81,7 +81,9 @@ int distance;
                 && (mtmp->mstrategy & STRAT_WAITMASK) != 0)
                 mtmp->mstrategy &= ~STRAT_WAITMASK;
             else if (distm < distance / 3
-                     && !resist(mtmp, TOOL_CLASS, 0, NOTELL))
+                     && !resist(mtmp, TOOL_CLASS, 0, NOTELL)
+                     /* some monsters are immune */
+                     && onscary(0, 0, mtmp))
                 monflee(mtmp, 0, FALSE, TRUE);
         }
     }
@@ -286,7 +288,7 @@ int force;
     for (x = start_x; x <= end_x; x++)
         for (y = start_y; y <= end_y; y++) {
             if ((mtmp = m_at(x, y)) != 0) {
-                wakeup(mtmp); /* peaceful monster will become hostile */
+                wakeup(mtmp, TRUE); /* peaceful monster will become hostile */
                 if (mtmp->mundetected && is_hider(mtmp->data)) {
                     mtmp->mundetected = 0;
                     if (cansee(x, y))
@@ -347,7 +349,7 @@ int force;
                         pline_The("throne falls into a chasm.");
 */
                         pline("\8bÊ\8dÀ\82Í\92n\8a\84\82ê\82É\97\8e\82¿\82½\81D");
-                /* Falls into next case */
+                    /*FALLTHRU*/
                 case ROOM:
                 case CORR: /* Try to make a pit */
                 do_pit:
@@ -414,35 +416,35 @@ int force;
                             mselftouch(mtmp, "Falling, ", TRUE);
 */
                             mselftouch(mtmp, "\97\8e\89º\92\86\81C", TRUE);
-                            if (mtmp->mhp > 0)
-                                if ((mtmp->mhp -=
-                                     rnd(m_already_trapped ? 4 : 6)) <= 0) {
-                                    if (!cansee(x, y))
+                            if (mtmp->mhp > 0) {
+                                mtmp->mhp -= rnd(m_already_trapped ? 4 : 6);
+                                if (mtmp->mhp <= 0) {
+                                    if (!cansee(x, y)) {
 /*JP
                                         pline("It is destroyed!");
 */
                                         pline("\89½\8eÒ\82©\82Í\8e\80\82ñ\82¾\81I");
-                                    else {
+                                    else {
 #if 0 /*JP*/
                                         You("destroy %s!",
                                             mtmp->mtame
-                                                ? x_monnam(
-                                                      mtmp, ARTICLE_THE,
-                                                      "poor",
-                                                      (has_mname(mtmp))
-                                                          ? SUPPRESS_SADDLE
-                                                          : 0,
-                                                      FALSE)
-                                                : mon_nam(mtmp));
-#else
+                                              ? x_monnam(mtmp, ARTICLE_THE,
+                                                         "poor",
+                                                         has_mname(mtmp)
+                                                           ? SUPPRESS_SADDLE
+                                                           : 0,
+                                                         FALSE)
+                                              : mon_nam(mtmp));
+#else /*JP:TODO \83T\83h\83\8b\8aÖ\98A\82Í\96¢\8f\88\97\9d */
                                         pline("%s%s\82Í\8e\80\82ñ\82¾\81I",
                                               mtmp->mtame
                                               ? "\82©\82í\82¢\82»\82¤\82È" : "",
                                               mon_nam(mtmp));
 #endif
                                     }
-                                    xkilled(mtmp, 0);
+                                    xkilled(mtmp, XKILL_NOMSG);
                                 }
+                            }
                         }
                     } else if (x == u.ux && y == u.uy) {
                         if (Levitation || Flying
@@ -534,6 +536,23 @@ int force;
         }
 }
 
+const char *
+generic_lvl_desc()
+{
+    if (Is_astralevel(&u.uz))
+        return "astral plane";
+    else if (In_endgame(&u.uz))
+        return "plane";
+    else if (Is_sanctum(&u.uz))
+        return "sanctum";
+    else if (In_sokoban(&u.uz))
+        return "puzzle";
+    else if (In_V_tower(&u.uz))
+        return "tower";
+    else
+        return "dungeon";
+}
+
 /*
  * The player is trying to extract something from his/her instrument.
  */
@@ -541,8 +560,7 @@ STATIC_OVL int
 do_improvisation(instr)
 struct obj *instr;
 {
-    int damage, do_spec = !Confusion;
-#if defined(MAC) || defined(AMIGA) || defined(VPIX_MUSIC) || defined(PCMUSIC)
+    int damage, mode, do_spec = !(Stunned || Confusion);
     struct obj itmp;
 
     itmp = *instr;
@@ -567,32 +585,66 @@ struct obj *instr;
 #ifdef PCMUSIC
     pc_speaker(&itmp, "C");
 #endif
-#endif /* MAC || AMIGA || VPIX_MUSIC || PCMUSIC */
 
-    if (!do_spec)
+#define PLAY_NORMAL   0x00
+#define PLAY_STUNNED  0x01
+#define PLAY_CONFUSED 0x02
+#define PLAY_HALLU    0x04
+    mode = PLAY_NORMAL;
+    if (Stunned)
+        mode |= PLAY_STUNNED;
+    if (Confusion)
+        mode |= PLAY_CONFUSED;
+    if (Hallucination)
+        mode |= PLAY_HALLU;
+
+    switch (mode) {
+    case PLAY_NORMAL:
 /*JP
-        pline("What you produce is quite far from music...");
+        You("start playing %s.", yname(instr));
 */
-        pline("\82 \82È\82½\82ª\91t\82Å\82½\82à\82Ì\82Í\89¹\8ay\82Æ\82Í\82Æ\82Ä\82à\8cÄ\82×\82È\82¢\81D\81D\81D");
-    else
+        You("%s\82ð\91t\82Å\82Í\82\82ß\82½\81D", yname(instr));
+        break;
+    case PLAY_STUNNED:
+/*JP
+        You("produce an obnoxious droning sound.");
+*/
+        break;
+    case PLAY_CONFUSED:
+        You("produce a raucous noise.");
+        break;
+    case PLAY_HALLU:
+        You("produce a kaleidoscopic display of floating butterfiles.");
+        break;
+    /* TODO? give some or all of these combinations their own feedback;
+       hallucination ones should reference senses other than hearing... */
+    case PLAY_STUNNED | PLAY_CONFUSED:
+    case PLAY_STUNNED | PLAY_HALLU:
+    case PLAY_CONFUSED | PLAY_HALLU:
+    case PLAY_STUNNED | PLAY_CONFUSED | PLAY_HALLU:
+    default:
 /*JP
-        You("start playing %s.", the(xname(instr)));
+        pline("What you produce is quite far from music...");
 */
-        You("%s\82ð\91t\82Å\82Í\82\82ß\82½\81D", the(xname(instr)));
+        pline("\82 \82È\82½\82ª\91t\82Å\82½\82à\82Ì\82Í\89¹\8ay\82Æ\82Í\82Æ\82Ä\82à\8cÄ\82×\82È\82¢\81D\81D\81D");
+        break;
+    }
+#undef PLAY_NORMAL
+#undef PLAY_STUNNED
+#undef PLAY_CONFUSED
+#undef PLAY_HALLU
 
-    switch (instr->otyp) {
+    switch (itmp.otyp) { /* note: itmp.otyp might differ from instr->otyp */
     case MAGIC_FLUTE: /* Make monster fall asleep */
-        if (do_spec && instr->spe > 0) {
-            consume_obj_charge(instr, TRUE);
+        consume_obj_charge(instr, TRUE);
 
 /*JP
             You("produce %s music.", Hallucination ? "piped" : "soft");
 */
             You("%s\82ð\91t\82Å\82½\81D", Hallucination ? "\82a\82f\82l" : "\93î\82ç\82©\82¢\8bÈ");
-            put_monsters_to_sleep(u.ulevel * 5);
-            exercise(A_DEX, TRUE);
-            break;
-        }              /* else FALLTHRU */
+        put_monsters_to_sleep(u.ulevel * 5);
+        exercise(A_DEX, TRUE);
+        break;
     case WOODEN_FLUTE: /* May charm snakes */
         do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25);
 /*JP
@@ -605,32 +657,30 @@ struct obj *instr;
         break;
     case FIRE_HORN:  /* Idem wand of fire */
     case FROST_HORN: /* Idem wand of cold */
-        if (do_spec && instr->spe > 0) {
-            consume_obj_charge(instr, TRUE);
+        consume_obj_charge(instr, TRUE);
 
-            if (!getdir((char *) 0)) {
+        if (!getdir((char *) 0)) {
 /*JP
                 pline("%s.", Tobjnam(instr, "vibrate"));
 */
                 pline("%s\82Í\90k\82¦\82½\81D", xname(instr));
-                break;
-            } else if (!u.dx && !u.dy && !u.dz) {
-                if ((damage = zapyourself(instr, TRUE)) != 0) {
-                    char buf[BUFSZ];
+            break;
+        } else if (!u.dx && !u.dy && !u.dz) {
+            if ((damage = zapyourself(instr, TRUE)) != 0) {
+                char buf[BUFSZ];
 
 /*JP
                     Sprintf(buf, "using a magical horn on %sself", uhim());
 */
                     Strcpy(buf, "\8e©\95ª\8e©\90g\82Ì\96\82\96@\82Ì\83z\83\8b\83\93\82Ì\97Í\82ð\97\81\82Ñ\82Ä");
-                    losehp(damage, buf, KILLED_BY); /* fire or frost damage */
-                }
-            } else {
-                buzz((instr->otyp == FROST_HORN) ? AD_COLD - 1 : AD_FIRE - 1,
-                     rn1(6, 6), u.ux, u.uy, u.dx, u.dy);
+                losehp(damage, buf, KILLED_BY); /* fire or frost damage */
             }
-            makeknown(instr->otyp);
-            break;
-        }             /* else FALLTHRU */
+        } else {
+            buzz((instr->otyp == FROST_HORN) ? AD_COLD - 1 : AD_FIRE - 1,
+                 rn1(6, 6), u.ux, u.uy, u.dx, u.dy);
+        }
+        makeknown(instr->otyp);
+        break;
     case TOOLED_HORN: /* Awaken or scare monsters */
 /*JP
         You("produce a frightful, grave sound.");
@@ -641,28 +691,26 @@ struct obj *instr;
         break;
     case BUGLE: /* Awaken & attract soldiers */
 /*JP
-        You("extract a loud noise from %s.", the(xname(instr)));
+        You("extract a loud noise from %s.", yname(instr));
 */
-        You("%s\82©\82ç\91å\82«\82È\8e¨\8fá\82è\82È\89¹\82ð\8fo\82µ\82½\81D", the(xname(instr)));
+        You("%s\82©\82ç\91å\82«\82È\8e¨\8fá\82è\82È\89¹\82ð\8fo\82µ\82½\81D", yname(instr));
         awaken_soldiers(&youmonst);
         exercise(A_WIS, FALSE);
         break;
     case MAGIC_HARP: /* Charm monsters */
-        if (do_spec && instr->spe > 0) {
-            consume_obj_charge(instr, TRUE);
+        consume_obj_charge(instr, TRUE);
 
 /*JP
             pline("%s very attractive music.", Tobjnam(instr, "produce"));
 */
             pline("%s\82Í\82Æ\82Ä\82à\96£\97Í\93I\82È\89¹\8ay\82ð\91t\82Å\82½\81D", xname(instr));
-            charm_monsters((u.ulevel - 1) / 3 + 1);
-            exercise(A_DEX, TRUE);
-            break;
-        }             /* else FALLTHRU */
+        charm_monsters((u.ulevel - 1) / 3 + 1);
+        exercise(A_DEX, TRUE);
+        break;
     case WOODEN_HARP: /* May calm Nymph */
         do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25);
 #if 0 /*JP*/
-        pline("%s %s.", The(xname(instr)),
+        pline("%s %s.", Yname2(instr),
               do_spec ? "produces a lilting melody" : "twangs");
 #else
         You("%s\81D", 
@@ -673,23 +721,21 @@ struct obj *instr;
         exercise(A_DEX, TRUE);
         break;
     case DRUM_OF_EARTHQUAKE: /* create several pits */
-        if (do_spec && instr->spe > 0) {
-            consume_obj_charge(instr, TRUE);
+        consume_obj_charge(instr, TRUE);
 
 /*JP
             You("produce a heavy, thunderous rolling!");
 */
             You("\8fd\8cú\82È\97\8b\82Ì\82æ\82¤\82È\89¹\82ð\91t\82Å\82½\81I");
 /*JP
-            pline_The("entire dungeon is shaking around you!");
+        pline_The("entire %s is shaking around you!", generic_lvl_desc());
 */
-            pline("\82 \82È\82½\82Ì\89ñ\82è\82Ì\96À\8b{\82ª\97h\82ê\82½\81I");
-            do_earthquake((u.ulevel - 1) / 3 + 1);
-            /* shake up monsters in a much larger radius... */
-            awaken_monsters(ROWNO * COLNO);
-            makeknown(DRUM_OF_EARTHQUAKE);
-            break;
-        }              /* else FALLTHRU */
+        pline("\82 \82È\82½\82Ì\89ñ\82è\82Ì%s\82ª\97h\82ê\82½\81I", generic_lvl_desc());
+        do_earthquake((u.ulevel - 1) / 3 + 1);
+        /* shake up monsters in a much larger radius... */
+        awaken_monsters(ROWNO * COLNO);
+        makeknown(DRUM_OF_EARTHQUAKE);
+        break;
     case LEATHER_DRUM: /* Awaken monsters */
 /*JP
         You("beat a deafening row!");
@@ -698,10 +744,11 @@ struct obj *instr;
         awaken_monsters(u.ulevel * 40);
         incr_itimeout(&HDeaf, rn1(20, 30));
         exercise(A_WIS, FALSE);
+        context.botl = TRUE;
         break;
     default:
         impossible("What a weird instrument (%d)!", instr->otyp);
-        break;
+        return 0;
     }
     return 2; /* That takes time */
 }
@@ -713,7 +760,7 @@ int
 do_play_instrument(instr)
 struct obj *instr;
 {
-    char buf[BUFSZ], c = 'y';
+    char buf[BUFSZ] = DUMMY, c = 'y';
     char *s;
     int x, y;
     boolean ok;
@@ -734,7 +781,8 @@ struct obj *instr;
         You("%s\82ð\89\89\91t\82·\82é\94\\97Í\82ª\82È\82¢\81D", the(distant_name(instr, xname)));
         return 0;
     }
-    if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE) {
+    if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE
+        && !(Stunned || Confusion || Hallucination)) {
 /*JP
         c = ynq("Improvise?");
 */
@@ -742,6 +790,7 @@ struct obj *instr;
         if (c == 'q')
             goto nevermind;
     }
+
     if (c == 'n') {
         if (u.uevent.uheard_tune == 2)
 /*JP
index 3a5c2d0..2006c65 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 o_init.c        $NHDT-Date: 1446892449 2015/11/07 10:34:09 $  $NHDT-Branch: master $:$NHDT-Revision: 1.20 $ */
+/* NetHack 3.6 o_init.c        $NHDT-Date: 1450318588 2015/12/17 02:16:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.22 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -450,11 +451,8 @@ dodiscovered() /* free after Robert Viduya */
 
     /* several classes are omitted from packorder; one is of interest here */
     Strcpy(classes, flags.inv_order);
-    if (!index(classes, VENOM_CLASS)) {
-        s = eos(classes);
-        *s++ = VENOM_CLASS;
-        *s = '\0';
-    }
+    if (!index(classes, VENOM_CLASS))
+        (void) strkitten(classes, VENOM_CLASS); /* append char to string */
 
     for (s = classes; *s; s++) {
         oclass = *s;
@@ -530,14 +528,17 @@ doclassdisco()
         discosyms[2 + MAXOCLASSES + 1], buf[BUFSZ];
     int i, ct, dis, xtras;
     boolean traditional;
-    winid tmpwin;
+    winid tmpwin = WIN_ERR;
     anything any;
     menu_item *pick_list = 0;
 
     discosyms[0] = '\0';
     traditional = (flags.menu_style == MENU_TRADITIONAL
                    || flags.menu_style == MENU_COMBINATION);
-    tmpwin = !traditional ? create_nhwindow(NHW_MENU) : WIN_ERR;
+    if (!traditional) {
+        tmpwin = create_nhwindow(NHW_MENU);
+        start_menu(tmpwin);
+    }
     any = zeroany;
     menulet = 'a';
 
@@ -567,7 +568,7 @@ doclassdisco()
        classes are omitted from packorder and one is of interest here */
     Strcpy(allclasses, flags.inv_order);
     if (!index(allclasses, VENOM_CLASS))
-        Sprintf(eos(allclasses), "%c", VENOM_CLASS);
+        (void) strkitten(allclasses, VENOM_CLASS); /* append char to string */
     /* construct discosyms[] */
     for (s = allclasses; *s; ++s) {
         oclass = *s;
@@ -608,8 +609,8 @@ doclassdisco()
             c = def_oc_syms[(int) *s].sym;
             if (!index(discosyms, c)) {
                 if (!xtras++)
-                    Sprintf(eos(discosyms), "%c", '\033');
-                Sprintf(eos(discosyms), "%c", c);
+                    (void) strkitten(discosyms, '\033');
+                (void) strkitten(discosyms, c);
             }
         }
         /* get the class (via its symbol character) */
@@ -727,8 +728,8 @@ rename_disco()
 
             if (oclass != prev_class) {
                 any.a_int = 0;
-                add_menu(tmpwin, NO_GLYPH, &any, ' ', iflags.menu_headings,
-                         ATR_NONE, let_to_name(oclass, FALSE, FALSE),
+                add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+                         let_to_name(oclass, FALSE, FALSE),
                          MENU_UNSELECTED);
                 prev_class = oclass;
             }
index 3c68674..3a8db8d 100644 (file)
@@ -984,7 +984,7 @@ SPELL("freeze sphere",   "hardcover",
 SPELL("blank paper", "plain", P_NONE, 18, 0, 0, 0, 0, HI_PAPER),
 /* tribute book for 3.6 */
 OBJECT(OBJ("novel", "paperback"),
-       BITS(0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, P_NONE, HI_PAPER),
+       BITS(0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, P_NONE, PAPER),
        0, SPBOOK_CLASS, 0, 0, 0, 20, 0, 0, 0, 1, 20, CLR_BRIGHT_BLUE),
 /* a special, one of a kind, spellbook */
 OBJECT(OBJ("Book of the Dead", "papyrus"),
index 22c50f4..1ec12c7 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 objnam.c        $NHDT-Date: 1447490776 2015/11/14 08:46:16 $  $NHDT-Branch: master $:$NHDT-Revision: 1.154 $ */
+/* NetHack 3.6 objnam.c        $NHDT-Date: 1521507553 2018/03/20 00:59:13 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.199 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 
 STATIC_DCL char *FDECL(strprepend, (char *, const char *));
 STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
+STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (char *, CHAR_P));
 STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
 STATIC_DCL char *NDECL(nextobuf);
 STATIC_DCL void FDECL(releaseobuf, (char *));
 STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
 STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
-STATIC_DCL boolean
-FDECL(singplur_lookup, (char *, char *, BOOLEAN_P, const char *const *));
+STATIC_DCL char *FDECL(doname_base, (struct obj *obj, unsigned));
+STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P,
+                                           const char *const *));
 STATIC_DCL char *FDECL(singplur_compound, (char *));
 STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
+STATIC_DCL boolean FDECL(badman, (const char *, BOOLEAN_P));
 #if 1 /*JP*/
 static char *FDECL(substitute, (char *,     char *,     char *));
 static char *FDECL(transpose, (char *buf,char *));
@@ -121,8 +125,12 @@ releaseobuf(bufp)
 char *bufp;
 {
     /* caller may not know whether bufp is the most recently allocated
-       buffer; if it isn't, do nothing */
-    if (bufp == obufs[obufidx])
+       buffer; if it isn't, do nothing; note that because of the somewhat
+       obscure PREFIX handling for object name formatting by xname(),
+       the pointer our caller has and is passing to us might be into the
+       middle of an obuf rather than the address returned by nextobuf() */
+    if (bufp >= obufs[obufidx]
+        && bufp < obufs[obufidx] + sizeof obufs[obufidx]) /* obufs[][BUFSZ] */
         obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
 }
 
@@ -131,11 +139,11 @@ obj_typename(otyp)
 register int otyp;
 {
     char *buf = nextobuf();
-    register struct objclass *ocl = &objects[otyp];
-    register const char *actualn = OBJ_NAME(*ocl);
-    register const char *dn = OBJ_DESCR(*ocl);
-    register const char *un = ocl->oc_uname;
-    register int nn = ocl->oc_name_known;
+    struct objclass *ocl = &objects[otyp];
+    const char *actualn = OBJ_NAME(*ocl);
+    const char *dn = OBJ_DESCR(*ocl);
+    const char *un = ocl->oc_uname;
+    int nn = ocl->oc_name_known;
 
     if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
         actualn = Japanese_item_name(otyp);
@@ -169,10 +177,15 @@ register int otyp;
         Strcat(buf, "\8fñ");
         break;
     case SPBOOK_CLASS:
+        if (otyp != SPE_NOVEL) {
 /*JP
         Strcpy(buf, "spellbook");
 */
         Strcat(buf, "\96\82\96@\8f\91");
+        } else {
+            Strcpy(buf, !nn ? "book" : "novel");
+            nn = 0;
+        }
         break;
     case RING_CLASS:
 /*JP
@@ -290,12 +303,13 @@ struct obj *obj;
     return TRUE;
 }
 
+/* used by distant_name() to pass extra information to xname_flags();
+   it would be much cleaner if this were a parameter, but that would
+   require all of the xname() and doname() calls to be modified */
+static int distantname = 0;
+
 /* Give the name of an object seen at a distance.  Unlike xname/doname,
- * we don't want to set dknown if it's not set already.  The kludge used is
- * to temporarily set Blind so that xname() skips the dknown setting.  This
- * assumes that we don't want to do this too often; if this function becomes
- * frequently used, it'd probably be better to pass a parameter to xname()
- * or doname() instead.
+ * we don't want to set dknown if it's not set already.
  */
 char *
 distant_name(obj, func)
@@ -304,10 +318,17 @@ char *FDECL((*func), (OBJ_P));
 {
     char *str;
 
-    long save_Blinded = Blinded;
-    Blinded = 1;
+    /* 3.6.1: this used to save Blind, set it, make the call, then restore
+     * the saved value; but the Eyes of the Overworld override blindness
+     * and let characters wearing them get dknown set for distant items.
+     *
+     * TODO? if the hero is wearing those Eyes, figure out whether the
+     * object is within X-ray radius and only treat it as distant when
+     * beyond that radius.  Logic is iffy but result might be interesting.
+     */
+    ++distantname;
     str = (*func)(obj);
-    Blinded = save_Blinded;
+    --distantname;
     return str;
 }
 
@@ -335,6 +356,135 @@ boolean juice; /* whether or not to append " juice" to the name */
 #endif
 }
 
+/* look up a named fruit by index (1..127) */
+struct fruit *
+fruit_from_indx(indx)
+int indx;
+{
+    struct fruit *f;
+
+    for (f = ffruit; f; f = f->nextf)
+        if (f->fid == indx)
+            break;
+    return f;
+}
+
+/* look up a named fruit by name */
+struct fruit *
+fruit_from_name(fname, exact, highest_fid)
+const char *fname;
+boolean exact; /* False => prefix or exact match, True = exact match only */
+int *highest_fid; /* optional output; only valid if 'fname' isn't found */
+{
+    struct fruit *f, *tentativef;
+    char *altfname;
+    unsigned k;
+    /*
+     * note: named fruits are case-senstive...
+     */
+
+    if (highest_fid)
+        *highest_fid = 0;
+    /* first try for an exact match */
+    for (f = ffruit; f; f = f->nextf)
+        if (!strcmp(f->fname, fname))
+            return f;
+        else if (highest_fid && f->fid > *highest_fid)
+            *highest_fid = f->fid;
+
+    /* didn't match as-is; if caller is willing to accept a prefix
+       match, try to find one; we want to find the longest prefix that
+       matches, not the first */
+    if (!exact) {
+        tentativef = 0;
+        for (f = ffruit; f; f = f->nextf) {
+            k = strlen(f->fname);
+            if (!strncmp(f->fname, fname, k)
+                && (!fname[k] || fname[k] == ' ')
+                && (!tentativef || k > strlen(tentativef->fname)))
+                tentativef = f;
+        }
+        f = tentativef;
+    }
+    /* if we still don't have a match, try singularizing the target;
+       for exact match, that's trivial, but for prefix, it's hard */
+    if (!f) {
+        altfname = makesingular(fname);
+        for (f = ffruit; f; f = f->nextf) {
+            if (!strcmp(f->fname, altfname))
+                break;
+        }
+        releaseobuf(altfname);
+    }
+    if (!f && !exact) {
+        char fnamebuf[BUFSZ], *p;
+        unsigned fname_k = strlen(fname); /* length of assumed plural fname */
+
+        tentativef = 0;
+        for (f = ffruit; f; f = f->nextf) {
+            k = strlen(f->fname);
+            /* reload fnamebuf[] each iteration in case it gets modified;
+               there's no need to recalculate fname_k */
+            Strcpy(fnamebuf, fname);
+            /* bug? if singular of fname is longer than plural,
+               failing the 'fname_k > k' test could skip a viable
+               candidate; unfortunately, we can't singularize until
+               after stripping off trailing stuff and we can't get
+               accurate fname_k until fname has been singularized;
+               compromise and use 'fname_k >= k' instead of '>',
+               accepting 1 char length discrepancy without risking
+               false match (I hope...) */
+            if (fname_k >= k && (p = index(&fnamebuf[k], ' ')) != 0) {
+                *p = '\0'; /* truncate at 1st space past length of f->fname */
+                altfname = makesingular(fnamebuf);
+                k = strlen(altfname); /* actually revised 'fname_k' */
+                if (!strcmp(f->fname, altfname)
+                    && (!tentativef || k > strlen(tentativef->fname)))
+                    tentativef = f;
+                releaseobuf(altfname); /* avoid churning through all obufs */
+            }
+        }
+        f = tentativef;
+    }
+    return f;
+}
+
+/* sort the named-fruit linked list by fruit index number */
+void
+reorder_fruit(forward)
+boolean forward;
+{
+    struct fruit *f, *allfr[1 + 127];
+    int i, j, k = SIZE(allfr);
+
+    for (i = 0; i < k; ++i)
+        allfr[i] = (struct fruit *) 0;
+    for (f = ffruit; f; f = f->nextf) {
+        /* without sanity checking, this would reduce to 'allfr[f->fid]=f' */
+        j = f->fid;
+        if (j < 1 || j >= k) {
+            impossible("reorder_fruit: fruit index (%d) out of range", j);
+            return; /* don't sort after all; should never happen... */
+        } else if (allfr[j]) {
+            impossible("reorder_fruit: duplicate fruit index (%d)", j);
+            return;
+        }
+        allfr[j] = f;
+    }
+    ffruit = 0; /* reset linked list; we're rebuilding it from scratch */
+    /* slot [0] will always be empty; must start 'i' at 1 to avoid
+       [k - i] being out of bounds during first iteration */
+    for (i = 1; i < k; ++i) {
+        /* for forward ordering, go through indices from high to low;
+           for backward ordering, go from low to high */
+        j = forward ? (k - i) : i;
+        if (allfr[j]) {
+            allfr[j]->nextf = ffruit;
+            ffruit = allfr[j];
+        }
+    }
+}
+
 char *
 xname(obj)
 struct obj *obj;
@@ -352,7 +502,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
     register struct objclass *ocl = &objects[typ];
     int nn = ocl->oc_name_known, omndx = obj->corpsenm;
     const char *actualn = OBJ_NAME(*ocl);
-    const char *dn = OBJ_DESCR(*ocl);
+    const char *dn = OBJ_DESCR(*ocl) ? OBJ_DESCR(*ocl) : actualn;
     const char *un = ocl->oc_uname;
     boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR);
     boolean known, dknown, bknown;
@@ -370,7 +520,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
      */
     if (!nn && ocl->oc_uses_known && ocl->oc_unique)
         obj->known = 0;
-    if (!Blind)
+    if (!Blind && !distantname)
         obj->dknown = TRUE;
     if (Role_if(PM_PRIEST))
         obj->bknown = TRUE;
@@ -428,6 +578,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
             Strcpy(buf, "poisoned ");
 */
             Strcpy(buf, "\93Å\82Ì\93h\82ç\82ê\82½");
+        /*FALLTHRU*/
     case VENOM_CLASS:
     case TOOL_CLASS:
 #if 1 /*JP*/
@@ -446,21 +597,21 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
             Strcpy(buf, (obj->spe < 3) ? "\8e¼\82Á\82½" : "\94G\82ê\82½");
 
         if (!dknown)
-            Strcat(buf, dn ? dn : actualn);
+            Strcat(buf, dn);
         else if (nn)
             Strcat(buf, actualn);
         else if (un) {
 #if 0 /*JP*/
-            Strcat(buf, dn ? dn : actualn);
+            Strcat(buf, dn);
             Strcat(buf, " called ");
             Strcat(buf, un);
 #else
             Strcat(buf, un);
             Strcat(buf, "\82Æ\8cÄ\82Î\82ê\82é");
-            Strcat(buf, dn ? dn : actualn);
+            Strcat(buf, dn);
 #endif
         } else
-            Strcat(buf, dn ? dn : actualn);
+            Strcat(buf, dn);
 #if 0 /*JP*/ /*\82±\82ê\82Í\8cê\8f\87\82Ì\8aÖ\8cW\82©\82ç\8fã\82Ì\95û\82Å\92è\8b`*/
         /* If we use an() here we'd have to remember never to use */
         /* it whenever calling doname() or xname(). */
@@ -546,29 +697,26 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
         break;
     case FOOD_CLASS:
         if (typ == SLIME_MOLD) {
-            register struct fruit *f;
+            struct fruit *f = fruit_from_indx(obj->spe);
 
-            for (f = ffruit; f; f = f->nextf) {
-                if (f->fid == obj->spe) {
-                    Strcpy(buf, f->fname);
-                    break;
-                }
-            }
             if (!f) {
                 impossible("Bad fruit #%d?", obj->spe);
                 Strcpy(buf, "fruit");
-            } else if (pluralize) {
-                /* ick; already pluralized fruit names
-                   are allowed--we want to try to avoid
-                   adding a redundant plural suffix */
-                Strcpy(buf, makeplural(makesingular(buf)));
-                pluralize = FALSE;
+            } else {
+                Strcpy(buf, f->fname);
+                if (pluralize) {
+                    /* ick; already pluralized fruit names
+                       are allowed--we want to try to avoid
+                       adding a redundant plural suffix */
+                    Strcpy(buf, makeplural(makesingular(buf)));
+                    pluralize = FALSE;
+                }
             }
             break;
         }
-        if (Is_pudding(obj)) {
+        if (obj->globby) {
             Sprintf(buf, "%s%s",
-                    (obj->owt < 100)
+                    (obj->owt <= 100)
 /*JP
                        ? "small "
 */
@@ -877,7 +1025,7 @@ nameit:
      brown potion               -- if oc_name_known not set
      potion of object detection -- if discovered
  */
-static char *
+STATIC_OVL char *
 minimal_xname(obj)
 struct obj *obj;
 {
@@ -1071,13 +1219,43 @@ char *prefix;
                                    : "");
 }
 
-static char *
-doname_base(obj, with_price)
-register struct obj *obj;
-boolean with_price;
+/* used to prevent rust on items where rust makes no difference */
+boolean
+erosion_matters(obj)
+struct obj *obj;
 {
-    boolean ispoisoned = FALSE;
-    boolean known, cknown, bknown, lknown;
+    switch (obj->oclass) {
+    case TOOL_CLASS:
+        /* it's possible for a rusty weptool to be polymorphed into some
+           non-weptool iron tool, in which case the rust implicitly goes
+           away, but it's also possible for it to be polymorphed into a
+           non-iron tool, in which case rust also implicitly goes away,
+           so there's no particular reason to try to handle the first
+           instance differently [this comment belongs in poly_obj()...] */
+        return is_weptool(obj) ? TRUE : FALSE;
+    case WEAPON_CLASS:
+    case ARMOR_CLASS:
+    case BALL_CLASS:
+    case CHAIN_CLASS:
+        return TRUE;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
+#define DONAME_WITH_PRICE 1
+#define DONAME_VAGUE_QUAN 2
+
+STATIC_OVL char *
+doname_base(obj, doname_flags)
+struct obj *obj;
+unsigned doname_flags;
+{
+    boolean ispoisoned = FALSE,
+            with_price = (doname_flags & DONAME_WITH_PRICE) != 0,
+            vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0;
+    boolean known, dknown, cknown, bknown, lknown;
     int omndx = obj->corpsenm;
     char prefix[PREFIX];
 #if 0 /*JP*/
@@ -1091,9 +1269,10 @@ boolean with_price;
 #endif
 
     if (iflags.override_ID) {
-        known = cknown = bknown = lknown = TRUE;
+        known = dknown = cknown = bknown = lknown = TRUE;
     } else {
         known = obj->known;
+        dknown = obj->dknown;
         cknown = obj->cknown;
         bknown = obj->bknown;
         lknown = obj->lknown;
@@ -1135,11 +1314,14 @@ boolean with_price;
 #endif
 
     if (obj->quan != 1L) {
+        if (dknown || !vague_quan)
 #if 0 /*JP*/
-        Sprintf(prefix, "%ld ", obj->quan);
+            Sprintf(prefix, "%ld ", obj->quan);
 #else /* \93ú\96{\8cê\82Æ\82µ\82Ä\82Í\90\94\8e\8c\82ª\82È\82¢\82Ì\82Í\95s\8e©\91R */
-        Sprintf(prefix, "%ld%s\82Ì", obj->quan, numeral(obj));
+            Sprintf(prefix, "%ld%s\82Ì", obj->quan, numeral(obj));
 #endif
+        else
+            Strcpy(prefix, "some ");
     } else if (obj->otyp == CORPSE) {
         /* skip article prefix for corpses [else corpse_xname()
            would have to be taught how to strip it off again] */
@@ -1165,11 +1347,11 @@ boolean with_price;
            making the prefix be redundant; note that 'known' flag
            isn't set when emptiness gets discovered because then
            charging magic would yield known number of new charges) */
-        && (obj->otyp == BAG_OF_TRICKS
+        && ((obj->otyp == BAG_OF_TRICKS)
              ? (obj->spe == 0 && !obj->known)
              /* not bag of tricks: empty if container which has no contents */
-             : (Is_container(obj) || obj->otyp == STATUE)
-            && !Has_contents(obj)))
+             : ((Is_container(obj) || obj->otyp == STATUE)
+                && !Has_contents(obj))))
 /*JP
         Strcat(prefix, "empty ");
 */
@@ -1219,8 +1401,11 @@ boolean with_price;
 
     if (lknown && Is_box(obj)) {
         if (obj->obroken)
+            /* 3.6.0 used "unlockable" here but that could be misunderstood
+               to mean "capable of being unlocked" rather than the intended
+               "not capable of being locked" */
 /*JP
-            Strcat(prefix, "unlockable ");
+            Strcat(prefix, "broken ");
 */
             Strcat(prefix, "\8c®\82Ì\89ó\82ê\82½");
         else if (obj->olocked)
@@ -1242,11 +1427,9 @@ boolean with_price;
         Strcat(prefix, "\96û\82Ì\93h\82ç\82ê\82½");
 
     if (cknown && Has_contents(obj)) {
-        /* we count all objects (obj->quantity); perhaps we should
-           count separate stacks instead (or even introduce a user
-           preference option to choose between the two alternatives)
-           since it's somewhat odd so see "containing 1002 items"
-           when there are 2 scrolls plus 1000 gold pieces */
+        /* we count the number of separate stacks, which corresponds
+           to the number of inventory slots needed to be able to take
+           everything out if no merges occur */
         long itemcount = count_contents(obj, FALSE, FALSE, TRUE);
 
 #if 0 /*JP*/
@@ -1257,7 +1440,7 @@ boolean with_price;
 #endif
     }
 
-    switch (obj->oclass) {
+    switch (is_weptool(obj) ? WEAPON_CLASS : obj->oclass) {
     case AMULET_CLASS:
         if (obj->owornmask & W_AMUL)
 /*JP
@@ -1265,35 +1448,31 @@ boolean with_price;
 */
             Strcat(bp, "(\90g\82É\82Â\82¯\82Ä\82¢\82é)");
         break;
+    case ARMOR_CLASS:
+        if (obj->owornmask & W_ARMOR)
+/*JP
+            Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
+*/
+            Strcat(bp, (obj == uskin) ? "(\94§\82É\96\84\82ß\82±\82Ü\82ê\82Ä\82¢\82é)"
+/*JP
+                                      : " (being worn)");
+*/
+                                      : "(\90g\82É\82Â\82¯\82Ä\82¢\82é)");
+        /*FALLTHRU*/
     case WEAPON_CLASS:
         if (ispoisoned)
 /*JP
             Strcat(prefix, "poisoned ");
 */
             Strcat(prefix, "\93Å\82Ì\93h\82ç\82ê\82½");
-    plus:
         add_erosion_words(obj, prefix);
         if (known) {
             Strcat(prefix, sitoa(obj->spe));
             Strcat(prefix, " ");
         }
         break;
-    case ARMOR_CLASS:
-        if (obj->owornmask & W_ARMOR)
-/*JP
-            Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
-*/
-            Strcat(bp, (obj == uskin) ? "(\94§\82É\96\84\82ß\82±\82Ü\82ê\82Ä\82¢\82é)"
-/*JP
-                                      : " (being worn)");
-*/
-                                      : "(\90g\82É\82Â\82¯\82Ä\82¢\82é)");
-        goto plus;
     case TOOL_CLASS:
-        /* weptools already get this done when we go to the +n code */
-        if (!is_weptool(obj))
-            add_erosion_words(obj, prefix);
-        if (obj->owornmask & (W_TOOL /* blindfold */ | W_SADDLE)) {
+        if (obj->owornmask & (W_TOOL | W_SADDLE)) { /* blindfold */
 /*JP
             Strcat(bp, " (being worn)");
 */
@@ -1301,14 +1480,22 @@ boolean with_price;
             break;
         }
         if (obj->otyp == LEASH && obj->leashmon != 0) {
-/*JP
-            Strcat(bp, " (in use)");
-*/
-            Strcat(bp, "(\8c\8b\82Ñ\82Â\82¯\82Ä\82¢\82é)");
+            struct monst *mlsh = find_mid(obj->leashmon, FM_FMON);
+
+            if (!mlsh) {
+                impossible("leashed monster not on this level");
+                obj->leashmon = 0;
+            } else {
+#if 0 /*JP*/
+                Sprintf(eos(bp), " (attached to %s)",
+                        a_monnam(mlsh));
+#else
+                Sprintf(eos(bp), " (%s\82É\8c\8b\82Ñ\82Â\82¯\82ç\82ê\82Ä\82¢\82é)",
+                        a_monnam(mlsh));
+#endif
+            }
             break;
         }
-        if (is_weptool(obj))
-            goto plus;
         if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
 #if 0 /*JP*/
             if (!obj->spe)
@@ -1347,7 +1534,6 @@ boolean with_price;
             goto charges;
         break;
     case WAND_CLASS:
-        add_erosion_words(obj, prefix);
     charges:
         if (known)
 /*JP
@@ -1363,7 +1549,6 @@ boolean with_price;
             Strcat(bp, "(\8cõ\82Á\82Ä\82¢\82é)");
         break;
     case RING_CLASS:
-        add_erosion_words(obj, prefix);
     ring:
         if (obj->owornmask & W_RINGR)
 /*JP
@@ -1394,13 +1579,20 @@ boolean with_price;
 */
             Strcat(prefix, "\90H\82×\82©\82¯\82Ì");
         if (obj->otyp == CORPSE) {
+            /* (quan == 1) => want corpse_xname() to supply article,
+               (quan != 1) => already have count or "some" as prefix;
+               "corpse" is already in the buffer returned by xname() */
+            unsigned cxarg = (((obj->quan != 1L) ? 0 : CXN_ARTICLE)
+                              | CXN_NOCORPSE);
+            char *cxstr = corpse_xname(obj, prefix, cxarg);
+
 #if 0 /*JP*/
-            Sprintf(prefix, "%s ",
-                    corpse_xname(obj, prefix, CXN_ARTICLE | CXN_NOCORPSE));
+            Sprintf(prefix, "%s ", cxstr);
 #else
-            Sprintf(prefix, "%s\82Ì",
-                    corpse_xname(obj, prefix, CXN_ARTICLE | CXN_NOCORPSE));
+            Sprintf(prefix, "%s\82Ì", cxstr);
 #endif
+            /* avoid having doname(corpse) consume an extra obuf */
+            releaseobuf(cxstr);
         } else if (obj->otyp == EGG) {
 #if 0 /* corpses don't tell if they're stale either */
             if (known && stale_egg(obj))
@@ -1552,7 +1744,7 @@ boolean with_price;
 
     /* show weight for items (debug tourist info)
      * aum is stolen from Crawl's "Arbitrary Unit of Measure" */
-    if (wizard) {
+    if (wizard && iflags.wizweight) {
         Sprintf(eos(bp), " (%d aum)", obj->owt);
     }
 #if 0 /*JP*/
@@ -1566,23 +1758,43 @@ boolean with_price;
 
 char *
 doname(obj)
-register struct obj *obj;
+struct obj *obj;
 {
-    return doname_base(obj, FALSE);
+    return doname_base(obj, (unsigned) 0);
 }
 
 /* Name of object including price. */
 char *
 doname_with_price(obj)
-register struct obj *obj;
+struct obj *obj;
+{
+    return doname_base(obj, DONAME_WITH_PRICE);
+}
+
+/* "some" instead of precise quantity if obj->dknown not set */
+char *
+doname_vague_quan(obj)
+struct obj *obj;
 {
-    return doname_base(obj, TRUE);
+    /* Used by farlook.
+     * If it hasn't been seen up close and quantity is more than one,
+     * use "some" instead of the quantity: "some gold pieces" rather
+     * than "25 gold pieces".  This is suboptimal, to put it mildly,
+     * because lookhere and pickup report the precise amount.
+     * Picking the item up while blind also shows the precise amount
+     * for inventory display, then dropping it while still blind leaves
+     * obj->dknown unset so the count reverts to "some" for farlook.
+     *
+     * TODO: add obj->qknown flag for 'quantity known' on stackable
+     * items; it could overlay obj->cknown since no containers stack.
+     */
+    return doname_base(obj, DONAME_VAGUE_QUAN);
 }
 
 /* used from invent.c */
 boolean
 not_fully_identified(otmp)
-register struct obj *otmp;
+struct obj *otmp;
 {
     /* gold doesn't have any interesting attributes [yet?] */
     if (otmp->oclass == COIN_CLASS)
@@ -1617,6 +1829,8 @@ register struct obj *otmp;
                           || is_flammable(otmp));
 }
 
+/* format a corpse name (xname() omits monster type; doname() calls us);
+   eatcorpse() also uses us for death reason when eating tainted glob */
 char *
 corpse_xname(otmp, adjective, cxn_flags)
 struct obj *otmp;
@@ -1633,10 +1847,14 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
             /* include "an" for "an ogre corpse */
         any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
             /* leave off suffix (do_name() appends "corpse" itself) */
-        omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0, possessive = FALSE;
+        omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
+        possessive = FALSE,
+        glob = (otmp->otyp != CORPSE && otmp->globby);
     const char *mname;
 
-    if (omndx == NON_PM) { /* paranoia */
+    if (glob) {
+        mname = OBJ_NAME(objects[otmp->otyp]); /* "glob of <monster>" */
+    } else if (omndx == NON_PM) { /* paranoia */
 /*JP
         mname = "thing";
 */
@@ -1701,7 +1919,9 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
             any_prefix = FALSE;
     }
 
-    if (!omit_corpse) {
+    if (glob) {
+        ; /* omit_corpse doesn't apply; quantity is always 1 */
+    } else if (!omit_corpse) {
 #if 0 /*JP*/
         Strcat(nambuf, " corpse");
         /* makeplural(nambuf) => append "s" to "corpse" */
@@ -1971,7 +2191,10 @@ const char *str;
         buf[0] = lowc(*str);
         Strcpy(&buf[1], str + 1);
         return buf;
-    } else if (*str < 'A' || *str > 'Z') {
+    } else if (*str < 'A' || *str > 'Z'
+               /* treat named fruit as not a proper name, even if player
+                  has assigned a capitalized proper name as his/her fruit */
+               || fruit_from_name(str, TRUE, (int *) 0)) {
         /* not a proper name, needs an article */
         insert_the = TRUE;
     } else {
@@ -2418,15 +2641,20 @@ static struct sing_plur one_off[] = {
     { "erinys", "erinyes" },
     { "foot", "feet" },
     { "fungus", "fungi" },
+    { "goose", "geese" },
     { "knife", "knives" },
     { "labrum", "labra" }, /* candelabrum */
     { "louse", "lice" },
     { "mouse", "mice" },
     { "mumak", "mumakil" },
     { "nemesis", "nemeses" },
+    { "ovum", "ova" },
+    { "ox", "oxen" },
+    { "passerby", "passersby" },
     { "rtex", "rtices" }, /* vortex */
-    { "tooth", "teeth" },
+    { "serum", "sera" },
     { "staff", "staves" },
+    { "tooth", "teeth" },
     { 0, 0 }
 };
 
@@ -2435,18 +2663,18 @@ static const char *const as_is[] = {
     "boots",   "shoes",     "gloves",    "lenses",   "scales",
     "eyes",    "gauntlets", "iron bars",
     /* both singular and plural are spelled the same */
-    "deer",    "fish",      "tuna",      "yaki",     "-hai",
-    "krill",   "manes",     "ninja",     "sheep",    "ronin",
-    "roshi",   "shito",     "tengu",     "ki-rin",   "Nazgul",
-    "gunyoki", "piranha",   "samurai",   "shuriken", 0,
+    "bison",   "deer",      "elk",       "fish",      "fowl",
+    "tuna",    "yaki",      "-hai",      "krill",     "manes",
+    "moose",   "ninja",     "sheep",     "ronin",     "roshi",
+    "shito",   "tengu",     "ki-rin",    "Nazgul",    "gunyoki",
+    "piranha", "samurai",   "shuriken", 0,
     /* Note:  "fish" and "piranha" are collective plurals, suitable
        for "wiped out all <foo>".  For "3 <foo>", they should be
        "fishes" and "piranhas" instead.  We settle for collective
        variant instead of attempting to support both. */
 };
 
-/* singularize/pluralize decisions common to both makesingular & makeplural
- */
+/* singularize/pluralize decisions common to both makesingular & makeplural */
 STATIC_OVL boolean
 singplur_lookup(basestr, endstring, to_plural, alt_as_is)
 char *basestr, *endstring;    /* base string, pointer to eos(string) */
@@ -2470,6 +2698,35 @@ const char *const *alt_as_is; /* another set like as_is[] */
         }
     }
 
+    /* avoid false hit on one_off[].plur == "lice" or .sing == "goose";
+       if more of these turn up, one_off[] entries will need to flagged
+       as to which are whole words and which are matchable as suffices
+       then matching in the loop below will end up becoming more complex */
+    if (!strcmpi(basestr, "slice")
+        || !strcmpi(basestr, "mongoose")) {
+        if (to_plural)
+            Strcasecpy(endstring, "s");
+        return TRUE;
+    }
+    /* skip "ox" -> "oxen" entry when pluralizing "<something>ox"
+       unless it is muskox */
+    if (to_plural && strlen(basestr) > 2 && !strcmpi(endstring - 2, "ox")
+        && strcmpi(endstring - 6, "muskox")) {
+        /* "fox" -> "foxes" */
+        Strcasecpy(endstring, "es");
+        return TRUE;
+    }
+    if (to_plural) {
+        if (!strcmpi(endstring - 3, "man")
+            && badman(basestr, to_plural)) {
+            Strcasecpy(endstring, "s");
+            return TRUE;
+        }
+    } else {
+        if (!strcmpi(endstring - 3, "men")
+            && badman(basestr, to_plural))
+            return TRUE;
+    }
     for (sp = one_off; sp->sing; sp++) {
         /* check whether endstring already matches */
         same = to_plural ? sp->plur : sp->sing;
@@ -2522,10 +2779,14 @@ char *str;
     return 0;
 }
 
-/* Plural routine; chiefly used for user-defined fruits.  We have to try to
- * account for everything reasonable the player has; something unreasonable
- * can still break the code.  However, it's still a lot more accurate than
- * "just add an s at the end", which Rogue uses...
+/* Plural routine; once upon a time it may have been chiefly used for
+ * user-defined fruits, but it is now used extensively throughout the
+ * program.
+ *
+ * For fruit, we have to try to account for everything reasonable the
+ * player has; something unreasonable can still break the code.
+ * However, it's still a lot more accurate than "just add an 's' at the
+ * end", which Rogue uses...
  *
  * Also used for plural monster names ("Wiped out all homunculi." or the
  * vanquished monsters list) and body parts.  A lot of unique monsters have
@@ -2576,7 +2837,7 @@ const char *oldstr;
     spot--;
     while (spot > str && *spot == ' ')
         spot--; /* Strip blanks from end */
-    *(spot + 1) = 0;
+    *(spot + 1) = '\0';
     /* Now spot is the last character of the string */
 
     len = strlen(str);
@@ -2591,7 +2852,6 @@ const char *oldstr;
     {
         static const char *const already_plural[] = {
             "ae",  /* algae, larvae, &c */
-            "men", /* also catches women, watchmen */
             "matzot", 0,
         };
 
@@ -2607,9 +2867,8 @@ const char *oldstr;
 
     /* man/men ("Wiped out all cavemen.") */
     if (len >= 3 && !strcmpi(spot - 2, "man")
-        /* exclude shamans and humans */
-        && (len < 6 || strcmpi(spot - 5, "shaman"))
-        && (len < 5 || strcmpi(spot - 4, "human"))) {
+        /* exclude shamans and humans etc */
+        && !badman(str, TRUE)) {
         Strcasecpy(spot - 1, "en");
         goto bottom;
     }
@@ -2789,7 +3048,8 @@ const char *oldstr;
 
     } else { /* input doesn't end in 's' */
 
-        if (!BSTRCMPI(bp, p - 3, "men")) {
+        if (!BSTRCMPI(bp, p - 3, "men")
+            && !badman(bp, FALSE)) {
             Strcasecpy(p - 2, "an");
             goto bottom;
         }
@@ -2821,6 +3081,54 @@ bottom:
 #endif
 }
 
+boolean
+badman(basestr, to_plural)
+const char *basestr;
+boolean to_plural;            /* true => makeplural, false => makesingular */
+{
+    int i, al;
+    char *endstr, *spot;
+    /* these are all the prefixes for *man that don't have a *men plural */
+    const char *no_men[] = {
+        "albu", "antihu", "anti", "ata", "auto", "bildungsro", "cai", "cay",
+        "ceru", "corner", "decu", "des", "dura", "fir", "hanu", "het",
+        "infrahu", "inhu", "nonhu", "otto", "out", "prehu", "protohu",
+        "subhu", "superhu", "talis", "unhu", "sha",
+        "hu", "un", "le", "re", "so", "to", "at", "a",
+    };
+    /* these are all the prefixes for *men that don't have a *man singular */
+    const char *no_man[] = {
+        "abdo", "acu", "agno", "ceru", "cogno", "cycla", "fleh", "grava",
+        "hegu", "preno", "sonar", "speci", "dai", "exa", "fla", "sta", "teg",
+        "tegu", "vela", "da", "hy", "lu", "no", "nu", "ra", "ru", "se", "vi", "ya",
+        "o", "a",
+    };
+
+    if (!basestr || strlen(basestr) < 4)
+        return FALSE;
+
+    endstr = eos((char *)basestr);
+
+    if (to_plural) {
+        for (i = 0; i < SIZE(no_men); i++) {
+            al = (int) strlen(no_men[i]);
+            spot = endstr - (al + 3);
+            if (!BSTRNCMPI(basestr, spot, no_men[i], al)
+                && (spot == basestr || *(spot - 1) == ' '))
+                return TRUE;
+        }
+    } else {
+        for (i = 0; i < SIZE(no_man); i++) {
+            al = (int) strlen(no_man[i]);
+            spot = endstr - (al + 3);
+            if (!BSTRNCMPI(basestr, spot, no_man[i], al)
+                && (spot == basestr || *(spot - 1) == ' '))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
 /* compare user string against object name string using fuzzy matching */
 STATIC_OVL boolean
 wishymatch(u_str, o_str, retry_inverted)
@@ -2981,6 +3289,9 @@ struct alt_spellings {
     { "grappling iron", GRAPPLING_HOOK },
     { "grapnel", GRAPPLING_HOOK },
     { "grapple", GRAPPLING_HOOK },
+    { "protection from shape shifters", RIN_PROTECTION_FROM_SHAPE_CHAN },
+    /* if we ever add other sizes, move this to o_ranges[] with "bag" */
+    { "box", LARGE_BOX },
     /* normally we wouldn't have to worry about unnecessary <space>, but
        " stone" will get stripped off, preventing a wishymatch; that actually
        lets "flint stone" be a match, so we also accept bogus "flintstone" */
@@ -2992,7 +3303,7 @@ struct alt_spellings {
 };
 #endif
 
-short
+STATIC_OVL short
 rnd_otyp_by_wpnskill(skill)
 schar skill;
 {
@@ -3015,6 +3326,58 @@ schar skill;
     return otyp;
 }
 
+STATIC_OVL short
+rnd_otyp_by_namedesc(name, oclass)
+char *name;
+char oclass;
+{
+    int i, n = 0;
+    short validobjs[NUM_OBJECTS];
+    register const char *zn;
+    long maxprob = 0;
+
+    if (!name)
+        return STRANGE_OBJECT;
+
+    memset((genericptr_t) validobjs, 0, sizeof(validobjs));
+
+    for (i = oclass ? bases[(int)oclass] : STRANGE_OBJECT + 1;
+         i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass);
+         ++i) {
+        /* don't match extra descriptions (w/o real name) */
+        if ((zn = OBJ_NAME(objects[i])) == 0)
+            continue;
+#if 1 /*JP*/
+        /*
+         * \81u\83C\83F\83\93\83_\81[\82Ì\96\82\8f\9c\82¯\81v\82ð\8aè\82Á\82½\82Æ\82«\82É\82±\82±\82Å\82Í\8bU\95¨\82É
+         * \82È\82ç\82È\82¢\82æ\82¤\82É\82·\82é\81B
+         * \94ñ\83E\83B\83U\81[\83h\83\82\81[\83h\82Å\82Ì\93ü\82ê\91Ö\82¦\8f\88\97\9d\82Í\8cã\82É\82 \82é\81B
+         */
+        if (i == FAKE_AMULET_OF_YENDOR)
+            continue;
+#endif
+        if (wishymatch(name, zn, TRUE)
+            || ((zn = OBJ_DESCR(objects[i])) != 0
+                && wishymatch(name, zn, FALSE))
+            || ((zn = objects[i].oc_uname) != 0
+                && wishymatch(name, zn, FALSE))) {
+            validobjs[n++] = (short) i;
+            maxprob += (objects[i].oc_prob + 1);
+        }
+    }
+
+    if (n > 0 && maxprob) {
+        long prob = rn2(maxprob);
+
+        i = 0;
+        while (i < n - 1
+               && (prob -= (objects[validobjs[i]].oc_prob + 1)) >= 0)
+            i++;
+        return validobjs[i];
+    }
+    return STRANGE_OBJECT;
+}
+
 /*
  * Return something wished for.  Specifying a null pointer for
  * the user request string results in a random object.  Otherwise,
@@ -3033,15 +3396,11 @@ struct obj *no_wish;
     register struct obj *otmp;
     int cnt, spe, spesgn, typ, very, rechrg;
     int blessed, uncursed, iscursed, ispoisoned, isgreased;
-    int eroded, eroded2, erodeproof;
+    int eroded, eroded2, erodeproof, locked, unlocked, broken;
     int halfeaten, mntmp, contents;
     int islit, unlabeled, ishistoric, isdiluted, trapped;
-#if 0 /*JP*/
     int tmp, tinv, tvariety;
-#else
-    int tvariety;
-#endif
-    int wetness;
+    int wetness, gsize = 0;
     struct fruit *f;
     int ftype = context.current_fruit;
     char fruitbuf[BUFSZ];
@@ -3060,12 +3419,14 @@ struct obj *no_wish;
      * automatically sticks 'candied' in front of such names.
      */
     char oclass;
-    char *un, *dn, *actualn;
+    char *un, *dn, *actualn, *origbp = bp;
     const char *name = 0;
 
-    cnt = spe = spesgn = typ = very = rechrg = blessed = uncursed = iscursed =
-        ispoisoned = isgreased = eroded = eroded2 = erodeproof = halfeaten =
-            islit = unlabeled = ishistoric = isdiluted = trapped = 0;
+    cnt = spe = spesgn = typ = 0;
+    very = rechrg = blessed = uncursed = iscursed = ispoisoned =
+        isgreased = eroded = eroded2 = erodeproof = halfeaten =
+        islit = unlabeled = ishistoric = isdiluted = trapped =
+        locked = unlocked = broken = 0;
     tvariety = RANDOM_TIN;
     mntmp = NON_PM;
 #define UNDEFINED 0
@@ -3185,6 +3546,13 @@ struct obj *no_wish;
                 trapped = 1;
         } else if (!strncmpi(bp, "untrapped ", l = 10)) {
             trapped = 2; /* not trapped */
+        /* locked, unlocked, broken: box/chest lock states */
+        } else if (!strncmpi(bp, "locked ", l = 7)) {
+            locked = 1, unlocked = broken = 0;
+        } else if (!strncmpi(bp, "unlocked ", l = 9)) {
+            unlocked = 1, locked = broken = 0;
+        } else if (!strncmpi(bp, "broken ", l = 7)) {
+            broken = 1, locked = unlocked = 0;
         } else if (!strncmpi(bp, "greased ", l = 8)) {
             isgreased = 1;
         } else if (!strncmpi(bp, "very ", l = 5)) {
@@ -3211,6 +3579,15 @@ struct obj *no_wish;
             isdiluted = 1;
         } else if (!strncmpi(bp, "empty ", l = 6)) {
             contents = EMPTY;
+        } else if (!strncmpi(bp, "small ", l = 6)) { /* glob sizes */
+            gsize = 1;
+        } else if (!strncmpi(bp, "medium ", l = 7)) {
+            /* xname() doesn't display "medium" but without this
+               there'd be no way to ask for the intermediate size */
+            gsize = 2;
+        } else if (!strncmpi(bp, "large ", l = 6)) {
+            /* "very large " had "very " peeled off on previous iteration */
+            gsize = (very != 1) ? 3 : 4;
         } else
             break;
         bp += l;
@@ -3310,24 +3687,25 @@ struct obj *no_wish;
 
 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\8f\88\97\9d\82µ\82È\82¢*/
     /*
-    Skip over "pair of ", "pairs of", "set of" and "sets of".
-
-    Accept "3 pair of boots" as well as "3 pairs of boots". It is valid
-    English either way.  See makeplural() for more on pair/pairs.
-
-    We should only double count if the object in question is not
-    referred to as a "pair of".  E.g. We should double if the player
-    types "pair of spears", but not if the player types "pair of
-    lenses".  Luckily (?) all objects that are referred to as pairs
-    -- boots, gloves, and lenses -- are also not mergable, so cnt is
-    ignored anyway.
-    */
+     * Skip over "pair of ", "pairs of", "set of" and "sets of".
+     *
+     * Accept "3 pair of boots" as well as "3 pairs of boots".  It is
+     * valid English either way.  See makeplural() for more on pair/pairs.
+     *
+     * We should only double count if the object in question is not
+     * referred to as a "pair of".  E.g. We should double if the player
+     * types "pair of spears", but not if the player types "pair of
+     * lenses".  Luckily (?) all objects that are referred to as pairs
+     * -- boots, gloves, and lenses -- are also not mergable, so cnt is
+     * ignored anyway.
+     */
     if (!strncmpi(bp, "pair of ", 8)) {
         bp += 8;
         cnt *= 2;
-    } else if (cnt > 1 && !strncmpi(bp, "pairs of ", 9)) {
+    } else if (!strncmpi(bp, "pairs of ", 9)) {
         bp += 9;
-        cnt *= 2;
+        if (cnt > 1)
+            cnt *= 2;
     } else if (!strncmpi(bp, "set of ", 7)) {
         bp += 7;
     } else if (!strncmpi(bp, "sets of ", 8)) {
@@ -3344,6 +3722,7 @@ struct obj *no_wish;
     if ((p = strstri(bp, "glob of ")) != 0
         || (p = strstri(bp, "globs of ")) != 0) {
         int globoffset = (*(p + 4) == 's') ? 9 : 8;
+
         if ((mntmp = name_to_mon(p + globoffset)) >= PM_GRAY_OOZE
             && mntmp <= PM_BLACK_PUDDING) {
             mntmp = NON_PM; /* lie to ourselves */
@@ -3357,46 +3736,49 @@ struct obj *no_wish;
          */
         if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ")
             && !strstri(bp, "finger ")) {
-            if (((p = strstri(bp, "tin of ")) != 0)
-                && (tmp = tin_variety_txt(p + 7, &tinv))
-                && (mntmp = name_to_mon(p + 7 + tmp)) >= LOW_PM) {
-                *(p + 3) = 0;
-                tvariety = tinv;
+            if ((p = strstri(bp, "tin of ")) != 0) {
+                if (!strcmpi(p + 7, "spinach")) {
+                    contents = SPINACH;
+                    mntmp = NON_PM;
+                } else {
+                    tmp = tin_variety_txt(p + 7, &tinv);
+                    tvariety = tinv;
+                    mntmp = name_to_mon(p + 7 + tmp);
+                }
+                typ = TIN;
+                goto typfnd;
             } else if ((p = strstri(bp, " of ")) != 0
                        && (mntmp = name_to_mon(p + 4)) >= LOW_PM)
                 *p = 0;
         }
     }
     /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
-    if (strncmpi(bp, "samurai sword", 13))   /* not the "samurai" monster! */
-        if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */
-            if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */
-                if (strncmpi(bp, "master key",
-                             10)) /* not the "master" rank */
-                    if (strncmpi(bp, "magenta", 7)) /* not the "mage" rank */
-                        if (mntmp < LOW_PM && strlen(bp) > 2
-                            && (mntmp = name_to_mon(bp)) >= LOW_PM) {
-                            int mntmptoo,
-                                mntmplen; /* double check for rank title */
-                            char *obp = bp;
-                            mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
-                            bp += mntmp != mntmptoo
-                                      ? (int) strlen(mons[mntmp].mname)
+    if (strncmpi(bp, "samurai sword", 13)  /* not the "samurai" monster! */
+        && strncmpi(bp, "wizard lock", 11) /* not the "wizard" monster! */
+        && strncmpi(bp, "ninja-to", 8)     /* not the "ninja" rank */
+        && strncmpi(bp, "master key", 10)  /* not the "master" rank */
+        && strncmpi(bp, "magenta", 7)) {   /* not the "mage" rank */
+        if (mntmp < LOW_PM && strlen(bp) > 2
+            && (mntmp = name_to_mon(bp)) >= LOW_PM) {
+            int mntmptoo, mntmplen; /* double check for rank title */
+            char *obp = bp;
+
+            mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
+            bp += (mntmp != mntmptoo) ? (int) strlen(mons[mntmp].mname)
                                       : mntmplen;
-                            if (*bp == ' ')
-                                bp++;
-                            else if (!strncmpi(bp, "s ", 2))
-                                bp += 2;
-                            else if (!strncmpi(bp, "es ", 3))
-                                bp += 3;
-                            else if (!*bp && !actualn && !dn && !un
-                                     && !oclass) {
-                                /* no referent; they don't really mean a
-                                 * monster type */
-                                bp = obp;
-                                mntmp = NON_PM;
-                            }
-                        }
+            if (*bp == ' ') {
+                bp++;
+            } else if (!strncmpi(bp, "s ", 2)) {
+                bp += 2;
+            } else if (!strncmpi(bp, "es ", 3)) {
+                bp += 3;
+            } else if (!*bp && !actualn && !dn && !un && !oclass) {
+                /* no referent; they don't really mean a monster type */
+                bp = obp;
+                mntmp = NON_PM;
+            }
+        }
+    }
 #else /*JP:\81u(\89ö\95¨\96¼)\82Ì(\83A\83C\83e\83\80)\81v\91Î\89\9e */
     {
         if ((mntmp = name_to_mon(bp)) >= LOW_PM) {
@@ -3513,7 +3895,8 @@ struct obj *no_wish;
      * well in the future. (TH)
      */
 #if 0 /*JP*/
-    if (!BSTRCMPI(bp, p - 10, "gold piece") || !BSTRCMPI(bp, p - 7, "zorkmid")
+    if (!BSTRCMPI(bp, p - 10, "gold piece")
+        || !BSTRCMPI(bp, p - 7, "zorkmid")
         || !strcmpi(bp, "gold") || !strcmpi(bp, "money")
         || !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
 #else
@@ -3545,15 +3928,19 @@ struct obj *no_wish;
       */
     /* Search for class names: XXXXX potion, scroll of XXXXX.  Avoid */
     /* false hits on, e.g., rings for "ring mail". */
-    if (strncmpi(bp, "enchant ", 8) && strncmpi(bp, "destroy ", 8)
+    if (strncmpi(bp, "enchant ", 8)
+        && strncmpi(bp, "destroy ", 8)
         && strncmpi(bp, "detect food", 11)
-        && strncmpi(bp, "food detection", 14) && strncmpi(bp, "ring mail", 9)
+        && strncmpi(bp, "food detection", 14)
+        && strncmpi(bp, "ring mail", 9)
         && strncmpi(bp, "studded leather armor", 21)
         && strncmpi(bp, "leather armor", 13)
-        && strncmpi(bp, "tooled horn", 11) && strncmpi(bp, "food ration", 11)
+        && strncmpi(bp, "tooled horn", 11)
+        && strncmpi(bp, "food ration", 11)
         && strncmpi(bp, "meat ring", 9))
         for (i = 0; i < (int) (sizeof wrpsym); i++) {
             register int j = strlen(wrp[i]);
+
             if (!strncmpi(bp, wrp[i], j)) {
                 oclass = wrpsym[i];
                 if (oclass != AMULET_CLASS) {
@@ -3635,7 +4022,10 @@ retry:
         ; /* avoid false hit on "* glass" */
     } else if (!BSTRCMPI(bp, p - 6, " glass") || !strcmpi(bp, "glass")) {
         register char *g = bp;
-        if (strstri(g, "broken"))
+
+        /* treat "broken glass" as a non-existent item; since "broken" is
+           also a chest/box prefix it might have been stripped off above */
+        if (broken || strstri(g, "broken"))
             return (struct obj *) 0;
         if (!strncmpi(g, "worthless ", 10))
             g += 10;
@@ -3670,46 +4060,26 @@ srch:
         for (i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
             register const char *zn;
 
-            if ((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) {
+            if ((zn = OBJ_NAME(objects[i])) != 0 && !strcmpi(actualn, zn)) {
                 typ = i;
                 goto typfnd;
             }
         }
-    }
-    i = oclass ? bases[(int) oclass] : 1;
-    while (i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass)) {
-        register const char *zn;
-
-        if (actualn && (zn = OBJ_NAME(objects[i])) != 0
-            && wishymatch(actualn, zn, TRUE)) {
-            typ = i;
+        /* "tin of foo" would be caught above, but plain "tin" has
+           a random chance of yielding "tin wand" unless we do this */
+        if (!strcmpi(actualn, "tin")) {
+            typ = TIN;
             goto typfnd;
         }
-#if 0 /*JP*/
-        if (dn && (zn = OBJ_DESCR(objects[i])) != 0
-            && wishymatch(dn, zn, FALSE)) {
-#else /*JP
-       * \81u\83C\83F\83\93\83_\81[\82Ì\96\82\8f\9c\82¯\81v\82ð\8aè\82Á\82½\82Æ\82«\82É\82±\82±\82Å\82Í\8bU\95¨\82É
-       * \82È\82ç\82È\82¢\82æ\82¤\82É\82·\82é\81B
-       * \94ñ\83E\83B\83U\81[\83h\83\82\81[\83h\82Å\82Ì\93ü\82ê\91Ö\82¦\8f\88\97\9d\82Í\8cã\82É\82 \82é\81B
-       */
-        if (i != FAKE_AMULET_OF_YENDOR &&
-            dn && (zn = OBJ_DESCR(objects[i])) != 0
-            && wishymatch(dn, zn, FALSE)) {
-#endif
-            /* don't match extra descriptions (w/o real name) */
-            if (!OBJ_NAME(objects[i]))
-                return (struct obj *) 0;
-            typ = i;
-            goto typfnd;
-        }
-        if (un && (zn = objects[i].oc_uname) != 0
-            && wishymatch(un, zn, FALSE)) {
-            typ = i;
-            goto typfnd;
-        }
-        i++;
     }
+
+    if (((typ = rnd_otyp_by_namedesc(actualn, oclass)) != STRANGE_OBJECT)
+        || ((typ = rnd_otyp_by_namedesc(dn, oclass)) != STRANGE_OBJECT)
+        || ((typ = rnd_otyp_by_namedesc(un, oclass)) != STRANGE_OBJECT)
+        || ((typ = rnd_otyp_by_namedesc(origbp, oclass)) != STRANGE_OBJECT))
+        goto typfnd;
+    typ = 0;
+
     if (actualn) {
         struct Jitem *j = Japanese_items;
 
@@ -4061,6 +4431,8 @@ typfnd:
         break;
 #ifdef MAIL
     case SCR_MAIL:
+        /* 0: delivered in-game via external event (or randomly for fake mail);
+           1: from bones or wishing; 2: written with marker */
         otmp->spe = 1;
         break;
 #endif
@@ -4069,7 +4441,7 @@ typfnd:
             otmp->spe = (rn2(10) ? -1 : 0);
             break;
         }
-    /* fall through, if wizard */
+        /*FALLTHRU*/
     default:
         otmp->spe = spe;
     }
@@ -4084,20 +4456,25 @@ typfnd:
             otmp->spe = 0; /* No spinach */
             if (dead_species(mntmp, FALSE)) {
                 otmp->corpsenm = NON_PM; /* it's empty */
-            } else if (!(mons[mntmp].geno & G_UNIQ)
+            } else if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
                        && !(mvitals[mntmp].mvflags & G_NOCORPSE)
                        && mons[mntmp].cnutrit != 0) {
                 otmp->corpsenm = mntmp;
             }
             break;
         case CORPSE:
-            if (!(mons[mntmp].geno & G_UNIQ)
+            if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
                 && !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
                 if (mons[mntmp].msound == MS_GUARDIAN)
                     mntmp = genus(mntmp, 1);
                 set_corpsenm(otmp, mntmp);
             }
             break;
+        case EGG:
+            mntmp = can_be_hatched(mntmp);
+            /* this also sets hatch timer if appropriate */
+            set_corpsenm(otmp, mntmp);
+            break;
         case FIGURINE:
             if (!(mons[mntmp].geno & G_UNIQ) && !is_human(&mons[mntmp])
 #ifdef MAIL
@@ -4106,11 +4483,6 @@ typfnd:
                 )
                 otmp->corpsenm = mntmp;
             break;
-        case EGG:
-            mntmp = can_be_hatched(mntmp);
-            /* this also sets hatch timer if appropriate */
-            set_corpsenm(otmp, mntmp);
-            break;
         case STATUE:
             otmp->corpsenm = mntmp;
             if (Has_contents(otmp) && verysmall(&mons[mntmp]))
@@ -4140,15 +4512,19 @@ typfnd:
         curse(otmp);
     }
 
-    /* set eroded */
-    if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) {
+    /* set eroded and erodeproof */
+    if (erosion_matters(otmp)) {
         if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
             otmp->oeroded = eroded;
         if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
             otmp->oeroded2 = eroded2;
-
-        /* set erodeproof */
-        if (erodeproof && !eroded && !eroded2)
+        /*
+         * 3.6.1: earlier versions included `&& !eroded && !eroded2' here,
+         * but damageproof combined with damaged is feasible (eroded
+         * armor modified by confused reading of cursed destroy armor)
+         * so don't prevent player from wishing for such a combination.
+         */
+        if (erodeproof && (is_damageable(otmp) || otmp->otyp == CRYSKNIFE))
             otmp->oerodeproof = (Luck >= 0 || wizard);
     }
 
@@ -4173,6 +4549,28 @@ typfnd:
         if (Is_box(otmp) || typ == TIN)
             otmp->otrapped = (trapped == 1);
     }
+    /* empty for containers rather than for tins */
+    if (contents == EMPTY) {
+        if (otmp->otyp == BAG_OF_TRICKS || otmp->otyp == HORN_OF_PLENTY) {
+            if (otmp->spe > 0)
+                otmp->spe = 0;
+        } else if (Has_contents(otmp)) {
+            /* this assumes that artifacts can't be randomly generated
+               inside containers */
+            delete_contents(otmp);
+            otmp->owt = weight(otmp);
+        }
+    }
+    /* set locked/unlocked/broken */
+    if (Is_box(otmp)) {
+        if (locked) {
+            otmp->olocked = 1, otmp->obroken = 0;
+        } else if (unlocked) {
+            otmp->olocked = 0, otmp->obroken = 0;
+        } else if (broken) {
+            otmp->olocked = 0, otmp->obroken = 1;
+        }
+    }
 
     if (isgreased)
         otmp->greased = 1;
@@ -4193,7 +4591,7 @@ typfnd:
         if (aname && objtyp == otmp->otyp)
             name = aname;
 
-        /* 3.6.0 tribute - fix up novel */
+        /* 3.6 tribute - fix up novel */
         if (otmp->otyp == SPE_NOVEL) {
             const char *novelname;
 
@@ -4203,7 +4601,8 @@ typfnd:
         }
 
         otmp = oname(otmp, name);
-        if (otmp->oartifact) {
+        /* name==aname => wished for artifact (otmp->oartifact => got it) */
+        if (otmp->oartifact || name == aname) {
             otmp->quan = 1L;
             u.uconduct.wisharti++; /* KMH, conduct */
         }
@@ -4233,7 +4632,11 @@ typfnd:
     }
     otmp->owt = weight(otmp);
     if (very && otmp->otyp == HEAVY_IRON_BALL)
-        otmp->owt += 160;
+        otmp->owt += IRON_BALL_W_INCR;
+    else if (gsize > 1 && otmp->globby)
+        /* 0: unspecified => small; 1: small => keep default owt of 20;
+           2: medium => 120; 3: large => 320; 4: very large => 520 */
+        otmp->owt += 100 + (gsize - 2) * 200;
 
     return otmp;
 }
@@ -4354,15 +4757,14 @@ const char *
 mimic_obj_name(mtmp)
 struct monst *mtmp;
 {
-    if (mtmp->m_ap_type == M_AP_OBJECT
-        && mtmp->mappearance != STRANGE_OBJECT) {
-        int idx = objects[mtmp->mappearance].oc_descr_idx;
+    if (mtmp->m_ap_type == M_AP_OBJECT) {
         if (mtmp->mappearance == GOLD_PIECE)
 /*JP
             return "gold";
 */
             return "\8bà\89Ý";
-        return obj_descr[idx].oc_name;
+        if (mtmp->mappearance != STRANGE_OBJECT)
+            return simple_typename(mtmp->mappearance);
     }
 /*JP
     return "whatcha-may-callit";
index 4b7a92d..20a0e88 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 options.c       $NHDT-Date: 1448241657 2015/11/23 01:20:57 $  $NHDT-Branch: master $:$NHDT-Revision: 1.243 $ */
+/* NetHack 3.6 options.c       $NHDT-Date: 1510963525 2017/11/18 00:05:25 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.319 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2008. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -32,11 +33,13 @@ NEARDATA struct instance_flags iflags; /* provide linkage */
 #define PREFER_TILED FALSE
 #endif
 
-#define MESSAGE_OPTION 1
-#define STATUS_OPTION 2
-#define MAP_OPTION 3
-#define MENU_OPTION 4
-#define TEXT_OPTION 5
+enum window_option_types {
+    MESSAGE_OPTION = 1,
+    STATUS_OPTION,
+    MAP_OPTION,
+    MENU_OPTION,
+    TEXT_OPTION
+};
 
 #define PILE_LIMIT_DFLT 5
 
@@ -80,6 +83,7 @@ static struct Bool_Opt {
 #else
     { "asksavedisk", (boolean *) 0, FALSE, SET_IN_FILE },
 #endif
+    { "autodescribe", &iflags.autodescribe, FALSE, SET_IN_GAME },
     { "autodig", &flags.autodig, FALSE, SET_IN_GAME },
     { "autoopen", &flags.autoopen, TRUE, SET_IN_GAME },
     { "autopickup", &flags.pickup, TRUE, SET_IN_GAME },
@@ -110,8 +114,7 @@ static struct Bool_Opt {
 #endif
     { "confirm", &flags.confirm, TRUE, SET_IN_GAME },
     { "dark_room", &flags.dark_room, TRUE, SET_IN_GAME },
-    { "eight_bit_tty", &iflags.wc_eight_bit_input, FALSE,
-      SET_IN_GAME }, /*WC*/
+    { "eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME }, /*WC*/
 #ifdef TTY_GRAPHICS
     { "extmenu", &iflags.extmenu, FALSE, SET_IN_GAME },
 #else
@@ -129,10 +132,14 @@ static struct Bool_Opt {
 #else
     { "flush", (boolean *) 0, FALSE, SET_IN_FILE },
 #endif
+    { "force_invmenu", &iflags.force_invmenu, FALSE, SET_IN_GAME },
     { "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE },
+    { "goldX", &iflags.goldX, FALSE, SET_IN_GAME },
     { "help", &flags.help, TRUE, SET_IN_GAME },
+    { "herecmd_menu", &iflags.herecmd_menu, FALSE, SET_IN_GAME },
     { "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/
     { "hilite_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME },
+    { "hitpointbar", &iflags.wc2_hitpointbar, FALSE, SET_IN_GAME }, /*WC2*/
 #ifndef MAC
     { "ignintr", &flags.ignintr, FALSE, SET_IN_GAME },
 #else
@@ -151,8 +158,13 @@ static struct Bool_Opt {
     { "mention_walls", &iflags.mention_walls, FALSE, SET_IN_GAME },
     { "menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME },
     /* for menu debugging only*/
-    { "menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME },
+    { "menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_WIZGAME },
     { "menu_objsyms", &iflags.menu_head_objsym, FALSE, SET_IN_GAME },
+#ifdef TTY_GRAPHICS
+    { "menu_overlay", &iflags.menu_overlay, TRUE, SET_IN_GAME },
+#else
+    { "menu_overlay", (boolean *) 0, FALSE, SET_IN_FILE },
+#endif
     { "mouse_support", &iflags.wc_mouse_support, TRUE, DISP_IN_GAME }, /*WC*/
 #ifdef NEWS
     { "news", &iflags.news, TRUE, DISP_IN_GAME },
@@ -187,7 +199,7 @@ static struct Bool_Opt {
       DISP_IN_GAME },
 #endif
     { "safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME },
-    { "sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME },
+    { "sanity_check", &iflags.sanity_check, FALSE, SET_IN_WIZGAME },
     { "selectsaved", &iflags.wc2_selectsaved, TRUE, DISP_IN_GAME }, /*WC*/
     { "showexp", &flags.showexp, FALSE, SET_IN_GAME },
     { "showrace", &flags.showrace, FALSE, SET_IN_GAME },
@@ -202,11 +214,7 @@ static struct Bool_Opt {
     { "sparkle", &flags.sparkle, TRUE, SET_IN_GAME },
     { "splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME }, /*WC*/
     { "standout", &flags.standout, FALSE, SET_IN_GAME },
-#if defined(STATUS_VIA_WINDOWPORT) && defined(STATUS_HILITES)
-    { "statushilites", &iflags.use_status_hilites, TRUE, SET_IN_GAME },
-#else
-    { "statushilites", &iflags.use_status_hilites, FALSE, DISP_IN_GAME },
-#endif
+    { "status_updates", &iflags.status_updates, TRUE, DISP_IN_GAME },
     { "tiled_map", &iflags.wc_tiled_map, PREFER_TILED, DISP_IN_GAME }, /*WC*/
     { "time", &flags.time, FALSE, SET_IN_GAME },
 #ifdef TIMED_DELAY
@@ -224,6 +232,14 @@ static struct Bool_Opt {
     { "use_inverse", &iflags.wc_inverse, FALSE, SET_IN_GAME }, /*WC*/
 #endif
     { "verbose", &flags.verbose, TRUE, SET_IN_GAME },
+#ifdef TTY_TILES_ESCCODES
+    { "vt_tiledata", &iflags.vt_tiledata, FALSE, SET_IN_FILE },
+#else
+    { "vt_tiledata", (boolean *) 0, FALSE, SET_IN_FILE },
+#endif
+    { "whatis_menu", &iflags.getloc_usemenu, FALSE, SET_IN_GAME },
+    { "whatis_moveskip", &iflags.getloc_moveskip, FALSE, SET_IN_GAME },
+    { "wizweight", &iflags.wizweight, FALSE, SET_IN_WIZGAME },
     { "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME },
 #ifdef ZEROCOMP
     { "zerocomp", &iflags.zerocomp,
@@ -272,7 +288,7 @@ static struct Comp_Opt {
     { "boulder", "deprecated (use S_boulder in sym file instead)", 1,
 */
     { "boulder",  "\8b\90\8aâ\82ð\95\\8e¦\82·\82é\83V\83\93\83{\83\8b\95\8e\9a", 1,
-      SET_IN_FILE },
+      SET_IN_GAME },
 #endif
 /*JP
     { "catname", "the name of your (first) cat (e.g., catname:Tabby)",
@@ -564,6 +580,13 @@ static struct Comp_Opt {
 */
     { "soundcard", "\8eg\97p\82µ\82Ä\82¢\82é\83T\83E\83\93\83h\83J\81[\83h\82Ì\8eí\97Þ", 20, SET_IN_FILE },
 #endif
+#ifdef STATUS_HILITES
+    { "statushilites",
+      "0=no status highlighting, N=show highlights for N turns",
+      20, SET_IN_GAME },
+#else
+    { "statushilites", "highlight control", 20, SET_IN_FILE },
+#endif
 #if 0 /*JP*/
     { "symset", "load a set of display symbols from the symbols file", 70,
       SET_IN_GAME },
@@ -580,6 +603,12 @@ static struct Comp_Opt {
       "symbols\83t\83@\83C\83\8b\82©\82ç\83\8d\81[\83O\83\8c\83x\83\8b\82Ì\95\\8e¦\83V\83\93\83{\83\8b\82Ì\90Ý\92è\82ð\93Ç\82Ý\8d\9e\82Þ", 70,
       SET_IN_GAME },
 #endif
+#ifdef WIN32
+/*JP
+    { "subkeyvalue", "override keystroke value", 7, SET_IN_FILE },
+*/
+    {"subkeyvalue", "\83L\81[\83}\83b\83s\83\93\83O\82ð\95Ï\8dX\82·\82é", 7, SET_IN_FILE },
+#endif
 /*JP
     { "suppress_alert", "suppress alerts about version-specific features", 8,
 */
@@ -588,7 +617,7 @@ static struct Comp_Opt {
 #if 0 /*JP*/
     { "tile_width", "width of tiles", 20, DISP_IN_GAME },   /*WC*/
 #else
-    { "tile_width", "\83^\83C\83\8b\82Ì\95\9d", 20, DISP_IN_GAME }, /*WC*/
+    { "tile_width", "\83^\83C\83\8b\82Ì\95\9d", 20, DISP_IN_GAME },   /*WC*/
 #endif
 #if 0 /*JP*/
     { "tile_height", "height of tiles", 20, DISP_IN_GAME }, /*WC*/
@@ -628,18 +657,18 @@ static struct Comp_Opt {
     { "videoshades", "\95\\8e¦\82É\83O\83\8c\83C\83X\83P\81[\83\8b\82ð\97p\82¢\82é", 32,
       DISP_IN_GAME },
 #endif
-#ifdef WIN32
-/*JP
-    { "subkeyvalue", "override keystroke value", 7, SET_IN_FILE },
-*/
-    {"subkeyvalue", "\83L\81[\83}\83b\83s\83\93\83O\82ð\95Ï\8dX\82·\82é", 7, SET_IN_FILE },
-#endif
+    { "whatis_coord", "show coordinates when auto-describing cursor position",
+      1, SET_IN_GAME },
+    { "whatis_filter",
+      "filter coordinate locations when targeting next or previous",
+      1, SET_IN_GAME },
 #if 0 /*JP*/
     { "windowcolors", "the foreground/background colors of windows", /*WC*/
+      80, DISP_IN_GAME },
 #else
-    { "windowcolors",  "\83E\83B\83\93\83h\83E\82ð\8ew\92è\82µ\82½\91O\8ci\90F/\94w\8ci\90F\82Å\95\\8e¦\82·\82é", /*WC*/
-#endif
+    { "windowcolors", "\83E\83B\83\93\83h\83E\82ð\8ew\92è\82µ\82½\91O\8ci\90F/\94w\8ci\90F\82Å\95\\8e¦\82·\82é", /*WC*/
       80, DISP_IN_GAME },
+#endif
 /*JP
     { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME },
 */
@@ -677,6 +706,8 @@ static struct Comp_Opt {
 
 #else /* use rest of file */
 
+extern char configfile[]; /* for messages */
+
 extern struct symparse loadsyms[];
 static boolean need_redraw; /* for doset() */
 
@@ -724,21 +755,22 @@ static char def_inv_order[MAXOCLASSES] = {
 typedef struct {
     const char *name;
     char cmd;
+    const char *desc;
 } menu_cmd_t;
 
-#define NUM_MENU_CMDS 11
-static const menu_cmd_t default_menu_cmd_info[NUM_MENU_CMDS] = {
-/* 0*/  { "menu_first_page", MENU_FIRST_PAGE },
       { "menu_last_page", MENU_LAST_PAGE },
       { "menu_next_page", MENU_NEXT_PAGE },
       { "menu_previous_page", MENU_PREVIOUS_PAGE },
       { "menu_select_all", MENU_SELECT_ALL },
-/* 5*/  { "menu_deselect_all", MENU_UNSELECT_ALL },
       { "menu_invert_all", MENU_INVERT_ALL },
       { "menu_select_page", MENU_SELECT_PAGE },
-        { "menu_deselect_page", MENU_UNSELECT_PAGE },
       { "menu_invert_page", MENU_INVERT_PAGE },
-/*10*/  { "menu_search", MENU_SEARCH },
+static const menu_cmd_t default_menu_cmd_info[] = {
+ { "menu_first_page", MENU_FIRST_PAGE, "Go to first page" },
+ { "menu_last_page", MENU_LAST_PAGE, "Go to last page" },
{ "menu_next_page", MENU_NEXT_PAGE, "Go to next page" },
{ "menu_previous_page", MENU_PREVIOUS_PAGE, "Go to previous page" },
{ "menu_select_all", MENU_SELECT_ALL, "Select all items" },
{ "menu_deselect_all", MENU_UNSELECT_ALL, "Unselect all items" },
+ { "menu_invert_all", MENU_INVERT_ALL, "Invert selection" },
{ "menu_select_page", MENU_SELECT_PAGE, "Select items in current page" },
{ "menu_deselect_page", MENU_UNSELECT_PAGE,
+   "Unselect items in current page" },
{ "menu_invert_page", MENU_INVERT_PAGE, "Invert current page selection" },
+ { "menu_search", MENU_SEARCH, "Search and toggle matching items" },
 };
 
 /*
@@ -752,45 +784,49 @@ static short n_menu_mapped = 0;
 
 static boolean initial, from_file;
 
-STATIC_DCL void FDECL(doset_add_menu, (winid, const char *, int));
 STATIC_DCL void FDECL(nmcpy, (char *, const char *, int));
 STATIC_DCL void FDECL(escapes, (const char *, char *));
 STATIC_DCL void FDECL(rejectoption, (const char *));
-STATIC_DCL void FDECL(badoption, (const char *));
 STATIC_DCL char *FDECL(string_for_opt, (char *, BOOLEAN_P));
 STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *, BOOLEAN_P));
 STATIC_DCL void FDECL(bad_negation, (const char *, BOOLEAN_P));
 STATIC_DCL int FDECL(change_inv_order, (char *));
-STATIC_DCL void FDECL(oc_to_str, (char *, char *));
+STATIC_DCL boolean FDECL(warning_opts, (char *, const char *));
 STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *));
-STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *));
-STATIC_DCL boolean FDECL(special_handling, (const char *,
-                                            BOOLEAN_P, BOOLEAN_P));
-STATIC_DCL void FDECL(warning_opts, (char *, const char *));
 STATIC_DCL boolean FDECL(duplicate_opt_detection, (const char *, int));
 STATIC_DCL void FDECL(complain_about_duplicate, (const char *, int));
 
-STATIC_OVL void FDECL(wc_set_font_name, (int, char *));
-STATIC_OVL int FDECL(wc_set_window_colors, (char *));
-STATIC_OVL boolean FDECL(is_wc_option, (const char *));
-STATIC_OVL boolean FDECL(wc_supported, (const char *));
-STATIC_OVL boolean FDECL(is_wc2_option, (const char *));
-STATIC_OVL boolean FDECL(wc2_supported, (const char *));
-STATIC_DCL void FDECL(remove_autopickup_exception,
-                      (struct autopickup_exception *));
-STATIC_OVL int FDECL(count_ape_maps, (int *, int *));
 STATIC_DCL const char *FDECL(attr2attrname, (int));
-STATIC_DCL int NDECL(query_color);
-STATIC_DCL int NDECL(query_msgtype);
-STATIC_DCL int FDECL(query_attr, (const char *));
 STATIC_DCL const char * FDECL(msgtype2name, (int));
+STATIC_DCL int NDECL(query_msgtype);
 STATIC_DCL boolean FDECL(msgtype_add, (int, char *));
 STATIC_DCL void FDECL(free_one_msgtype, (int));
 STATIC_DCL int NDECL(msgtype_count);
+STATIC_DCL boolean FDECL(test_regex_pattern, (const char *, const char *));
 STATIC_DCL boolean FDECL(add_menu_coloring_parsed, (char *, int, int));
 STATIC_DCL void FDECL(free_one_menu_coloring, (int));
 STATIC_DCL int NDECL(count_menucolors);
+STATIC_DCL boolean FDECL(parse_role_opts, (BOOLEAN_P, const char *,
+                                           char *, char **));
+
+STATIC_DCL void FDECL(oc_to_str, (char *, char *));
+STATIC_DCL void FDECL(doset_add_menu, (winid, const char *, int));
+STATIC_DCL void FDECL(opts_add_others, (winid, const char *, int,
+                                        char *, int));
 STATIC_DCL int FDECL(handle_add_list_remove, (const char *, int));
+STATIC_DCL boolean FDECL(special_handling, (const char *,
+                                            BOOLEAN_P, BOOLEAN_P));
+STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *));
+STATIC_DCL void FDECL(remove_autopickup_exception,
+                      (struct autopickup_exception *));
+STATIC_DCL int FDECL(count_ape_maps, (int *, int *));
+
+STATIC_DCL boolean FDECL(is_wc_option, (const char *));
+STATIC_DCL boolean FDECL(wc_supported, (const char *));
+STATIC_DCL boolean FDECL(is_wc2_option, (const char *));
+STATIC_DCL boolean FDECL(wc2_supported, (const char *));
+STATIC_DCL void FDECL(wc_set_font_name, (int, char *));
+STATIC_DCL int FDECL(wc_set_window_colors, (char *));
 
 void
 reglyph_darkroom()
@@ -838,10 +874,13 @@ boolean val_allowed;
 
         if (!p || (q && q < p))
             p = q;
-        while (p && p > user_string && isspace((uchar) * (p - 1)))
-            p--;
-        if (p)
+        if (p) {
+            /* 'user_string' hasn't necessarily been through mungspaces()
+               so might have tabs or consecutive spaces */
+            while (p > user_string && isspace((uchar) *(p - 1)))
+                p--;
             len = (int) (p - user_string);
+        }
     }
 
     return (boolean) (len >= min_length
@@ -877,17 +916,20 @@ initoptions()
 #ifdef SYSCF_FILE
     /* If SYSCF_FILE is specified, it _must_ exist... */
     assure_syscf_file();
+    config_error_init(TRUE, SYSCF_FILE, FALSE);
+
     /* ... and _must_ parse correctly. */
     if (!read_config_file(SYSCF_FILE, SET_IN_SYS)) {
-        raw_printf("Error(s) found in SYSCF_FILE, quitting.");
-        terminate(EXIT_FAILURE);
+        if (config_error_done())
+            nh_terminate(EXIT_FAILURE);
     }
+    config_error_done();
     /*
      * TODO [maybe]: parse the sysopt entries which are space-separated
      * lists of usernames into arrays with one name per element.
      */
 #endif
-#endif
+#endif /* SYSCF */
     initoptions_finish();
 }
 
@@ -944,10 +986,11 @@ initoptions_init()
     iflags.prevmsg_window = 's';
 #endif
     iflags.menu_headings = ATR_INVERSE;
+    iflags.getpos_coords = GPCOORDS_NONE;
 
     /* hero's role, race, &c haven't been chosen yet */
-    flags.initrole = flags.initrace = flags.initgend = flags.initalign =
-        ROLE_NONE;
+    flags.initrole = flags.initrace = flags.initgend = flags.initalign
+        ROLE_NONE;
 
     /* Set the default monster and object class symbols. */
     init_symbols();
@@ -957,6 +1000,12 @@ initoptions_init()
 
     iflags.travelcc.x = iflags.travelcc.y = -1;
 
+    /* for "special achievement" tracking (see obj.h,
+       create_object(sp_lev.c), addinv_core1(invent.c) */
+    iflags.mines_prize_type = LUCKSTONE;
+    iflags.soko_prize_type1 = BAG_OF_HOLDING;
+    iflags.soko_prize_type2 = AMULET_OF_REFLECTION;
+
     /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */
     (void) memcpy((genericptr_t) flags.inv_order,
                   (genericptr_t) def_inv_order, sizeof flags.inv_order);
@@ -1026,18 +1075,29 @@ initoptions_finish()
             if (*opts == '@')
                 opts++; /* @filename */
             /* looks like a filename */
-            if (strlen(opts) < BUFSZ / 2)
+            if (strlen(opts) < BUFSZ / 2) {
+                config_error_init(TRUE, opts, CONFIG_ERROR_SECURE);
                 read_config_file(opts, SET_IN_FILE);
+                config_error_done();
+            }
         } else {
+            config_error_init(TRUE, (char *) 0, FALSE);
             read_config_file((char *) 0, SET_IN_FILE);
+            config_error_done();
             /* let the total length of options be long;
              * parseoptions() will check each individually
              */
-            parseoptions(opts, TRUE, FALSE);
+            config_error_init(FALSE, "NETHACKOPTIONS", FALSE);
+            (void) parseoptions(opts, TRUE, FALSE);
+            config_error_done();
         }
     } else
-#endif
+#endif /* !MAC */
+    /*else*/ {
+        config_error_init(TRUE, (char *) 0, FALSE);
         read_config_file((char *) 0, SET_IN_FILE);
+        config_error_done();
+    }
 
     (void) fruitadd(pl_fruit, (struct fruit *) 0);
     /*
@@ -1051,6 +1111,19 @@ initoptions_finish()
     if (iflags.bouldersym)
         update_bouldersym();
     reglyph_darkroom();
+
+#ifdef STATUS_HILITES
+    /*
+     * A multi-interface binary might only support status highlighting
+     * for some of the interfaces; check whether we asked for it but are
+     * using one which doesn't.
+     */
+    if (iflags.hilite_delta && !wc2_supported("statushilites")) {
+        raw_printf("Status highlighting not supported for %s interface.",
+                   windowprocs.name);
+        iflags.hilite_delta = 0;
+    }
+#endif
     return;
 }
 
@@ -1077,6 +1150,10 @@ int maxlen;
  * has the effect of 'meta'-ing the value which follows (so that the
  * alternate character set will be enabled).
  *
+ * X     normal key X
+ * ^X    control-X
+ * \mX   meta-X
+ *
  * For 3.4.3 and earlier, input ending with "\M", backslash, or caret
  * prior to terminating '\0' would pull that '\0' into the output and then
  * keep processing past it, potentially overflowing the output buffer.
@@ -1110,8 +1187,8 @@ char *tp;
         } else if (*cp == '^') { /* expand control-character syntax */
             cval = (*++cp & 0x1f);
             ++cp;
-            /* remaining cases are all for backslash and we know cp[1] is not
-             * \0 */
+
+        /* remaining cases are all for backslash; we know cp[1] is not \0 */
         } else if (index(dec, cp[1])) {
             ++cp; /* move past backslash to first digit */
             do {
@@ -1164,47 +1241,31 @@ rejectoption(optname)
 const char *optname;
 {
 #ifdef MICRO
-    pline("\"%s\" settable only from %s.", optname, lastconfigfile);
+    pline("\"%s\" settable only from %s.", optname, configfile);
 #else
     pline("%s can be set only from NETHACKOPTIONS or %s.", optname,
-          lastconfigfile);
+          configfile);
 #endif
 }
 
-STATIC_OVL void
-badoption(opts)
-const char *opts;
-{
-    if (!initial) {
-        if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1))
-            option_help();
-        else
-            pline("Bad syntax: %s.  Enter \"?g\" for help.", opts);
-        return;
-    }
-#ifdef MAC
-    else
-        return;
-#endif
+/*
 
-    if (from_file)
-        raw_printf("Bad syntax in OPTIONS in %s: %s%s.\n", lastconfigfile,
-#ifdef WIN32
-                    "\n",
-#else
-                    "",
-#endif
-                    opts);
-    else
-        raw_printf("Bad syntax in NETHACKOPTIONS: %s%s.\n",
-#ifdef WIN32
-                    "\n",
-#else
-                    "",
-#endif
-                    opts);
-    wait_synch();
-}
+# errors:
+OPTIONS=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+OPTIONS
+OPTIONS=
+MSGTYPE=stop"You swap places with "
+MSGTYPE=st.op "You swap places with "
+MSGTYPE=stop "You swap places with \"
+MENUCOLOR=" blessed "green&none
+MENUCOLOR=" holy " = green&reverse
+MENUCOLOR=" cursed " = red&uline
+MENUCOLOR=" unholy " = reed
+OPTIONS=!legacy:true,fooo
+OPTIONS=align:!pin
+OPTIONS=gender
+
+*/
 
 STATIC_OVL char *
 string_for_opt(opts, val_optional)
@@ -1220,7 +1281,7 @@ boolean val_optional;
 
     if (!colon || !*++colon) {
         if (!val_optional)
-            badoption(opts);
+            config_error_add("Missing parameter for '%s'", opts);
         return (char *) 0;
     }
     return colon;
@@ -1262,35 +1323,50 @@ change_inv_order(op)
 char *op;
 {
     int oc_sym, num;
-    char *sp, buf[BUFSZ];
+    char *sp, buf[QBUFSZ];
+    int retval = 1;
 
     num = 0;
-    /*  !!!! probably unnecessary with gold as normal inventory */
+    if (!index(op, GOLD_SYM))
+        buf[num++] = COIN_CLASS;
 
     for (sp = op; *sp; sp++) {
+        boolean fail = FALSE;
         oc_sym = def_char_to_objclass(*sp);
         /* reject bad or duplicate entries */
-        if (oc_sym == MAXOCLASSES || oc_sym == RANDOM_CLASS
-            || oc_sym == ILLOBJ_CLASS || !index(flags.inv_order, oc_sym)
-            || index(sp + 1, *sp))
-            return 0;
+        if (oc_sym == MAXOCLASSES) { /* not an object class char */
+            config_error_add("Not an object class '%c'", *sp);
+            retval = 0;
+            fail = TRUE;
+        } else if (!index(flags.inv_order, oc_sym)) {
+            /* VENOM_CLASS, RANDOM_CLASS, and ILLOBJ_CLASS are excluded
+               because they aren't in def_inv_order[] so don't make it
+               into flags.inv_order, hence always fail this index() test */
+            config_error_add("Object class '%c' not allowed", *sp);
+            retval = 0;
+            fail = TRUE;
+        } else if (index(sp + 1, *sp)) {
+            config_error_add("Duplicate object class '%c'", *sp);
+            retval = 0;
+            fail = TRUE;
+        }
         /* retain good ones */
-        buf[num++] = (char) oc_sym;
+        if (!fail)
+            buf[num++] = (char) oc_sym;
     }
     buf[num] = '\0';
 
     /* fill in any omitted classes, using previous ordering */
     for (sp = flags.inv_order; *sp; sp++)
-        if (!index(buf, *sp)) {
-            buf[num++] = *sp;
-            buf[num] = '\0'; /* explicitly terminate for next index() */
-        }
+        if (!index(buf, *sp))
+            (void) strkitten(&buf[num++], *sp);
+    buf[MAXOCLASSES - 1] = '\0';
 
     Strcpy(flags.inv_order, buf);
-    return 1;
+    return retval;
 }
 
-STATIC_OVL void
+STATIC_OVL boolean
 warning_opts(opts, optype)
 register char *opts;
 const char *optype;
@@ -1299,7 +1375,7 @@ const char *optype;
     int length, i;
 
     if (!(opts = string_for_env_opt(optype, opts, FALSE)))
-        return;
+        return FALSE;
     escapes(opts, opts);
 
     length = (int) strlen(opts);
@@ -1309,6 +1385,7 @@ const char *optype;
                                      : opts[i] ? (uchar) opts[i]
                                                : def_warnsyms[i].sym;
     assign_warnings(translate);
+    return TRUE;
 }
 
 void
@@ -1328,26 +1405,22 @@ char *op;
 const char *optn;
 {
     char buf[BUFSZ];
-    boolean rejectver = FALSE;
     unsigned long fnv = get_feature_notice_ver(op); /* version.c */
 
     if (fnv == 0L)
         return 0;
-    if (fnv > get_current_feature_ver())
-        rejectver = TRUE;
-    else
-        flags.suppress_alert = fnv;
-    if (rejectver) {
+    if (fnv > get_current_feature_ver()) {
         if (!initial) {
             You_cant("disable new feature alerts for future versions.");
         } else {
-            Sprintf(buf,
-                    "\n%s=%s Invalid reference to a future version ignored",
-                    optn, op);
-            badoption(buf);
+            config_error_add(
+                        "%s=%s Invalid reference to a future version ignored",
+                             optn, op);
         }
         return 0;
     }
+
+    flags.suppress_alert = fnv;
     if (!initial) {
         Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
                 FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
@@ -1368,14 +1441,14 @@ int on_or_off;
         /*-- ON --*/
         if (iflags.opt_booldup)
             impossible("iflags.opt_booldup already on (memory leak)");
-        iflags.opt_booldup = (int *) alloc(SIZE(boolopt) * sizeof(int));
+        iflags.opt_booldup = (int *) alloc(SIZE(boolopt) * sizeof (int));
         optptr = iflags.opt_booldup;
         for (k = 0; k < SIZE(boolopt); ++k)
             *optptr++ = 0;
 
         if (iflags.opt_compdup)
             impossible("iflags.opt_compdup already on (memory leak)");
-        iflags.opt_compdup = (int *) alloc(SIZE(compopt) * sizeof(int));
+        iflags.opt_compdup = (int *) alloc(SIZE(compopt) * sizeof (int));
         optptr = iflags.opt_compdup;
         for (k = 0; k < SIZE(compopt); ++k)
             *optptr++ = 0;
@@ -1435,9 +1508,8 @@ int iscompound; /* 0 == boolean option, 1 == compound */
      * For now just return.
      */
 #else /* !MAC */
-    raw_printf("\nWarning - %s option specified multiple times: %s.\n",
-               iscompound ? "compound" : "boolean", opts);
-    wait_synch();
+    config_error_add("%s option specified multiple times: %s",
+                     iscompound ? "compound" : "boolean", opts);
 #endif /* ?MAC */
     return;
 }
@@ -1455,7 +1527,10 @@ STATIC_VAR const struct paranoia_opts {
        takes precedence and "all" isn't present in the interactive menu,
        and "d"ie vs "d"eath, synonyms for each other so doesn't matter;
        (also "p"ray vs "P"aranoia, "pray" takes precedence since "Paranoia"
-       is just a synonym for "Confirm") */
+       is just a synonym for "Confirm"); "b"ones vs "br"eak-wand, the
+       latter requires at least two letters; "wand"-break vs "Were"-change,
+       both require at least two letters during config processing and use
+       case-senstivity for 'O's interactive menu */
     { PARANOID_CONFIRM, "Confirm", 1, "Paranoia", 2,
       "for \"yes\" confirmations, require \"no\" to reject" },
     { PARANOID_QUIT, "quit", 1, "explore", 1,
@@ -1466,12 +1541,14 @@ STATIC_VAR const struct paranoia_opts {
       "yes vs y to save bones data when dying in debug mode" },
     { PARANOID_HIT, "attack", 1, "hit", 1,
       "yes vs y to attack a peaceful monster" },
+    { PARANOID_BREAKWAND, "wand-break", 2, "break-wand", 2,
+      "yes vs y to break a wand via (a)pply" },
+    { PARANOID_WERECHANGE, "Were-change", 2, (const char *) 0, 0,
+      "yes vs y to change form when lycanthropy is controllable" },
     { PARANOID_PRAY, "pray", 1, 0, 0,
       "y to pray (supersedes old \"prayconfirm\" option)" },
     { PARANOID_REMOVE, "Remove", 1, "Takeoff", 1,
       "always pick from inventory for Remove and Takeoff" },
-    { PARANOID_BREAKWAND, "wand", 1, "breakwand", 2,
-      "yes vs y to break a wand" },
     /* for config file parsing; interactive menu skips these */
     { 0, "none", 4, 0, 0, 0 }, /* require full word match */
     { ~0, "all", 3, 0, 0, 0 }, /* ditto */
@@ -1491,14 +1568,25 @@ static const struct {
     { "magenta", CLR_MAGENTA },
     { "cyan", CLR_CYAN },
     { "gray", CLR_GRAY },
-    { "grey", CLR_GRAY },
     { "orange", CLR_ORANGE },
     { "light green", CLR_BRIGHT_GREEN },
     { "yellow", CLR_YELLOW },
     { "light blue", CLR_BRIGHT_BLUE },
     { "light magenta", CLR_BRIGHT_MAGENTA },
     { "light cyan", CLR_BRIGHT_CYAN },
-    { "white", CLR_WHITE }
+    { "white", CLR_WHITE },
+    { "no color", NO_COLOR },
+    { NULL, CLR_BLACK }, /* everything after this is an alias */
+    { "transparent", NO_COLOR },
+    { "purple", CLR_MAGENTA },
+    { "light purple", CLR_BRIGHT_MAGENTA },
+    { "bright purple", CLR_BRIGHT_MAGENTA },
+    { "grey", CLR_GRAY },
+    { "bright red", CLR_ORANGE },
+    { "bright green", CLR_BRIGHT_GREEN },
+    { "bright blue", CLR_BRIGHT_BLUE },
+    { "bright magenta", CLR_BRIGHT_MAGENTA },
+    { "bright cyan", CLR_BRIGHT_CYAN }
 };
 
 static const struct {
@@ -1510,7 +1598,10 @@ static const struct {
     { "dim", ATR_DIM },
     { "underline", ATR_ULINE },
     { "blink", ATR_BLINK },
-    { "inverse", ATR_INVERSE }
+    { "inverse", ATR_INVERSE },
+    { NULL, ATR_NONE }, /* everything after this is an alias */
+    { "normal", ATR_NONE },
+    { "uline", ATR_ULINE }
 };
 
 const char *
@@ -1520,12 +1611,36 @@ int clr;
     int i;
 
     for (i = 0; i < SIZE(colornames); i++)
-        if (colornames[i].color == clr)
+        if (colornames[i].name && colornames[i].color == clr)
             return colornames[i].name;
     return (char *) 0;
 }
 
-const char *
+int
+match_str2clr(str)
+char *str;
+{
+    int i, c = CLR_MAX;
+
+    /* allow "lightblue", "light blue", and "light-blue" to match "light blue"
+       (also junk like "_l i-gh_t---b l u e" but we won't worry about that);
+       also copes with trailing space; mungspaces removed any leading space */
+    for (i = 0; i < SIZE(colornames); i++)
+        if (colornames[i].name
+            && fuzzymatch(str, colornames[i].name, " -_", TRUE)) {
+            c = colornames[i].color;
+            break;
+        }
+    if (i == SIZE(colornames) && (*str >= '0' && *str <= '9'))
+        c = atoi(str);
+
+    if (c == CLR_MAX)
+        config_error_add("Unknown color '%s'", str);
+
+    return c;
+}
+
+STATIC_OVL const char *
 attr2attrname(attr)
 int attr;
 {
@@ -1538,7 +1653,28 @@ int attr;
 }
 
 int
-query_color()
+match_str2attr(str, complain)
+const char *str;
+boolean complain;
+{
+    int i, a = -1;
+
+    for (i = 0; i < SIZE(attrnames); i++)
+        if (attrnames[i].name
+            && fuzzymatch(str, attrnames[i].name, " -_", TRUE)) {
+            a = attrnames[i].attr;
+            break;
+        }
+
+    if (a == -1 && complain)
+        config_error_add("Unknown text attribute '%s'", str);
+
+    return a;
+}
+
+int
+query_color(prompt)
+const char *prompt;
 {
     winid tmpwin;
     anything any;
@@ -1549,13 +1685,13 @@ query_color()
     start_menu(tmpwin);
     any = zeroany;
     for (i = 0; i < SIZE(colornames); i++) {
-        if (!strcmp(colornames[i].name, "grey"))
-            continue;
+        if (!colornames[i].name)
+            break;
         any.a_int = i + 1;
         add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, colornames[i].name,
                  MENU_UNSELECTED);
     }
-    end_menu(tmpwin, "Pick a color");
+    end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick a color");
     pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
     destroy_nhwindow(tmpwin);
     if (pick_cnt > 0) {
@@ -1579,11 +1715,13 @@ const char *prompt;
     start_menu(tmpwin);
     any = zeroany;
     for (i = 0; i < SIZE(attrnames); i++) {
+        if (!attrnames[i].name)
+            break;
         any.a_int = i + 1;
         add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr,
                  attrnames[i].name, MENU_UNSELECTED);
     }
-    end_menu(tmpwin, prompt ? prompt : "Pick an attribute");
+    end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick an attribute");
     pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
     destroy_nhwindow(tmpwin);
     if (pick_cnt > 0) {
@@ -1596,7 +1734,7 @@ const char *prompt;
 
 static const struct {
     const char *name;
-    const xchar msgtyp;
+    xchar msgtyp;
     const char *descr;
 } msgtype_names[] = {
     { "show", MSGTYP_NORMAL, "Show message normally" },
@@ -1607,7 +1745,7 @@ static const struct {
     { "norep", MSGTYP_NOREP, "Do not repeat the message" }
 };
 
-const char *
+STATIC_OVL const char *
 msgtype2name(typ)
 int typ;
 {
@@ -1647,26 +1785,20 @@ query_msgtype()
     return -1;
 }
 
-boolean
+STATIC_OVL boolean
 msgtype_add(typ, pattern)
 int typ;
 char *pattern;
 {
-    struct plinemsg_type *tmp
-              = (struct plinemsg_type *) alloc(sizeof (struct plinemsg_type));
+    struct plinemsg_type
+        *tmp = (struct plinemsg_type *) alloc(sizeof (struct plinemsg_type));
 
-    if (!tmp)
-        return FALSE;
     tmp->msgtype = typ;
     tmp->regex = regex_init();
     if (!regex_compile(pattern, tmp->regex)) {
         static const char *re_error = "MSGTYPE regex error";
 
-        if (!iflags.window_inited)
-            raw_printf("\n%s: %s\n", re_error, regex_error_desc(tmp->regex));
-        else
-            pline("%s: %s", re_error, regex_error_desc(tmp->regex));
-        wait_synch();
+        config_error_add("%s: %s", re_error, regex_error_desc(tmp->regex));
         regex_free(tmp->regex);
         free((genericptr_t) tmp);
         return FALSE;
@@ -1691,7 +1823,7 @@ msgtype_free()
     plinemsg_types = (struct plinemsg_type *) 0;
 }
 
-void
+STATIC_OVL void
 free_one_msgtype(idx)
 int idx; /* 0 .. */
 {
@@ -1718,21 +1850,44 @@ int idx; /* 0 .. */
 }
 
 int
-msgtype_type(msg)
+msgtype_type(msg, norepeat)
 const char *msg;
+boolean norepeat; /* called from Norep(via pline) */
 {
     struct plinemsg_type *tmp = plinemsg_types;
 
     while (tmp) {
+        /* we don't exclude entries with negative msgtype values
+           because then the msg might end up matching a later pattern */
         if (regex_match(msg, tmp->regex))
             return tmp->msgtype;
         tmp = tmp->next;
     }
-    return MSGTYP_NORMAL;
+    return norepeat ? MSGTYP_NOREP : MSGTYP_NORMAL;
 }
 
-int
-msgtype_count()
+/* negate one or more types of messages so that their type handling will
+   be disabled or re-enabled; MSGTYPE_NORMAL (value 0) is not affected */
+void
+hide_unhide_msgtypes(hide, hide_mask)
+boolean hide;
+int hide_mask;
+{
+    struct plinemsg_type *tmp;
+    int mt;
+
+    /* negative msgtype value won't be recognized by pline, so does nothing */
+    for (tmp = plinemsg_types; tmp; tmp = tmp->next) {
+        mt = tmp->msgtype;
+        if (!hide)
+            mt = -mt; /* unhide: negate negative, yielding positive */
+        if (mt > 0 && ((1 << mt) & hide_mask))
+            tmp->msgtype = -tmp->msgtype;
+    }
+}
+
+STATIC_OVL int
+msgtype_count(VOID_ARGS)
 {
     int c = 0;
     struct plinemsg_type *tmp = plinemsg_types;
@@ -1762,10 +1917,41 @@ char *str;
             }
         if (typ != -1)
             return msgtype_add(typ, pattern);
+        else
+            config_error_add("Unknown message type '%s'", msgtype);
+    } else {
+        config_error_add("Malformed MSGTYPE");
     }
     return FALSE;
 }
 
+STATIC_OVL boolean
+test_regex_pattern(str, errmsg)
+const char *str;
+const char *errmsg;
+{
+    static const char re_error[] = "Regex error";
+    struct nhregex *match;
+    boolean retval = TRUE;
+
+    if (!str)
+        return FALSE;
+
+    match = regex_init();
+    if (!match) {
+        config_error_add("NHregex error");
+        return FALSE;
+    }
+
+    if (!regex_compile(str, match)) {
+        config_error_add("%s: %s", errmsg ? errmsg : re_error,
+                         regex_error_desc(match));
+        retval = FALSE;
+    }
+    regex_free(match);
+    return retval;
+}
+
 boolean
 add_menu_coloring_parsed(str, c, a)
 char *str;
@@ -1779,11 +1965,7 @@ int c, a;
     tmp = (struct menucoloring *) alloc(sizeof (struct menucoloring));
     tmp->match = regex_init();
     if (!regex_compile(str, tmp->match)) {
-        if (!iflags.window_inited)
-            raw_printf("\n%s: %s\n", re_error, regex_error_desc(tmp->match));
-        else
-            pline("%s: %s", re_error, regex_error_desc(tmp->match));
-        wait_synch();
+        config_error_add("%s: %s", re_error, regex_error_desc(tmp->match));
         regex_free(tmp->match);
         free(tmp);
         return FALSE;
@@ -1799,47 +1981,34 @@ int c, a;
 
 /* parse '"regex_string"=color&attr' and add it to menucoloring */
 boolean
-add_menu_coloring(str)
-char *str;
+add_menu_coloring(tmpstr)
+char *tmpstr;
 {
-    int i, c = NO_COLOR, a = ATR_NONE;
+    int c = NO_COLOR, a = ATR_NONE;
     char *tmps, *cs, *amp;
+    char str[BUFSZ];
 
-    if (!str || (cs = index(str, '=')) == 0)
+    Sprintf(str, "%s", tmpstr);
+
+    if (!tmpstr || (cs = index(str, '=')) == 0) {
+        config_error_add("Malformed MENUCOLOR");
         return FALSE;
+    }
 
     tmps = cs + 1; /* advance past '=' */
     mungspaces(tmps);
     if ((amp = index(tmps, '&')) != 0)
         *amp = '\0';
 
-    /* allow "lightblue", "light blue", and "light-blue" to match "light blue"
-       (also junk like "_l i-gh_t---b l u e" but we won't worry about that);
-       also copes with trailing space; mungspaces removed any leading space */
-    for (i = 0; i < SIZE(colornames); i++)
-        if (fuzzymatch(tmps, colornames[i].name, " -_", TRUE)) {
-            c = colornames[i].color;
-            break;
-        }
-    if (i == SIZE(colornames) && (*tmps >= '0' && *tmps <= '9'))
-        c = atoi(tmps);
-
-    if (c > 15)
+    c = match_str2clr(tmps);
+    if (c >= CLR_MAX)
         return FALSE;
 
     if (amp) {
         tmps = amp + 1; /* advance past '&' */
-        /* unlike colors, none of he attribute names has any embedded spaces,
-           but use of fuzzymatch() allows us ignore the presence of leading
-           and/or trailing (and also embedded) spaces in the user's string;
-           dash and underscore skipping could be omitted but does no harm */
-        for (i = 0; i < SIZE(attrnames); i++)
-            if (fuzzymatch(tmps, attrnames[i].name, " -_", TRUE)) {
-                a = attrnames[i].attr;
-                break;
-            }
-        if (i == SIZE(attrnames) && (*tmps >= '0' && *tmps <= '9'))
-            a = atoi(tmps);
+        a = match_str2attr(tmps, TRUE);
+        if (a == -1)
+            return FALSE;
     }
 
     /* the regexp portion here has not been condensed by mungspaces() */
@@ -1860,7 +2029,7 @@ char *str;
 
 boolean
 get_menu_coloring(str, color, attr)
-char *str;
+const char *str;
 int *color, *attr;
 {
     struct menucoloring *tmpmc;
@@ -1890,7 +2059,7 @@ free_menu_coloring()
     }
 }
 
-void
+STATIC_OVL void
 free_one_menu_coloring(idx)
 int idx; /* 0 .. */
 {
@@ -1916,8 +2085,8 @@ int idx; /* 0 .. */
     }
 }
 
-int
-count_menucolors()
+STATIC_OVL int
+count_menucolors(VOID_ARGS)
 {
     int count = 0;
     struct menucoloring *tmp = menu_colorings;
@@ -1929,26 +2098,86 @@ count_menucolors()
     return count;
 }
 
-void
+STATIC_OVL boolean
+parse_role_opts(negated, fullname, opts, opp)
+boolean negated;
+const char *fullname;
+char *opts;
+char **opp;
+{
+    char *op = *opp;
+
+    if (negated) {
+        bad_negation(fullname, FALSE);
+    } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
+        boolean val_negated = FALSE;
+
+        while ((*op == '!') || !strncmpi(op, "no", 2)) {
+            if (*op == '!')
+                op++;
+            else
+                op += 2;
+            val_negated = !val_negated;
+        }
+        if (val_negated) {
+            if (!setrolefilter(op)) {
+                config_error_add("Unknown negated parameter '%s'", op);
+                return FALSE;
+            }
+        } else {
+            if (duplicate_opt_detection(opts, 1))
+                complain_about_duplicate(opts, 1);
+            *opp = op;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/* Check if character c is illegal as a menu command key */
+boolean
+illegal_menu_cmd_key(c)
+char c;
+{
+    if (c == 0 || c == '\r' || c == '\n' || c == '\033'
+        || c == ' ' || digit(c) || (letter(c) && c != '@')) {
+        config_error_add("Reserved menu command key '%s'", visctrl(c));
+        return TRUE;
+    } else { /* reject default object class symbols */
+        int j;
+        for (j = 1; j < MAXOCLASSES; j++)
+            if (c == def_oc_syms[j].sym) {
+                config_error_add("Menu command key '%s' is an object class",
+                                 visctrl(c));
+                return TRUE;
+            }
+    }
+    return FALSE;
+}
+
+boolean
 parseoptions(opts, tinitial, tfrom_file)
 register char *opts;
 boolean tinitial, tfrom_file;
 {
-    register char *op;
+    char *op;
     unsigned num;
-    boolean negated, val_negated, duplicate;
+    boolean negated, duplicate;
     int i;
     const char *fullname;
+    boolean retval = TRUE;
 
     initial = tinitial;
     from_file = tfrom_file;
     if ((op = index(opts, ',')) != 0) {
         *op++ = 0;
-        parseoptions(op, initial, from_file);
+        if (!parseoptions(op, initial, from_file))
+            retval = FALSE;
     }
     if (strlen(opts) > BUFSZ / 2) {
-        badoption("option too long");
-        return;
+        config_error_add("Option too long, max length is %i characters",
+                         (BUFSZ / 2));
+        return FALSE;
     }
 
     /* strip leading and trailing white space */
@@ -1958,8 +2187,10 @@ boolean tinitial, tfrom_file;
     while (--op >= opts && isspace((uchar) *op))
         *op = '\0';
 
-    if (!*opts)
-        return;
+    if (!*opts) {
+        config_error_add("Empty statement");
+        return FALSE;
+    }
     negated = FALSE;
     while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
         if (*opts == '!')
@@ -1979,28 +2210,30 @@ boolean tinitial, tfrom_file;
     if (match_optname(opts, "female", 3, FALSE)) {
         if (duplicate_opt_detection(opts, 0))
             complain_about_duplicate(opts, 0);
-        if (!initial && flags.female == negated)
-            pline("That is not anatomically possible.");
-        else
+        if (!initial && flags.female == negated) {
+            config_error_add("That is not anatomically possible.");
+            return FALSE;
+        } else
             flags.initgend = flags.female = !negated;
-        return;
+        return retval;
     }
 
     if (match_optname(opts, "male", 4, FALSE)) {
         if (duplicate_opt_detection(opts, 0))
             complain_about_duplicate(opts, 0);
-        if (!initial && flags.female != negated)
-            pline("That is not anatomically possible.");
-        else
+        if (!initial && flags.female != negated) {
+            config_error_add("That is not anatomically possible.");
+            return FALSE;
+        } else
             flags.initgend = flags.female = negated;
-        return;
+        return retval;
     }
 
 #if defined(MICRO) && !defined(AMIGA)
     /* included for compatibility with old NetHack.cnf files */
     if (match_optname(opts, "IBM_", 4, FALSE)) {
         iflags.BIOS = !negated;
-        return;
+        return retval;
     }
 #endif /* MICRO */
 
@@ -2011,132 +2244,73 @@ boolean tinitial, tfrom_file;
     /* align:string */
     fullname = "align";
     if (match_optname(opts, fullname, sizeof("align") - 1, TRUE)) {
-        if (negated) {
-            bad_negation(fullname, FALSE);
-        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
-            val_negated = FALSE;
-            while ((*op == '!') || !strncmpi(op, "no", 2)) {
-                if (*op == '!')
-                    op++;
-                else
-                    op += 2;
-                val_negated = !val_negated;
-            }
-            if (val_negated) {
-                if (!setrolefilter(op))
-                    badoption(opts);
-            } else {
-                if (duplicate_opt_detection(opts, 1))
-                    complain_about_duplicate(opts, 1);
-                if ((flags.initalign = str2align(op)) == ROLE_NONE)
-                    badoption(opts);
+        if (parse_role_opts(negated, fullname, opts, &op)) {
+            if ((flags.initalign = str2align(op)) == ROLE_NONE) {
+                config_error_add("Unknown %s '%s'", fullname, op);
+                return FALSE;
             }
-        }
-        return;
+        } else
+            return FALSE;
+        return retval;
     }
 
     /* role:string or character:string */
     fullname = "role";
     if (match_optname(opts, fullname, 4, TRUE)
         || match_optname(opts, (fullname = "character"), 4, TRUE)) {
-        if (negated) {
-            bad_negation(fullname, FALSE);
-        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
-            val_negated = FALSE;
-            while ((*op == '!') || !strncmpi(op, "no", 2)) {
-                if (*op == '!')
-                    op++;
-                else
-                    op += 2;
-                val_negated = !val_negated;
-            }
-            if (val_negated) {
-                if (!setrolefilter(op))
-                    badoption(opts);
-            } else {
-                if (duplicate_opt_detection(opts, 1))
-                    complain_about_duplicate(opts, 1);
-                if ((flags.initrole = str2role(op)) == ROLE_NONE)
-                    badoption(opts);
-                else /* Backwards compatibility */
-                    nmcpy(pl_character, op, PL_NSIZ);
-            }
-        }
-        return;
+        if (parse_role_opts(negated, fullname, opts, &op)) {
+            if ((flags.initrole = str2role(op)) == ROLE_NONE) {
+                config_error_add("Unknown %s '%s'", fullname, op);
+                return FALSE;
+            } else /* Backwards compatibility */
+                nmcpy(pl_character, op, PL_NSIZ);
+        } else
+            return FALSE;
+        return retval;
     }
 
     /* race:string */
     fullname = "race";
     if (match_optname(opts, fullname, 4, TRUE)) {
-        if (negated) {
-            bad_negation(fullname, FALSE);
-        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
-            val_negated = FALSE;
-            while ((*op == '!') || !strncmpi(op, "no", 2)) {
-                if (*op == '!')
-                    op++;
-                else
-                    op += 2;
-                val_negated = !val_negated;
-            }
-            if (val_negated) {
-                if (!setrolefilter(op))
-                    badoption(opts);
-            } else {
-                if (duplicate_opt_detection(opts, 1))
-                    complain_about_duplicate(opts, 1);
-                if ((flags.initrace = str2race(op)) == ROLE_NONE)
-                    badoption(opts);
-                else /* Backwards compatibility */
-                    pl_race = *op;
-            }
-        }
-        return;
+        if (parse_role_opts(negated, fullname, opts, &op)) {
+            if ((flags.initrace = str2race(op)) == ROLE_NONE) {
+                config_error_add("Unknown %s '%s'", fullname, op);
+                return FALSE;
+            } else /* Backwards compatibility */
+                pl_race = *op;
+        } else
+            return FALSE;
+        return retval;
     }
 
     /* gender:string */
     fullname = "gender";
     if (match_optname(opts, fullname, 4, TRUE)) {
-        if (negated) {
-            bad_negation(fullname, FALSE);
-        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
-            val_negated = FALSE;
-            while ((*op == '!') || !strncmpi(op, "no", 2)) {
-                if (*op == '!')
-                    op++;
-                else
-                    op += 2;
-                val_negated = !val_negated;
-            }
-            if (val_negated) {
-                if (!setrolefilter(op))
-                    badoption(opts);
-            } else {
-                if (duplicate_opt_detection(opts, 1))
-                    complain_about_duplicate(opts, 1);
-                if ((flags.initgend = str2gend(op)) == ROLE_NONE)
-                    badoption(opts);
-                else
-                    flags.female = flags.initgend;
-            }
-        }
-        return;
+        if (parse_role_opts(negated, fullname, opts, &op)) {
+            if ((flags.initgend = str2gend(op)) == ROLE_NONE) {
+                config_error_add("Unknown %s '%s'", fullname, op);
+                return FALSE;
+            } else
+                flags.female = flags.initgend;
+        } else
+            return FALSE;
+        return retval;
     }
 
     /* We always check for duplicates on the remaining compound options,
        although individual option processing can choose to complain or not */
 
-    duplicate =
-        duplicate_opt_detection(opts, 1); /* 1 means check compounds */
+    duplicate = duplicate_opt_detection(opts, 1); /* 1: check compounds */
 
     fullname = "pettype";
     if (match_optname(opts, fullname, 3, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
         if ((op = string_for_env_opt(fullname, opts, negated)) != 0) {
-            if (negated)
+            if (negated) {
                 bad_negation(fullname, TRUE);
-            else
+                return FALSE;
+            } else
                 switch (lowc(*op)) {
                 case 'd': /* dog */
                     preferred_pet = 'd';
@@ -2158,52 +2332,61 @@ boolean tinitial, tfrom_file;
                     preferred_pet = '\0';
                     break;
                 default:
-#if 0 /*JP*/
-                    pline("Unrecognized pet type '%s'.", op);
-#else
+/*JP
+                    config_error_add("Unrecognized pet type '%s'.", op);
+*/
                     pline("'%s'\82Í\83y\83b\83g\82Ì\8eí\97Þ\82Æ\82µ\82Ä\8eó\82¯\95t\82¯\82ç\82ê\82Ü\82¹\82ñ\81D", op);
-#endif
+                    return FALSE;
                     break;
                 }
         } else if (negated)
             preferred_pet = 'n';
-        return;
+        return retval;
     }
 
     fullname = "catname";
     if (match_optname(opts, fullname, 3, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
-        if (negated)
+        if (negated) {
             bad_negation(fullname, FALSE);
-        else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
+            return FALSE;
+        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
             nmcpy(catname, op, PL_PSIZ);
+        } else
+            return FALSE;
         sanitize_name(catname);
-        return;
+        return retval;
     }
 
     fullname = "dogname";
     if (match_optname(opts, fullname, 3, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
-        if (negated)
+        if (negated) {
             bad_negation(fullname, FALSE);
-        else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
+            return FALSE;
+        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
             nmcpy(dogname, op, PL_PSIZ);
+        } else
+            return FALSE;
         sanitize_name(dogname);
-        return;
+        return retval;
     }
 
     fullname = "horsename";
     if (match_optname(opts, fullname, 5, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
-        if (negated)
+        if (negated) {
             bad_negation(fullname, FALSE);
-        else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
+            return FALSE;
+        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
             nmcpy(horsename, op, PL_PSIZ);
+        } else
+            return FALSE;
         sanitize_name(horsename);
-        return;
+        return retval;
     }
 
     fullname = "number_pad";
@@ -2221,14 +2404,14 @@ boolean tinitial, tfrom_file;
                 iflags.num_pad_mode = 0;
             }
         } else if (negated) {
-            bad_negation("number_pad", TRUE);
-            return;
+            bad_negation(fullname, TRUE);
+            return FALSE;
         } else {
             int mode = atoi(op);
 
             if (mode < -1 || mode > 4 || (mode == 0 && *op != '0')) {
-                badoption(opts);
-                return;
+                config_error_add("Illegal %s parameter '%s'", fullname, op);
+                return FALSE;
             } else if (mode <= 0) {
                 iflags.num_pad = FALSE;
                 /* German keyboard; y and z keys swapped */
@@ -2246,7 +2429,7 @@ boolean tinitial, tfrom_file;
         }
         reset_commands(FALSE);
         number_pad(iflags.num_pad ? 1 : 0);
-        return;
+        return retval;
     }
 
     fullname = "roguesymset";
@@ -2255,20 +2438,22 @@ boolean tinitial, tfrom_file;
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
+            return FALSE;
         } else if ((op = string_for_opt(opts, FALSE)) != 0) {
             symset[ROGUESET].name = dupstr(op);
             if (!read_sym_file(ROGUESET)) {
                 clear_symsetentry(ROGUESET, TRUE);
-                raw_printf("Unable to load symbol set \"%s\" from \"%s\".",
+                config_error_add("Unable to load symbol set \"%s\" from \"%s\"",
                            op, SYMBOLS);
-                wait_synch();
+                return FALSE;
             } else {
                 if (!initial && Is_rogue_level(&u.uz))
                     assign_graphics(ROGUESET);
                 need_redraw = TRUE;
             }
-        }
-        return;
+        } else
+            return FALSE;
+        return retval;
     }
 
     fullname = "symset";
@@ -2277,19 +2462,22 @@ boolean tinitial, tfrom_file;
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
+            return FALSE;
         } else if ((op = string_for_opt(opts, FALSE)) != 0) {
             symset[PRIMARY].name = dupstr(op);
             if (!read_sym_file(PRIMARY)) {
                 clear_symsetentry(PRIMARY, TRUE);
-                raw_printf("Unable to load symbol set \"%s\" from \"%s\".",
-                           op, SYMBOLS);
-                wait_synch();
+                config_error_add(
+                               "Unable to load symbol set \"%s\" from \"%s\"",
+                                 op, SYMBOLS);
+                return FALSE;
             } else {
-                switch_symbols(TRUE);
+                switch_symbols(symset[PRIMARY].name != (char *) 0);
                 need_redraw = TRUE;
             }
-        }
-        return;
+        } else
+            return FALSE;
+        return retval;
     }
 
     fullname = "runmode";
@@ -2307,21 +2495,27 @@ boolean tinitial, tfrom_file;
                 flags.runmode = RUN_STEP;
             else if (!strncmpi(op, "crawl", strlen(op)))
                 flags.runmode = RUN_CRAWL;
-            else
-                badoption(opts);
-        }
-        return;
+            else {
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
+            }
+        } else
+            return FALSE;
+        return retval;
     }
 
     /* menucolor:"regex_string"=color */
     fullname = "menucolor";
     if (match_optname(opts, fullname, 9, TRUE)) {
-        if (negated)
+        if (negated) {
             bad_negation(fullname, FALSE);
-        else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
+            return FALSE;
+        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
             if (!add_menu_coloring(op))
-                badoption(opts);
-        return;
+                return FALSE;
+        } else
+            return FALSE;
+        return retval;
     }
 
     fullname = "msghistory";
@@ -2331,9 +2525,11 @@ boolean tinitial, tfrom_file;
         op = string_for_env_opt(fullname, opts, negated);
         if ((negated && !op) || (!negated && op)) {
             iflags.msg_history = negated ? 0 : atoi(op);
-        } else if (negated)
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
 
     fullname = "msg_window";
@@ -2350,9 +2546,9 @@ boolean tinitial, tfrom_file;
         } else {
             if (negated) {
                 bad_negation(fullname, TRUE);
-                return;
+                return FALSE;
             }
-            tmp = tolower(*op);
+            tmp = lowc(*op);
         }
         switch (tmp) {
         case 's': /* single message history cycle (default if negated) */
@@ -2367,11 +2563,13 @@ boolean tinitial, tfrom_file;
         case 'r': /* full page (reversed) */
             iflags.prevmsg_window = 'r';
             break;
-        default:
-            badoption(opts);
+        default: {
+            config_error_add("Unknown %s parameter '%s'", fullname, op);
+            return FALSE;
+        }
         }
 #endif
-        return;
+        return retval;
     }
 
     /* WINCAP
@@ -2407,8 +2605,8 @@ boolean tinitial, tfrom_file;
             else if (!strncmpi(fontopts, "_size_status", 11))
                 opttype = STATUS_OPTION;
             else {
-                badoption(opts);
-                return;
+                config_error_add("Unknown %s parameter '%s'", fullname, opts);
+                return FALSE;
             }
             if (duplicate)
                 complain_about_duplicate(opts, 1);
@@ -2432,26 +2630,30 @@ boolean tinitial, tfrom_file;
                     break;
                 }
             }
-            return;
+            return retval;
         } else {
-            badoption(opts);
+            config_error_add("Unknown %s parameter '%s'", fullname, opts);
+            return FALSE;
         }
         if (opttype > 0 && (op = string_for_opt(opts, FALSE)) != 0) {
             wc_set_font_name(opttype, op);
 #ifdef MAC
             set_font_name(opttype, op);
 #endif
-            return;
-        } else if (negated)
+            return retval;
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
+
 #ifdef CHANGE_COLOR
     if (match_optname(opts, "palette", 3, TRUE)
 #ifdef MAC
         || match_optname(opts, "hicolor", 3, TRUE)
 #endif
-            ) {
+        ) {
         int color_number, color_incr;
 
 #ifndef WIN32
@@ -2462,25 +2664,26 @@ boolean tinitial, tfrom_file;
         if (match_optname(opts, "hicolor", 3, TRUE)) {
             if (negated) {
                 bad_negation("hicolor", FALSE);
-                return;
+                return FALSE;
             }
             color_number = CLR_MAX + 4; /* HARDCODED inverse number */
             color_incr = -1;
-        } else {
+        } else
 #endif
+        {
             if (negated) {
                 bad_negation("palette", FALSE);
-                return;
+                return FALSE;
             }
             color_number = 0;
             color_incr = 1;
-#ifdef MAC
         }
-#endif
 #ifdef WIN32
         op = string_for_opt(opts, TRUE);
-        if (!alternative_palette(op))
-            badoption(opts);
+        if (!alternative_palette(op)) {
+            config_error_add("Error in palette parameter '%s'", op);
+            return FALSE;
+        }
 #else
         if ((op = string_for_opt(opts, FALSE)) != (char *) 0) {
             char *pt = op;
@@ -2503,8 +2706,8 @@ boolean tinitial, tfrom_file;
 #else
                         rgb <<= 8;
 #endif
-                        tmp = *(pt++);
-                        if (isalpha(tmp)) {
+                        tmp = *pt++;
+                        if (isalpha((uchar) tmp)) {
                             tmp = (tmp + 9) & 0xf; /* Assumes ASCII... */
                         } else {
                             tmp &= 0xf; /* Digits in ASCII too... */
@@ -2516,9 +2719,8 @@ boolean tinitial, tfrom_file;
                         rgb += tmp;
                     }
                 }
-                if (*pt == '/') {
+                if (*pt == '/')
                     pt++;
-                }
                 change_color(color_number, rgb, reverse);
                 color_number += color_incr;
             }
@@ -2527,7 +2729,7 @@ boolean tinitial, tfrom_file;
         if (!initial) {
             need_redraw = TRUE;
         }
-        return;
+        return retval;
     }
 #endif /* CHANGE_COLOR */
 
@@ -2541,44 +2743,47 @@ boolean tinitial, tfrom_file;
         if (negated) {
             if (op) {
                 bad_negation("fruit", TRUE);
-                return;
+                return FALSE;
             }
             op = &empty_str;
             goto goodfruit;
         }
         if (!op)
-            return;
+            return FALSE;
         if (!initial) {
             struct fruit *f;
+            int fnum = 0;
 
-            num = 0;
-            for (f = ffruit; f; f = f->nextf) {
-                if (!strcmp(op, f->fname))
-                    break;
-                num++;
-            }
-            if (!flags.made_fruit) {
-                for (forig = ffruit; forig; forig = forig->nextf) {
-                    if (!strcmp(pl_fruit, forig->fname)) {
-                        break;
-                    }
+            /* count number of named fruits; if 'op' is found among them,
+               then the count doesn't matter because we won't be adding it */
+            f = fruit_from_name(op, FALSE, &fnum);
+            if (!f) {
+                if (!flags.made_fruit)
+                    forig = fruit_from_name(pl_fruit, FALSE, (int *) 0);
+
+                if (!forig && fnum >= 100) {
+#if 0 /*JP*/
+                    config_error_add(
+                             "Doing that so many times isn't very fruitful.");
+#else
+                    config_error_add(
+                             "\82»\82ñ\82È\82É\89½\89ñ\82à\82â\82Á\82Ä\82à\82Ù\82Æ\82ñ\82Ç\88Ó\96¡\82Í\82È\82¢\81D");
+#endif
+                    return retval;
                 }
             }
-            if (!forig && num >= 100) {
-/*JP
-                pline("Doing that so many times isn't very fruitful.");
-*/
-                pline("\82»\82ñ\82È\82É\89½\89ñ\82à\82â\82Á\82Ä\82à\82Ù\82Æ\82ñ\82Ç\88Ó\96¡\82Í\82È\82¢\81D");
-                return;
-            }
         }
     goodfruit:
         nmcpy(pl_fruit, op, PL_FSIZ);
         sanitize_name(pl_fruit);
-        /* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */
+        /* OBJ_NAME(objects[SLIME_MOLD]) won't work for this after
+           initialization; it gets changed to generic "fruit" */
         if (!*pl_fruit)
             nmcpy(pl_fruit, "slime mold", PL_FSIZ);
         if (!initial) {
+            /* if 'forig' is nonNull, we replace it rather than add
+               a new fruit; it can only be nonNull if no fruits have
+               been created since the previous name was put in place */
             (void) fruitadd(pl_fruit, forig);
             pline("Fruit is now \"%s\".", pl_fruit);
         }
@@ -2587,35 +2792,90 @@ boolean tinitial, tfrom_file;
          * no fruit option at all.  Also, we don't want people
          * setting multiple fruits in their options.)
          */
-        return;
+        return retval;
+    }
+
+    fullname = "whatis_coord";
+    if (match_optname(opts, fullname, 8, TRUE)) {
+        if (duplicate)
+            complain_about_duplicate(opts, 1);
+        if (negated) {
+            iflags.getpos_coords = GPCOORDS_NONE;
+            return retval;
+        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
+            static char gpcoords[] = { GPCOORDS_NONE, GPCOORDS_COMPASS,
+                                       GPCOORDS_COMFULL, GPCOORDS_MAP,
+                                       GPCOORDS_SCREEN, '\0' };
+            char c = lowc(*op);
+
+            if (c && index(gpcoords, c))
+                iflags.getpos_coords = c;
+            else {
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
+            }
+        } else
+            return FALSE;
+        return retval;
+    }
+
+    fullname = "whatis_filter";
+    if (match_optname(opts, fullname, 8, TRUE)) {
+        if (duplicate)
+            complain_about_duplicate(opts, 1);
+        if (negated) {
+            iflags.getloc_filter = GFILTER_NONE;
+            return retval;
+        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
+            char c = lowc(*op);
+
+            switch (c) {
+            case 'n':
+                iflags.getloc_filter = GFILTER_NONE;
+                break;
+            case 'v':
+                iflags.getloc_filter = GFILTER_VIEW;
+                break;
+            case 'a':
+                iflags.getloc_filter = GFILTER_AREA;
+                break;
+            default: {
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
+            }
+            }
+        } else
+            return FALSE;
+        return retval;
     }
 
     fullname = "warnings";
     if (match_optname(opts, fullname, 5, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
-        if (negated)
+        if (negated) {
             bad_negation(fullname, FALSE);
-        else
-            warning_opts(opts, fullname);
-        return;
+            return FALSE;
+        }
+        return warning_opts(opts, fullname);
     }
 
-#ifdef BACKWARD_COMPAT
     /* boulder:symbol */
     fullname = "boulder";
     if (match_optname(opts, fullname, 7, TRUE)) {
+#ifdef BACKWARD_COMPAT
         int clash = 0;
+
         if (duplicate)
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
-            return;
+            return FALSE;
         }
         /* if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
          */
         if (!(opts = string_for_opt(opts, FALSE)))
-            return;
+            return FALSE;
         escapes(opts, opts);
         if (def_char_to_monclass(opts[0]) != MAXMCLASSES)
             clash = 1;
@@ -2624,31 +2884,42 @@ boolean tinitial, tfrom_file;
         if (clash) {
             /* symbol chosen matches a used monster or warning
                symbol which is not good - reject it*/
-            pline(
+            config_error_add(
                 "Badoption - boulder symbol '%c' conflicts with a %s symbol.",
-                opts[0], (clash == 1) ? "monster" : "warning");
+                             opts[0], (clash == 1) ? "monster" : "warning");
         } else {
             /*
              * Override the default boulder symbol.
              */
             iflags.bouldersym = (uchar) opts[0];
         }
-        if (!initial)
+        /* for 'initial', update_bouldersym() is done in initoptions_finish(),
+           after all symset options have been processed */
+        if (!initial) {
+            update_bouldersym();
             need_redraw = TRUE;
-        return;
-    }
+        }
+        return retval;
+#else
+        config_error_add("'%s' no longer supported; use S_boulder:c instead",
+                         fullname);
+        return FALSE;
 #endif
+    }
 
     /* name:string */
     fullname = "name";
     if (match_optname(opts, fullname, 4, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
-        if (negated)
+        if (negated) {
             bad_negation(fullname, FALSE);
-        else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
+            return FALSE;
+        } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
             nmcpy(plname, op, PL_NSIZ);
-        return;
+        } else
+            return FALSE;
+        return retval;
     }
 
     /* altkeyhandler:string */
@@ -2658,13 +2929,15 @@ boolean tinitial, tfrom_file;
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
+            return FALSE;
         } else if ((op = string_for_opt(opts, negated)) != 0) {
 #ifdef WIN32
             (void) strncpy(iflags.altkeyhandler, op, MAX_ALTKEYHANDLER - 5);
             load_keyboard_handler();
 #endif
-        }
-        return;
+        } else
+            return FALSE;
+        return retval;
     }
 
     /* WINCAP
@@ -2681,12 +2954,17 @@ boolean tinitial, tfrom_file;
                 iflags.wc_align_status = ALIGN_RIGHT;
             else if (!strncmpi(op, "bottom", sizeof("bottom") - 1))
                 iflags.wc_align_status = ALIGN_BOTTOM;
-            else
-                badoption(opts);
-        } else if (negated)
+            else {
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
+            }
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
+
     /* WINCAP
      * align_message:[left|top|right|bottom] */
     fullname = "align_message";
@@ -2703,26 +2981,31 @@ boolean tinitial, tfrom_file;
                 iflags.wc_align_message = ALIGN_RIGHT;
             else if (!strncmpi(op, "bottom", sizeof("bottom") - 1))
                 iflags.wc_align_message = ALIGN_BOTTOM;
-            else
-                badoption(opts);
-        } else if (negated)
+            else {
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
+            }
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
-    /* the order to list the pack */
+
+    /* the order to list inventory */
     fullname = "packorder";
     if (match_optname(opts, fullname, 4, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
-            return;
+            return FALSE;
         } else if (!(op = string_for_opt(opts, FALSE)))
-            return;
+            return FALSE;
 
         if (!change_inv_order(op))
-            badoption(opts);
-        return;
+            return FALSE;
+        return retval;
     }
 
     /* user can change required response for some prompts (quit, die, hit),
@@ -2739,7 +3022,9 @@ boolean tinitial, tfrom_file;
         } else if ((op = string_for_opt(opts, TRUE)) != 0) {
             char *pp, buf[BUFSZ];
 
-            op = mungspaces(strcpy(buf, op));
+            strncpy(buf, op, sizeof buf - 1);
+            buf[sizeof buf - 1] = '\0';
+            op = mungspaces(buf);
             for (;;) {
                 /* We're looking to parse
                    "paranoid_confirm:whichone wheretwo whothree"
@@ -2767,17 +3052,19 @@ boolean tinitial, tfrom_file;
                 if (i == SIZE(paranoia)) {
                     /* didn't match anything, so arg is bad;
                        any flags already set will stay set */
-                    badoption(opts);
-                    break;
+                    config_error_add("Unknown %s parameter '%s'",
+                                     fullname, op);
+                    return FALSE;
                 }
                 /* move on to next token */
                 if (pp)
                     op = pp + 1;
                 else
                     break; /* no next token */
-            }              /* for(;;) */
-        }
-        return;
+            } /* for(;;) */
+        } else
+            return FALSE;
+        return retval;
     }
 
     /* accept deprecated boolean; superseded by paranoid_confirm:pray */
@@ -2787,7 +3074,7 @@ boolean tinitial, tfrom_file;
             flags.paranoia_bits &= ~PARANOID_PRAY;
         else
             flags.paranoia_bits |= PARANOID_PRAY;
-        return;
+        return retval;
     }
 
     /* maximum burden picked up before prompt (Warren Cheung) */
@@ -2797,45 +3084,42 @@ boolean tinitial, tfrom_file;
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
-            return;
+            return FALSE;
         } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
-            switch (tolower(*op)) {
-            /* Unencumbered */
-            case 'u':
+            switch (lowc(*op)) {
+            case 'u': /* Unencumbered */
                 flags.pickup_burden = UNENCUMBERED;
                 break;
-            /* Burdened (slight encumbrance) */
-            case 'b':
+            case 'b': /* Burdened (slight encumbrance) */
                 flags.pickup_burden = SLT_ENCUMBER;
                 break;
-            /* streSsed (moderate encumbrance) */
-            case 's':
+            case 's': /* streSsed (moderate encumbrance) */
                 flags.pickup_burden = MOD_ENCUMBER;
                 break;
-            /* straiNed (heavy encumbrance) */
-            case 'n':
+            case 'n': /* straiNed (heavy encumbrance) */
                 flags.pickup_burden = HVY_ENCUMBER;
                 break;
-            /* OverTaxed (extreme encumbrance) */
-            case 'o':
+            case 'o': /* OverTaxed (extreme encumbrance) */
             case 't':
                 flags.pickup_burden = EXT_ENCUMBER;
                 break;
-            /* overLoaded */
-            case 'l':
+            case 'l': /* overLoaded */
                 flags.pickup_burden = OVERLOADED;
                 break;
             default:
-                badoption(opts);
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
             }
-        }
-        return;
+        } else
+            return FALSE;
+        return retval;
     }
 
     /* types of objects to pick up automatically */
-    if (match_optname(opts, "pickup_types", 8, TRUE)) {
+    fullname = "pickup_types";
+    if (match_optname(opts, fullname, 8, TRUE)) {
         char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1], qbuf[QBUFSZ],
-            abuf[BUFSZ];
+            abuf[BUFSZ] = DUMMY;
         int oc_sym;
         boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
 
@@ -2850,18 +3134,18 @@ boolean tinitial, tfrom_file;
                    value is a synonym for autopickup of all types
                    (and during initialization, we can't prompt yet) */
                 flags.pickup = !negated;
-                return;
+                return retval;
             }
             oc_to_str(flags.inv_order, ocl);
             use_menu = TRUE;
             if (flags.menu_style == MENU_TRADITIONAL
                 || flags.menu_style == MENU_COMBINATION) {
                 use_menu = FALSE;
-#if 0 /*JP*/
-                Sprintf(qbuf, "New pickup_types: [%s am] (%s)", ocl,
+#if 0 /*JP:T*/
+                Sprintf(qbuf, "New %s: [%s am] (%s)", fullname, ocl,
                         *tbuf ? tbuf : "all");
 #else
-                Sprintf(qbuf, "\90V\82µ\82¢pickup_type\82ð\93ü\97Í\82µ\82Ä\82­\82¾\82³\82¢\81F[%s am] (%s)", ocl,
+                Sprintf(qbuf, "\90V\82µ\82¢%s: [%s am] (%s)", fullname, ocl,
                         *tbuf ? tbuf : "all");
 #endif
                 getlin(qbuf, abuf);
@@ -2883,8 +3167,8 @@ boolean tinitial, tfrom_file;
             }
         }
         if (negated) {
-            bad_negation("pickup_types", TRUE);
-            return;
+            bad_negation(fullname, TRUE);
+            return FALSE;
         }
         while (*op == ' ')
             op++;
@@ -2901,10 +3185,12 @@ boolean tinitial, tfrom_file;
                     badopt = TRUE;
                 op++;
             }
-            if (badopt)
-                badoption(opts);
+            if (badopt) {
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
+            }
         }
-        return;
+        return retval;
     }
 
     /* pile limit: when walking over objects, number which triggers
@@ -2916,14 +3202,15 @@ boolean tinitial, tfrom_file;
         op = string_for_opt(opts, negated);
         if ((negated && !op) || (!negated && op))
             flags.pile_limit = negated ? 0 : atoi(op);
-        else if (negated)
+        else if (negated) {
             bad_negation(fullname, TRUE);
-        else /* !op */
+            return FALSE;
+        } else /* !op */
             flags.pile_limit = PILE_LIMIT_DFLT;
         /* sanity check */
         if (flags.pile_limit < 0)
             flags.pile_limit = PILE_LIMIT_DFLT;
-        return;
+        return retval;
     }
 
     /* play mode: normal, explore/discovery, or debug/wizard */
@@ -2934,8 +3221,10 @@ boolean tinitial, tfrom_file;
         if (negated)
             bad_negation(fullname, FALSE);
         if (duplicate || negated)
-            return;
-        op = string_for_opt(opts, TRUE);
+            return FALSE;
+        op = string_for_opt(opts, FALSE);
+        if (!op)
+            return FALSE;
         if (!strncmpi(op, "normal", 6) || !strcmpi(op, "play")) {
             wizard = discover = FALSE;
         } else if (!strncmpi(op, "explore", 6)
@@ -2944,9 +3233,10 @@ boolean tinitial, tfrom_file;
         } else if (!strncmpi(op, "debug", 5) || !strncmpi(op, "wizard", 6)) {
             wizard = TRUE, discover = FALSE;
         } else {
-            raw_printf("Invalid value for \"%s\":%s.", fullname, op);
+            config_error_add("Invalid value for \"%s\":%s", fullname, op);
+            return FALSE;
         }
-        return;
+        return retval;
     }
 
     /* WINCAP
@@ -2961,15 +3251,20 @@ boolean tinitial, tfrom_file;
                 iflags.wc_player_selection = VIA_DIALOG;
             else if (!strncmpi(op, "prompt", sizeof("prompt") - 1))
                 iflags.wc_player_selection = VIA_PROMPTS;
-            else
-                badoption(opts);
-        } else if (negated)
+            else {
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
+            }
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
 
     /* things to disclose at end of game */
-    if (match_optname(opts, "disclose", 7, TRUE)) {
+    fullname = "disclose";
+    if (match_optname(opts, fullname, 7, TRUE)) {
         /*
          * The order that the end_disclose options are stored:
          *      inventory, attribs, vanquished, genocided,
@@ -2991,15 +3286,14 @@ boolean tinitial, tfrom_file;
          * and the presence of a i,a,g,v, or c without a prefix
          * sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT.
          */
-        boolean badopt = FALSE;
         int idx, prefix_val;
 
         if (duplicate)
             complain_about_duplicate(opts, 1);
         op = string_for_opt(opts, TRUE);
         if (op && negated) {
-            bad_negation("disclose", TRUE);
-            return;
+            bad_negation(fullname, TRUE);
+            return FALSE;
         }
         /* "disclose" without a value means "all with prompting"
            and negated means "none without prompting" */
@@ -3010,7 +3304,7 @@ boolean tinitial, tfrom_file;
                 flags.end_disclose[num] = negated
                                               ? DISCLOSE_NO_WITHOUT_PROMPT
                                               : DISCLOSE_PROMPT_DEFAULT_YES;
-            return;
+            return retval;
         }
 
         num = 0;
@@ -3018,7 +3312,9 @@ boolean tinitial, tfrom_file;
         while (*op && num < sizeof flags.end_disclose - 1) {
             static char valid_settings[] = {
                 DISCLOSE_PROMPT_DEFAULT_YES, DISCLOSE_PROMPT_DEFAULT_NO,
-                DISCLOSE_YES_WITHOUT_PROMPT, DISCLOSE_NO_WITHOUT_PROMPT, '\0'
+                DISCLOSE_PROMPT_DEFAULT_SPECIAL,
+                DISCLOSE_YES_WITHOUT_PROMPT, DISCLOSE_NO_WITHOUT_PROMPT,
+                DISCLOSE_SPECIAL_WITHOUT_PROMPT, '\0'
             };
             register char c, *dop;
 
@@ -3035,6 +3331,12 @@ boolean tinitial, tfrom_file;
                     continue;
                 }
                 if (prefix_val != -1) {
+                    if (*dop != 'v') {
+                        if (prefix_val == DISCLOSE_PROMPT_DEFAULT_SPECIAL)
+                            prefix_val = DISCLOSE_PROMPT_DEFAULT_YES;
+                        if (prefix_val == DISCLOSE_SPECIAL_WITHOUT_PROMPT)
+                            prefix_val = DISCLOSE_YES_WITHOUT_PROMPT;
+                    }
                     flags.end_disclose[idx] = prefix_val;
                     prefix_val = -1;
                 } else
@@ -3043,33 +3345,34 @@ boolean tinitial, tfrom_file;
                 prefix_val = c;
             } else if (c == ' ') {
                 ; /* do nothing */
-            } else
-                badopt = TRUE;
+            } else {
+                config_error_add("Unknown %s parameter '%c'", fullname, *op);
+                return FALSE;
+            }
             op++;
         }
-        if (badopt)
-            badoption(opts);
-        return;
+        return retval;
     }
 #if 1 /*JP*/
     if (!strncmpi(opts, "kcode", 3)){
         if ((op = string_for_env_opt("kcode", opts, FALSE)) != 0){
             setkcode(*op);
         }
-        return;
+        return retval;
     }
 #endif
 
     /* scores:5t[op] 5a[round] o[wn] */
-    if (match_optname(opts, "scores", 4, TRUE)) {
+    fullname = "scores";
+    if (match_optname(opts, fullname, 4, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
         if (negated) {
-            bad_negation("scores", FALSE);
-            return;
+            bad_negation(fullname, FALSE);
+            return FALSE;
         }
         if (!(op = string_for_opt(opts, FALSE)))
-            return;
+            return FALSE;
 
         while (*op) {
             int inum = 1;
@@ -3099,33 +3402,36 @@ boolean tinitial, tfrom_file;
                 flags.end_own = !negated;
                 break;
             default:
-                badoption(opts);
-                return;
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
             }
             while (letter(*++op) || *op == ' ')
                 continue;
             if (*op == '/')
                 op++;
         }
-        return;
+        return retval;
     }
 
     fullname = "sortloot";
     if (match_optname(opts, fullname, 4, TRUE)) {
         op = string_for_env_opt(fullname, opts, FALSE);
         if (op) {
-            switch (tolower(*op)) {
-            case 'n':
-            case 'l':
-            case 'f':
-                flags.sortloot = tolower(*op);
+            char c = lowc(*op);
+
+            switch (c) {
+            case 'n': /* none */
+            case 'l': /* loot (pickup) */
+            case 'f': /* full (pickup + invent) */
+                flags.sortloot = c;
                 break;
             default:
-                badoption(opts);
-                return;
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
             }
-        }
-        return;
+        } else
+            return FALSE;
+        return retval;
     }
 
     fullname = "suppress_alert";
@@ -3133,11 +3439,12 @@ boolean tinitial, tfrom_file;
         if (duplicate)
             complain_about_duplicate(opts, 1);
         op = string_for_opt(opts, negated);
-        if (negated)
+        if (negated) {
             bad_negation(fullname, FALSE);
-        else if (op)
+            return FALSE;
+        } else if (op)
             (void) feature_alert_opts(op, fullname);
-        return;
+        return retval;
     }
 
 #ifdef VIDEOSHADES
@@ -3149,13 +3456,13 @@ boolean tinitial, tfrom_file;
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
-            return;
+            return FALSE;
         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
-            return;
+            return FALSE;
         }
-        if (!assign_videocolors(opts))
-            badoption(opts);
-        return;
+        if (!assign_videocolors(opts)) /* TODO: error msg */
+            return FALSE;
+        return retval;
     }
     /* videoshades:string */
     fullname = "videoshades";
@@ -3164,13 +3471,13 @@ boolean tinitial, tfrom_file;
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
-            return;
+            return FALSE;
         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
-            return;
+            return FALSE;
         }
-        if (!assign_videoshades(opts))
-            badoption(opts);
-        return;
+        if (!assign_videoshades(opts)) /* TODO: error msg */
+            return FALSE;
+        return retval;
     }
 #endif /* VIDEOSHADES */
 #ifdef MSDOS
@@ -3182,13 +3489,13 @@ boolean tinitial, tfrom_file;
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
-            return;
+            return FALSE;
         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
-            return;
+            return FALSE;
         }
-        if (!assign_video(opts))
-            badoption(opts);
-        return;
+        if (!assign_video(opts)) /* TODO: error msg */
+            return FALSE;
+        return retval;
     }
 #endif /* NO_TERMS */
     /* soundcard:string -- careful not to match boolean 'sound' */
@@ -3198,13 +3505,13 @@ boolean tinitial, tfrom_file;
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
-            return;
+            return FALSE;
         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
-            return;
+            return FALSE;
         }
-        if (!assign_soundcard(opts))
-            badoption(opts);
-        return;
+        if (!assign_soundcard(opts)) /* TODO: error msg */
+            return FALSE;
+        return retval;
     }
 #endif /* MSDOS */
 
@@ -3242,51 +3549,66 @@ boolean tinitial, tfrom_file;
             else if (!strncmpi(op, "fit_to_screen",
                                sizeof("fit_to_screen") - 1))
                 iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
-            else
-                badoption(opts);
-        } else if (negated)
+            else {
+                config_error_add("Unknown %s parameter '%s'", fullname, op);
+                return FALSE;
+            }
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
+
     /* WINCAP
      * scroll_amount:nn */
     fullname = "scroll_amount";
-    if (match_optname(opts, fullname, sizeof("scroll_amount") - 1, TRUE)) {
+    if (match_optname(opts, fullname, sizeof "scroll_amount" - 1, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
         op = string_for_opt(opts, negated);
         if ((negated && !op) || (!negated && op)) {
             iflags.wc_scroll_amount = negated ? 1 : atoi(op);
-        } else if (negated)
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
+
     /* WINCAP
      * scroll_margin:nn */
     fullname = "scroll_margin";
-    if (match_optname(opts, fullname, sizeof("scroll_margin") - 1, TRUE)) {
+    if (match_optname(opts, fullname, sizeof "scroll_margin" - 1, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
         op = string_for_opt(opts, negated);
         if ((negated && !op) || (!negated && op)) {
             iflags.wc_scroll_margin = negated ? 5 : atoi(op);
-        } else if (negated)
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
+
     fullname = "subkeyvalue";
     if (match_optname(opts, fullname, 5, TRUE)) {
         /* no duplicate complaint here */
         if (negated) {
             bad_negation(fullname, FALSE);
+            return FALSE;
         } else {
 #if defined(WIN32)
             op = string_for_opt(opts, 0);
+            if (!op)
+                return FALSE;
             map_subkeyvalue(op);
 #endif
         }
-        return;
+        return retval;
     }
+
     /* WINCAP
      * tile_width:nn */
     fullname = "tile_width";
@@ -3296,9 +3618,11 @@ boolean tinitial, tfrom_file;
         op = string_for_opt(opts, negated);
         if ((negated && !op) || (!negated && op)) {
             iflags.wc_tile_width = negated ? 0 : atoi(op);
-        } else if (negated)
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
     /* WINCAP
      * tile_file:name */
@@ -3309,10 +3633,10 @@ boolean tinitial, tfrom_file;
         if ((op = string_for_opt(opts, FALSE)) != 0) {
             if (iflags.wc_tile_file)
                 free(iflags.wc_tile_file);
-            iflags.wc_tile_file = (char *) alloc(strlen(op) + 1);
-            Strcpy(iflags.wc_tile_file, op);
-        }
-        return;
+            iflags.wc_tile_file = dupstr(op);
+        } else
+            return FALSE;
+        return retval;
     }
     /* WINCAP
      * tile_height:nn */
@@ -3323,10 +3647,13 @@ boolean tinitial, tfrom_file;
         op = string_for_opt(opts, negated);
         if ((negated && !op) || (!negated && op)) {
             iflags.wc_tile_height = negated ? 0 : atoi(op);
-        } else if (negated)
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
+
     /* WINCAP
      * vary_msgcount:nn */
     fullname = "vary_msgcount";
@@ -3336,36 +3663,56 @@ boolean tinitial, tfrom_file;
         op = string_for_opt(opts, negated);
         if ((negated && !op) || (!negated && op)) {
             iflags.wc_vary_msgcount = negated ? 0 : atoi(op);
-        } else if (negated)
+        } else if (negated) {
             bad_negation(fullname, TRUE);
-        return;
+            return FALSE;
+        }
+        return retval;
     }
+
+    /*
+     * windowtype:  option to choose the interface for binaries built
+     * with support for more than one interface (tty + X11, for instance).
+     *
+     * Ideally, 'windowtype' should be processed first, because it
+     * causes the wc_ and wc2_ flags to be set up.
+     * For user, making it be first in a config file is trivial, use
+     * OPTIONS=windowtype:Foo
+     * as the first non-comment line of the file.
+     * Making it first in NETHACKOPTIONS requires it to be at the _end_
+     * because option strings are processed from right to left.
+     */
     fullname = "windowtype";
     if (match_optname(opts, fullname, 3, TRUE)) {
         if (duplicate)
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
-            return;
+            return FALSE;
         } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
             char buf[WINTYPELEN];
+
             nmcpy(buf, op, WINTYPELEN);
             choose_windows(buf);
-        }
-        return;
+        } else
+            return FALSE;
+        return retval;
     }
+
 #ifdef WINCHAIN
     fullname = "windowchain";
     if (match_optname(opts, fullname, 3, TRUE)) {
         if (negated) {
             bad_negation(fullname, FALSE);
-            return;
+            return FALSE;
         } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
             char buf[WINTYPELEN];
+
             nmcpy(buf, op, WINTYPELEN);
             addto_windowchain(buf);
-        }
-        return;
+        } else
+            return FALSE;
+        return retval;
     }
 #endif
 
@@ -3378,15 +3725,16 @@ boolean tinitial, tfrom_file;
         if (duplicate)
             complain_about_duplicate(opts, 1);
         if ((op = string_for_opt(opts, FALSE)) != 0) {
-            if (!wc_set_window_colors(op))
-                badoption(opts);
+            if (!wc_set_window_colors(op)) /* TODO: error msg*/
+                return FALSE;
         } else if (negated)
             bad_negation(fullname, TRUE);
-        return;
+        return retval;
     }
 
     /* menustyle:traditional or combination or full or partial */
-    if (match_optname(opts, "menustyle", 4, TRUE)) {
+    fullname = "menustyle";
+    if (match_optname(opts, fullname, 4, TRUE)) {
         int tmp;
         boolean val_required = (strlen(opts) > 5 && !negated);
 
@@ -3394,107 +3742,127 @@ boolean tinitial, tfrom_file;
             complain_about_duplicate(opts, 1);
         if (!(op = string_for_opt(opts, !val_required))) {
             if (val_required)
-                return; /* string_for_opt gave feedback */
+                return FALSE; /* string_for_opt gave feedback */
             tmp = negated ? 'n' : 'f';
         } else {
-            tmp = tolower(*op);
+            tmp = lowc(*op);
         }
         switch (tmp) {
         case 'n': /* none */
-        case 't': /* traditional */
+        case 't': /* traditional: prompt for class(es) by symbol,
+                     prompt for each item within class(es) one at a time */
             flags.menu_style = MENU_TRADITIONAL;
             break;
-        case 'c': /* combo: trad.class sel+menu */
+        case 'c': /* combination: prompt for class(es) by symbol,
+                     choose items within selected class(es) by menu */
             flags.menu_style = MENU_COMBINATION;
             break;
-        case 'p': /* partial: no class menu */
-            flags.menu_style = MENU_PARTIAL;
-            break;
-        case 'f': /* full: class menu + menu */
+        case 'f': /* full: choose class(es) by first menu,
+                     choose items within selected class(es) by second menu */
             flags.menu_style = MENU_FULL;
             break;
+        case 'p': /* partial: skip class filtering,
+                     choose items among all classes by menu */
+            flags.menu_style = MENU_PARTIAL;
+            break;
         default:
-            badoption(opts);
+            config_error_add("Unknown %s parameter '%s'", fullname, op);
+            return FALSE;
         }
-        return;
+        return retval;
     }
 
     fullname = "menu_headings";
     if (match_optname(opts, fullname, 12, TRUE)) {
+        int tmpattr;
+
         if (duplicate)
             complain_about_duplicate(opts, 1);
         if (negated) {
             bad_negation(fullname, FALSE);
-            return;
+            return FALSE;
         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
-            return;
+            return FALSE;
         }
-        for (i = 0; i < SIZE(attrnames); i++)
-            if (!strcmpi(opts, attrnames[i].name)) {
-                iflags.menu_headings = attrnames[i].attr;
-                return;
-            }
-        badoption(opts);
-        return;
+        tmpattr = match_str2attr(opts, TRUE);
+        if (tmpattr == -1)
+            return FALSE;
+        else
+            iflags.menu_headings = tmpattr;
+        return retval;
     }
 
     /* check for menu command mapping */
-    for (i = 0; i < NUM_MENU_CMDS; i++) {
+    for (i = 0; i < SIZE(default_menu_cmd_info); i++) {
         fullname = default_menu_cmd_info[i].name;
         if (duplicate)
             complain_about_duplicate(opts, 1);
         if (match_optname(opts, fullname, (int) strlen(fullname), TRUE)) {
             if (negated) {
                 bad_negation(fullname, FALSE);
+                return FALSE;
             } else if ((op = string_for_opt(opts, FALSE)) != 0) {
-                int j;
                 char c, op_buf[BUFSZ];
-                boolean isbad = FALSE;
 
                 escapes(op, op_buf);
                 c = *op_buf;
 
-                if (c == 0 || c == '\r' || c == '\n' || c == '\033'
-                    || c == ' ' || digit(c) || (letter(c) && c != '@'))
-                    isbad = TRUE;
-                else /* reject default object class symbols */
-                    for (j = 1; j < MAXOCLASSES; j++)
-                        if (c == def_oc_syms[i].sym) {
-                            isbad = TRUE;
-                            break;
-                        }
-
-                if (isbad)
-                    badoption(opts);
-                else
+                if (illegal_menu_cmd_key(c)) {
+                    return FALSE;
+                } else
                     add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
             }
-            return;
+            return retval;
         }
     }
-#if defined(STATUS_VIA_WINDOWPORT) && defined(STATUS_HILITES)
+
     /* hilite fields in status prompt */
-    if (match_optname(opts, "hilite_status", 13, TRUE)) {
+    fullname = "hilite_status";
+    if (match_optname(opts, fullname, 13, TRUE)) {
+#ifdef STATUS_HILITES
         if (duplicate)
             complain_about_duplicate(opts, 1);
         op = string_for_opt(opts, TRUE);
         if (op && negated) {
-            clear_status_hilites(tfrom_file);
-            return;
+            clear_status_hilites();
+            return retval;
         } else if (!op) {
-            /* a value is mandatory */
-            badoption(opts);
-            return;
+            config_error_add("Value is mandatory for hilite_status");
+            return FALSE;
         }
-        if (!set_status_hilites(op, tfrom_file))
-            badoption(opts);
-        return;
+        if (!parse_status_hl1(op, tfrom_file))
+            return FALSE;
+        return retval;
+#else
+        config_error_add("'%s' is not supported", fullname);
+        return FALSE;
+#endif
     }
+
+    /* control over whether highlights should be displayed, and for how long */
+    fullname = "statushilites";
+    if (match_optname(opts, fullname, 9, TRUE)) {
+#ifdef STATUS_HILITES
+        if (negated) {
+            iflags.hilite_delta = 0L;
+        } else {
+            op = string_for_opt(opts, TRUE);
+            iflags.hilite_delta = (!op || !*op) ? 3L : atol(op);
+            if (iflags.hilite_delta < 0L)
+                iflags.hilite_delta = 1L;
+        }
+        if (!tfrom_file)
+            reset_status_hilites();
+        return retval;
+#else
+        config_error_add("'%s' is not supported", fullname);
+        return FALSE;
 #endif
+    }
 
-#if defined(BACKWARD_COMPAT)
     fullname = "DECgraphics";
     if (match_optname(opts, fullname, 3, TRUE)) {
+#ifdef BACKWARD_COMPAT
         boolean badflag = FALSE;
 
         if (duplicate)
@@ -3512,14 +3880,21 @@ boolean tinitial, tfrom_file;
                     switch_symbols(TRUE);
             }
             if (badflag) {
-                pline("Failure to load symbol set %s.", fullname);
-                wait_synch();
+                config_error_add("Failure to load symbol set %s.", fullname);
+                return FALSE;
             }
         }
-        return;
-    }
+        return retval;
+#else
+        config_error_add("'%s' no longer supported; use 'symset:%s' instead",
+                         fullname, fullname);
+        return FALSE;
+#endif
+    } /* "DECgraphics" */
+
     fullname = "IBMgraphics";
     if (match_optname(opts, fullname, 3, TRUE)) {
+#ifdef BACKWARD_COMPAT
         const char *sym_name = fullname;
         boolean badflag = FALSE;
 
@@ -3541,20 +3916,25 @@ boolean tinitial, tfrom_file;
                 }
             }
             if (badflag) {
-                pline("Failure to load symbol set %s.", sym_name);
-                wait_synch();
+                config_error_add("Failure to load symbol set %s.", sym_name);
+                return FALSE;
             } else {
                 switch_symbols(TRUE);
                 if (!initial && Is_rogue_level(&u.uz))
                     assign_graphics(ROGUESET);
             }
         }
-        return;
-    }
+        return retval;
+#else
+        config_error_add("'%s' no longer supported; use 'symset:%s' instead",
+                         fullname, fullname);
+        return FALSE;
 #endif
-#ifdef MAC_GRAPHICS_ENV
+    } /* "IBMgraphics" */
+
     fullname = "MACgraphics";
     if (match_optname(opts, fullname, 3, TRUE)) {
+#if defined(MAC_GRAPHICS_ENV) && defined(BACKWARD_COMPAT)
         boolean badflag = FALSE;
 
         if (duplicate)
@@ -3570,34 +3950,63 @@ boolean tinitial, tfrom_file;
                 }
             }
             if (badflag) {
-                pline("Failure to load symbol set %s.", fullname);
-                wait_synch();
+                config_error_add("Failure to load symbol set %s.", fullname);
+                return FALSE;
             } else {
                 switch_symbols(TRUE);
                 if (!initial && Is_rogue_level(&u.uz))
                     assign_graphics(ROGUESET);
             }
         }
-        return;
-    }
+        return retval;
+#else   /* !(MAC_GRAPHICS_ENV && BACKWARD_COMPAT) */
+        config_error_add("'%s' %s; use 'symset:%s' instead",
+                         fullname,
+#ifdef MAC_GRAPHICS_ENV /* implies BACKWARD_COMPAT is not defined */
+                         "no longer supported",
+#else
+                         "is not supported",
 #endif
+                         fullname);
+        return FALSE;
+#endif  /* ?(MAC_GRAPHICS_ENV && BACKWARD_COMPAT) */
+    } /* "MACgraphics" */
 
     /* OK, if we still haven't recognized the option, check the boolean
      * options list
      */
     for (i = 0; boolopt[i].name; i++) {
-        if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
+        if (match_optname(opts, boolopt[i].name, 3, TRUE)) {
             /* options that don't exist */
             if (!boolopt[i].addr) {
                 if (!initial && !negated)
                     pline_The("\"%s\" option is not available.",
                               boolopt[i].name);
-                return;
+                return retval;
             }
             /* options that must come from config file */
             if (!initial && (boolopt[i].optflags == SET_IN_FILE)) {
                 rejectoption(boolopt[i].name);
-                return;
+                return retval;
+            }
+
+            op = string_for_opt(opts, TRUE);
+
+            if (op) {
+                if (negated) {
+                    config_error_add(
+                           "Negated boolean '%s' should not have a parameter",
+                                     boolopt[i].name);
+                    return FALSE;
+                }
+                if (!strcmp(op, "true") || !strcmp(op, "yes")) {
+                    negated = FALSE;
+                } else if (!strcmp(op, "false") || !strcmp(op, "no")) {
+                    negated = TRUE;
+                } else {
+                    config_error_add("Illegal parameter for a boolean");
+                    return FALSE;
+                }
             }
 
             *(boolopt[i].addr) = !negated;
@@ -3605,42 +4014,43 @@ boolean tinitial, tfrom_file;
             /* 0 means boolean opts */
             if (duplicate_opt_detection(boolopt[i].name, 0))
                 complain_about_duplicate(boolopt[i].name, 0);
-
 #ifdef RLECOMP
-            if ((boolopt[i].addr) == &iflags.rlecomp) {
-                if (*boolopt[i].addr)
-                    set_savepref("rlecomp");
-                else
-                    set_savepref("!rlecomp");
-            }
+            if (boolopt[i].addr == &iflags.rlecomp)
+                set_savepref(iflags.rlecomp ? "rlecomp" : "!rlecomp");
 #endif
 #ifdef ZEROCOMP
-            if ((boolopt[i].addr) == &iflags.zerocomp) {
-                if (*boolopt[i].addr)
-                    set_savepref("zerocomp");
-                else
-                    set_savepref("externalcomp");
+            if (boolopt[i].addr == &iflags.zerocomp)
+                set_savepref(iflags.zerocomp ? "zerocomp" : "externalcomp");
+#endif
+            if (boolopt[i].addr == &iflags.wc_ascii_map) {
+                /* toggling ascii_map; set tiled_map to its opposite;
+                   what does it mean to turn off ascii map if tiled map
+                   isn't supported? -- right now, we do nothing */
+                iflags.wc_tiled_map = negated;
+            } else if (boolopt[i].addr == &iflags.wc_tiled_map) {
+                /* toggling tiled_map; set ascii_map to its opposite;
+                   as with ascii_map, what does it mean to turn off tiled
+                   map if ascii map isn't supported? */
+                iflags.wc_ascii_map = negated;
             }
-#endif
             /* only do processing below if setting with doset() */
             if (initial)
-                return;
+                return retval;
 
-            if ((boolopt[i].addr) == &flags.time
-                || (boolopt[i].addr) == &flags.showexp
+            if (boolopt[i].addr == &flags.time
 #ifdef SCORE_ON_BOTL
-                || (boolopt[i].addr) == &flags.showscore
+                || boolopt[i].addr == &flags.showscore
 #endif
-                ) {
-#ifdef STATUS_VIA_WINDOWPORT
+                || boolopt[i].addr == &flags.showexp) {
+#ifdef STATUS_HILITES
                 status_initialize(REASSESS_ONLY);
 #endif
                 context.botl = TRUE;
-            } else if ((boolopt[i].addr) == &flags.invlet_constant) {
+            } else if (boolopt[i].addr == &flags.invlet_constant) {
                 if (flags.invlet_constant)
                     reassign();
-            } else if (((boolopt[i].addr) == &flags.lit_corridor)
-                       || ((boolopt[i].addr) == &flags.dark_room)) {
+            } else if (boolopt[i].addr == &flags.lit_corridor
+                       || boolopt[i].addr == &flags.dark_room) {
                 /*
                  * All corridor squares seen via night vision or
                  * candles & lamps change.  Update them by calling
@@ -3652,15 +4062,23 @@ boolean tinitial, tfrom_file;
                 vision_full_recalc = 1; /* delayed recalc */
                 if (iflags.use_color)
                     need_redraw = TRUE; /* darkroom refresh */
-            } else if ((boolopt[i].addr) == &iflags.use_inverse
-                       || (boolopt[i].addr) == &flags.showrace
-                       || (boolopt[i].addr) == &iflags.hilite_pet) {
+            } else if (boolopt[i].addr == &flags.showrace
+                       || boolopt[i].addr == &iflags.use_inverse
+                       || boolopt[i].addr == &iflags.hilite_pile
+                       || boolopt[i].addr == &iflags.hilite_pet
+                       || boolopt[i].addr == &iflags.wc_ascii_map
+                       || boolopt[i].addr == &iflags.wc_tiled_map) {
+                need_redraw = TRUE;
+#ifdef STATUS_HILITES
+            } else if (boolopt[i].addr == &iflags.wc2_hitpointbar) {
+                status_initialize(REASSESS_ONLY);
                 need_redraw = TRUE;
+#endif
 #ifdef TEXTCOLOR
-            } else if ((boolopt[i].addr) == &iflags.use_color) {
+            } else if (boolopt[i].addr == &iflags.use_color) {
                 need_redraw = TRUE;
 #ifdef TOS
-                if ((boolopt[i].addr) == &iflags.use_color && iflags.BIOS) {
+                if (iflags.BIOS) {
                     if (colors_changed)
                         restore_colors();
                     else
@@ -3669,12 +4087,74 @@ boolean tinitial, tfrom_file;
 #endif
 #endif /* TEXTCOLOR */
             }
-            return;
+            return retval;
         }
     }
 
+    /* Is it a symbol? */
+    if (strstr(opts, "S_") == opts && parsesymbols(opts)) {
+        switch_symbols(TRUE);
+        check_gold_symbol();
+        return retval;
+    }
+
     /* out of valid options */
-    badoption(opts);
+    config_error_add("Unknown option '%s'", opts);
+    return FALSE;
+}
+
+/* parse key:command */
+boolean
+parsebindings(bindings)
+char* bindings;
+{
+    char *bind;
+    char key;
+    int i;
+    boolean ret = FALSE;
+
+    /* break off first binding from the rest; parse the rest */
+    if ((bind = index(bindings, ',')) != 0) {
+        *bind++ = 0;
+        ret |= parsebindings(bind);
+    }
+
+    /* parse a single binding: first split around : */
+    if (! (bind = index(bindings, ':')))
+        return FALSE; /* it's not a binding */
+    *bind++ = 0;
+
+    /* read the key to be bound */
+    key = txt2key(bindings);
+    if (!key) {
+        config_error_add("Unknown key binding key '%s'", bindings);
+        return FALSE;
+    }
+
+    bind = trimspaces(bind);
+
+    /* is it a special key? */
+    if (bind_specialkey(key, bind))
+        return TRUE;
+
+    /* is it a menu command? */
+    for (i = 0; i < SIZE(default_menu_cmd_info); i++) {
+        if (!strcmp(default_menu_cmd_info[i].name, bind)) {
+            if (illegal_menu_cmd_key(key)) {
+                config_error_add("Bad menu key %s:%s", visctrl(key), bind);
+                return FALSE;
+            } else
+                add_menu_cmd_alias(key, default_menu_cmd_info[i].cmd);
+            return TRUE;
+        }
+    }
+
+    /* extended command? */
+    if (!bind_key(key, bind)) {
+        config_error_add("Unknown key binding command '%s'", bind);
+        return FALSE;
+    }
+    return TRUE;
 }
 
 static NEARDATA const char *menutype[] = { "traditional", "combination",
@@ -3727,6 +4207,20 @@ char from_ch, to_ch;
     }
 }
 
+char
+get_menu_cmd_key(ch)
+char ch;
+{
+    char *found = index(mapped_menu_op, ch);
+
+    if (found) {
+        int idx = (int) (found - mapped_menu_op);
+
+        ch = mapped_menu_cmds[idx];
+    }
+    return ch;
+}
+
 /*
  * Map the given character to its corresponding menu command.  If it
  * doesn't match anything, just return the original.
@@ -3736,22 +4230,78 @@ map_menu_cmd(ch)
 char ch;
 {
     char *found = index(mapped_menu_cmds, ch);
+
     if (found) {
         int idx = (int) (found - mapped_menu_cmds);
+
         ch = mapped_menu_op[idx];
     }
     return ch;
 }
 
+void
+show_menu_controls(win, dolist)
+winid win;
+boolean dolist;
+{
+    char buf[BUFSZ];
+
+    putstr(win, 0, "Menu control keys:");
+    if (dolist) {
+        int i;
+
+        for (i = 0; i < SIZE(default_menu_cmd_info); i++) {
+            Sprintf(buf, "%-8s %s",
+                    visctrl(get_menu_cmd_key(default_menu_cmd_info[i].cmd)),
+                    default_menu_cmd_info[i].desc);
+            putstr(win, 0, buf);
+        }
+    } else {
+        putstr(win, 0, "");
+        putstr(win, 0, "          Page    All items");
+        Sprintf(buf, "  Select   %s       %s",
+                visctrl(get_menu_cmd_key(MENU_SELECT_PAGE)),
+                visctrl(get_menu_cmd_key(MENU_SELECT_ALL)));
+        putstr(win, 0, buf);
+        Sprintf(buf, "Deselect   %s       %s",
+                visctrl(get_menu_cmd_key(MENU_UNSELECT_PAGE)),
+                visctrl(get_menu_cmd_key(MENU_UNSELECT_ALL)));
+        putstr(win, 0, buf);
+        Sprintf(buf, "  Invert   %s       %s",
+                visctrl(get_menu_cmd_key(MENU_INVERT_PAGE)),
+                visctrl(get_menu_cmd_key(MENU_INVERT_ALL)));
+        putstr(win, 0, buf);
+        putstr(win, 0, "");
+        Sprintf(buf, "   Go to   %s   Next page",
+                visctrl(get_menu_cmd_key(MENU_NEXT_PAGE)));
+        putstr(win, 0, buf);
+        Sprintf(buf, "           %s   Previous page",
+                visctrl(get_menu_cmd_key(MENU_PREVIOUS_PAGE)));
+        putstr(win, 0, buf);
+        Sprintf(buf, "           %s   First page",
+                visctrl(get_menu_cmd_key(MENU_FIRST_PAGE)));
+        putstr(win, 0, buf);
+        Sprintf(buf, "           %s   Last page",
+                visctrl(get_menu_cmd_key(MENU_LAST_PAGE)));
+        putstr(win, 0, buf);
+        putstr(win, 0, "");
+        Sprintf(buf, "           %s   Search and toggle matching entries",
+                visctrl(get_menu_cmd_key(MENU_SEARCH)));
+        putstr(win, 0, buf);
+    }
+}
+
 #if defined(MICRO) || defined(MAC) || defined(WIN32)
 #define OPTIONS_HEADING "OPTIONS"
 #else
 #define OPTIONS_HEADING "NETHACKOPTIONS"
 #endif
 
-static char fmtstr_doset_add_menu[] = "%s%-15s [%s]   ";
-static char fmtstr_doset_add_menu_tab[] = "%s\t[%s]";
+static char fmtstr_doset[] = "%s%-15s [%s]   ";
+static char fmtstr_doset_tab[] = "%s\t[%s]";
+static char n_currently_set[] = "(%d currently set)";
 
+/* doset('O' command) menu entries for compound options */
 STATIC_OVL void
 doset_add_menu(win, option, indexoffset)
 winid win;          /* window to add to */
@@ -3785,31 +4335,125 @@ int indexoffset;    /* value to add to index in compopt[], or zero
     }
     /* "    " replaces "a - " -- assumes menus follow that style */
     if (!iflags.menu_tab_sep)
-        Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ", option,
+        Sprintf(buf, fmtstr_doset, any.a_int ? "" : "    ", option,
                 value);
     else
-        Sprintf(buf, fmtstr_doset_add_menu_tab, option, value);
+        Sprintf(buf, fmtstr_doset_tab, option, value);
     add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
 }
 
-/* Changing options via menu by Per Liboriussen */
-int
-doset()
+STATIC_OVL void
+opts_add_others(win, name, id, bufx, nset)
+winid win;
+const char *name;
+int id;
+char *bufx;
+int nset;
 {
     char buf[BUFSZ], buf2[BUFSZ];
+    anything any = zeroany;
+
+    any.a_int = id;
+    if (!bufx)
+        Sprintf(buf2, n_currently_set, nset);
+    else
+        Sprintf(buf2, "%s", bufx);
+    if (!iflags.menu_tab_sep)
+        Sprintf(buf, fmtstr_doset, any.a_int ? "" : "    ",
+                name, buf2);
+    else
+        Sprintf(buf, fmtstr_doset_tab, name, buf2);
+    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
+}
+
+int
+count_apes(VOID_ARGS)
+{
+    return count_ape_maps((int *) 0, (int *) 0);
+}
+
+enum opt_other_enums {
+    OPT_OTHER_MSGTYPE = -4,
+    OPT_OTHER_MENUCOLOR = -3,
+    OPT_OTHER_STATHILITE = -2,
+    OPT_OTHER_APEXC = -1
+    /* these must be < 0 */
+};
+
+static struct other_opts {
+    const char *name;
+    int optflags;
+    enum opt_other_enums code;
+    int NDECL((*othr_count_func));
+} othropt[] = {
+    { "autopickup exceptions", SET_IN_GAME, OPT_OTHER_APEXC, count_apes },
+    { "menucolors", SET_IN_GAME, OPT_OTHER_MENUCOLOR, count_menucolors },
+    { "message types", SET_IN_GAME, OPT_OTHER_MSGTYPE, msgtype_count },
+#ifdef STATUS_HILITES
+    { "status hilite rules", SET_IN_GAME, OPT_OTHER_STATHILITE,
+      count_status_hilites },
+#endif
+    { (char *) 0, 0, (enum opt_other_enums) 0 },
+};
+
+/* the 'O' command */
+int
+doset() /* changing options via menu by Per Liboriussen */
+{
+    static boolean made_fmtstr = FALSE;
+    char buf[BUFSZ], buf2[BUFSZ] = DUMMY;
+    const char *name;
     int i = 0, pass, boolcount, pick_cnt, pick_idx, opt_indx;
     boolean *bool_p;
     winid tmpwin;
     anything any;
     menu_item *pick_list;
-    int indexoffset, startpass, endpass;
+    int indexoffset, startpass, endpass, optflags;
     boolean setinitial = FALSE, fromfile = FALSE;
-    int biggest_name = 0;
-    const char *n_currently_set = "(%d currently set)";
+    unsigned longest_name_len;
 
     tmpwin = create_nhwindow(NHW_MENU);
     start_menu(tmpwin);
 
+#ifdef notyet /* SYSCF */
+    /* XXX I think this is still fragile.  Fixing initial/from_file and/or
+       changing the SET_* etc to bitmaps will let me make this better. */
+    if (wizard)
+        startpass = SET_IN_SYS;
+    else
+#endif
+        startpass = DISP_IN_GAME;
+    endpass = (wizard) ? SET_IN_WIZGAME : SET_IN_GAME;
+
+    if (!made_fmtstr && !iflags.menu_tab_sep) {
+        /* spin through the options to find the longest name
+           and adjust the format string accordingly */
+        longest_name_len = 0;
+        for (pass = 0; pass <= 2; pass++)
+            for (i = 0; (name = ((pass == 0)
+                                 ? boolopt[i].name
+                                 : (pass == 1)
+                                   ? compopt[i].name
+                                   : othropt[i].name)) != 0; i++) {
+                if (pass == 0 && !boolopt[i].addr)
+                    continue;
+                optflags = (pass == 0) ? boolopt[i].optflags
+                                       : (pass == 1)
+                                         ? compopt[i].optflags
+                                         : othropt[i].optflags;
+                if (optflags < startpass || optflags > endpass)
+                    continue;
+                if ((is_wc_option(name) && !wc_supported(name))
+                    || (is_wc2_option(name) && !wc2_supported(name)))
+                    continue;
+
+                if (strlen(name) > longest_name_len)
+                    longest_name_len = strlen(name);
+            }
+        Sprintf(fmtstr_doset, "%%s%%-%us [%%s]", longest_name_len);
+        made_fmtstr = TRUE;
+    }
+
     any = zeroany;
     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
 /*JP
@@ -3819,29 +4463,25 @@ doset()
     any.a_int = 0;
     /* first list any other non-modifiable booleans, then modifiable ones */
     for (pass = 0; pass <= 1; pass++)
-        for (i = 0; boolopt[i].name; i++)
+        for (i = 0; (name = boolopt[i].name) != 0; i++)
             if ((bool_p = boolopt[i].addr) != 0
-                && ((boolopt[i].optflags == DISP_IN_GAME && pass == 0)
-                    || (boolopt[i].optflags == SET_IN_GAME && pass == 1))) {
+                && ((boolopt[i].optflags <= DISP_IN_GAME && pass == 0)
+                    || (boolopt[i].optflags >= SET_IN_GAME && pass == 1))) {
                 if (bool_p == &flags.female)
                     continue; /* obsolete */
-                if (bool_p == &iflags.sanity_check && !wizard)
-                    continue;
-                if (bool_p == &iflags.menu_tab_sep && !wizard)
-                    continue;
-                if (is_wc_option(boolopt[i].name)
-                    && !wc_supported(boolopt[i].name))
+                if (boolopt[i].optflags == SET_IN_WIZGAME && !wizard)
                     continue;
-                if (is_wc2_option(boolopt[i].name)
-                    && !wc2_supported(boolopt[i].name))
+                if ((is_wc_option(name) && !wc_supported(name))
+                    || (is_wc2_option(name) && !wc2_supported(name)))
                     continue;
+
                 any.a_int = (pass == 0) ? 0 : i + 1;
                 if (!iflags.menu_tab_sep)
-                    Sprintf(buf, "%s%-17s [%s]", pass == 0 ? "    " : "",
-                            boolopt[i].name, *bool_p ? "true" : "false");
+                    Sprintf(buf, fmtstr_doset, (pass == 0) ? "    " : "",
+                            name, *bool_p ? "true" : "false");
                 else
-                    Sprintf(buf, "%s\t[%s]", boolopt[i].name,
-                            *bool_p ? "true" : "false");
+                    Sprintf(buf, fmtstr_doset_tab,
+                            name, *bool_p ? "true" : "false");
                 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
                          MENU_UNSELECTED);
             }
@@ -3860,85 +4500,42 @@ doset()
              MENU_UNSELECTED);
 #endif
 
-#ifdef notyet /* SYSCF */
-    /* XXX I think this is still fragile.  Fixing initial/from_file and/or
-     changing
-     the SET_* etc to bitmaps will let me make this better. */
-    if (wizard)
-        startpass = SET_IN_SYS;
-    else
-#endif
-        startpass = DISP_IN_GAME;
-    endpass = SET_IN_GAME;
-
-    /* spin through the options to find the biggest name
-       and adjust the format string accordingly if needed */
-    biggest_name = 0;
-    for (i = 0; compopt[i].name; i++)
-        if (compopt[i].optflags >= startpass && compopt[i].optflags <= endpass
-            && strlen(compopt[i].name) > (unsigned) biggest_name)
-            biggest_name = (int) strlen(compopt[i].name);
-    if (biggest_name > 30)
-        biggest_name = 30;
-    if (!iflags.menu_tab_sep)
-        Sprintf(fmtstr_doset_add_menu, "%%s%%-%ds [%%s]", biggest_name);
-
-    /* deliberately put `playmode', `name', `role', `race', `gender' first
-       (also alignment if anything ever comes before it in compopt[]) */
+    /* deliberately put playmode, name, role+race+gender+align first */
     doset_add_menu(tmpwin, "playmode", 0);
     doset_add_menu(tmpwin, "name", 0);
     doset_add_menu(tmpwin, "role", 0);
     doset_add_menu(tmpwin, "race", 0);
     doset_add_menu(tmpwin, "gender", 0);
+    doset_add_menu(tmpwin, "align", 0);
 
     for (pass = startpass; pass <= endpass; pass++)
-        for (i = 0; compopt[i].name; i++)
+        for (i = 0; (name = compopt[i].name) != 0; i++)
             if (compopt[i].optflags == pass) {
-                if (!strcmp(compopt[i].name, "playmode")
-                    || !strcmp(compopt[i].name, "name")
-                    || !strcmp(compopt[i].name, "role")
-                    || !strcmp(compopt[i].name, "race")
-                    || !strcmp(compopt[i].name, "gender"))
-                    continue;
-                else if (is_wc_option(compopt[i].name)
-                         && !wc_supported(compopt[i].name))
+                if (!strcmp(name, "playmode")  || !strcmp(name, "name")
+                    || !strcmp(name, "role")   || !strcmp(name, "race")
+                    || !strcmp(name, "gender") || !strcmp(name, "align"))
                     continue;
-                else if (is_wc2_option(compopt[i].name)
-                         && !wc2_supported(compopt[i].name))
+                if ((is_wc_option(name) && !wc_supported(name))
+                    || (is_wc2_option(name) && !wc2_supported(name)))
                     continue;
-                else
-                    doset_add_menu(tmpwin, compopt[i].name,
-                                   (pass == DISP_IN_GAME) ? 0 : indexoffset);
+
+                doset_add_menu(tmpwin, name,
+                               (pass == DISP_IN_GAME) ? 0 : indexoffset);
             }
-    any.a_int = -4;
-    Sprintf(buf2, n_currently_set, msgtype_count());
-    Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
-            "message types", buf2);
-    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
-    any.a_int = -3;
-    Sprintf(buf2, n_currently_set, count_menucolors());
-    Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
-            "menucolors", buf2);
-    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
-#ifdef STATUS_VIA_WINDOWPORT
-#ifdef STATUS_HILITES
-    any.a_int = -2;
-    get_status_hilites(buf2, 60);
-    if (!*buf2)
-        Sprintf(buf2, "%s", "(none)");
-    if (!iflags.menu_tab_sep)
-        Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
-                "status_hilites", buf2);
-    else
-        Sprintf(buf, fmtstr_doset_add_menu_tab, "status_hilites", buf2);
-    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
-#endif
-#endif
-    any.a_int = -1;
-    Sprintf(buf2, n_currently_set, count_ape_maps((int *) 0, (int *) 0));
-    Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
-            "autopickup exceptions", buf2);
-    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
+
+    any = zeroany;
+    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+             "Other settings:", MENU_UNSELECTED);
+
+    for (i = 0; (name = othropt[i].name) != 0; i++) {
+        if ((is_wc_option(name) && !wc_supported(name))
+            || (is_wc2_option(name) && !wc2_supported(name)))
+            continue;
+        opts_add_others(tmpwin, name, othropt[i].code,
+                        (char *) 0, othropt[i].othr_count_func());
+    }
+
 #ifdef PREFIXES_IN_USE
     any = zeroany;
     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
@@ -3961,26 +4558,24 @@ doset()
          */
         for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
             opt_indx = pick_list[pick_idx].item.a_int - 1;
-            if (opt_indx == -2) {
-                /* -2 due to -1 offset for select_menu() */
+            if (opt_indx < -1)
+                opt_indx++; /* -1 offset for select_menu() */
+            if (opt_indx == OPT_OTHER_APEXC) {
                 (void) special_handling("autopickup_exception", setinitial,
                                         fromfile);
-#ifdef STATUS_VIA_WINDOWPORT
 #ifdef STATUS_HILITES
-            } else if (opt_indx == -3) {
-                /* -3 due to -1 offset for select_menu() */
+            } else if (opt_indx == OPT_OTHER_STATHILITE) {
                 if (!status_hilite_menu()) {
                     pline("Bad status hilite(s) specified.");
                 } else {
-                    if (wc2_supported("status_hilites"))
-                        preference_update("status_hilites");
+                    if (wc2_supported("hilite_status"))
+                        preference_update("hilite_status");
                 }
 #endif
-#endif
-            } else if (opt_indx == -4) {
+            } else if (opt_indx == OPT_OTHER_MENUCOLOR) {
                     (void) special_handling("menucolors", setinitial,
                                             fromfile);
-            } else if (opt_indx == -5) {
+            } else if (opt_indx == OPT_OTHER_MSGTYPE) {
                     (void) special_handling("msgtype", setinitial, fromfile);
             } else if (opt_indx < boolcount) {
                 /* boolean option */
@@ -4018,20 +4613,21 @@ doset()
 
     destroy_nhwindow(tmpwin);
     if (need_redraw) {
+        check_gold_symbol();
         reglyph_darkroom();
         (void) doredraw();
     }
     return 0;
 }
 
-int
+STATIC_OVL int
 handle_add_list_remove(optname, numtotal)
 const char *optname;
 int numtotal;
 {
     winid tmpwin;
     anything any;
-    int i, pick_cnt, pick_idx, opt_idx;
+    int i, pick_cnt, opt_idx;
     menu_item *pick_list = (menu_item *) 0;
     static const struct action {
         char letr;
@@ -4065,6 +4661,7 @@ int numtotal;
     any = zeroany;
     for (i = 0; i < SIZE(action_titles); i++) {
         char tmpbuf[BUFSZ];
+
         any.a_int++;
         /* omit list and remove if there aren't any yet */
         if (!numtotal && (i == 1 || i == 2))
@@ -4072,27 +4669,20 @@ int numtotal;
         Sprintf(tmpbuf, action_titles[i].desc,
                 (i == 1) ? makeplural(optname) : optname);
         add_menu(tmpwin, NO_GLYPH, &any, action_titles[i].letr, 0, ATR_NONE,
-                 tmpbuf,
-#if 0 /* this ought to work but doesn't... */
-                 (action_titles[i].letr == 'x') ? MENU_SELECTED :
-#endif
-                 MENU_UNSELECTED);
+                 tmpbuf, (i == 3) ? MENU_SELECTED : MENU_UNSELECTED);
     }
 /*JP
     end_menu(tmpwin, "Do what?");
 */
     end_menu(tmpwin, "\82Ç\82¤\82·\82é\81H");
     if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
-        for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
-            opt_idx = pick_list[pick_idx].item.a_int - 1;
-        }
+        opt_idx = pick_list[0].item.a_int - 1;
+        if (pick_cnt > 1 && opt_idx == 3)
+            opt_idx = pick_list[1].item.a_int - 1;
         free((genericptr_t) pick_list);
-        pick_list = (menu_item *) 0;
-    }
-    destroy_nhwindow(tmpwin);
-
-    if (pick_cnt < 1)
+    } else
         opt_idx = 3; /* none selected, exit menu */
+    destroy_nhwindow(tmpwin);
     return opt_idx;
 }
 
@@ -4106,7 +4696,7 @@ boolean setinitial, setfromfile;
 {
     winid tmpwin;
     anything any;
-    int i;
+    int i, n;
     char buf[BUFSZ];
 
     /* Special handling of menustyle, pickup_burden, pickup_types,
@@ -4117,6 +4707,7 @@ boolean setinitial, setfromfile;
     if (!strcmp("menustyle", optname)) {
         const char *style_name;
         menu_item *style_pick = (menu_item *) 0;
+
         tmpwin = create_nhwindow(NHW_MENU);
         start_menu(tmpwin);
         any = zeroany;
@@ -4202,6 +4793,7 @@ boolean setinitial, setfromfile;
         };
         int disc_cat[NUM_DISCLOSURE_OPTIONS];
         int pick_cnt, pick_idx, opt_idx;
+        char c;
         menu_item *disclosure_pick = (menu_item *) 0;
 
         tmpwin = create_nhwindow(NHW_MENU);
@@ -4232,6 +4824,7 @@ boolean setinitial, setfromfile;
 
         for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
             if (disc_cat[i]) {
+                c = flags.end_disclose[i];
 /*JP
                 Sprintf(buf, "Disclosure options for %s:",
 */
@@ -4242,36 +4835,53 @@ boolean setinitial, setfromfile;
                 any = zeroany;
                 /* 'y','n',and '+' work as alternate selectors; '-' doesn't */
                 any.a_char = DISCLOSE_NO_WITHOUT_PROMPT;
-                add_menu(tmpwin, NO_GLYPH, &any, 'a', any.a_char, ATR_NONE,
+                add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
 /*JP
                          "Never disclose, without prompting",
 */
                          "\8am\94F\82¹\82¸\82É\8fo\97Í\82à\82µ\82È\82¢",
-                         MENU_UNSELECTED);
+                         (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
                 any.a_char = DISCLOSE_YES_WITHOUT_PROMPT;
-                add_menu(tmpwin, NO_GLYPH, &any, 'b', any.a_char, ATR_NONE,
+                add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
 /*JP
                          "Always disclose, without prompting",
 */
                          "\8am\94F\82¹\82¸\82É\8fo\97Í\82·\82é",
-                         MENU_UNSELECTED);
+                         (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
+                if (*disclosure_names[i] == 'v') {
+                    any.a_char = DISCLOSE_SPECIAL_WITHOUT_PROMPT; /* '#' */
+                    add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
+                             "Always disclose, pick sort order from menu",
+                             (c == any.a_char) ? MENU_SELECTED
+                                               : MENU_UNSELECTED);
+                }
                 any.a_char = DISCLOSE_PROMPT_DEFAULT_NO;
-                add_menu(tmpwin, NO_GLYPH, &any, 'c', any.a_char, ATR_NONE,
+                add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
 /*JP
                          "Prompt, with default answer of \"No\"",
 */
                          "\8am\94F\82·\82é\81C\83f\83t\83H\83\8b\83g\82Í\81u\8fo\97Í\82µ\82È\82¢\81v",
-                         MENU_UNSELECTED);
+                         (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
                 any.a_char = DISCLOSE_PROMPT_DEFAULT_YES;
-                add_menu(tmpwin, NO_GLYPH, &any, 'd', any.a_char, ATR_NONE,
+                add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
 /*JP
                          "Prompt, with default answer of \"Yes\"",
 */
                          "\8am\94F\82·\82é\81C\83f\83t\83H\83\8b\83g\82Í\81u\8fo\97Í\82·\82é\81v",
-                         MENU_UNSELECTED);
+                         (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
+                if (*disclosure_names[i] == 'v') {
+                    any.a_char = DISCLOSE_PROMPT_DEFAULT_SPECIAL; /* '?' */
+                    add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
+                "Prompt, with default answer of \"Ask\" to request sort menu",
+                             (c == any.a_char) ? MENU_SELECTED
+                                               : MENU_UNSELECTED);
+                }
                 end_menu(tmpwin, buf);
-                if (select_menu(tmpwin, PICK_ONE, &disclosure_pick) > 0) {
-                    flags.end_disclose[i] = disclosure_pick->item.a_char;
+                n = select_menu(tmpwin, PICK_ONE, &disclosure_pick);
+                if (n > 0) {
+                    flags.end_disclose[i] = disclosure_pick[0].item.a_char;
+                    if (n > 1 && flags.end_disclose[i] == c)
+                        flags.end_disclose[i] = disclosure_pick[1].item.a_char;
                     free((genericptr_t) disclosure_pick);
                 }
                 destroy_nhwindow(tmpwin);
@@ -4299,6 +4909,96 @@ boolean setinitial, setfromfile;
             free((genericptr_t) mode_pick);
         }
         destroy_nhwindow(tmpwin);
+    } else if (!strcmp("whatis_coord", optname)) {
+        menu_item *window_pick = (menu_item *) 0;
+        int pick_cnt;
+        char gp = iflags.getpos_coords;
+
+        tmpwin = create_nhwindow(NHW_MENU);
+        start_menu(tmpwin);
+        any = zeroany;
+        any.a_char = GPCOORDS_COMPASS;
+        add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMPASS,
+                 0, ATR_NONE, "compass ('east' or '3s' or '2n,4w')",
+                 (gp == GPCOORDS_COMPASS) ? MENU_SELECTED : MENU_UNSELECTED);
+        any.a_char = GPCOORDS_COMFULL;
+        add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMFULL, 0, ATR_NONE,
+                 "full compass ('east' or '3south' or '2north,4west')",
+                 (gp == GPCOORDS_COMFULL) ? MENU_SELECTED : MENU_UNSELECTED);
+        any.a_char = GPCOORDS_MAP;
+        add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_MAP,
+                 0, ATR_NONE, "map <x,y>",
+                 (gp == GPCOORDS_MAP) ? MENU_SELECTED : MENU_UNSELECTED);
+        any.a_char = GPCOORDS_SCREEN;
+        add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_SCREEN,
+                 0, ATR_NONE, "screen [row,column]",
+                 (gp == GPCOORDS_SCREEN) ? MENU_SELECTED : MENU_UNSELECTED);
+        any.a_char = GPCOORDS_NONE;
+        add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_NONE,
+                 0, ATR_NONE, "none (no coordinates displayed)",
+                 (gp == GPCOORDS_NONE) ? MENU_SELECTED : MENU_UNSELECTED);
+        any.a_long = 0L;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+        Sprintf(buf, "map: upper-left: <%d,%d>, lower-right: <%d,%d>%s",
+                1, 0, COLNO - 1, ROWNO - 1,
+                flags.verbose ? "; column 0 unused, off left edge" : "");
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
+        if (strcmp(windowprocs.name, "tty"))
+            add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+       "screen: row is offset to accommodate tty interface's use of top line",
+                     MENU_UNSELECTED);
+#if COLNO == 80
+#define COL80ARG flags.verbose ? "; column 80 is not used" : ""
+#else
+#define COL80ARG ""
+#endif
+        Sprintf(buf, "screen: upper-left: [%02d,%02d], lower-right: [%d,%d]%s",
+                0 + 2, 1, ROWNO - 1 + 2, COLNO - 1, COL80ARG);
+#undef COL80ARG
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+        end_menu(tmpwin,
+            "Select coordinate display when auto-describing a map position:");
+        if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &window_pick)) > 0) {
+            iflags.getpos_coords = window_pick[0].item.a_char;
+            /* PICK_ONE doesn't unselect preselected entry when
+               selecting another one */
+            if (pick_cnt > 1 && iflags.getpos_coords == gp)
+                iflags.getpos_coords = window_pick[1].item.a_char;
+            free((genericptr_t) window_pick);
+        }
+        destroy_nhwindow(tmpwin);
+    } else if (!strcmp("whatis_filter", optname)) {
+        menu_item *window_pick = (menu_item *) 0;
+        int pick_cnt;
+        char gf = iflags.getloc_filter;
+
+        tmpwin = create_nhwindow(NHW_MENU);
+        start_menu(tmpwin);
+        any = zeroany;
+        any.a_char = (GFILTER_NONE + 1);
+        add_menu(tmpwin, NO_GLYPH, &any, 'n',
+                 0, ATR_NONE, "no filtering",
+                 (gf == GFILTER_NONE) ? MENU_SELECTED : MENU_UNSELECTED);
+        any.a_char = (GFILTER_VIEW + 1);
+        add_menu(tmpwin, NO_GLYPH, &any, 'v',
+                 0, ATR_NONE, "in view only",
+                 (gf == GFILTER_VIEW) ? MENU_SELECTED : MENU_UNSELECTED);
+        any.a_char = (GFILTER_AREA + 1);
+        add_menu(tmpwin, NO_GLYPH, &any, 'a',
+                 0, ATR_NONE, "in same area",
+                 (gf == GFILTER_AREA) ? MENU_SELECTED : MENU_UNSELECTED);
+        end_menu(tmpwin,
+      "Select location filtering when going for next/previous map position:");
+        if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &window_pick)) > 0) {
+            iflags.getloc_filter = (window_pick[0].item.a_char - 1);
+            /* PICK_ONE doesn't unselect preselected entry when
+               selecting another one */
+            if (pick_cnt > 1 && iflags.getloc_filter == gf)
+                iflags.getloc_filter = (window_pick[1].item.a_char - 1);
+            free((genericptr_t) window_pick);
+        }
+        destroy_nhwindow(tmpwin);
     } else if (!strcmp("msg_window", optname)) {
 #ifdef TTY_GRAPHICS
         /* by Christian W. Cooper */
@@ -4340,11 +5040,17 @@ boolean setinitial, setfromfile;
             sortl_name = sortltype[i];
             any.a_char = *sortl_name;
             add_menu(tmpwin, NO_GLYPH, &any, *sortl_name, 0, ATR_NONE,
-                     sortl_name, MENU_UNSELECTED);
+                     sortl_name, (flags.sortloot == *sortl_name)
+                                    ? MENU_SELECTED : MENU_UNSELECTED);
         }
         end_menu(tmpwin, "Select loot sorting type:");
-        if (select_menu(tmpwin, PICK_ONE, &sortl_pick) > 0) {
-            flags.sortloot = sortl_pick->item.a_char;
+        n = select_menu(tmpwin, PICK_ONE, &sortl_pick);
+        if (n > 0) {
+            char c = sortl_pick[0].item.a_char;
+
+            if (n > 1 && c == flags.sortloot)
+                c = sortl_pick[1].item.a_char;
+            flags.sortloot = c;
             free((genericptr_t) sortl_pick);
         }
         destroy_nhwindow(tmpwin);
@@ -4461,28 +5167,30 @@ boolean setinitial, setfromfile;
             iflags.menu_headings = mhattr;
     } else if (!strcmp("msgtype", optname)) {
         int opt_idx, nmt, mttyp;
-        char mtbuf[BUFSZ];
+        char mtbuf[BUFSZ] = DUMMY;
 
     msgtypes_again:
         nmt = msgtype_count();
         opt_idx = handle_add_list_remove("message type", nmt);
-        if (opt_idx == 3) {
-            ; /* done--fall through to function exit */
+        if (opt_idx == 3) { /* done */
+            return TRUE;
         } else if (opt_idx == 0) { /* add new */
             getlin("What new message pattern?", mtbuf);
-            if (*mtbuf == '\033' || !*mtbuf)
-                goto msgtypes_again;
-            mttyp = query_msgtype();
-            if (mttyp == -1)
-                goto msgtypes_again;
-            if (!msgtype_add(mttyp, mtbuf)) {
+            if (*mtbuf == '\033')
+                return TRUE;
+            if (*mtbuf
+                && test_regex_pattern(mtbuf, (const char *)0)
+                && (mttyp = query_msgtype()) != -1
+                && !msgtype_add(mttyp, mtbuf)) {
                 pline("Error adding the message type.");
                 wait_synch();
-                goto msgtypes_again;
             }
-        } else { /* list or remove */
+            goto msgtypes_again;
+        } else { /* list (1) or remove (2) */
             int pick_idx, pick_cnt;
             int mt_idx;
+            unsigned ln;
+            const char *mtype;
             menu_item *pick_list = (menu_item *) 0;
             struct plinemsg_type *tmp = plinemsg_types;
 
@@ -4491,10 +5199,14 @@ boolean setinitial, setfromfile;
             any = zeroany;
             mt_idx = 0;
             while (tmp) {
-                const char *mtype = msgtype2name(tmp->msgtype);
-
+                mtype = msgtype2name(tmp->msgtype);
                 any.a_int = ++mt_idx;
-                Sprintf(mtbuf, "%-5s \"%s\"", mtype, tmp->pattern);
+                Sprintf(mtbuf, "%-5s \"", mtype);
+                ln = sizeof mtbuf - strlen(mtbuf) - sizeof "\"";
+                if (strlen(tmp->pattern) > ln)
+                    Strcat(strncat(mtbuf, tmp->pattern, ln - 3), "...\"");
+                else
+                    Strcat(mtbuf, "\"");
                 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mtbuf,
                          MENU_UNSELECTED);
                 tmp = tmp->next;
@@ -4517,31 +5229,31 @@ boolean setinitial, setfromfile;
         }
     } else if (!strcmp("menucolors", optname)) {
         int opt_idx, nmc, mcclr, mcattr;
-        char mcbuf[BUFSZ];
+        char mcbuf[BUFSZ] = DUMMY;
 
     menucolors_again:
         nmc = count_menucolors();
         opt_idx = handle_add_list_remove("menucolor", nmc);
-        if (opt_idx == 3) {
-            ;                      /* done--fall through to function exit */
+        if (opt_idx == 3) { /* done */
+            return TRUE;
         } else if (opt_idx == 0) { /* add new */
             getlin("What new menucolor pattern?", mcbuf);
-            if (*mcbuf == '\033' || !*mcbuf)
-                goto menucolors_again;
-            mcclr = query_color();
-            if (mcclr == -1)
-                goto menucolors_again;
-            mcattr = query_attr(NULL);
-            if (mcattr == -1)
-                goto menucolors_again;
-            if (!add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
+            if (*mcbuf == '\033')
+                return TRUE;
+            if (*mcbuf
+                && test_regex_pattern(mcbuf, (const char *)0)
+                && (mcclr = query_color((char *) 0)) != -1
+                && (mcattr = query_attr((char *) 0)) != -1
+                && !add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
                 pline("Error adding the menu color.");
                 wait_synch();
-                goto menucolors_again;
             }
-        } else { /* list or remove */
+            goto menucolors_again;
+        } else { /* list (1) or remove (2) */
             int pick_idx, pick_cnt;
             int mc_idx;
+            unsigned ln;
+            const char *sattr, *sclr;
             menu_item *pick_list = (menu_item *) 0;
             struct menucoloring *tmp = menu_colorings;
 
@@ -4550,13 +5262,22 @@ boolean setinitial, setfromfile;
             any = zeroany;
             mc_idx = 0;
             while (tmp) {
-                const char *sattr = attr2attrname(tmp->attr);
-                const char *sclr = clr2colorname(tmp->color);
-
-                any.a_int = (++mc_idx);
-                Sprintf(mcbuf, "\"%s\"=%s%s%s", tmp->origstr, sclr,
+                sattr = attr2attrname(tmp->attr);
+                sclr = clr2colorname(tmp->color);
+                any.a_int = ++mc_idx;
+                /* construct suffix */
+                Sprintf(buf, "\"\"=%s%s%s", sclr,
                         (tmp->attr != ATR_NONE) ? " & " : "",
                         (tmp->attr != ATR_NONE) ? sattr : "");
+                /* now main string */
+                ln = sizeof buf - strlen(buf) - 1; /* length available */
+                Strcpy(mcbuf, "\"");
+                if (strlen(tmp->origstr) > ln)
+                    Strcat(strncat(mcbuf, tmp->origstr, ln - 3), "...");
+                else
+                    Strcat(mcbuf, tmp->origstr);
+                /* combine main string and suffix */
+                Strcat(mcbuf, &buf[1]); /* skip buf[]'s initial quote */
                 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mcbuf,
                          MENU_UNSELECTED);
                 tmp = tmp->next;
@@ -4579,35 +5300,33 @@ boolean setinitial, setfromfile;
         }
     } else if (!strcmp("autopickup_exception", optname)) {
         int opt_idx, pass, totalapes = 0, numapes[2] = { 0, 0 };
-        char apebuf[1 + BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */
+        char apebuf[1 + BUFSZ] = DUMMY; /* so &apebuf[1] is BUFSZ long for getlin() */
         struct autopickup_exception *ape;
 
     ape_again:
         totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
         opt_idx = handle_add_list_remove("autopickup exception", totalapes);
-        if (opt_idx == 3) {
-            ;                      /* done--fall through to function exit */
+        if (opt_idx == 3) { /* done */
+            return TRUE;
         } else if (opt_idx == 0) { /* add new */
 /*JP
             getlin("What new autopickup exception pattern?", &apebuf[1]);
 */
             getlin("\90V\82µ\82¢\8e©\93®\8fE\82¢\97á\8aO\82Ì\83p\83^\81[\83\93\82ð\93ü\97Í\82µ\82Ä\82­\82¾\82³\82¢\81F", &apebuf[1]);
             mungspaces(&apebuf[1]); /* regularize whitespace */
-            if (apebuf[1] == '\033') {
-                ; /* fall through to function exit */
-            } else {
-                if (apebuf[1]) {
-                    apebuf[0] = '\"';
-                    /* guarantee room for \" prefix and \"\0 suffix;
-                       -2 is good enough for apebuf[] but -3 makes
-                       sure the whole thing fits within normal BUFSZ */
-                    apebuf[sizeof apebuf - 3] = '\0';
-                    Strcat(apebuf, "\"");
-                    add_autopickup_exception(apebuf);
-                }
-                goto ape_again;
+            if (apebuf[1] == '\033')
+                return TRUE;
+            if (apebuf[1]) {
+                apebuf[0] = '\"';
+                /* guarantee room for \" prefix and \"\0 suffix;
+                   -2 is good enough for apebuf[] but -3 makes
+                   sure the whole thing fits within normal BUFSZ */
+                apebuf[sizeof apebuf - 3] = '\0';
+                Strcat(apebuf, "\"");
+                add_autopickup_exception(apebuf);
             }
-        } else { /* list or remove */
+            goto ape_again;
+        } else { /* list (1) or remove (2) */
             int pick_idx, pick_cnt;
             menu_item *pick_list = (menu_item *) 0;
 
@@ -4626,6 +5345,7 @@ boolean setinitial, setfromfile;
                          MENU_UNSELECTED);
                 for (i = 0; i < numapes[pass] && ape; i++) {
                     any.a_void = (opt_idx == 1) ? 0 : ape;
+                    /* length of pattern plus quotes is less than BUFSZ */
                     Sprintf(apebuf, "\"%s\"", ape->pattern);
                     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, apebuf,
                              MENU_UNSELECTED);
@@ -4666,10 +5386,7 @@ boolean setinitial, setfromfile;
         struct symsetentry *sl;
         int res, which_set, setcount = 0, chosen = -2;
 
-        if (rogueflag)
-            which_set = ROGUESET;
-        else
-            which_set = PRIMARY;
+        which_set = rogueflag ? ROGUESET : PRIMARY;
 
         /* clear symset[].name as a flag to read_sym_file() to build list */
         symset_name = symset[which_set].name;
@@ -4733,7 +5450,9 @@ boolean setinitial, setfromfile;
                 }
                 sl = sl->next;
             }
-            end_menu(tmpwin, "Select symbol set:");
+            Sprintf(buf, "Select %ssymbol set:",
+                    rogueflag ? "rogue level " : "");
+            end_menu(tmpwin, buf);
             if (select_menu(tmpwin, PICK_ONE, &symset_pick) > 0) {
                 chosen = symset_pick->item.a_int - 2;
                 free((genericptr_t) symset_pick);
@@ -4823,6 +5542,7 @@ boolean setinitial, setfromfile;
                 assign_graphics(ROGUESET);
         } else if (!rogueflag)
             assign_graphics(PRIMARY);
+        preference_update("symset");
         need_redraw = TRUE;
         return TRUE;
 
@@ -4980,36 +5700,23 @@ char *buf;
         Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj));
     else if (!strcmp(optname, "horsename"))
         Sprintf(buf, "%s", horsename[0] ? horsename : none);
-    else if (!strcmp(optname, "map_mode"))
+    else if (!strcmp(optname, "map_mode")) {
+        i = iflags.wc_map_mode;
         Sprintf(buf, "%s",
-                iflags.wc_map_mode == MAP_MODE_TILES
-                  ? "tiles"
-                  : iflags.wc_map_mode == MAP_MODE_ASCII4x6
-                     ? "ascii4x6"
-                     : iflags.wc_map_mode == MAP_MODE_ASCII6x8
-                        ? "ascii6x8"
-                        : iflags.wc_map_mode == MAP_MODE_ASCII8x8
-                           ? "ascii8x8"
-                           : iflags.wc_map_mode == MAP_MODE_ASCII16x8
-                              ? "ascii16x8"
-                              : iflags.wc_map_mode == MAP_MODE_ASCII7x12
-                                 ? "ascii7x12"
-                                 : iflags.wc_map_mode == MAP_MODE_ASCII8x12
-                                    ? "ascii8x12"
-                                    : iflags.wc_map_mode
-                                      == MAP_MODE_ASCII16x12
-                                       ? "ascii16x12"
-                                       : iflags.wc_map_mode
-                                         == MAP_MODE_ASCII12x16
-                                          ? "ascii12x16"
-                                          : iflags.wc_map_mode
-                                            == MAP_MODE_ASCII10x18
-                                             ? "ascii10x18"
-                                             : iflags.wc_map_mode
-                                               == MAP_MODE_ASCII_FIT_TO_SCREEN
-                                                ? "fit_to_screen"
-                                                : defopt);
-    else if (!strcmp(optname, "menustyle"))
+                (i == MAP_MODE_TILES) ? "tiles"
+                : (i == MAP_MODE_ASCII4x6) ? "ascii4x6"
+                  : (i == MAP_MODE_ASCII6x8) ? "ascii6x8"
+                    : (i == MAP_MODE_ASCII8x8) ? "ascii8x8"
+                      : (i == MAP_MODE_ASCII16x8) ? "ascii16x8"
+                        : (i == MAP_MODE_ASCII7x12) ? "ascii7x12"
+                          : (i == MAP_MODE_ASCII8x12) ? "ascii8x12"
+                            : (i == MAP_MODE_ASCII16x12) ? "ascii16x12"
+                              : (i == MAP_MODE_ASCII12x16) ? "ascii12x16"
+                                : (i == MAP_MODE_ASCII10x18) ? "ascii10x18"
+                                  : (i == MAP_MODE_ASCII_FIT_TO_SCREEN)
+                                    ? "fit_to_screen"
+                                    : defopt);
+    } else if (!strcmp(optname, "menustyle"))
         Sprintf(buf, "%s", menutype[(int) flags.menu_style]);
     else if (!strcmp(optname, "menu_deselect_all"))
         Sprintf(buf, "%s", to_be_done);
@@ -5041,13 +5748,10 @@ char *buf;
         Sprintf(buf, "%u", iflags.msg_history);
 #ifdef TTY_GRAPHICS
     } else if (!strcmp(optname, "msg_window")) {
-        Sprintf(buf, "%s", (iflags.prevmsg_window == 's')
-                               ? "single"
-                               : (iflags.prevmsg_window == 'c')
-                                     ? "combination"
-                                     : (iflags.prevmsg_window == 'f')
-                                           ? "full"
-                                           : "reversed");
+        Sprintf(buf, "%s", (iflags.prevmsg_window == 's') ? "single"
+                           : (iflags.prevmsg_window == 'c') ? "combination"
+                             : (iflags.prevmsg_window == 'f') ? "full"
+                               : "reversed");
 #endif
     } else if (!strcmp(optname, "name")) {
         Sprintf(buf, "%s", plname);
@@ -5090,20 +5794,9 @@ char *buf;
         char tmpbuf[QBUFSZ];
 
         tmpbuf[0] = '\0';
-        if (ParanoidConfirm)
-            Strcat(tmpbuf, " Confirm");
-        if (ParanoidQuit)
-            Strcat(tmpbuf, " quit");
-        if (ParanoidDie)
-            Strcat(tmpbuf, " die");
-        if (ParanoidBones)
-            Strcat(tmpbuf, " bones");
-        if (ParanoidHit)
-            Strcat(tmpbuf, " attack");
-        if (ParanoidPray)
-            Strcat(tmpbuf, " pray");
-        if (ParanoidRemove)
-            Strcat(tmpbuf, " Remove");
+        for (i = 0; paranoia[i].flagmask != 0; ++i)
+            if (flags.paranoia_bits & paranoia[i].flagmask)
+                Sprintf(eos(tmpbuf), " %s", paranoia[i].argname);
         Strcpy(buf, tmpbuf[0] ? &tmpbuf[1] : "none");
     } else if (!strcmp(optname, "pettype")) {
 #if 0 /*JP*/
@@ -5139,6 +5832,18 @@ char *buf;
         Sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m));
     } else if (!strcmp(optname, "runmode")) {
         Sprintf(buf, "%s", runmodes[flags.runmode]);
+    } else if (!strcmp(optname, "whatis_coord")) {
+        Sprintf(buf, "%s",
+                (iflags.getpos_coords == GPCOORDS_MAP) ? "map"
+                : (iflags.getpos_coords == GPCOORDS_COMPASS) ? "compass"
+                : (iflags.getpos_coords == GPCOORDS_COMFULL) ? "full compass"
+                : (iflags.getpos_coords == GPCOORDS_SCREEN) ? "screen"
+                : "none");
+    } else if (!strcmp(optname, "whatis_filter")) {
+        Sprintf(buf, "%s",
+                (iflags.getloc_filter == GFILTER_VIEW) ? "view"
+                : (iflags.getloc_filter == GFILTER_AREA) ? "area"
+                : "none");
     } else if (!strcmp(optname, "scores")) {
         Sprintf(buf, "%d top/%d around%s", flags.end_top, flags.end_around,
                 flags.end_own ? "/own" : "");
@@ -5168,6 +5873,14 @@ char *buf;
     } else if (!strcmp(optname, "soundcard")) {
         Sprintf(buf, "%s", to_be_done);
 #endif
+#ifdef STATUS_HILITES
+    } else if (!strcmp("statushilites", optname)) {
+        if (!iflags.hilite_delta)
+            Strcpy(buf, "0 (off: don't highlight status fields)");
+        else
+            Sprintf(buf, "%ld (on: highlight status for %ld turns)",
+                    iflags.hilite_delta, iflags.hilite_delta);
+#endif
     } else if (!strcmp(optname, "suppress_alert")) {
         if (flags.suppress_alert == 0L)
             Strcpy(buf, none);
@@ -5287,39 +6000,49 @@ int
 add_autopickup_exception(mapping)
 const char *mapping;
 {
+    static const char
+        APE_regex_error[] = "regex error in AUTOPICKUP_EXCEPTION",
+        APE_syntax_error[] = "syntax error in AUTOPICKUP_EXCEPTION";
+
     struct autopickup_exception *ape, **apehead;
-    char text[256], *text2;
+    char text[256], end;
+    int n;
     boolean grab = FALSE;
 
-    if (sscanf(mapping, "\"%255[^\"]\"", text) == 1) {
-        text2 = &text[0];
-        if (*text2 == '<') { /* force autopickup */
-            grab = TRUE;
-            ++text2;
-        } else if (*text2 == '>') { /* default - Do not pickup */
-            grab = FALSE;
-            ++text2;
-        }
-        apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB]
-                         : &iflags.autopickup_exceptions[AP_LEAVE];
-        ape = (struct autopickup_exception *) alloc(
-                                        sizeof (struct autopickup_exception));
-        ape->regex = regex_init();
-        if (!regex_compile(text2, ape->regex)) {
-            raw_print("regex error in AUTOPICKUP_EXCEPTION");
-            regex_free(ape->regex);
-            free((genericptr_t) ape);
-            return 0;
-        }
-        ape->pattern = (char *) alloc(strlen(text2) + 1);
-        strcpy(ape->pattern, text2);
-        ape->grab = grab;
-        ape->next = *apehead;
-        *apehead = ape;
+    /* scan length limit used to be 255, but smaller size allows the
+       quoted value to fit within BUFSZ, simplifying formatting elsewhere;
+       this used to ignore the possibility of trailing junk but now checks
+       for it, accepting whitespace but rejecting anything else unless it
+       starts with '#" for a comment */
+    end = '\0';
+    if ((n = sscanf(mapping, "\"<%253[^\"]\" %c", text, &end)) == 1
+        || (n == 2 && end == '#')) {
+        grab = TRUE;
+    } else if ((n = sscanf(mapping, "\">%253[^\"]\" %c", text, &end)) == 1
+               || (n = sscanf(mapping, "\"%253[^\"]\" %c", text, &end)) == 1
+               || (n == 2 && end == '#')) {
+        grab = FALSE;
     } else {
-        raw_print("syntax error in AUTOPICKUP_EXCEPTION");
+        config_error_add("%s", APE_syntax_error);
+        return 0;
+    }
+
+    ape = (struct autopickup_exception *) alloc(sizeof *ape);
+    ape->regex = regex_init();
+    if (!regex_compile(text, ape->regex)) {
+        config_error_add("%s: %s", APE_regex_error,
+                         regex_error_desc(ape->regex));
+        regex_free(ape->regex);
+        free((genericptr_t) ape);
         return 0;
     }
+    apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB]
+                     : &iflags.autopickup_exceptions[AP_LEAVE];
+
+    ape->pattern = dupstr(text);
+    ape->grab = grab;
+    ape->next = *apehead;
+    *apehead = ape;
     return 1;
 }
 
@@ -5354,8 +6077,9 @@ count_ape_maps(leave, grab)
 int *leave, *grab;
 {
     struct autopickup_exception *ape;
-    int pass, totalapes, numapes[2] = { 0, 0 };
+    int pass, totalapes, numapes[2];
 
+    numapes[0] = numapes[1] = 0;
     for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
         ape = iflags.autopickup_exceptions[pass];
         while (ape) {
@@ -5420,7 +6144,7 @@ free_symsets()
 }
 
 /* Parse the value of a SYMBOLS line from a config file */
-void
+boolean
 parsesymbols(opts)
 register char *opts;
 {
@@ -5430,7 +6154,8 @@ register char *opts;
 
     if ((op = index(opts, ',')) != 0) {
         *op++ = 0;
-        parsesymbols(op);
+        if (!parsesymbols(op))
+            return FALSE;
     }
 
     /* S_sample:string */
@@ -5439,7 +6164,7 @@ register char *opts;
     if (!strval)
         strval = index(opts, '=');
     if (!strval)
-        return;
+        return FALSE;
     *strval++ = '\0';
 
     /* strip leading and trailing white space from symname and strval */
@@ -5448,12 +6173,13 @@ register char *opts;
 
     symp = match_sym(symname);
     if (!symp)
-        return;
+        return FALSE;
 
     if (symp->range && symp->range != SYM_CONTROL) {
         val = sym_val(strval);
         update_l_symset(symp, val);
     }
+    return TRUE;
 }
 
 struct symparse *
@@ -5483,11 +6209,41 @@ char *buf;
 
 int
 sym_val(strval)
-char *strval;
+const char *strval;
 {
     char buf[QBUFSZ];
+
     buf[0] = '\0';
-    escapes(strval, buf);
+    if (!strval[0] || !strval[1]) { /* empty, or single character */
+        /* if single char is space or tab, leave buf[0]=='\0' */
+        if (!isspace((uchar) strval[0]))
+            buf[0] = strval[0];
+    } else if (strval[0] == '\'') { /* single quote */
+        /* simple matching single quote; we know strval[1] isn't '\0' */
+        if (strval[2] == '\'' && !strval[3]) {
+            /* accepts '\' as backslash and ''' as single quote */
+            buf[0] = strval[1];
+
+        /* if backslash, handle single or double quote or second backslash */
+        } else if (strval[1] == '\\' && strval[2] && strval[3] == '\''
+            && index("'\"\\", strval[2]) && !strval[4]) {
+            buf[0] = strval[2];
+
+        /* not simple quote or basic backslash;
+           strip closing quote and let escapes() deal with it */
+        } else {
+            char *p, tmp[QBUFSZ];
+
+            (void) strncpy(tmp, strval + 1, sizeof tmp - 1);
+            tmp[sizeof tmp - 1] = '\0';
+            if ((p = rindex(tmp, '\'')) != 0) {
+                *p = '\0';
+                escapes(tmp, buf);
+            } /* else buf[0] stays '\0' */
+        }
+    } else /* not lone char nor single quote */
+        escapes(strval, buf);
+
     return (int) *buf;
 }
 
@@ -5547,9 +6303,9 @@ option_help()
 
     datawin = create_nhwindow(NHW_TEXT);
 /*JP
-    Sprintf(buf, "Set options as OPTIONS=<options> in %s", lastconfigfile);
+    Sprintf(buf, "Set options as OPTIONS=<options> in %s", configfile);
 */
-    Sprintf(buf, "\83I\83v\83V\83\87\83\93\82Í%s\82Ì\92\86\82ÅOPTIONS=<options>\82Æ\90Ý\92è\82µ\82Ü\82·", lastconfigfile);
+    Sprintf(buf, "\83I\83v\83V\83\87\83\93\82Í%s\82Ì\92\86\82ÅOPTIONS=<options>\82Æ\90Ý\92è\82µ\82Ü\82·", configfile);
     opt_intro[CONFIG_SLOT] = (const char *) buf;
     for (i = 0; opt_intro[i]; i++)
         putstr(datawin, 0, opt_intro[i]);
@@ -5660,7 +6416,6 @@ struct fruit *replace_fruit;
         /* disallow naming after other foods (since it'd be impossible
          * to tell the difference)
          */
-
         for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS; i++) {
             if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) {
                 found = TRUE;
@@ -5670,15 +6425,15 @@ struct fruit *replace_fruit;
         {
             char *c;
 
-            c = pl_fruit;
-
             for (c = pl_fruit; *c >= '0' && *c <= '9'; c++)
-                ;
+                continue;
             if (isspace((uchar) *c) || *c == 0)
                 numeric = TRUE;
         }
-        if (found || numeric || !strncmp(str, "cursed ", 7)
-            || !strncmp(str, "uncursed ", 9) || !strncmp(str, "blessed ", 8)
+        if (found || numeric
+            || !strncmp(str, "cursed ", 7)
+            || !strncmp(str, "uncursed ", 9)
+            || !strncmp(str, "blessed ", 8)
             || !strncmp(str, "partly eaten ", 13)
             || (!strncmp(str, "tin of ", 7)
                 && (!strcmp(str + 7, "spinach")
@@ -5701,41 +6456,39 @@ struct fruit *replace_fruit;
          */
         flags.made_fruit = FALSE;
         if (replace_fruit) {
-            for (f = ffruit; f; f = f->nextf) {
-                if (f == replace_fruit) {
-                    copynchars(f->fname, str, PL_FSIZ - 1);
-                    goto nonew;
-                }
-            }
+            /* replace_fruit is already part of the fruit chain;
+               update it in place rather than looking it up again */
+            f = replace_fruit;
+            copynchars(f->fname, str, PL_FSIZ - 1);
+            goto nonew;
         }
     } else {
         /* not user_supplied, so assumed to be from bones */
         copynchars(altname, str, PL_FSIZ - 1);
         sanitize_name(altname);
         flags.made_fruit = TRUE; /* for safety.  Any fruit name added from a
-                                    bones level should exist anyway. */
-    }
-    for (f = ffruit; f; f = f->nextf) {
-        if (f->fid > highest_fruit_id)
-            highest_fruit_id = f->fid;
-        if (!strncmp(str, f->fname, PL_FSIZ - 1)
-            || (*altname && !strcmp(altname, f->fname)))
-            goto nonew;
+                                  * bones level should exist anyway. */
     }
-    /* if adding another fruit would overflow spe, use a random
-       fruit instead... we've got a lot to choose from.
+    f = fruit_from_name(*altname ? altname : str, FALSE, &highest_fruit_id);
+    if (f)
+        goto nonew;
+
+    /* Maximum number of named fruits is 127, even if obj->spe can
+       handle bigger values.  If adding another fruit would overflow,
+       use a random fruit instead... we've got a lot to choose from.
        current_fruit remains as is. */
     if (highest_fruit_id >= 127)
         return rnd(127);
 
     f = newfruit();
+    (void) memset((genericptr_t) f, 0, sizeof (struct fruit));
     copynchars(f->fname, *altname ? altname : str, PL_FSIZ - 1);
     f->fid = ++highest_fruit_id;
     /* we used to go out of our way to add it at the end of the list,
        but the order is arbitrary so use simpler insertion at start */
     f->nextf = ffruit;
     ffruit = f;
-nonew:
+ nonew:
     if (user_specified)
         context.current_fruit = f->fid;
     return f->fid;
@@ -5841,50 +6594,56 @@ char *class_select;
     return ret;
 }
 
-struct wc_Opt wc_options[] = { { "ascii_map", WC_ASCII_MAP },
-                               { "color", WC_COLOR },
-                               { "eight_bit_tty", WC_EIGHT_BIT_IN },
-                               { "hilite_pet", WC_HILITE_PET },
-                               { "popup_dialog", WC_POPUP_DIALOG },
-                               { "player_selection", WC_PLAYER_SELECTION },
-                               { "preload_tiles", WC_PRELOAD_TILES },
-                               { "tiled_map", WC_TILED_MAP },
-                               { "tile_file", WC_TILE_FILE },
-                               { "tile_width", WC_TILE_WIDTH },
-                               { "tile_height", WC_TILE_HEIGHT },
-                               { "use_inverse", WC_INVERSE },
-                               { "align_message", WC_ALIGN_MESSAGE },
-                               { "align_status", WC_ALIGN_STATUS },
-                               { "font_map", WC_FONT_MAP },
-                               { "font_menu", WC_FONT_MENU },
-                               { "font_message", WC_FONT_MESSAGE },
+static struct wc_Opt wc_options[] = {
+    { "ascii_map", WC_ASCII_MAP },
+    { "color", WC_COLOR },
+    { "eight_bit_tty", WC_EIGHT_BIT_IN },
+    { "hilite_pet", WC_HILITE_PET },
+    { "popup_dialog", WC_POPUP_DIALOG },
+    { "player_selection", WC_PLAYER_SELECTION },
+    { "preload_tiles", WC_PRELOAD_TILES },
+    { "tiled_map", WC_TILED_MAP },
+    { "tile_file", WC_TILE_FILE },
+    { "tile_width", WC_TILE_WIDTH },
+    { "tile_height", WC_TILE_HEIGHT },
+    { "use_inverse", WC_INVERSE },
+    { "align_message", WC_ALIGN_MESSAGE },
+    { "align_status", WC_ALIGN_STATUS },
+    { "font_map", WC_FONT_MAP },
+    { "font_menu", WC_FONT_MENU },
+    { "font_message", WC_FONT_MESSAGE },
 #if 0
-                               {"perm_invent", WC_PERM_INVENT},
-#endif
-                               { "font_size_map", WC_FONTSIZ_MAP },
-                               { "font_size_menu", WC_FONTSIZ_MENU },
-                               { "font_size_message", WC_FONTSIZ_MESSAGE },
-                               { "font_size_status", WC_FONTSIZ_STATUS },
-                               { "font_size_text", WC_FONTSIZ_TEXT },
-                               { "font_status", WC_FONT_STATUS },
-                               { "font_text", WC_FONT_TEXT },
-                               { "map_mode", WC_MAP_MODE },
-                               { "scroll_amount", WC_SCROLL_AMOUNT },
-                               { "scroll_margin", WC_SCROLL_MARGIN },
-                               { "splash_screen", WC_SPLASH_SCREEN },
-                               { "vary_msgcount", WC_VARY_MSGCOUNT },
-                               { "windowcolors", WC_WINDOWCOLORS },
-                               { "mouse_support", WC_MOUSE_SUPPORT },
-                               { (char *) 0, 0L } };
-
-struct wc_Opt wc2_options[] = { { "fullscreen", WC2_FULLSCREEN },
-                                { "softkeyboard", WC2_SOFTKEYBOARD },
-                                { "wraptext", WC2_WRAPTEXT },
-                                { "use_darkgray", WC2_DARKGRAY },
-#ifdef STATUS_VIA_WINDOWPORT
-                                { "hilite_status", WC2_HILITE_STATUS },
-#endif
-                                { (char *) 0, 0L } };
+    {"perm_invent", WC_PERM_INVENT},
+#endif
+    { "font_size_map", WC_FONTSIZ_MAP },
+    { "font_size_menu", WC_FONTSIZ_MENU },
+    { "font_size_message", WC_FONTSIZ_MESSAGE },
+    { "font_size_status", WC_FONTSIZ_STATUS },
+    { "font_size_text", WC_FONTSIZ_TEXT },
+    { "font_status", WC_FONT_STATUS },
+    { "font_text", WC_FONT_TEXT },
+    { "map_mode", WC_MAP_MODE },
+    { "scroll_amount", WC_SCROLL_AMOUNT },
+    { "scroll_margin", WC_SCROLL_MARGIN },
+    { "splash_screen", WC_SPLASH_SCREEN },
+    { "vary_msgcount", WC_VARY_MSGCOUNT },
+    { "windowcolors", WC_WINDOWCOLORS },
+    { "mouse_support", WC_MOUSE_SUPPORT },
+    { (char *) 0, 0L }
+};
+static struct wc_Opt wc2_options[] = {
+    { "fullscreen", WC2_FULLSCREEN },
+    { "softkeyboard", WC2_SOFTKEYBOARD },
+    { "wraptext", WC2_WRAPTEXT },
+    { "use_darkgray", WC2_DARKGRAY },
+    { "hitpointbar", WC2_HITPOINTBAR },
+    { "hilite_status", WC2_HILITE_STATUS },
+    /* name shown in 'O' menu is different */
+    { "status hilite rules", WC2_HILITE_STATUS },
+    /* statushilites doesn't have its own bit */
+    { "statushilites", WC2_HILITE_STATUS },
+    { (char *) 0, 0L }
+};
 
 /*
  * If a port wants to change or ensure that the SET_IN_SYS,
@@ -5965,13 +6724,11 @@ STATIC_OVL boolean
 wc_supported(optnam)
 const char *optnam;
 {
-    int k = 0;
+    int k;
 
-    while (wc_options[k].wc_name) {
-        if (!strcmp(wc_options[k].wc_name, optnam)
-            && (windowprocs.wincap & wc_options[k].wc_bit))
-            return TRUE;
-        k++;
+    for (k = 0; wc_options[k].wc_name; ++k) {
+        if (!strcmp(wc_options[k].wc_name, optnam))
+            return (windowprocs.wincap & wc_options[k].wc_bit) ? TRUE : FALSE;
     }
     return FALSE;
 }
@@ -6025,13 +6782,12 @@ STATIC_OVL boolean
 wc2_supported(optnam)
 const char *optnam;
 {
-    int k = 0;
+    int k;
 
-    while (wc2_options[k].wc_name) {
-        if (!strcmp(wc2_options[k].wc_name, optnam)
-            && (windowprocs.wincap2 & wc2_options[k].wc_bit))
-            return TRUE;
-        k++;
+    for (k = 0; wc2_options[k].wc_name; ++k) {
+        if (!strcmp(wc2_options[k].wc_name, optnam))
+            return (windowprocs.wincap2 & wc2_options[k].wc_bit) ? TRUE
+                                                                 : FALSE;
     }
     return FALSE;
 }
index 0a208c8..861f471 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 pager.c $NHDT-Date: 1448482543 2015/11/25 20:15:43 $  $NHDT-Branch: master $:$NHDT-Revision: 1.86 $ */
+/* NetHack 3.6 pager.c $NHDT-Date: 1523142395 2018/04/07 23:06:35 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.123 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -22,8 +23,18 @@ STATIC_DCL struct permonst *FDECL(lookat, (int, int, char *, char *));
 STATIC_DCL void FDECL(checkfile, (char *, struct permonst *,
                                   BOOLEAN_P, BOOLEAN_P));
 STATIC_DCL void FDECL(look_all, (BOOLEAN_P,BOOLEAN_P));
-STATIC_DCL boolean FDECL(help_menu, (int *));
+STATIC_DCL void NDECL(whatdoes_help);
 STATIC_DCL void NDECL(docontact);
+STATIC_DCL void NDECL(dispfile_help);
+STATIC_DCL void NDECL(dispfile_shelp);
+STATIC_DCL void NDECL(dispfile_optionfile);
+STATIC_DCL void NDECL(dispfile_license);
+STATIC_DCL void NDECL(dispfile_debughelp);
+STATIC_DCL void NDECL(hmenu_doextversion);
+STATIC_DCL void NDECL(hmenu_dohistory);
+STATIC_DCL void NDECL(hmenu_dowhatis);
+STATIC_DCL void NDECL(hmenu_dowhatdoes);
+STATIC_DCL void NDECL(hmenu_doextlist);
 #ifdef PORT_HELP
 extern void NDECL(port_help);
 #endif
@@ -57,6 +68,8 @@ const char *new_str;
         return 0;
 
     space_left = BUFSZ - strlen(buf) - 1;
+    if (space_left < 1)
+        return 0;
 #if 0 /*JP*/
     (void) strncat(buf, " or ", space_left);
     (void) strncat(buf, new_str, space_left - 4);
@@ -97,9 +110,69 @@ char *outbuf;
         Sprintf(eos(outbuf), ", mounted on %s", y_monnam(u.usteed));
 */
         Sprintf(eos(outbuf), "\81C%s\82É\8fæ\82Á\82Ä\82¢\82é", y_monnam(u.usteed));
+    if (u.uundetected || (Upolyd && youmonst.m_ap_type))
+        mhidden_description(&youmonst, FALSE, eos(outbuf));
     return outbuf;
 }
 
+/* describe a hidden monster; used for look_at during extended monster
+   detection and for probing; also when looking at self */
+void
+mhidden_description(mon, altmon, outbuf)
+struct monst *mon;
+boolean altmon; /* for probing: if mimicking a monster, say so */
+char *outbuf;
+{
+    struct obj *otmp;
+    boolean fakeobj, isyou = (mon == &youmonst);
+    int x = isyou ? u.ux : mon->mx, y = isyou ? u.uy : mon->my,
+        glyph = (level.flags.hero_memory && !isyou) ? levl[x][y].glyph
+                                                    : glyph_at(x, y);
+
+    *outbuf = '\0';
+    if (mon->m_ap_type == M_AP_FURNITURE
+        || mon->m_ap_type == M_AP_OBJECT) {
+        Strcpy(outbuf, ", mimicking ");
+        if (mon->m_ap_type == M_AP_FURNITURE) {
+            Strcat(outbuf, an(defsyms[mon->mappearance].explanation));
+        } else if (mon->m_ap_type == M_AP_OBJECT
+                   /* remembered glyph, not glyph_at() which is 'mon' */
+                   && glyph_is_object(glyph)) {
+        objfrommap:
+            otmp = (struct obj *) 0;
+            fakeobj = object_from_map(glyph, x, y, &otmp);
+            Strcat(outbuf, (otmp && otmp->otyp != STRANGE_OBJECT)
+                              ? ansimpleoname(otmp)
+                              : an(obj_descr[STRANGE_OBJECT].oc_name));
+            if (fakeobj)
+                dealloc_obj(otmp);
+        } else {
+            Strcat(outbuf, something);
+        }
+    } else if (mon->m_ap_type == M_AP_MONSTER) {
+        if (altmon)
+            Sprintf(outbuf, ", masquerading as %s",
+                    an(mons[mon->mappearance].mname));
+    } else if (isyou ? u.uundetected : mon->mundetected) {
+        Strcpy(outbuf, ", hiding");
+        if (hides_under(mon->data)) {
+            Strcat(outbuf, " under ");
+            /* remembered glyph, not glyph_at() which is 'mon' */
+            if (glyph_is_object(glyph))
+                goto objfrommap;
+            Strcat(outbuf, something);
+        } else if (is_hider(mon->data)) {
+            Sprintf(eos(outbuf), " on the %s",
+                    (is_flyer(mon->data) || mon->data->mlet == S_PIERCER)
+                       ? "ceiling"
+                       : surface(x, y)); /* trapper */
+        } else {
+            if (mon->data->mlet == S_EEL && is_pool(x, y))
+                Strcat(outbuf, " in murky water");
+        }
+    }
+}
+
 /* extracted from lookat(); also used by namefloorobj() */
 boolean
 object_from_map(glyph, x, y, obj_p)
@@ -108,10 +181,16 @@ struct obj **obj_p;
 {
     boolean fakeobj = FALSE;
     struct monst *mtmp;
-    struct obj *otmp = vobj_at(x, y);
+    struct obj *otmp;
     int glyphotyp = glyph_to_obj(glyph);
 
     *obj_p = (struct obj *) 0;
+    /* TODO: check inside containers in case glyph came from detection */
+    if ((otmp = sobj_at(glyphotyp, x, y)) == 0)
+        for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj)
+            if (otmp->ox == x && otmp->oy == y && otmp->otyp == glyphotyp)
+                break;
+
     /* there might be a mimic here posing as an object */
     mtmp = m_at(x, y);
     if (mtmp && is_obj_mappear(mtmp, (unsigned) glyphotyp))
@@ -132,9 +211,18 @@ struct obj **obj_p;
         if (mtmp && has_mcorpsenm(mtmp)) /* mimic as corpse/statue */
             otmp->corpsenm = MCORPSENM(mtmp);
     }
-    /* if located at adjacent spot, mark it as having been seen up close */
-    if (otmp && distu(x, y) <= 2 && !Blind && !Hallucination)
-        otmp->dknown = 1;
+    /* if located at adjacent spot, mark it as having been seen up close
+       (corpse type will be known even if dknown is 0, so we don't need a
+       touch check for cockatrice corpse--we're looking without touching) */
+    if (otmp && distu(x, y) <= 2 && !Blind && !Hallucination
+        /* redundant: we only look for an object which matches current
+           glyph among floor and buried objects; when !Blind, any buried
+           object's glyph will have been replaced by whatever is present
+           on the surface as soon as we moved next to its spot */
+        && (fakeobj || otmp->where == OBJ_FLOOR) /* not buried */
+        /* terrain mode views what's already known, doesn't learn new stuff */
+        && !iflags.terrainmode) /* so don't set dknown when in terrain mode */
+        otmp->dknown = 1; /* if a pile, clearly see the top item only */
 
     *obj_p = otmp;
     return fakeobj; /* when True, caller needs to dealloc *obj_p */
@@ -150,14 +238,16 @@ int x, y, glyph;
 
     if (otmp) {
         Strcpy(buf, (otmp->otyp != STRANGE_OBJECT)
-                     ? distant_name(otmp, xname)
+                     ? distant_name(otmp, doname_vague_quan)
                      : obj_descr[STRANGE_OBJECT].oc_name);
         if (fakeobj)
             dealloc_obj(otmp), otmp = 0;
     } else
         Strcpy(buf, something); /* sanity precaution */
 
-    if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR)
+    if (otmp && otmp->where == OBJ_BURIED)
+        Strcat(buf, " (buried)");
+    else if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR)
 /*JP
         Strcat(buf, " embedded in stone");
 */
@@ -196,11 +286,9 @@ int x, y;
     char *name, monnambuf[BUFSZ];
     boolean accurate = !Hallucination;
 
-    if (mtmp->data == &mons[PM_COYOTE] && accurate)
-        name = coyotename(mtmp, monnambuf);
-    else
-        name = distant_monnam(mtmp, ARTICLE_NONE, monnambuf);
-
+    name = (mtmp->data == &mons[PM_COYOTE] && accurate)
+              ? coyotename(mtmp, monnambuf)
+              : distant_monnam(mtmp, ARTICLE_NONE, monnambuf);
 #if 0 /*JP*/
     Sprintf(buf, "%s%s%s",
             (mtmp->mx != x || mtmp->my != y)
@@ -214,19 +302,27 @@ int x, y;
             name);
 #else
     Sprintf(buf, "%s%s%s",
-            (mtmp->mtame && accurate) ? "\8eè\82È\82¸\82¯\82ç\82ê\82½" :
-            (mtmp->mpeaceful && accurate) ? "\97F\8dD\93I\82È" : "",
+            (mtmp->mtame && accurate)
+                ? "\8eè\82È\82¸\82¯\82ç\82ê\82½"
+                : (mtmp->mpeaceful && accurate)
+                    ? "\97F\8dD\93I\82È"
+                    : "",
             name,
-            (mtmp->mx != x || mtmp->my != y) ?
-            ((mtmp->isshk && accurate)
-             ? "\82Ì\90K\94ö" : "\82Ì\90K\94ö") : "");
+            (mtmp->mx != x || mtmp->my != y)
+                ? ((mtmp->isshk && accurate) ? "\82Ì\90K\94ö" : "\82Ì\90K\94ö")
+                : "");
 #endif
-    if (u.ustuck == mtmp)
-        Strcat(buf, (Upolyd && sticks(youmonst.data))
+    if (u.ustuck == mtmp) {
+        if (u.uswallow || iflags.save_uswallow) /* monster detection */
+            Strcat(buf, is_animal(mtmp->data)
+                          ? ", swallowing you" : ", engulfing you");
+        else
+            Strcat(buf, (Upolyd && sticks(youmonst.data))
 /*JP
                      ? ", being held" : ", holding you");
 */
                      ? "\81C\82 \82È\82½\82ª\92Í\82Ü\82¦\82Ä\82¢\82é" : "\81C\82 \82È\82½\82ð\92Í\82Ü\82¦\82Ä\82¢\82é");
+    }
     if (mtmp->mleashed)
 /*JP
         Strcat(buf, ", leashed to you");
@@ -246,6 +342,11 @@ int x, y;
                     an(defsyms[trap_to_defsym(tt)].explanation));
     }
 
+    /* we know the hero sees a monster at this location, but if it's shown
+       due to persistant monster detection he might remember something else */
+    if (mtmp->mundetected || mtmp->m_ap_type)
+        mhidden_description(mtmp, FALSE, eos(buf));
+
     if (monbuf) {
         unsigned how_seen = howmonseen(mtmp);
 
@@ -308,17 +409,26 @@ int x, y;
                     Strcat(monbuf, ", ");
             }
             if (how_seen & MONSEEN_WARNMON) {
-                if (Hallucination)
+                if (Hallucination) {
 /*JP
                     Strcat(monbuf, "paranoid delusion");
 */
                     Strcat(monbuf, "\95Î\8e·\93I\96Ï\91z");
-                else
+                } else {
+                    unsigned long mW = (context.warntype.obj
+                                        | context.warntype.polyd),
+                                  m2 = mtmp->data->mflags2;
+                    const char *whom = ((mW & M2_HUMAN & m2) ? "human"
+                                        : (mW & M2_ELF & m2) ? "elf"
+                                          : (mW & M2_ORC & m2) ? "orc"
+                                            : (mW & M2_DEMON & m2) ? "demon"
+                                              : mtmp->data->mname);
+
 /*JP
-                    Sprintf(eos(monbuf), "warned of %s",
+                    Sprintf(eos(monbuf), "warned of %s", makeplural(whom));
 */
-                    Sprintf(eos(monbuf), "%s\82ð\8cx\8d\90\82µ\82Ä\82¢\82é",
-                            makeplural(mtmp->data->mname));
+                    Sprintf(eos(monbuf), "%s\82ð\8cx\8d\90\82µ\82Ä\82¢\82é", whom);
+                }
                 how_seen &= ~MONSEEN_WARNMON;
                 if (how_seen)
                     Strcat(monbuf, ", ");
@@ -347,7 +457,9 @@ char *buf, *monbuf;
 
     buf[0] = monbuf[0] = '\0';
     glyph = glyph_at(x, y);
-    if (u.ux == x && u.uy == y && canspotself()) {
+    if (u.ux == x && u.uy == y && canspotself()
+        && !(iflags.save_uswallow && glyph == mon_to_glyph(u.ustuck))
+        && (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0)) {
         /* fill in buf[] */
         (void) self_lookat(buf);
 
@@ -361,7 +473,8 @@ char *buf, *monbuf;
            (even if you could also see yourself via other means).
            Sensing self while blind or swallowed is treated as if it
            were by normal vision (cf canseeself()). */
-        if ((Invisible || u.uundetected) && !Blind && !u.uswallow) {
+        if ((Invisible || u.uundetected) && !Blind
+            && !(u.uswallow || iflags.save_uswallow)) {
             unsigned how = 0;
 
             if (Infravision)
@@ -373,34 +486,32 @@ char *buf, *monbuf;
 
             if (how)
 #if 0 /*JP*/
-                Sprintf(
-                    eos(buf), " [seen: %s%s%s%s%s]",
-                    (how & 1) ? "infravision" : "",
-                    /* add comma if telep and infrav */
-                    ((how & 3) > 2) ? ", " : "", (how & 2) ? "telepathy" : "",
-                    /* add comma if detect and (infrav or telep or both) */
-                    ((how & 7) > 4) ? ", " : "",
-                    (how & 4) ? "monster detection" : "");
+                Sprintf(eos(buf), " [seen: %s%s%s%s%s]",
+                        (how & 1) ? "infravision" : "",
+                        /* add comma if telep and infrav */
+                        ((how & 3) > 2) ? ", " : "",
+                        (how & 2) ? "telepathy" : "",
+                        /* add comma if detect and (infrav or telep or both) */
+                        ((how & 7) > 4) ? ", " : "",
+                        (how & 4) ? "monster detection" : "");
 #else
-                Sprintf(
-                    eos(buf), " [\8a´\92m: %s%s%s%s%s]",
-                    (how & 1) ? "\90Ô\8aO\90ü" : "",
-                    /* add comma if telep and infrav */
-                    ((how & 3) > 2) ? ", " : "", (how & 2) ? "\83e\83\8c\83p\83V\81[" : "",
-                    /* add comma if detect and (infrav or telep or both) */
-                    ((how & 7) > 4) ? ", " : "",
-                    (how & 4) ? "\89ö\95¨\8a´\92m" : "");
+                Sprintf(eos(buf), " [\8a´\92m: %s%s%s%s%s]",
+                        (how & 1) ? "\90Ô\8aO\90ü" : "",
+                        /* add comma if telep and infrav */
+                        ((how & 3) > 2) ? ", " : "",
+                        (how & 2) ? "\83e\83\8c\83p\83V\81[" : "",
+                        /* add comma if detect and (infrav or telep or both) */
+                        ((how & 7) > 4) ? ", " : "",
+                        (how & 4) ? "\89ö\95¨\8a´\92m" : "");
 #endif
         }
     } else if (u.uswallow) {
-        /* all locations when swallowed other than the hero are the monster */
-#if 0 /*JP*/
-        Sprintf(buf, "interior of %s",
-                Blind ? "a monster" : a_monnam(u.ustuck));
-#else
-        Sprintf(buf, "%s\82Ì\93à\95\94",
-                Blind ? "\89ö\95¨" : a_monnam(u.ustuck));
-#endif
+        /* when swallowed, we're only called for spots adjacent to hero,
+           and blindness doesn't prevent hero from feeling what holds him */
+/*JP
+        Sprintf(buf, "interior of %s", a_monnam(u.ustuck));
+*/
+        Sprintf(buf, "%s\82Ì\93à\95\94", a_monnam(u.ustuck));
         pm = u.ustuck->data;
     } else if (glyph_is_monster(glyph)) {
         bhitpos.x = x;
@@ -408,13 +519,30 @@ char *buf, *monbuf;
         if ((mtmp = m_at(x, y)) != 0) {
             look_at_monster(buf, monbuf, mtmp, x, y);
             pm = mtmp->data;
+        } else if (Hallucination) {
+            /* 'monster' must actually be a statue */
+            Strcpy(buf, rndmonnam((char *) 0));
         }
     } else if (glyph_is_object(glyph)) {
         look_at_object(buf, x, y, glyph); /* fill in buf[] */
     } else if (glyph_is_trap(glyph)) {
         int tnum = what_trap(glyph_to_trap(glyph));
 
-        Strcpy(buf, defsyms[trap_to_defsym(tnum)].explanation);
+        /* Trap detection displays a bear trap at locations having
+         * a trapped door or trapped container or both.
+         * TODO: we should create actual trap types for doors and
+         * chests so that they can have their own glyphs and tiles.
+         */
+        if (trapped_chest_at(tnum, x, y))
+            Strcpy(buf, "trapped chest"); /* might actually be a large box */
+        else if (trapped_door_at(tnum, x, y))
+            Strcpy(buf, "trapped door"); /* not "trap door"... */
+        else
+            Strcpy(buf, defsyms[trap_to_defsym(tnum)].explanation);
+    } else if (glyph_is_warning(glyph)) {
+        int warnindx = glyph_to_warning(glyph);
+
+        Strcpy(buf, def_warnsyms[warnindx].explanation);
     } else if (!glyph_is_cmap(glyph)) {
 /*JP
         Strcpy(buf, "unexplored area");
@@ -475,6 +603,11 @@ char *buf, *monbuf;
 */
                 Strcpy(buf, "\96¢\92T\8dõ");
                 break;
+            } else if (Underwater && !Is_waterlevel(&u.uz)) {
+                /* "unknown" == previously mapped but not visible when
+                   submerged; better terminology appreciated... */
+                Strcpy(buf, (distu(x, y) <= 2) ? "land" : "unknown");
+                break;
             } else if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR) {
 /*JP
                 Strcpy(buf, "stone");
@@ -482,7 +615,7 @@ char *buf, *monbuf;
                 Strcpy(buf, "\8aâ\94Õ");
                 break;
             }
-            /*else FALLTHRU*/
+            /*FALLTHRU*/
         default:
             Strcpy(buf, defsyms[glyph_to_cmap(glyph)].explanation);
             break;
@@ -508,11 +641,9 @@ struct permonst *pm;
 boolean user_typed_name, without_asking;
 {
     dlb *fp;
-    char buf[BUFSZ], newstr[BUFSZ];
+    char buf[BUFSZ], newstr[BUFSZ], givenname[BUFSZ];
     char *ep, *dbase_str;
     unsigned long txt_offset = 0L;
-    int chk_skip;
-    boolean found_in_file = FALSE, skipping_entry = FALSE;
     winid datawin = WIN_ERR;
 
     fp = dlb_fopen(DATAFILE, "r");
@@ -524,12 +655,10 @@ boolean user_typed_name, without_asking;
 #endif
         return;
     }
-
-    /*
-     * If someone passed us garbage, prevent fault.
-     */
-    if (!inp || (inp && strlen(inp) > (BUFSZ - 1))) {
-        pline("bad do_look buffer passed!");
+    /* If someone passed us garbage, prevent fault. */
+    if (!inp || strlen(inp) > (BUFSZ - 1)) {
+        impossible("bad do_look buffer passed (%s)!",
+                   !inp ? "null" : "too long");
         return;
     }
 
@@ -543,6 +672,18 @@ boolean user_typed_name, without_asking;
         dbase_str = strcpy(newstr, inp);
     (void) lcase(dbase_str);
 
+    /*
+     * TODO:
+     * The switch from xname() to doname_vague_quan() in look_at_obj()
+     * had the unintendded side-effect of making names picked from
+     * pointing at map objects become harder to simplify for lookup.
+     * We should split the prefix and suffix handling used by wish
+     * parsing and also wizmode monster generation out into separate
+     * routines and use those routines here.  This currently lacks
+     * erosion handling and probably lots of other bits and pieces
+     * that wishing already understands and most of this duplicates
+     * stuff already done for wish handling or monster generation.
+     */
     if (!strncmp(dbase_str, "interior of ", 12))
         dbase_str += 12;
     if (!strncmp(dbase_str, "a ", 2))
@@ -551,6 +692,15 @@ boolean user_typed_name, without_asking;
         dbase_str += 3;
     else if (!strncmp(dbase_str, "the ", 4))
         dbase_str += 4;
+    else if (!strncmp(dbase_str, "some ", 5))
+        dbase_str += 5;
+    else if (digit(*dbase_str)) {
+        /* remove count prefix ("2 ya") which can come from looking at map */
+        while (digit(*dbase_str))
+            ++dbase_str;
+        if (*dbase_str == ' ')
+            ++dbase_str;
+    }
     if (!strncmp(dbase_str, "tame ", 5))
         dbase_str += 5;
     else if (!strncmp(dbase_str, "peaceful ", 9))
@@ -559,126 +709,199 @@ boolean user_typed_name, without_asking;
         dbase_str += 10;
     if (!strncmp(dbase_str, "saddled ", 8))
         dbase_str += 8;
+    if (!strncmp(dbase_str, "blessed ", 8))
+        dbase_str += 8;
+    else if (!strncmp(dbase_str, "uncursed ", 9))
+        dbase_str += 9;
+    else if (!strncmp(dbase_str, "cursed ", 7))
+        dbase_str += 7;
+    if (!strncmp(dbase_str, "empty ", 6))
+        dbase_str += 6;
+    if (!strncmp(dbase_str, "partly used ", 12))
+        dbase_str += 12;
+    else if (!strncmp(dbase_str, "partly eaten ", 13))
+        dbase_str += 13;
     if (!strncmp(dbase_str, "statue of ", 10))
         dbase_str[6] = '\0';
     else if (!strncmp(dbase_str, "figurine of ", 12))
         dbase_str[8] = '\0';
+    /* remove enchantment ("+0 aklys"); [for 3.6.0 and earlier, this wasn't
+       needed because looking at items on the map used xname() rather than
+       doname() hence known enchantment was implicitly suppressed] */
+    if (*dbase_str && index("+-", dbase_str[0]) && digit(dbase_str[1])) {
+        ++dbase_str; /* skip sign */
+        while (digit(*dbase_str))
+            ++dbase_str;
+        if (*dbase_str == ' ')
+            ++dbase_str;
+    }
+    /* "towel", "wet towel", and "moist towel" share one data.base entry;
+       for "wet towel", we keep prefix so that the prompt will ask about
+       "wet towel"; for "moist towel", we also want to ask about "wet towel".
+       (note: strncpy() only terminates output string if the specified
+       count is bigger than the length of the substring being copied) */
+    if (!strncmp(dbase_str, "moist towel", 11))
+        (void) strncpy(dbase_str += 2, "wet", 3); /* skip "mo" replace "ist" */
 
     /* Make sure the name is non-empty. */
     if (*dbase_str) {
-        /* adjust the input to remove "named " and convert to lower case */
-        char *alt = 0; /* alternate description */
-
-        if ((ep = strstri(dbase_str, " named ")) != 0)
+        long pass1offset = -1L;
+        int chk_skip, pass = 1;
+        boolean yes_to_moreinfo, found_in_file, pass1found_in_file,
+                skipping_entry;
+        char *ap, *alt = 0; /* alternate description */
+
+        /* adjust the input to remove "named " and "called " */
+        if ((ep = strstri(dbase_str, " named ")) != 0) {
             alt = ep + 7;
-        else
-            ep = strstri(dbase_str, " called ");
-        if (!ep)
+            if ((ap = strstri(dbase_str, " called ")) != 0 && ap < ep)
+                ep = ap; /* "named" is alt but truncate at "called" */
+        } else if ((ep = strstri(dbase_str, " called ")) != 0) {
+            copynchars(givenname, ep + 8, BUFSZ - 1);
+            alt = givenname;
+        } else
             ep = strstri(dbase_str, ", ");
         if (ep && ep > dbase_str)
             *ep = '\0';
+        /* remove charges or "(lit)" or wizmode "(N aum)" */
+        if ((ep = strstri(dbase_str, " (")) != 0 && ep > dbase_str)
+            *ep = '\0';
+        if (alt && (ap = strstri(alt, " (")) != 0 && ap > alt)
+            *ap = '\0';
 
         /*
          * If the object is named, then the name is the alternate description;
          * otherwise, the result of makesingular() applied to the name is.
-         * This
-         * isn't strictly optimal, but named objects of interest to the user
-         * will usually be found under their name, rather than under their
-         * object type, so looking for a singular form is pointless.
+         * This isn't strictly optimal, but named objects of interest to the
+         * user will usually be found under their name, rather than under
+         * their object type, so looking for a singular form is pointless.
          */
         if (!alt)
             alt = makesingular(dbase_str);
 
-        /* skip first record; read second */
-        txt_offset = 0L;
-        if (!dlb_fgets(buf, BUFSZ, fp) || !dlb_fgets(buf, BUFSZ, fp)) {
-            impossible("can't read 'data' file");
-            (void) dlb_fclose(fp);
-            return;
-        } else if (sscanf(buf, "%8lx\n", &txt_offset) < 1 || txt_offset == 0L)
-            goto bad_data_file;
-
-        /* look for the appropriate entry */
-        while (dlb_fgets(buf, BUFSZ, fp)) {
-            if (*buf == '.')
-                break; /* we passed last entry without success */
-
-            if (digit(*buf)) {
-                /* a number indicates the end of current entry */
-                skipping_entry = FALSE;
-            } else if (!skipping_entry) {
-                if (!(ep = index(buf, '\n')))
-                    goto bad_data_file;
-                *ep = 0;
-                /* if we match a key that begins with "~", skip this entry */
-                chk_skip = (*buf == '~') ? 1 : 0;
-                if (pmatch(&buf[chk_skip], dbase_str)
-                    || (alt && pmatch(&buf[chk_skip], alt))) {
-                    if (chk_skip) {
-                        skipping_entry = TRUE;
-                        continue;
-                    } else {
-                        found_in_file = TRUE;
-                        break;
+        pass1found_in_file = FALSE;
+        for (pass = !strcmp(alt, dbase_str) ? 0 : 1; pass >= 0; --pass) {
+            found_in_file = skipping_entry = FALSE;
+            txt_offset = 0L;
+            if (dlb_fseek(fp, txt_offset, SEEK_SET) < 0 ) {
+                impossible("can't get to start of 'data' file");
+                goto checkfile_done;
+            }
+            /* skip first record; read second */
+            if (!dlb_fgets(buf, BUFSZ, fp) || !dlb_fgets(buf, BUFSZ, fp)) {
+                impossible("can't read 'data' file");
+                goto checkfile_done;
+            } else if (sscanf(buf, "%8lx\n", &txt_offset) < 1
+                       || txt_offset == 0L)
+                goto bad_data_file;
+
+            /* look for the appropriate entry */
+            while (dlb_fgets(buf, BUFSZ, fp)) {
+                if (*buf == '.')
+                    break; /* we passed last entry without success */
+
+                if (digit(*buf)) {
+                    /* a number indicates the end of current entry */
+                    skipping_entry = FALSE;
+                } else if (!skipping_entry) {
+                    if (!(ep = index(buf, '\n')))
+                        goto bad_data_file;
+                    (void) strip_newline((ep > buf) ? ep - 1 : ep);
+                    /* if we match a key that begins with "~", skip
+                       this entry */
+                    chk_skip = (*buf == '~') ? 1 : 0;
+                    if ((pass == 0 && pmatch(&buf[chk_skip], dbase_str))
+                        || (pass == 1 && alt && pmatch(&buf[chk_skip], alt))) {
+                        if (chk_skip) {
+                            skipping_entry = TRUE;
+                            continue;
+                        } else {
+                            found_in_file = TRUE;
+                            if (pass == 1)
+                                pass1found_in_file = TRUE;
+                            break;
+                        }
                     }
                 }
             }
-        }
-    }
+            if (found_in_file) {
+                long entry_offset, fseekoffset;
+                int entry_count;
+                int i;
+
+                /* skip over other possible matches for the info */
+                do {
+                    if (!dlb_fgets(buf, BUFSZ, fp))
+                        goto bad_data_file;
+                } while (!digit(*buf));
+                if (sscanf(buf, "%ld,%d\n", &entry_offset, &entry_count) < 2)
+                    goto bad_data_file;
+                fseekoffset = (long) txt_offset + entry_offset;
+                if (pass == 1)
+                    pass1offset = fseekoffset;
+                else if (fseekoffset == pass1offset)
+                    goto checkfile_done;
 
-    if (found_in_file) {
-        long entry_offset;
-        int entry_count;
-        int i;
+                yes_to_moreinfo = FALSE;
+                if (!user_typed_name && !without_asking) {
+                    char *entrytext = pass ? alt : dbase_str;
+                    char question[QBUFSZ];
 
-        /* skip over other possible matches for the info */
-        do {
-            if (!dlb_fgets(buf, BUFSZ, fp))
-                goto bad_data_file;
-        } while (!digit(*buf));
-        if (sscanf(buf, "%ld,%d\n", &entry_offset, &entry_count) < 2) {
-        bad_data_file:
-            impossible("'data' file in wrong format or corrupted");
-            /* window will exist if we came here from below via 'goto' */
-            if (datawin != WIN_ERR)
-                destroy_nhwindow(datawin);
-            (void) dlb_fclose(fp);
-            return;
-        }
+#if 0 /*JP*/
+                    Strcpy(question, "More info about \"");
+                    /* +2 => length of "\"?" */
+                    copynchars(eos(question), entrytext,
+                               (int) (sizeof question - 1
+                                      - (strlen(question) + 2)));
+                    Strcat(question, "\"?");
+#else
+                    Strcpy(question, "\81u");
+                    /* +16 => "\81v\82Ì\8fÚ\8d×\82ð\8c©\82é\81H"\82Ì\92·\82³ */
+                    copynchars(eos(question), entrytext,
+                               (int) (sizeof question - 1
+                                      - (strlen(question) + 16)));
+                    Strcat(question, "\81v\82Ì\8fÚ\8d×\82ð\8c©\82é\81H");
+#endif
+                    if (yn(question) == 'y')
+                        yes_to_moreinfo = TRUE;
+                }
 
-/*JP
-        if (user_typed_name || without_asking || yn("More info?") == 'y') {
-*/
-        if (user_typed_name || without_asking || yn("\8fÚ\8d×\82ð\8c©\82é\81H") == 'y') {
-            if (dlb_fseek(fp, (long) txt_offset + entry_offset, SEEK_SET)
-                < 0) {
+                if (user_typed_name || without_asking || yes_to_moreinfo) {
+                    if (dlb_fseek(fp, fseekoffset, SEEK_SET) < 0) {
 /*JP
                 pline("? Seek error on 'data' file!");
 */
                 pline("'data'\83t\83@\83C\83\8b\82Ì\83V\81[\83N\83G\83\89\81[\81I");
-                (void) dlb_fclose(fp);
-                return;
-            }
-            datawin = create_nhwindow(NHW_MENU);
-            for (i = 0; i < entry_count; i++) {
-                if (!dlb_fgets(buf, BUFSZ, fp))
-                    goto bad_data_file;
-                if ((ep = index(buf, '\n')) != 0)
-                    *ep = 0;
-                if (index(buf + 1, '\t') != 0)
-                    (void) tabexpand(buf + 1);
-                putstr(datawin, 0, buf + 1);
-            }
-            display_nhwindow(datawin, FALSE);
-            destroy_nhwindow(datawin);
-        }
-    } else if (user_typed_name)
+                        goto checkfile_done;
+                    }
+                    datawin = create_nhwindow(NHW_MENU);
+                    for (i = 0; i < entry_count; i++) {
+                        if (!dlb_fgets(buf, BUFSZ, fp))
+                            goto bad_data_file;
+                        (void) strip_newline(buf);
+                        if (index(buf + 1, '\t') != 0)
+                            (void) tabexpand(buf + 1);
+                        putstr(datawin, 0, buf + 1);
+                    }
+                    display_nhwindow(datawin, FALSE);
+                    destroy_nhwindow(datawin), datawin = WIN_ERR;
+                }
+            } else if (user_typed_name && pass == 0 && !pass1found_in_file)
 /*JP
         pline("I don't have any information on those things.");
 */
         pline("\82»\82ñ\82È\96¼\91O\82Í\95·\82¢\82½\82±\82Æ\82ª\82È\82¢\81D");
+        }
+    }
+    goto checkfile_done; /* skip error feedback */
 
+ bad_data_file:
+    impossible("'data' file in wrong format or corrupted");
+ checkfile_done:
+    if (datawin != WIN_ERR)
+        destroy_nhwindow(datawin);
     (void) dlb_fclose(fp);
+    return;
 }
 
 int
@@ -689,19 +912,21 @@ int sym;
 char *out_str;
 const char **firstmatch;
 {
-    boolean need_to_look = FALSE;
-    int glyph = NO_GLYPH;
+/*JP
+    static const char mon_interior[] = "the interior of a monster",
+*/
+    static const char mon_interior[] = "\89ö\95¨\82Ì\93à\95\94",
+/*JP
+                      unreconnoitered[] = "unreconnoitered";
+*/
+                      unreconnoitered[] = "\96¢\8aÏ\8e@";
     static char look_buf[BUFSZ];
     char prefix[BUFSZ];
-    int found = 0; /* count of matching syms found */
-    int i, alt_i;
-    int skipped_venom = 0;
-    boolean hit_trap;
+    int i, alt_i, glyph = NO_GLYPH,
+        skipped_venom = 0, found = 0; /* count of matching syms found */
+    boolean hit_trap, need_to_look = FALSE,
+            submerged = (Underwater && !Is_waterlevel(&u.uz));
     const char *x_str;
-/*JP
-    static const char *mon_interior = "the interior of a monster";
-*/
-    static const char *mon_interior = "\89ö\95¨\82Ì\93à\95\94";
 
     if (looked) {
         int oc;
@@ -721,63 +946,100 @@ const char **firstmatch;
      */
 
     /*
-     * Special case: if identifying from the screen, and we're swallowed,
-     * and looking at something other than our own symbol, then just say
-     * "the interior of a monster".
+     * Handle restricted vision range (limited to adjacent spots when
+     * swallowed or underwater) cases first.
+     *
+     * 3.6.0 listed anywhere on map, other than self, as "interior
+     * of a monster" when swallowed, and non-adjacent water or
+     * non-water anywhere as "dark part of a room" when underwater.
+     * "unreconnoitered" is an attempt to convey "even if you knew
+     * what was there earlier, you don't know what is there in the
+     * current circumstance".
+     *
+     * (Note: 'self' will always be visible when swallowed so we don't
+     * need special swallow handling for <ux,uy>.
+     * Another note: for '#terrain' without monsters, u.uswallow and
+     * submerged will always both be False and skip this code.)
      */
-    if (u.uswallow && looked
-        && (is_swallow_sym(sym) || (int) showsyms[S_stone] == sym)) {
+    x_str = 0;
+    if (!looked) {
+        ; /* skip special handling */
+    } else if (((u.uswallow || submerged) && distu(cc.x, cc.y) > 2)
+               /* detection showing some category, so mostly background */
+               || ((iflags.terrainmode & (TER_DETECT | TER_MAP)) == TER_DETECT
+                   && glyph == cmap_to_glyph(S_stone))) {
+        x_str = unreconnoitered;
+        need_to_look = FALSE;
+    } else if (is_swallow_sym(sym)) {
+        x_str = mon_interior;
+        need_to_look = TRUE; /* for specific monster type */
+    }
+    if (x_str) {
+        /* we know 'found' is zero here, but guard against some other
+           special case being inserted ahead of us someday */
         if (!found) {
-            Sprintf(out_str, "%s%s", prefix, mon_interior);
-            *firstmatch = mon_interior;
+            Sprintf(out_str, "%s%s", prefix, x_str);
+            *firstmatch = x_str;
+            found++;
         } else {
-            found += append_str(out_str, mon_interior);
+            found += append_str(out_str, x_str); /* not 'an(x_str)' */
         }
-        need_to_look = TRUE;
-        goto didlook;
+        /* for is_swallow_sym(), we want to list the current symbol's
+           other possibilities (wand for '/', throne for '\\', &c) so
+           don't jump to the end for the x_str==mon_interior case */
+        if (x_str == unreconnoitered)
+            goto didlook;
     }
 
     /* Check for monsters */
-    for (i = 0; i < MAXMCLASSES; i++) {
-        if (sym == (looked ? showsyms[i + SYM_OFF_M] : def_monsyms[i].sym)
-            && def_monsyms[i].explain) {
-            need_to_look = TRUE;
-            if (!found) {
-                Sprintf(out_str, "%s%s", prefix, an(def_monsyms[i].explain));
-                *firstmatch = def_monsyms[i].explain;
-                found++;
-            } else {
-                found += append_str(out_str, an(def_monsyms[i].explain));
+    if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) {
+        for (i = 0; i < MAXMCLASSES; i++) {
+            if (sym == (looked ? showsyms[i + SYM_OFF_M] : def_monsyms[i].sym)
+                && def_monsyms[i].explain) {
+                need_to_look = TRUE;
+                if (!found) {
+                    Sprintf(out_str, "%s%s",
+                            prefix, an(def_monsyms[i].explain));
+                    *firstmatch = def_monsyms[i].explain;
+                    found++;
+                } else {
+                    found += append_str(out_str, an(def_monsyms[i].explain));
+                }
             }
         }
-    }
-    /* handle '@' as a special case if it refers to you and you're
-       playing a character which isn't normally displayed by that
-       symbol; firstmatch is assumed to already be set for '@' */
-    if ((looked ? (sym == showsyms[S_HUMAN + SYM_OFF_M]
-                   && cc.x == u.ux && cc.y == u.uy)
-                : (sym == def_monsyms[S_HUMAN].sym && !flags.showrace))
-        && !(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
-#if 0 /*JP*/
-        found += append_str(out_str, "you"); /* tack on "or you" */
+        /* handle '@' as a special case if it refers to you and you're
+           playing a character which isn't normally displayed by that
+           symbol; firstmatch is assumed to already be set for '@' */
+        if ((looked ? (sym == showsyms[S_HUMAN + SYM_OFF_M]
+                       && cc.x == u.ux && cc.y == u.uy)
+                    : (sym == def_monsyms[S_HUMAN].sym && !flags.showrace))
+            && !(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
+#if 0 /*JP:T*/
+            found += append_str(out_str, "you"); /* tack on "or you" */
 #else
-        found += append_str(out_str, "\82 \82È\82½"); /* tack on "or you" */
+            found += append_str(out_str, "\82 \82È\82½"); /* tack on "or you" */
 #endif
+    }
 
     /* Now check for objects */
-    for (i = 1; i < MAXOCLASSES; i++) {
-        if (sym == (looked ? showsyms[i + SYM_OFF_O] : def_oc_syms[i].sym)) {
-            need_to_look = TRUE;
-            if (looked && i == VENOM_CLASS) {
-                skipped_venom++;
-                continue;
-            }
-            if (!found) {
-                Sprintf(out_str, "%s%s", prefix, an(def_oc_syms[i].explain));
-                *firstmatch = def_oc_syms[i].explain;
-                found++;
-            } else {
-                found += append_str(out_str, an(def_oc_syms[i].explain));
+    if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
+        for (i = 1; i < MAXOCLASSES; i++) {
+            if (sym == (looked ? showsyms[i + SYM_OFF_O]
+                               : def_oc_syms[i].sym)
+                || (looked && i == ROCK_CLASS && glyph_is_statue(glyph))) {
+                need_to_look = TRUE;
+                if (looked && i == VENOM_CLASS) {
+                    skipped_venom++;
+                    continue;
+                }
+                if (!found) {
+                    Sprintf(out_str, "%s%s",
+                            prefix, an(def_oc_syms[i].explain));
+                    *firstmatch = def_oc_syms[i].explain;
+                    found++;
+                } else {
+                    found += append_str(out_str, an(def_oc_syms[i].explain));
+                }
             }
         }
     }
@@ -792,9 +1054,6 @@ const char **firstmatch;
         }
     }
 
-#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
-#define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
-
     /* Now check for graphics symbols */
     alt_i = (sym == (looked ? showsyms[0] : defsyms[0].sym)) ? 0 : (2 + 1);
     for (hit_trap = FALSE, i = 0; i < MAXPCHARS; i++) {
@@ -802,15 +1061,17 @@ const char **firstmatch;
            i == 0 three times: unexplored, stone, dark part of a room */
         if (alt_i < 2) {
 /*JP
-            x_str = !alt_i++ ? "unexplored" : "stone";
+            x_str = !alt_i++ ? "unexplored" : submerged ? "unknown" : "stone";
 */
-            x_str = !alt_i++ ? "\96¢\92T\8dõ" : "\8aâ\94Õ";
+            x_str = !alt_i++ ? "\96¢\92T\8dõ" : submerged ? "\96¢\92m" : "\8aâ\94Õ";
             i = 0; /* for second iteration, undo loop increment */
             /* alt_i is now 1 or 2 */
         } else {
             if (alt_i++ == 2)
                 i = 0; /* undo loop increment */
             x_str = defsyms[i].explanation;
+            if (submerged && !strcmp(x_str, defsyms[0].explanation))
+                x_str = "land"; /* replace "dark part of a room" */
             /* alt_i is now 3 or more and no longer of interest */
         }
         if (sym == (looked ? showsyms[i] : defsyms[i].sym) && *x_str) {
@@ -821,6 +1082,7 @@ const char **firstmatch;
             int article = strstri(x_str, " of a room") ? 2
                           : !(alt_i <= 2
                               || strcmp(x_str, "air") == 0
+                              || strcmp(x_str, "land") == 0
                               || strcmp(x_str, "water") == 0);
 
 #endif
@@ -842,7 +1104,7 @@ const char **firstmatch;
                 }
                 *firstmatch = x_str;
                 found++;
-            } else if (!u.uswallow && !(hit_trap && is_cmap_trap(i))
+            } else if (!(hit_trap && is_cmap_trap(i))
                        && !(found >= 3 && is_cmap_drawbridge(i))
                        /* don't mention vibrating square outside of Gehennom
                           unless this happens to be one (hallucination?) */
@@ -917,6 +1179,10 @@ const char **firstmatch;
      * If we are looking at the screen, follow multiple possibilities or
      * an ambiguous explanation by something more detailed.
      */
+
+    if (found > 4)
+        Sprintf(out_str, "%s", "That can be many things");
+
  didlook:
     if (looked) {
         if (found > 1 || need_to_look) {
@@ -942,12 +1208,6 @@ const char **firstmatch;
     return found;
 }
 
-/* getpos() return values */
-#define LOOK_TRADITIONAL 0 /* '.' -- ask about "more info?" */
-#define LOOK_QUICK 1       /* ',' -- skip "more info?" */
-#define LOOK_ONCE 2        /* ';' -- skip and stop looping */
-#define LOOK_VERBOSE 3     /* ':' -- show more info w/o asking */
-
 /* also used by getpos hack in do_name.c */
 /*JP
 const char what_is_an_unknown_object[] = "an unknown object";
@@ -961,7 +1221,7 @@ coord *click_cc;
 {
     boolean quick = (mode == 1); /* use cursor; don't search for "more info" */
     boolean clicklook = (mode == 2); /* right mouse-click method */
-    char out_str[BUFSZ];
+    char out_str[BUFSZ] = DUMMY;
     const char *firstmatch = 0;
     struct permonst *pm = 0;
     int i = '\0', ans = 0;
@@ -975,9 +1235,7 @@ coord *click_cc;
         if (quick) {
             from_screen = TRUE; /* yes, we want to use the cursor */
             i = 'y';
-        }
-
-        if (i != 'y') {
+        } else {
             menu_item *pick_list = (menu_item *) 0;
             winid win;
             anything any;
@@ -1092,6 +1350,10 @@ coord *click_cc;
             getlin("Specify what? (type the word)", out_str);
 */
             getlin("\89½\82ð\92²\82×\82é\81H(\95\8e\9a\82ð\93ü\82ê\82Ä\82Ë)", out_str);
+            if (strcmp(out_str, " ")) /* keep single space as-is */
+                /* remove leading and trailing whitespace and
+                   condense consecutive internal whitespace */
+                mungspaces(out_str);
             if (out_str[0] == '\0' || out_str[0] == '\033')
                 return 0;
 
@@ -1149,10 +1411,8 @@ coord *click_cc;
                     pline("\95¨\91Ì\82ð\8ew\92è\82µ\82Ä\82­\82¾\82³\82¢\81D");
 
                 ans = getpos(&cc, quick, what_is_an_unknown_object);
-                if (ans < 0 || cc.x < 0) {
-                    flags.verbose = save_verbose;
-                    return 0; /* done */
-                }
+                if (ans < 0 || cc.x < 0)
+                    break; /* done */
                 flags.verbose = FALSE; /* only print long question once */
             }
         }
@@ -1162,8 +1422,7 @@ coord *click_cc;
 
         /* Finally, print out our explanation. */
         if (found) {
-            /* Used putmixed() because there may be an encoded glyph present
-             */
+            /* use putmixed() because there may be an encoded glyph present */
             putmixed(WIN_MESSAGE, 0, out_str);
 
             /* check the data file for information about this thing */
@@ -1196,12 +1455,7 @@ boolean do_mons; /* True => monsters, False => objects */
 {
     winid win;
     int x, y, lo_x, lo_y, hi_x, hi_y, glyph, count = 0;
-    char buf[BUFSZ], outbuf[BUFSZ], coordbuf[12], fmt[12]; /* "%02d,%02d" */
-
-    /* row,column orientation rather than cartesian x,y */
-    Sprintf(fmt, "%%%sd,%%%sd",
-            (ROWNO <= 100) ? "02" : (ROWNO <= 1000) ? "03" : "",
-            (COLNO <= 100) ? "02" : (COLNO <= 1000) ? "03" : "");
+    char lookbuf[BUFSZ], outbuf[BUFSZ];
 
     win = create_nhwindow(NHW_TEXT);
     lo_y = nearby ? max(u.uy - BOLT_LIM, 0) : 0;
@@ -1210,7 +1464,7 @@ boolean do_mons; /* True => monsters, False => objects */
     hi_x = nearby ? min(u.ux + BOLT_LIM, COLNO - 1) : COLNO - 1;
     for (y = lo_y; y <= hi_y; y++) {
         for (x = lo_x; x <= hi_x; x++) {
-            buf[0] = '\0';
+            lookbuf[0] = '\0';
             glyph = glyph_at(x, y);
             if (do_mons) {
                 if (glyph_is_monster(glyph)) {
@@ -1219,49 +1473,56 @@ boolean do_mons; /* True => monsters, False => objects */
                     bhitpos.x = x; /* [is this actually necessary?] */
                     bhitpos.y = y;
                     if (x == u.ux && y == u.uy && canspotself()) {
-                        (void) self_lookat(buf);
+                        (void) self_lookat(lookbuf);
                         ++count;
                     } else if ((mtmp = m_at(x, y)) != 0) {
-                        look_at_monster(buf, (char *) 0, mtmp, x, y);
+                        look_at_monster(lookbuf, (char *) 0, mtmp, x, y);
                         ++count;
                     }
                 } else if (glyph_is_invisible(glyph)) {
                     /* remembered, unseen, creature */
-                    Strcpy(buf, invisexplain);
+                    Strcpy(lookbuf, invisexplain);
                     ++count;
                 } else if (glyph_is_warning(glyph)) {
                     int warnindx = glyph_to_warning(glyph);
 
-                    Strcpy(buf, def_warnsyms[warnindx].explanation);
+                    Strcpy(lookbuf, def_warnsyms[warnindx].explanation);
                     ++count;
                 }
             } else { /* !do_mons */
                 if (glyph_is_object(glyph)) {
-                    look_at_object(buf, x, y, glyph);
+                    look_at_object(lookbuf, x, y, glyph);
                     ++count;
                 }
             }
-            if (*buf) {
-                if (count == 1) {
-                    char which[12];
+            if (*lookbuf) {
+                char coordbuf[20], which[12], cmode;
 
+                cmode = (iflags.getpos_coords != GPCOORDS_NONE)
+                           ? iflags.getpos_coords : GPCOORDS_MAP;
+                if (count == 1) {
                     Strcpy(which, do_mons ? "monsters" : "objects");
-                    if (nearby) {
-                        Sprintf(coordbuf, fmt, u.uy, u.ux);
+                    if (nearby)
                         Sprintf(outbuf, "%s currently shown near %s:",
-                                upstart(which), coordbuf);
-                    } else
+                                upstart(which),
+                                (cmode != GPCOORDS_COMPASS)
+                                  ? coord_desc(u.ux, u.uy, coordbuf, cmode)
+                                  : !canspotself() ? "your position" : "you");
+                    else
                         Sprintf(outbuf, "All %s currently shown on the map:",
                                 which);
                     putstr(win, 0, outbuf);
                     putstr(win, 0, "");
                 }
-                Sprintf(coordbuf, fmt, y, x);
-                /* prefix: "C  row,column  " */
-                Sprintf(outbuf, "%s  %s  ", encglyph(glyph), coordbuf);
+                /* prefix: "coords  C  " where 'C' is mon or obj symbol */
+                Sprintf(outbuf, (cmode == GPCOORDS_SCREEN) ? "%s  "
+                                  : (cmode == GPCOORDS_MAP) ? "%8s  "
+                                      : "%12s  ",
+                        coord_desc(x, y, coordbuf, cmode));
+                Sprintf(eos(outbuf), "%s  ", encglyph(glyph));
                 /* guard against potential overflow */
-                buf[sizeof buf - 1 - strlen(outbuf)] = '\0';
-                Strcat(outbuf, buf);
+                lookbuf[sizeof lookbuf - 1 - strlen(outbuf)] = '\0';
+                Strcat(outbuf, lookbuf);
                 putmixed(win, 0, outbuf);
             }
         }
@@ -1300,12 +1561,24 @@ int
 doidtrap()
 {
     register struct trap *trap;
-    int x, y, tt;
+    int x, y, tt, glyph;
 
     if (!getdir("^"))
         return 0;
     x = u.ux + u.dx;
     y = u.uy + u.dy;
+
+    /* check fake bear trap from confused gold detection */
+    glyph = glyph_at(x, y);
+    if (glyph_is_trap(glyph) && (tt = glyph_to_trap(glyph)) == BEAR_TRAP) {
+        boolean chesttrap = trapped_chest_at(tt, x, y);
+
+        if (chesttrap || trapped_door_at(tt, x, y)) {
+            pline("That is a trapped %s.", chesttrap ? "chest" : "door");
+            return 0; /* trap ID'd, but no time elapses */
+        }
+    }
+
     for (trap = ftrap; trap; trap = trap->ntrap)
         if (trap->tx == x && trap->ty == y) {
             if (!trap->tseen)
@@ -1351,46 +1624,265 @@ doidtrap()
     return 0;
 }
 
+/*
+    Implements a rudimentary if/elif/else/endif interpretor and use
+    conditionals in dat/cmdhelp to describe what command each keystroke
+    currently invokes, so that there isn't a lot of "(debug mode only)"
+    and "(if number_pad is off)" cluttering the feedback that the user
+    sees.  (The conditionals add quite a bit of clutter to the raw data
+    but users don't see that.  number_pad produces a lot of conditional
+    commands:  basic letters vs digits, 'g' vs 'G' for '5', phone
+    keypad vs normal layout of digits, and QWERTZ keyboard swap between
+    y/Y/^Y/M-y/M-Y/M-^Y and z/Z/^Z/M-z/M-Z/M-^Z.)
+    
+    The interpretor understands
+     '&#' for comment,
+     '&? option' for 'if' (also '&? !option'
+                           or '&? option=value[,value2,...]'
+                           or '&? !option=value[,value2,...]'),
+     '&: option' for 'elif' (with argument variations same as 'if';
+                             any number of instances for each 'if'),
+     '&:' for 'else' (also '&: #comment';
+                      0 or 1 instance for a given 'if'), and
+     '&.' for 'endif' (also '&. #comment'; required for each 'if').
+    
+    The option handling is a bit of a mess, with no generality for
+    which options to deal with and only a comma separated list of
+    integer values for the '=value' part.  number_pad is the only
+    supported option that has a value; the few others (wizard/debug,
+    rest_on_space, #if SHELL, #if SUSPEND) are booleans.
+*/
+
+STATIC_DCL void
+whatdoes_help()
+{
+    dlb *fp;
+    char *p, buf[BUFSZ];
+    winid tmpwin = create_nhwindow(NHW_TEXT);
+
+    fp = dlb_fopen(KEYHELP, "r");
+    if (!fp) {
+/*JP
+        pline("Cannot open \"%s\" data file!", KEYHELP);
+*/
+        pline("\83f\81[\83^\83t\83@\83C\83\8b\"%s\"\82ð\8aJ\82¯\82È\82¢\81I", KEYHELP);
+        display_nhwindow(WIN_MESSAGE, TRUE);
+        return;
+    }
+    while (dlb_fgets(buf, (int) sizeof buf, fp)) {
+        if (*buf == '#')
+            continue;
+        for (p = buf; *p; p++)
+            if (*p != ' ' && *p != '\t')
+                break;
+        putstr(tmpwin, 0, p);
+    }
+    (void) dlb_fclose(fp);
+    display_nhwindow(tmpwin, TRUE);
+    destroy_nhwindow(tmpwin);
+}
+
+#if 0
+#define WD_STACKLIMIT 5
+struct wd_stack_frame {
+    Bitfield(active, 1);
+    Bitfield(been_true, 1);
+    Bitfield(else_seen, 1);
+};
+
+STATIC_DCL boolean FDECL(whatdoes_cond, (char *, struct wd_stack_frame *,
+                                         int *, int));
+
+STATIC_OVL boolean
+whatdoes_cond(buf, stack, depth, lnum)
+char *buf;
+struct wd_stack_frame *stack;
+int *depth, lnum;
+{
+    const char badstackfmt[] = "cmdhlp: too many &%c directives at line %d.";
+    boolean newcond, neg, gotopt;
+    char *p, *q, act = buf[1];
+    int np = 0;
+
+    newcond = (act == '?' || !stack[*depth].been_true);
+    buf += 2;
+    mungspaces(buf);
+    if (act == '#' || *buf == '#' || !*buf || !newcond) {
+        gotopt = (*buf && *buf != '#');
+        *buf = '\0';
+        neg = FALSE; /* lint suppression */
+        p = q = (char *) 0;
+    } else {
+        gotopt = TRUE;
+        if ((neg = (*buf == '!')) != 0)
+            if (*++buf == ' ')
+                ++buf;
+        p = index(buf, '='), q = index(buf, ':');
+        if (!p || (q && q < p))
+            p = q;
+        if (p) { /* we have a value specified */
+            /* handle a space before or after (or both) '=' (or ':') */
+            if (p > buf && p[-1] == ' ')
+                p[-1] = '\0'; /* end of keyword in buf[] */
+            *p++ = '\0'; /* terminate keyword, advance to start of value */
+            if (*p == ' ')
+                p++;
+        }
+    }
+    if (*buf && (act == '?' || act == ':')) {
+        if (!strcmpi(buf, "number_pad")) {
+            if (!p) {
+                newcond = iflags.num_pad;
+            } else {
+                /* convert internal encoding (separate yes/no and 0..3)
+                   back to user-visible one (-1..4) */
+                np = iflags.num_pad ? (1 + iflags.num_pad_mode) /* 1..4 */
+                                    : (-1 * iflags.num_pad_mode); /* -1..0 */
+                newcond = FALSE;
+                for (; p; p = q) {
+                    q = index(p, ',');
+                    if (q)
+                        *q++ = '\0';
+                    if (atoi(p) == np) {
+                        newcond = TRUE;
+                        break;
+                    }
+                }
+            }
+        } else if (!strcmpi(buf, "rest_on_space")) {
+            newcond = flags.rest_on_space;
+        } else if (!strcmpi(buf, "debug") || !strcmpi(buf, "wizard")) {
+            newcond = flags.debug; /* == wizard */
+        } else if (!strcmpi(buf, "shell")) {
+#ifdef SHELL
+            /* should we also check sysopt.shellers? */
+            newcond = TRUE;
+#else
+            newcond = FALSE;
+#endif
+        } else if (!strcmpi(buf, "suspend")) {
+#ifdef SUSPEND
+            /* sysopt.shellers is also used for dosuspend()... */
+            newcond = TRUE;
+#else
+            newcond = FALSE;
+#endif
+        } else {
+            impossible(
+                "cmdhelp: unrecognized &%c conditional at line %d: \"%.20s\"",
+                       act, lnum, buf);
+            neg = FALSE;
+        }
+        /* this works for number_pad too: &? !number_pad:-1,0
+           would be true for 1..4 after negation */
+        if (neg)
+            newcond = !newcond;
+    }
+    switch (act) {
+    default:
+    case '#': /* comment */
+        break;
+    case '.': /* endif */
+        if (--*depth < 0) {
+            impossible(badstackfmt, '.', lnum);
+            *depth = 0;
+        }
+        break;
+    case ':': /* else or elif */
+        if (*depth == 0 || stack[*depth].else_seen) {
+            impossible(badstackfmt, ':', lnum);
+            *depth = 1; /* so that stack[*depth - 1] is a valid access */
+        }
+        if (stack[*depth].active || stack[*depth].been_true
+            || !stack[*depth - 1].active)
+            stack[*depth].active = 0;
+        else if (newcond)
+            stack[*depth].active = stack[*depth].been_true = 1;
+        if (!gotopt)
+            stack[*depth].else_seen = 1;
+        break;
+    case '?': /* if */
+        if (++*depth >= WD_STACKLIMIT) {
+            impossible(badstackfmt, '?', lnum);
+            *depth = WD_STACKLIMIT - 1;
+        }
+        stack[*depth].active = (newcond && stack[*depth - 1].active) ? 1 : 0;
+        stack[*depth].been_true = stack[*depth].active;
+        stack[*depth].else_seen = 0;
+        break;
+    }
+    return stack[*depth].active ? TRUE : FALSE;
+}
+#endif /* 0 */
+
 char *
 dowhatdoes_core(q, cbuf)
 char q;
 char *cbuf;
 {
+    char buf[BUFSZ];
+#if 0
     dlb *fp;
-    char bufr[BUFSZ];
-    register char *buf = &bufr[6], *ep, ctrl, meta;
-
+    struct wd_stack_frame stack[WD_STACKLIMIT];
+    boolean cond;
+    int ctrl, meta, depth = 0, lnum = 0;
+#endif /* 0 */
+    const char *ec_desc;
+
+    if ((ec_desc = key2extcmddesc(q)) != NULL) {
+        char keybuf[QBUFSZ];
+
+        Sprintf(buf, "%-8s%s.", key2txt(q, keybuf), ec_desc);
+        Strcpy(cbuf, buf);
+        return cbuf;
+    }
+    return 0;
+#if 0
     fp = dlb_fopen(CMDHELPFILE, "r");
     if (!fp) {
-#if 0 /*JP*/
-        pline("Cannot open data file!");
-#else
-        pline("\83f\81[\83^\83t\83@\83C\83\8b\82ð\8aJ\82¯\82È\82¢\81I");
-#endif
+        pline("Cannot open \"%s\" data file!", CMDHELPFILE);
         return 0;
     }
 
-    ctrl = ((q <= '\033') ? (q - 1 + 'A') : 0);
-    meta = ((0x80 & q) ? (0x7f & q) : 0);
-    while (dlb_fgets(buf, BUFSZ - 6, fp)) {
-        if ((ctrl && *buf == '^' && *(buf + 1) == ctrl)
-            || (meta && *buf == 'M' && *(buf + 1) == '-'
-                && *(buf + 2) == meta) || *buf == q) {
-            ep = index(buf, '\n');
-            if (ep)
-                *ep = 0;
-            if (ctrl && buf[2] == '\t') {
-                buf = bufr + 1;
-                (void) strncpy(buf, "^?      ", 8);
-                buf[1] = ctrl;
-            } else if (meta && buf[3] == '\t') {
-                buf = bufr + 2;
+    meta = (0x80 & (uchar) q) != 0;
+    if (meta)
+        q &= 0x7f;
+    ctrl = (0x1f & (uchar) q) == (uchar) q;
+    if (ctrl)
+        q |= 0x40; /* NUL -> '@', ^A -> 'A', ... ^Z -> 'Z', ^[ -> '[', ... */
+    else if (q == 0x7f)
+        ctrl = 1, q = '?';
+
+    (void) memset((genericptr_t) stack, 0, sizeof stack);
+    cond = stack[0].active = 1;
+    while (dlb_fgets(buf, sizeof buf, fp)) {
+        ++lnum;
+        if (buf[0] == '&' && buf[1] && index("?:.#", buf[1])) {
+            cond = whatdoes_cond(buf, stack, &depth, lnum);
+            continue;
+        }
+        if (!cond)
+            continue;
+        if (meta ? (buf[0] == 'M' && buf[1] == '-'
+                    && (ctrl ? buf[2] == '^' && highc(buf[3]) == q
+                             : buf[2] == q))
+                 : (ctrl ? buf[0] == '^' && highc(buf[1]) == q
+                         : buf[0] == q)) {
+            (void) strip_newline(buf);
+            if (index(buf, '\t'))
+                (void) tabexpand(buf);
+            if (meta && ctrl && buf[4] == ' ') {
+                (void) strncpy(buf, "M-^?    ", 8);
+                buf[3] = q;
+            } else if (meta && buf[3] == ' ') {
                 (void) strncpy(buf, "M-?     ", 8);
-                buf[2] = meta;
-            } else if (buf[1] == '\t') {
-                buf = bufr;
+                buf[2] = q;
+            } else if (ctrl && buf[2] == ' ') {
+                (void) strncpy(buf, "^?      ", 8);
+                buf[1] = q;
+            } else if (buf[1] == ' ') {
+                (void) strncpy(buf, "?       ", 8);
                 buf[0] = q;
-                (void) strncpy(buf + 1, "       ", 7);
             }
             (void) dlb_fclose(fp);
             Strcpy(cbuf, buf);
@@ -1398,37 +1890,66 @@ char *cbuf;
         }
     }
     (void) dlb_fclose(fp);
+    if (depth != 0)
+        impossible("cmdhelp: mismatched &? &: &. conditionals.");
     return (char *) 0;
+#endif /* 0 */
 }
 
 int
 dowhatdoes()
 {
+    static boolean once = FALSE;
     char bufr[BUFSZ];
     char q, *reslt;
 
+    if (!once) {
+        pline("Ask about '&' or '?' to get more info.%s",
+#ifdef ALTMETA
+              iflags.altmeta ? "  (For ESC, type it twice.)" :
+#endif
+              "");
+        once = TRUE;
+    }
 #if defined(UNIX) || defined(VMS)
-    introff();
+    introff(); /* disables ^C but not ^\ */
 #endif
 /*JP
     q = yn_function("What command?", (char *) 0, '\0');
 */
     q = yn_function("\82Ç\82¤\82¢\82¤\83R\83}\83\93\83h\81H", (char *) 0, '\0');
+#ifdef ALTMETA
+    if (q == '\033' && iflags.altmeta) {
+        /* in an ideal world, we would know whether another keystroke
+           was already pending, but this is not an ideal world...
+           if user typed ESC, we'll essentially hang until another
+           character is typed */
+        q = yn_function("]", (char *) 0, '\0');
+        if (q != '\033')
+            q = (char) ((uchar) q | 0200);
+    }
+#endif /*ALTMETA*/
 #if defined(UNIX) || defined(VMS)
-    intron();
+    intron(); /* reenables ^C */
 #endif
     reslt = dowhatdoes_core(q, bufr);
-    if (reslt)
-        pline1(reslt);
-    else
-/*JP
-        pline("I've never heard of such commands.");
-*/
-        pline("\82»\82ñ\82È\83R\83}\83\93\83h\82Í\95·\82¢\82½\82±\82Æ\82ª\82È\82¢\81D");
+    if (reslt) {
+        if (q == '&' || q == '?')
+            whatdoes_help();
+        pline("%s", reslt);
+    } else {
+#if 0 /*JP*/
+        pline("No such command '%s', char code %d (0%03o or 0x%02x).",
+              visctrl(q), (uchar) q, (uchar) q, (uchar) q);
+#else
+        pline("\82»\82ñ\82È\83R\83}\83\93\83h'%s'\81C\95\8e\9a\83R\81[\83h%d(0%03o \82Ü\82½\82Í 0x%02x)\82Í\82È\82¢\81D",
+              visctrl(q), (uchar) q, (uchar) q, (uchar) q);
+#endif
+    }
     return 0;
 }
 
-void
+STATIC_OVL void
 docontact()
 {
     winid cwin = create_nhwindow(NHW_TEXT);
@@ -1458,83 +1979,173 @@ docontact()
     destroy_nhwindow(cwin);
 }
 
-/* data for help_menu() */
-static const char *help_menu_items[] = {
-#if 0 /*JP*/
-    /*  0*/ "About NetHack (version information).",
-    /*  1*/ "Long description of the game and commands.",
-    /*  2*/ "List of game commands.",
-    /*  3*/ "Concise history of NetHack.",
-    /*  4*/ "Info on a character in the game display.",
-    /*  5*/ "Info on what a given key does.",
-    /*  6*/ "List of game options.",
-    /*  7*/ "Longer explanation of game options.",
-    /*  8*/ "List of extended commands.",
-    /*  9*/ "The NetHack license.",
-    /* 10*/ "Support information.",
-#ifdef PORT_HELP
-    "%s-specific help and commands.",
-#define PORT_HELP_ID 100
-#define WIZHLP_SLOT 12
-#else
-#define WIZHLP_SLOT 11
-#endif
-    "List of wizard-mode commands.", "", (char *) 0
-#else /*JP*/
-    /*  0*/ "NetHack\82É\82Â\82¢\82Ä(\83o\81[\83W\83\87\83\93\8fî\95ñ)",
-    /*  1*/ "\83Q\81[\83\80\82¨\82æ\82Ñ\83R\83}\83\93\83h\82Ì\89ð\90à(\92·\95¶)",
-    /*  2*/ "\83R\83}\83\93\83h\88ê\97\97",
-    /*  3*/ "NetHack\82Ì\8aÈ\92P\82È\97ð\8ej",
-    /*  4*/ "\89æ\96Ê\82É\95\\8e¦\82³\82ê\82é\95\8e\9a\82Ì\90à\96¾",
-    /*  5*/ "\82±\82Ì\83L\81[\82ª\89½\82ð\88Ó\96¡\82·\82é\82©\82Ì\90à\96¾",
-    /*  6*/ "\83Q\81[\83\80\82Ì\83I\83v\83V\83\87\83\93\88ê\97\97",
-    /*  7*/ "\83Q\81[\83\80\82Ì\83I\83v\83V\83\87\83\93\88ê\97\97(\92·\95¶)",
-    /*  8*/ "\8ag\92£\83R\83}\83\93\83h\88ê\97\97",
-    /*  9*/ "NetHack\82Ì\83\89\83C\83Z\83\93\83X",
-    /* 10*/ "\83T\83|\81[\83g\8fî\95ñ",
+void
+dispfile_help()
+{
+    display_file(HELP, TRUE);
+}
+
+void
+dispfile_shelp()
+{
+    display_file(SHELP, TRUE);
+}
+
+void
+dispfile_optionfile()
+{
+    display_file(OPTIONFILE, TRUE);
+}
+
+void
+dispfile_license()
+{
+    display_file(LICENSE, TRUE);
+}
+
+void
+dispfile_debughelp()
+{
+    display_file(DEBUGHELP, TRUE);
+}
+
+void
+hmenu_doextversion()
+{
+    (void) doextversion();
+}
+
+void
+hmenu_dohistory()
+{
+    (void) dohistory();
+}
+
+void
+hmenu_dowhatis()
+{
+    (void) dowhatis();
+}
+
+void
+hmenu_dowhatdoes()
+{
+    (void) dowhatdoes();
+}
+
+void
+hmenu_doextlist()
+{
+    (void) doextlist();
+}
+
+void
+domenucontrols()
+{
+    winid cwin = create_nhwindow(NHW_TEXT);
+    show_menu_controls(cwin, FALSE);
+    display_nhwindow(cwin, FALSE);
+    destroy_nhwindow(cwin);
+}
+
+/* data for dohelp() */
+static struct {
+    void (*f)();
+    const char *text;
+} help_menu_items[] = {
+/*JP
+    { hmenu_doextversion, "About NetHack (version information)." },
+*/
+    { hmenu_doextversion, "NetHack\82É\82Â\82¢\82Ä(\83o\81[\83W\83\87\83\93\8fî\95ñ)" },
+/*JP
+    { dispfile_help, "Long description of the game and commands." },
+*/
+    { dispfile_help, "\83Q\81[\83\80\82¨\82æ\82Ñ\83R\83}\83\93\83h\82Ì\89ð\90à(\92·\95¶)" },
+/*JP
+    { dispfile_shelp, "List of game commands." },
+*/
+    { dispfile_shelp, "\83R\83}\83\93\83h\88ê\97\97" },
+/*JP
+    { hmenu_dohistory, "Concise history of NetHack." },
+*/
+    { hmenu_dohistory, "NetHack\82Ì\8aÈ\92P\82È\97ð\8ej" },
+/*JP
+    { hmenu_dowhatis, "Info on a character in the game display." },
+*/
+    { hmenu_dowhatis, "\89æ\96Ê\82É\95\\8e¦\82³\82ê\82é\95\8e\9a\82Ì\90à\96¾" },
+/*JP
+    { hmenu_dowhatdoes, "Info on what a given key does." },
+*/
+    { hmenu_dowhatdoes, "\82±\82Ì\83L\81[\82ª\89½\82ð\88Ó\96¡\82·\82é\82©\82Ì\90à\96¾" },
+/*JP
+    { option_help, "List of game options." },
+*/
+    { option_help, "\83Q\81[\83\80\82Ì\83I\83v\83V\83\87\83\93\88ê\97\97" },
+/*JP
+    { dispfile_optionfile, "Longer explanation of game options." },
+*/
+    { dispfile_optionfile, "\83Q\81[\83\80\82Ì\83I\83v\83V\83\87\83\93\88ê\97\97(\92·\95¶)" },
+/*JP
+    { dokeylist, "Full list of keyboard commands" },
+*/
+    { dokeylist, "\83L\81[\83{\81[\83h\83R\83}\83\93\83h\82Ì\8a®\91S\82È\88ê\97\97" },
+/*JP
+    { hmenu_doextlist, "List of extended commands." },
+*/
+    { hmenu_doextlist, "\8ag\92£\83R\83}\83\93\83h\88ê\97\97" },
+/*JP
+    { domenucontrols, "List menu control keys" },
+*/
+    { domenucontrols, "\83\81\83j\83\85\81[\90§\8cä\83L\81[\88ê\97\97s" },
+/*JP
+    { dispfile_license, "The NetHack license." },
+*/
+    { dispfile_license, "NetHack\82Ì\83\89\83C\83Z\83\93\83X" },
+/*JP
+    { docontact, "Support information." },
+*/
+    { docontact, "\83T\83|\81[\83g\8fî\95ñ" },
 #ifdef PORT_HELP
-    "%s\82É\93Á\97L\82Ì\83w\83\8b\83v\82¨\82æ\82Ñ\83R\83}\83\93\83h",
-#define PORT_HELP_ID 100
-#define WIZHLP_SLOT 12
-#else
-#define WIZHLP_SLOT 11
+/*JP
+    { port_help, "%s-specific help and commands." },
+*/
+    { port_help, "%s\82É\93Á\97L\82Ì\83w\83\8b\83v\82Æ\83R\83}\83\93\83h" },
 #endif
-    "\83E\83B\83U\81[\83h\83\82\81[\83h\82Ì\83R\83}\83\93\83h\88ê\97\97", "", (char *) 0
-#endif /*JP*/
+/*JP
+    { dispfile_debughelp, "List of wizard-mode commands." },
+*/
+    { dispfile_debughelp, "\83E\83B\83U\81[\83h\83\82\81[\83h\82Ì\83R\83}\83\93\83h\88ê\97\97" },
+    { NULL, (char *) 0 }
 };
 
-STATIC_OVL boolean
-help_menu(sel)
-int *sel;
+/* the '?' command */
+int
+dohelp()
 {
     winid tmpwin = create_nhwindow(NHW_MENU);
-#ifdef PORT_HELP
     char helpbuf[QBUFSZ];
-#endif
     int i, n;
     menu_item *selected;
     anything any;
+    int sel;
+    char *bufptr;
 
     any = zeroany; /* zero all bits */
     start_menu(tmpwin);
-    if (!wizard)
-        help_menu_items[WIZHLP_SLOT] = "",
-        help_menu_items[WIZHLP_SLOT + 1] = (char *) 0;
-    for (i = 0; help_menu_items[i]; i++)
-#ifdef PORT_HELP
-        /* port-specific line has a %s in it for the PORT_ID */
-        if (help_menu_items[i][0] == '%') {
-            Sprintf(helpbuf, help_menu_items[i], PORT_ID);
-            any.a_int = PORT_HELP_ID + 1;
-            add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, helpbuf,
-                     MENU_UNSELECTED);
-        } else
-#endif
-        {
-            any.a_int = (*help_menu_items[i]) ? i + 1 : 0;
-            add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
-                     help_menu_items[i], MENU_UNSELECTED);
+
+    for (i = 0; help_menu_items[i].text; i++) {
+        if (!wizard && help_menu_items[i].f == dispfile_debughelp)
+            continue;
+        if (help_menu_items[i].text[0] == '%') {
+            Sprintf(helpbuf, help_menu_items[i].text, PORT_ID);
+            bufptr = helpbuf;
+        } else {
+            bufptr = (char *)help_menu_items[i].text;
         }
+        any.a_int = i + 1;
+        add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+                 bufptr, MENU_UNSELECTED);
+    }
 /*JP
     end_menu(tmpwin, "Select one item:");
 */
@@ -1542,64 +2153,9 @@ int *sel;
     n = select_menu(tmpwin, PICK_ONE, &selected);
     destroy_nhwindow(tmpwin);
     if (n > 0) {
-        *sel = selected[0].item.a_int - 1;
+        sel = selected[0].item.a_int - 1;
         free((genericptr_t) selected);
-        return TRUE;
-    }
-    return FALSE;
-}
-
-/* the '?' command */
-int
-dohelp()
-{
-    int sel = 0;
-
-    if (help_menu(&sel)) {
-        switch (sel) {
-        case 0:
-            (void) doextversion();
-            break;
-        case 1:
-            display_file(HELP, TRUE);
-            break;
-        case 2:
-            display_file(SHELP, TRUE);
-            break;
-        case 3:
-            (void) dohistory();
-            break;
-        case 4:
-            (void) dowhatis();
-            break;
-        case 5:
-            (void) dowhatdoes();
-            break;
-        case 6:
-            option_help();
-            break;
-        case 7:
-            display_file(OPTIONFILE, TRUE);
-            break;
-        case 8:
-            (void) doextlist();
-            break;
-        case 9:
-            display_file(LICENSE, TRUE);
-            break;
-        case 10:
-            (void) docontact();
-            break;
-#ifdef PORT_HELP
-        case PORT_HELP_ID:
-            port_help();
-            break;
-#endif
-        default:
-            /* handle slot 11 or 12 */
-            display_file(DEBUGHELP, TRUE);
-            break;
-        }
+        (void)(*help_menu_items[sel].f)();
     }
     return 0;
 }
index cd0080c..dbe7ae7 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 pickup.c        $NHDT-Date: 1445556881 2015/10/22 23:34:41 $  $NHDT-Branch: master $:$NHDT-Revision: 1.162 $ */
+/* NetHack 3.6 pickup.c        $NHDT-Date: 1516581051 2018/01/22 00:30:51 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.194 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -8,7 +9,7 @@
 /* JNetHack may be freely redistributed.  See license for details. */
 
 /*
- *     Contains code for picking objects up, and container use.
+ *      Contains code for picking objects up, and container use.
  */
 
 #include "hack.h"
@@ -16,9 +17,9 @@
 #define CONTAINED_SYM '>' /* from invent.c */
 
 STATIC_DCL void FDECL(simple_look, (struct obj *, BOOLEAN_P));
-STATIC_DCL boolean
-FDECL(query_classes, (char *, boolean *, boolean *, const char *,
-                      struct obj *, BOOLEAN_P, int *));
+STATIC_DCL boolean FDECL(query_classes, (char *, boolean *, boolean *,
+                                         const char *, struct obj *,
+                                         BOOLEAN_P, int *));
 STATIC_DCL boolean FDECL(fatal_corpse_mistake, (struct obj *, BOOLEAN_P));
 STATIC_DCL void FDECL(check_here, (BOOLEAN_P));
 STATIC_DCL boolean FDECL(n_or_more, (struct obj *));
@@ -30,28 +31,29 @@ STATIC_DCL int FDECL(autopick, (struct obj *, int, menu_item **));
 STATIC_DCL int FDECL(count_categories, (struct obj *, int));
 STATIC_DCL long FDECL(carry_count, (struct obj *, struct obj *, long,
                                     BOOLEAN_P, int *, int *));
-STATIC_DCL int FDECL(lift_object,
-                     (struct obj *, struct obj *, long *, BOOLEAN_P));
+STATIC_DCL int FDECL(lift_object, (struct obj *, struct obj *, long *,
+                                   BOOLEAN_P));
 STATIC_DCL boolean FDECL(mbag_explodes, (struct obj *, int));
+STATIC_DCL long FDECL(boh_loss, (struct obj *container, int));
 STATIC_PTR int FDECL(in_container, (struct obj *));
 STATIC_PTR int FDECL(out_container, (struct obj *));
+STATIC_DCL void FDECL(removed_from_icebox, (struct obj *));
 STATIC_DCL long FDECL(mbag_item_gone, (int, struct obj *));
 STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
-STATIC_DCL void NDECL(explain_container_prompt);
+STATIC_DCL void FDECL(explain_container_prompt, (BOOLEAN_P));
 STATIC_DCL int FDECL(traditional_loot, (BOOLEAN_P));
 STATIC_DCL int FDECL(menu_loot, (int, BOOLEAN_P));
 STATIC_DCL char FDECL(in_or_out_menu, (const char *, struct obj *, BOOLEAN_P,
-                                       BOOLEAN_P, BOOLEAN_P));
-STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
+                                       BOOLEAN_P, BOOLEAN_P, BOOLEAN_P));
 STATIC_DCL boolean FDECL(able_to_loot, (int, int, BOOLEAN_P));
 STATIC_DCL boolean NDECL(reverse_loot);
 STATIC_DCL boolean FDECL(mon_beside, (int, int));
-STATIC_DCL int FDECL(do_loot_cont, (struct obj **));
+STATIC_DCL int FDECL(do_loot_cont, (struct obj **, int, int));
 STATIC_DCL void FDECL(tipcontainer, (struct obj *));
 
 /* define for query_objlist() and autopickup() */
 #define FOLLOW(curr, flags) \
-    (((flags) &BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
+    (((flags) & BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
 
 /*
  *  How much the weight of the given container will change when the given
@@ -66,24 +68,26 @@ STATIC_DCL void FDECL(tipcontainer, (struct obj *));
 /* if you can figure this out, give yourself a hearty pat on the back... */
 #define GOLD_CAPACITY(w, n) (((w) * -100L) - ((n) + 50L) - 1L)
 
-/* A variable set in use_container(), to be used by the callback routines  */
-/* in_container() and out_container() from askchain() and use_container(). */
-/* Also used by menu_loot() and container_gone().                         */
+/* A variable set in use_container(), to be used by the callback routines
+   in_container() and out_container() from askchain() and use_container().
+   Also used by menu_loot() and container_gone(). */
 static NEARDATA struct obj *current_container;
+static NEARDATA boolean abort_looting;
 #define Icebox (current_container->otyp == ICE_BOX)
 
+static const char
 /*JP
-static const char moderateloadmsg[] = "You have a little trouble lifting";
+        moderateloadmsg[] = "You have a little trouble lifting",
 */
-static const char moderateloadmsg[] = "\82ð\8e\9d\82Á\82½\82ç\8f­\82µ\82Ó\82ç\82Â\82¢\82½";
+        moderateloadmsg[] = "\82ð\8e\9d\82Á\82½\82ç\8f­\82µ\82Ó\82ç\82Â\82¢\82½",
 /*JP
-static const char nearloadmsg[] = "You have much trouble lifting";
+        nearloadmsg[] = "You have much trouble lifting",
 */
-static const char nearloadmsg[] = "\82Í\82¸\82Á\82µ\82è\82Æ\8c¨\82É\82Ì\82µ\82©\82©\82Á\82½";
+        nearloadmsg[] = "\82Í\82¸\82Á\82µ\82è\82Æ\8c¨\82É\82Ì\82µ\82©\82©\82Á\82½",
 /*JP
-static const char overloadmsg[] = "You have extreme difficulty lifting";
+        overloadmsg[] = "You have extreme difficulty lifting";
 */
-static const char overloadmsg[] = "\82ð\8e\9d\82¿\82 \82°\82é\82Ì\82Í\82Æ\82Ä\82à\82Â\82ç\82¢";
+        overloadmsg[] = "\82ð\8e\9d\82¿\82 \82°\82é\82Ì\82Í\82Æ\82Ä\82à\82Â\82ç\82¢";
 
 /* BUG: this lets you look at cockatrice corpses while blind without
    touching them */
@@ -103,6 +107,7 @@ boolean here;     /* flag for type of obj list linkage */
         pline1(doname(otmp));
     } else {
         winid tmpwin = create_nhwindow(NHW_MENU);
+
         putstr(tmpwin, 0, "");
         do {
             putstr(tmpwin, 0, doname(otmp));
@@ -139,15 +144,15 @@ int *itemcount;
 
 /*
  * Suppose some '?' and '!' objects are present, but '/' objects aren't:
- *     "a" picks all items without further prompting;
- *     "A" steps through all items, asking one by one;
- *     "?" steps through '?' items, asking, and ignores '!' ones;
- *     "/" becomes 'A', since no '/' present;
- *     "?a" or "a?" picks all '?' without further prompting;
- *     "/a" or "a/" becomes 'A' since there aren't any '/'
- *         (bug fix:  3.1.0 thru 3.1.3 treated it as "a");
- *     "?/a" or "a?/" or "/a?",&c picks all '?' even though no '/'
- *         (ie, treated as if it had just been "?a").
+ *      "a" picks all items without further prompting;
+ *      "A" steps through all items, asking one by one;
+ *      "?" steps through '?' items, asking, and ignores '!' ones;
+ *      "/" becomes 'A', since no '/' present;
+ *      "?a" or "a?" picks all '?' without further prompting;
+ *      "/a" or "a/" becomes 'A' since there aren't any '/'
+ *          (bug fix:  3.1.0 thru 3.1.3 treated it as "a");
+ *      "?/a" or "a?/" or "/a?",&c picks all '?' even though no '/'
+ *          (ie, treated as if it had just been "?a").
  */
 /*JP CHECK: 3.4.3 \82Å\82Ì\8cÄ\82Ñ\8fo\82µ\8c³
 pickup.c:572:("\8fE\82¤")   if (!query_classes(oclasses, &selective, &all_of_a_type,
@@ -164,45 +169,57 @@ struct obj *objs;
 boolean here;
 int *menu_on_demand;
 {
-    char ilets[30], inbuf[BUFSZ]; /* FIXME: hardcoded ilets[] length */
+    char ilets[36], inbuf[BUFSZ] = DUMMY; /* FIXME: hardcoded ilets[] length */
     int iletct, oclassct;
-    boolean not_everything;
+    boolean not_everything, filtered;
     char qbuf[QBUFSZ];
     boolean m_seen;
-    int itemcount;
+    int itemcount, bcnt, ucnt, ccnt, xcnt, ocnt;
 
     oclasses[oclassct = 0] = '\0';
     *one_at_a_time = *everything = m_seen = FALSE;
+    if (menu_on_demand)
+        *menu_on_demand = 0;
     iletct = collect_obj_classes(ilets, objs, here,
                                  (boolean FDECL((*), (OBJ_P))) 0, &itemcount);
-    if (iletct == 0) {
+    if (iletct == 0)
         return FALSE;
-    } else if (iletct == 1) {
+
+    if (iletct == 1) {
         oclasses[0] = def_char_to_objclass(ilets[0]);
         oclasses[1] = '\0';
-        if (itemcount && menu_on_demand) {
-            ilets[iletct++] = 'm';
-            *menu_on_demand = 0;
-            ilets[iletct] = '\0';
-        }
     } else { /* more than one choice available */
-        const char *where = 0;
-        register char sym, oc_of_sym, *p;
         /* additional choices */
         ilets[iletct++] = ' ';
         ilets[iletct++] = 'a';
         ilets[iletct++] = 'A';
         ilets[iletct++] = (objs == invent ? 'i' : ':');
-        if (menu_on_demand) {
-            ilets[iletct++] = 'm';
-            *menu_on_demand = 0;
-        }
-        ilets[iletct] = '\0';
+    }
+    if (itemcount && menu_on_demand)
+        ilets[iletct++] = 'm';
+    if (count_unpaid(objs))
+        ilets[iletct++] = 'u';
+
+    tally_BUCX(objs, here, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
+    if (bcnt)
+        ilets[iletct++] = 'B';
+    if (ucnt)
+        ilets[iletct++] = 'U';
+    if (ccnt)
+        ilets[iletct++] = 'C';
+    if (xcnt)
+        ilets[iletct++] = 'X';
+    ilets[iletct] = '\0';
+
+    if (iletct > 1) {
+        const char *where = 0;
+        char sym, oc_of_sym, *p;
+
     ask_again:
         oclasses[oclassct = 0] = '\0';
         *one_at_a_time = *everything = FALSE;
-        not_everything = FALSE;
-#if 0 /*JP*/
+        not_everything = filtered = FALSE;
+#if 0 /*JP:T*/
         Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]", action,
                 ilets);
 #else
@@ -213,8 +230,7 @@ int *menu_on_demand;
         if (*inbuf == '\033')
             return FALSE;
 
-        for (p = inbuf; (sym = *p++);) {
-            /* new A function (selective all) added by GAN 01/09/87 */
+        for (p = inbuf; (sym = *p++) != 0; ) {
             if (sym == ' ')
                 continue;
             else if (sym == 'A')
@@ -233,6 +249,9 @@ int *menu_on_demand;
                 goto ask_again;
             } else if (sym == 'm') {
                 m_seen = TRUE;
+            } else if (index("uBUCX", sym)) {
+                add_valid_menu_class(sym); /* 'u' or 'B','U','C',or 'X' */
+                filtered = TRUE;
             } else {
                 oc_of_sym = def_char_to_objclass(sym);
                 if (index(ilets, sym)) {
@@ -241,15 +260,10 @@ int *menu_on_demand;
                     oclasses[oclassct] = '\0';
                 } else {
                     if (!where)
-                        where =
 /*JP
-                            !strcmp(action, "pick up")
+                        where = !strcmp(action, "pick up") ? "here"
 */
-                            !strcmp(action, "\8fE\82¤")
-/*JP
-                                ? "here"
-*/
-                                ? "\82±\82±"
+                        where = !strcmp(action, "\8fE\82¤") ? "\82±\82±"
 /*JP
                                 : !strcmp(action, "take out") ? "inside" : "";
 */
@@ -267,9 +281,11 @@ int *menu_on_demand;
                     not_everything = TRUE;
                 }
             }
-        }
+        } /* for p:sym in inbuf */
+
         if (m_seen && menu_on_demand) {
-            *menu_on_demand = (*everything || !oclassct) ? -2 : -3;
+            *menu_on_demand = (((*everything || !oclassct) && !filtered)
+                               ? -2 : -3);
             return FALSE;
         }
         if (!oclassct && (!*everything || not_everything)) {
@@ -371,6 +387,14 @@ struct obj *obj;
 static char valid_menu_classes[MAXOCLASSES + 1 + 4 + 1];
 static boolean class_filter, bucx_filter, shop_filter;
 
+/* check valid_menu_classes[] for an entry; also used by askchain() */
+boolean
+menu_class_present(c)
+int c;
+{
+    return (c && index(valid_menu_classes, c)) ? TRUE : FALSE;
+}
+
 void
 add_valid_menu_class(c)
 int c;
@@ -380,7 +404,7 @@ int c;
     if (c == 0) { /* reset */
         vmc_count = 0;
         class_filter = bucx_filter = shop_filter = FALSE;
-    } else {
+    } else if (!menu_class_present(c)) {
         valid_menu_classes[vmc_count++] = (char) c;
         /* categorize the new class */
         switch (c) {
@@ -422,12 +446,25 @@ boolean
 allow_category(obj)
 struct obj *obj;
 {
-    /* unpaid and BUC checks don't apply to coins */
+    /* For coins, if any class filter is specified, accept if coins
+     * are included regardless of whether either unpaid or BUC-status
+     * is also specified since player has explicitly requested coins.
+     * If no class filtering is specified but bless/curse state is,
+     * coins are either unknown or uncursed based on an option setting.
+     */
     if (obj->oclass == COIN_CLASS)
-        return index(valid_menu_classes, COIN_CLASS) ? TRUE : FALSE;
+        return class_filter
+                 ? (index(valid_menu_classes, COIN_CLASS) ? TRUE : FALSE)
+                 : shop_filter /* coins are never unpaid, but check anyway */
+                    ? (obj->unpaid ? TRUE : FALSE)
+                    : bucx_filter
+                       ? (index(valid_menu_classes, iflags.goldX ? 'X' : 'U')
+                          ? TRUE : FALSE)
+                       : TRUE; /* catchall: no filters specified, so accept */
 
     if (Role_if(PM_PRIEST))
         obj->bknown = TRUE;
+
     /*
      * There are three types of filters possible and the first and
      * third can have more than one entry:
@@ -444,6 +481,7 @@ struct obj *obj;
      * in accepting all scrolls and potions regardless of bless/curse
      * state plus all blessed non-scroll, non-potion objects.)
      */
+
     /* if class is expected but obj's class is not in the list, reject */
     if (class_filter && !index(valid_menu_classes, obj->oclass))
         return FALSE;
@@ -455,8 +493,8 @@ struct obj *obj;
     /* check for particular bless/curse state */
     if (bucx_filter) {
         /* first categorize this object's bless/curse state */
-        char bucx =
-            !obj->bknown ? 'X' : obj->blessed ? 'B' : obj->cursed ? 'C' : 'U';
+        char bucx = !obj->bknown ? 'X'
+                      : obj->blessed ? 'B' : obj->cursed ? 'C' : 'U';
 
         /* if its category is not in the list, reject */
         if (!index(valid_menu_classes, bucx))
@@ -473,11 +511,10 @@ allow_cat_no_uchain(obj)
 struct obj *obj;
 {
     if (obj != uchain
-       && ((index(valid_menu_classes,'u') && obj->unpaid)
+        && ((index(valid_menu_classes, 'u') && obj->unpaid)
             || index(valid_menu_classes, obj->oclass)))
-       return TRUE;
-    else
-       return FALSE;
+        return TRUE;
+    return FALSE;
 }
 #endif
 
@@ -486,8 +523,7 @@ boolean
 is_worn_by_type(otmp)
 register struct obj *otmp;
 {
-    return (boolean) (!!(otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON))
-                      && index(valid_menu_classes, otmp->oclass) != 0);
+    return (is_worn(otmp) && allow_category(otmp)) ? TRUE : FALSE;
 }
 
 /*
@@ -495,9 +531,9 @@ register struct obj *otmp;
  * or a monster's inventory if swallowed.
  *
  * Arg what:
- *     >0  autopickup
- *     =0  interactive
- *     <0  pickup count of something
+ *      >0  autopickup
+ *      =0  interactive
+ *      <0  pickup count of something
  *
  * Returns 1 if tried to pick something up, whether
  * or not it succeeded.
@@ -509,7 +545,7 @@ int what; /* should be a long */
     int i, n, res, count, n_tried = 0, n_picked = 0;
     menu_item *pick_list = (menu_item *) 0;
     boolean autopickup = what > 0;
-    struct obj *objchain;
+    struct obj **objchain_p;
     int traverse_how;
 
     /* we might have arrived here while fainted or sleeping, via
@@ -526,7 +562,8 @@ int what; /* should be a long */
         count = 0;
 
     if (!u.uswallow) {
-        struct trap *ttmp = t_at(u.ux, u.uy);
+        struct trap *ttmp;
+
         /* no auto-pick if no-pick move, nothing there, or in a pool */
         if (autopickup && (context.nopick || !OBJ_AT(u.ux, u.uy)
                            || (is_pool(u.ux, u.uy) && !Underwater)
@@ -534,11 +571,11 @@ int what; /* should be a long */
             read_engr_at(u.ux, u.uy);
             return 0;
         }
-
         /* no pickup if levitating & not on air or water level */
         if (!can_reach_floor(TRUE)) {
             if ((multi && !context.run) || (autopickup && !flags.pickup)
-                || (ttmp && uteetering_at_seen_pit(ttmp)))
+                || ((ttmp = t_at(u.ux, u.uy)) != 0
+                    && uteetering_at_seen_pit(ttmp)))
                 read_engr_at(u.ux, u.uy);
             return 0;
         }
@@ -569,10 +606,10 @@ int what; /* should be a long */
 
     add_valid_menu_class(0); /* reset */
     if (!u.uswallow) {
-        objchain = level.objects[u.ux][u.uy];
+        objchain_p = &level.objects[u.ux][u.uy];
         traverse_how = BY_NEXTHERE;
     } else {
-        objchain = u.ustuck->minvent;
+        objchain_p = &u.ustuck->minvent;
         traverse_how = 0; /* nobj */
     }
     /*
@@ -582,34 +619,38 @@ int what; /* should be a long */
      * to make things less confusing.
      */
     if (autopickup) {
-        n = autopick(objchain, traverse_how, &pick_list);
+        n = autopick(*objchain_p, traverse_how, &pick_list);
         goto menu_pickup;
     }
 
     if (flags.menu_style != MENU_TRADITIONAL || iflags.menu_requested) {
         /* use menus exclusively */
+        traverse_how |= AUTOSELECT_SINGLE | INVORDER_SORT;
         if (count) { /* looking for N of something */
-            char buf[QBUFSZ];
+            char qbuf[QBUFSZ];
+
 /*JP
-            Sprintf(buf, "Pick %d of what?", count);
+            Sprintf(qbuf, "Pick %d of what?", count);
 */
-            Sprintf(buf, "\89½\82ð%d\8cÂ\8fE\82¢\82Ü\82·\82©\81H", count);
+            Sprintf(qbuf, "\89½\82ð%d\8cÂ\8fE\82¢\82Ü\82·\82©\81H", count);
             val_for_n_or_more = count; /* set up callback selector */
-            n = query_objlist(buf, objchain, traverse_how | AUTOSELECT_SINGLE
-                                                 | INVORDER_SORT,
+            n = query_objlist(qbuf, objchain_p, traverse_how,
                               &pick_list, PICK_ONE, n_or_more);
             /* correct counts, if any given */
             for (i = 0; i < n; i++)
                 pick_list[i].count = count;
         } else {
-/*JP
-            n = query_objlist("Pick up what?", objchain,
-*/
-            n = query_objlist("\89½\82ð\8fE\82¢\82Ü\82·\82©\81H", objchain,
-                              traverse_how | AUTOSELECT_SINGLE | INVORDER_SORT
-                                  | FEEL_COCKATRICE,
+#if 0 /*JP*/
+            n = query_objlist("Pick up what?", objchain_p,
+                              (traverse_how | FEEL_COCKATRICE),
                               &pick_list, PICK_ANY, all_but_uchain);
+#else
+            n = query_objlist("\89½\82ð\8fE\82¢\82Ü\82·\82©\81H", objchain_p,
+                              (traverse_how | FEEL_COCKATRICE),
+                              &pick_list, PICK_ANY, all_but_uchain);
+#endif
         }
+
     menu_pickup:
         n_tried = n;
         for (n_picked = i = 0; i < n; i++) {
@@ -626,8 +667,8 @@ int what; /* should be a long */
         /* old style interface */
         int ct = 0;
         long lcount;
-        boolean all_of_a_type, selective;
-        char oclasses[MAXOCLASSES];
+        boolean all_of_a_type, selective, bycat;
+        char oclasses[MAXOCLASSES + 10]; /* +10: room for B,U,C,X plus slop */
         struct obj *obj, *obj2;
 
         oclasses[0] = '\0';   /* types to consider (empty for all) */
@@ -635,13 +676,12 @@ int what; /* should be a long */
         selective = FALSE;    /* ask for each item */
 
         /* check for more than one object */
-        for (obj = objchain; obj;
-             obj = (traverse_how == BY_NEXTHERE) ? obj->nexthere : obj->nobj)
+        for (obj = *objchain_p; obj; obj = FOLLOW(obj, traverse_how))
             ct++;
 
         if (ct == 1 && count) {
             /* if only one thing, then pick it */
-            obj = objchain;
+            obj = *objchain_p;
             lcount = min(obj->quan, (long) count);
             n_tried++;
             if (pickup_object(obj, lcount, FALSE) > 0)
@@ -655,36 +695,46 @@ int what; /* should be a long */
             There("are %s objects here.", (ct <= 10) ? "several" : "many");
 */
             pline("\82±\82±\82É\82Í%s\82à\82Ì\82ª\82 \82é\81D", (ct <= 10) ? "\82¢\82­\82Â\82©" : "\91ò\8eR\82Ì");
+#if 0 /*JP*/
             if (!query_classes(oclasses, &selective, &all_of_a_type,
-/*JP
-                               "pick up", objchain,
-*/
-                               "\8fE\82¤", objchain,
-                               traverse_how == BY_NEXTHERE, &via_menu)) {
+                               "pick up", *objchain_p,
+                               (traverse_how & BY_NEXTHERE) ? TRUE : FALSE,
+                               &via_menu)) {
+#else
+            if (!query_classes(oclasses, &selective, &all_of_a_type,
+                               "\8fE\82¤", *objchain_p,
+                               (traverse_how & BY_NEXTHERE) ? TRUE : FALSE,
+                               &via_menu)) {
+#endif
                 if (!via_menu)
-                    return 0;
-                n = query_objlist(
-/*JP
-                    "Pick up what?", objchain,
-*/
-                    "\89½\82ð\8fE\82¢\82Ü\82·\82©\81H", objchain,
-                    traverse_how | (selective ? 0 : INVORDER_SORT),
-                    &pick_list, PICK_ANY,
-                    via_menu == -2 ? allow_all : allow_category);
+                    goto pickupdone;
+                if (selective)
+                    traverse_how |= INVORDER_SORT;
+#if 0 /*JP*/
+                n = query_objlist("Pick up what?", objchain_p, traverse_how,
+                                  &pick_list, PICK_ANY,
+                                  (via_menu == -2) ? allow_all
+                                                   : allow_category);
+#else
+                n = query_objlist("\89½\82ð\8fE\82¢\82Ü\82·\82©\81H", objchain_p, traverse_how,
+                                  &pick_list, PICK_ANY,
+                                  (via_menu == -2) ? allow_all
+                                                   : allow_category);
+#endif
                 goto menu_pickup;
             }
         }
-
-        for (obj = objchain; obj; obj = obj2) {
-            if (traverse_how == BY_NEXTHERE)
-                obj2 = obj->nexthere; /* perhaps obj will be picked up */
-            else
-                obj2 = obj->nobj;
-            lcount = -1L;
-
-            if (!selective && oclasses[0] && !index(oclasses, obj->oclass))
+        bycat = (menu_class_present('B') || menu_class_present('U')
+                 || menu_class_present('C') || menu_class_present('X'));
+
+        for (obj = *objchain_p; obj; obj = obj2) {
+            obj2 = FOLLOW(obj, traverse_how);
+            if (bycat ? !allow_category(obj)
+                      : (!selective && oclasses[0]
+                         && !index(oclasses, obj->oclass)))
                 continue;
 
+            lcount = -1L;
             if (!all_of_a_type) {
                 char qbuf[BUFSZ];
 
@@ -714,7 +764,7 @@ int what; /* should be a long */
                     lcount = (long) yn_number;
                     if (lcount > obj->quan)
                         lcount = obj->quan;
-                /* fall thru */
+                    /*FALLTHRU*/
                 default: /* 'y' */
                     break;
                 }
@@ -728,7 +778,7 @@ int what; /* should be a long */
             n_picked += res;
         }
     end_query:
-        ; /* semicolon needed by brain-damaged compilers */
+        ; /* statement required after label */
     }
 
     if (!u.uswallow) {
@@ -737,12 +787,14 @@ int what; /* should be a long */
 
         /* position may need updating (invisible hero) */
         if (n_picked)
-            newsym(u.ux, u.uy);
+            newsym_force(u.ux, u.uy);
 
         /* check if there's anything else here after auto-pickup is done */
         if (autopickup)
             check_here(n_picked > 0);
     }
+ pickupdone:
+    add_valid_menu_class(0); /* reset */
     return (n_tried > 0);
 }
 
@@ -754,18 +806,54 @@ boolean grab; /* forced pickup, rather than forced leave behind? */
     /*
      *  Does the text description of this match an exception?
      */
-    char *objdesc = makesingular(doname(obj));
-    struct autopickup_exception *ape =
-        (grab) ? iflags.autopickup_exceptions[AP_GRAB]
-               : iflags.autopickup_exceptions[AP_LEAVE];
-    while (ape) {
-        if (regex_match(objdesc, ape->regex))
-            return TRUE;
-        ape = ape->next;
+    struct autopickup_exception
+        *ape = (grab) ? iflags.autopickup_exceptions[AP_GRAB]
+                      : iflags.autopickup_exceptions[AP_LEAVE];
+
+    if (ape) {
+        char *objdesc = makesingular(doname(obj));
+
+        while (ape) {
+            if (regex_match(objdesc, ape->regex))
+                return TRUE;
+            ape = ape->next;
+        }
     }
     return FALSE;
 }
 
+boolean
+autopick_testobj(otmp, calc_costly)
+struct obj *otmp;
+boolean calc_costly;
+{
+    static boolean costly = FALSE;
+    const char *otypes = flags.pickup_types;
+    boolean pickit;
+
+    /* calculate 'costly' just once for a given autopickup operation */
+    if (calc_costly)
+        costly = (otmp->where == OBJ_FLOOR
+                  && costly_spot(otmp->ox, otmp->oy));
+
+    /* first check: reject if an unpaid item in a shop */
+    if (costly && !otmp->no_charge)
+        return FALSE;
+
+    /* check for pickup_types */
+    pickit = (!*otypes || index(otypes, otmp->oclass));
+    /* check for "always pick up */
+    if (!pickit)
+        pickit = is_autopickup_exception(otmp, TRUE);
+    /* then for "never pick up */
+    if (pickit)
+        pickit = !is_autopickup_exception(otmp, FALSE);
+    /* pickup_thrown overrides pickup_types and exceptions */
+    if (!pickit)
+        pickit = (flags.pickup_thrown && otmp->was_thrown);
+    return pickit;
+}
+
 /*
  * Pick from the given list using flags.pickup_types.  Return the number
  * of items picked (not counts).  Create an array that returns pointers
@@ -782,37 +870,19 @@ menu_item **pick_list; /* list of objects and counts to pick up */
     menu_item *pi; /* pick item */
     struct obj *curr;
     int n;
-    boolean pickit;
-    const char *otypes = flags.pickup_types;
+    boolean check_costly = TRUE;
 
     /* first count the number of eligible items */
     for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) {
-        pickit = (!*otypes || index(otypes, curr->oclass));
-        /* check for "always pick up */
-        if (!pickit)
-            pickit = is_autopickup_exception(curr, TRUE);
-        /* then for "never pick up */
-        if (pickit)
-            pickit = !is_autopickup_exception(curr, FALSE);
-        /* pickup_thrown overrides pickup_types and exceptions */
-        if (!pickit)
-            pickit = (flags.pickup_thrown && curr->was_thrown);
-        /* finally, do we count this object? */
-        if (pickit)
+        if (autopick_testobj(curr, check_costly))
             ++n;
+        check_costly = FALSE; /* only need to check once per autopickup */
     }
 
     if (n) {
-        *pick_list = pi = (menu_item *) alloc(sizeof(menu_item) * n);
+        *pick_list = pi = (menu_item *) alloc(sizeof (menu_item) * n);
         for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) {
-            pickit = (!*otypes || index(otypes, curr->oclass));
-            if (!pickit)
-                pickit = is_autopickup_exception(curr, TRUE);
-            if (pickit)
-                pickit = !is_autopickup_exception(curr, FALSE);
-            if (!pickit)
-                pickit = (flags.pickup_thrown && curr->was_thrown);
-            if (pickit) {
+            if (autopick_testobj(curr, FALSE)) {
                 pi[n].item.a_obj = curr;
                 pi[n].count = curr->quan;
                 n++;
@@ -830,33 +900,34 @@ menu_item **pick_list; /* list of objects and counts to pick up */
  * returned counts are guaranteed to be in bounds and non-zero.
  *
  * Query flags:
- *     BY_NEXTHERE       - Follow object list via nexthere instead of nobj.
- *     AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
- *                         use it.
- *     USE_INVLET        - Use object's invlet.
- *     INVORDER_SORT     - Use hero's pack order.
- *     INCLUDE_HERO      - Showing engulfer's invent; show hero too.
- *     SIGNAL_NOMENU     - Return -1 rather than 0 if nothing passes "allow".
- *     SIGNAL_ESCAPE     - Return -1 rather than 0 if player uses ESC to
- *                         pick nothing.
+ *      BY_NEXTHERE       - Follow object list via nexthere instead of nobj.
+ *      AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
+ *                          use it.
+ *      USE_INVLET        - Use object's invlet.
+ *      INVORDER_SORT     - Use hero's pack order.
+ *      INCLUDE_HERO      - Showing engulfer's invent; show hero too.
+ *      SIGNAL_NOMENU     - Return -1 rather than 0 if nothing passes "allow".
+ *      SIGNAL_ESCAPE     - Return -1 rather than 0 if player uses ESC to
+ *                          pick nothing.
+ *      FEEL_COCKATRICE   - touch corpse.
  */
 int
-query_objlist(qstr, olist, qflags, pick_list, how, allow)
+query_objlist(qstr, olist_p, qflags, pick_list, how, allow)
 const char *qstr;                 /* query string */
-struct obj *olist;                /* the list to pick from */
+struct obj **olist_p;             /* the list to pick from */
 int qflags;                       /* options to control the query */
 menu_item **pick_list;            /* return list of items picked */
 int how;                          /* type of query */
 boolean FDECL((*allow), (OBJ_P)); /* allow function */
 {
-    int i, n, actualn;
+    int i, n;
     winid win;
-    struct obj *curr, *last, fake_hero_object;
-    struct obj **oarray;
+    struct obj *curr, *last, fake_hero_object, *olist = *olist_p;
     char *pack;
     anything any;
-    boolean printed_type_name, sorted = (qflags & INVORDER_SORT) != 0,
-                               engulfer = (qflags & INCLUDE_HERO) != 0;
+    boolean printed_type_name, first,
+            sorted = (qflags & INVORDER_SORT) != 0,
+            engulfer = (qflags & INCLUDE_HERO) != 0;
 
     *pick_list = (menu_item *) 0;
     if (!olist && !engulfer)
@@ -868,7 +939,6 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
             last = curr;
             n++;
         }
-    actualn = n;
     if (engulfer) {
         ++n;
         /* don't autoselect swallowed hero if it's the only choice */
@@ -879,27 +949,26 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
         return (qflags & SIGNAL_NOMENU) ? -1 : 0;
 
     if (n == 1 && (qflags & AUTOSELECT_SINGLE)) {
-        *pick_list = (menu_item *) alloc(sizeof(menu_item));
+        *pick_list = (menu_item *) alloc(sizeof (menu_item));
         (*pick_list)->item.a_obj = last;
         (*pick_list)->count = last->quan;
         return 1;
     }
 
-    oarray = objarr_init(actualn);
-    /* Add objects to the array */
-    i = 0;
-    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
-        if ((*allow)(curr)) {
-            objarr_set(curr, i++, oarray, (flags.sortloot == 'f'
-                                           || (flags.sortloot == 'l'
-                                               && !(qflags & USE_INVLET))));
-        }
+    if (sorted || flags.sortloot != 'n') {
+        sortloot(&olist,
+                 (((flags.sortloot == 'f'
+                    || (flags.sortloot == 'l' && !(qflags & USE_INVLET)))
+                   ? SORTLOOT_LOOT
+                   : (qflags & USE_INVLET) ? SORTLOOT_INVLET : 0)
+                  | (flags.sortpack ? SORTLOOT_PACK : 0)),
+                 (qflags & BY_NEXTHERE) ? TRUE : FALSE);
+        *olist_p = olist;
     }
 
     win = create_nhwindow(NHW_MENU);
     start_menu(win);
     any = zeroany;
-
     /*
      * Run through the list and add the objects to the menu.  If
      * INVORDER_SORT is set, we'll run through the list once for
@@ -907,38 +976,41 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
      * be called once per object in the list.
      */
     pack = flags.inv_order;
+    first = TRUE;
     do {
         printed_type_name = FALSE;
-        for (i = 0; i < actualn; i++) {
-            curr = oarray[i];
+        for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
+            if (sorted && curr->oclass != *pack)
+                continue;
             if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE
                 && will_feel_cockatrice(curr, FALSE)) {
                 destroy_nhwindow(win); /* stop the menu and revert */
                 (void) look_here(0, FALSE);
                 return 0;
             }
-            if ((!sorted || curr->oclass == *pack) && (*allow)(curr)) {
+            if ((*allow)(curr)) {
                 /* if sorting, print type name (once only) */
                 if (sorted && !printed_type_name) {
                     any = zeroany;
                     add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
                              let_to_name(*pack, FALSE,
-                                         (how != PICK_NONE)
-                                             && iflags.menu_head_objsym),
+                                         ((how != PICK_NONE)
+                                          && iflags.menu_head_objsym)),
                              MENU_UNSELECTED);
                     printed_type_name = TRUE;
                 }
 
                 any.a_obj = curr;
                 add_menu(win, obj_to_glyph(curr), &any,
-                         (qflags & USE_INVLET) ? curr->invlet : 0,
+                         (qflags & USE_INVLET) ? curr->invlet
+                           : (first && curr->oclass == COIN_CLASS) ? '$' : 0,
                          def_oc_syms[(int) objects[curr->otyp].oc_class].sym,
                          ATR_NONE, doname_with_price(curr), MENU_UNSELECTED);
+                first = FALSE;
             }
         }
         pack++;
     } while (sorted && *pack);
-    free(oarray);
 
     if (engulfer) {
         char buf[BUFSZ];
@@ -1022,6 +1094,7 @@ int how;               /* type of query */
     boolean collected_type_name;
     char invlet;
     int ccount;
+    boolean FDECL((*ofilter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
     boolean do_unpaid = FALSE;
     boolean do_blessed = FALSE, do_cursed = FALSE, do_uncursed = FALSE,
             do_buc_unknown = FALSE;
@@ -1032,19 +1105,21 @@ int how;               /* type of query */
         return 0;
     if ((qflags & UNPAID_TYPES) && count_unpaid(olist))
         do_unpaid = TRUE;
-    if ((qflags & BUC_BLESSED) && count_buc(olist, BUC_BLESSED)) {
+    if (qflags & WORN_TYPES)
+        ofilter = is_worn;
+    if ((qflags & BUC_BLESSED) && count_buc(olist, BUC_BLESSED, ofilter)) {
         do_blessed = TRUE;
         num_buc_types++;
     }
-    if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED)) {
+    if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED, ofilter)) {
         do_cursed = TRUE;
         num_buc_types++;
     }
-    if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED)) {
+    if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED, ofilter)) {
         do_uncursed = TRUE;
         num_buc_types++;
     }
-    if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN)) {
+    if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN, ofilter)) {
         do_buc_unknown = TRUE;
         num_buc_types++;
     }
@@ -1054,8 +1129,7 @@ int how;               /* type of query */
     if (ccount == 1 && !do_unpaid && num_buc_types <= 1
         && !(qflags & BILLED_TYPES)) {
         for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
-            if ((qflags & WORN_TYPES)
-                && !(curr->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON)))
+            if (ofilter && !(*ofilter)(curr))
                 continue;
             break;
         }
@@ -1072,6 +1146,26 @@ int how;               /* type of query */
     win = create_nhwindow(NHW_MENU);
     start_menu(win);
     pack = flags.inv_order;
+
+    if (qflags & CHOOSE_ALL) {
+        invlet = 'A';
+        any = zeroany;
+        any.a_int = 'A';
+        add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
+/*JP
+                 (qflags & WORN_TYPES) ? "Auto-select every item being worn"
+*/
+                 (qflags & WORN_TYPES) ? "\90g\82É\82Â\82¯\82ç\82ê\82é\95¨\91S\82Ä"
+/*JP
+                                       : "Auto-select every item",
+*/
+                                       : "\91S\82Ä",
+                 MENU_UNSELECTED);
+
+        any = zeroany;
+        add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+    }
+
     if ((qflags & ALL_TYPES) && (ccount > 1)) {
         invlet = 'a';
         any = zeroany;
@@ -1089,8 +1183,7 @@ int how;               /* type of query */
         collected_type_name = FALSE;
         for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
             if (curr->oclass == *pack) {
-                if ((qflags & WORN_TYPES)
-                    && !(curr->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON)))
+                if (ofilter && !(*ofilter)(curr))
                     continue;
                 if (!collected_type_name) {
                     any = zeroany;
@@ -1112,6 +1205,13 @@ int how;               /* type of query */
             return 0;
         }
     } while (*pack);
+
+    if (do_unpaid || (qflags & BILLED_TYPES) || do_blessed || do_cursed
+        || do_uncursed || do_buc_unknown) {
+        any = zeroany;
+        add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+    }
+
     /* unpaid items if there are any */
     if (do_unpaid) {
         invlet = 'u';
@@ -1134,22 +1234,10 @@ int how;               /* type of query */
 */
                  "\96¢\95¥\82Å\8eg\82Á\82Ä\82µ\82Ü\82Á\82½\82à\82Ì", MENU_UNSELECTED);
     }
-    if (qflags & CHOOSE_ALL) {
-        invlet = 'A';
-        any = zeroany;
-        any.a_int = 'A';
-        add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
-/*JP
-                 (qflags & WORN_TYPES) ? "Auto-select every item being worn"
-*/
-                 (qflags & WORN_TYPES) ? "\90g\82É\82Â\82¯\82ç\82ê\82é\95¨\91S\82Ä"
-/*JP
-                                       : "Auto-select every item",
-*/
-                                       : "\91S\82Ä",
-                 MENU_UNSELECTED);
-    }
-    /* items with b/u/c/unknown if there are any */
+
+    /* items with b/u/c/unknown if there are any;
+       this cluster of menu entries is in alphabetical order,
+       reversing the usual sequence of 'U' and 'C' in BUCX */
     if (do_blessed) {
         invlet = 'B';
         any = zeroany;
@@ -1184,11 +1272,13 @@ int how;               /* type of query */
         invlet = 'X';
         any = zeroany;
         any.a_int = 'X';
+#if 0 /*JP*/
+        add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
+                 "Items of unknown Bless/Curse status", MENU_UNSELECTED);
+#else
         add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
-/*JP
-                 "Items of unknown B/C/U status", MENU_UNSELECTED);
-*/
                  "\8fj\95\9f\81^\8eô\82¢\82ª\82í\82©\82ç\82È\82¢\82à\82Ì", MENU_UNSELECTED);
+#endif
     }
     end_menu(win, qstr);
     n = select_menu(win, how, pick_list);
@@ -1309,7 +1399,7 @@ int *wt_before, *wt_after;
          * object and calling weight.
          *
          * This works for containers only because containers
-         * don't merge.                -dean
+         * don't merge.  -dean
          */
         for (qq = 1L; qq <= count; qq++) {
             obj->quan = qq;
@@ -1446,8 +1536,8 @@ boolean telekinesis;
         return -1;
     }
 
-    *cnt_p =
-        carry_count(obj, container, *cnt_p, telekinesis, &old_wt, &new_wt);
+    *cnt_p = carry_count(obj, container, *cnt_p, telekinesis,
+                         &old_wt, &new_wt);
     if (*cnt_p < 1L) {
         result = -1; /* nothing lifted */
     } else if (obj->oclass != COIN_CLASS
@@ -1610,26 +1700,43 @@ struct obj *
 pick_obj(otmp)
 struct obj *otmp;
 {
+    struct obj *result;
+    int ox = otmp->ox, oy = otmp->oy;
+    boolean robshop = (!u.uswallow && otmp != uball && costly_spot(ox, oy));
+
     obj_extract_self(otmp);
-    if (!u.uswallow && otmp != uball && costly_spot(otmp->ox, otmp->oy)) {
+    newsym(ox, oy);
+
+    /* for shop items, addinv() needs to be after addtobill() (so that
+       object merger can take otmp->unpaid into account) but before
+       remote_robbery() (which calls rob_shop() which calls setpaid()
+       after moving costs of unpaid items to shop debt; setpaid()
+       calls clear_unpaid() for lots of object chains, but 'otmp' isn't
+       on any of those between obj_extract_self() and addinv(); for
+       3.6.0, 'otmp' remained flagged as an unpaid item in inventory
+       and triggered impossible() every time inventory was examined) */
+    if (robshop) {
         char saveushops[5], fakeshop[2];
 
         /* addtobill cares about your location rather than the object's;
            usually they'll be the same, but not when using telekinesis
            (if ever implemented) or a grappling hook */
         Strcpy(saveushops, u.ushops);
-        fakeshop[0] = *in_rooms(otmp->ox, otmp->oy, SHOPBASE);
+        fakeshop[0] = *in_rooms(ox, oy, SHOPBASE);
         fakeshop[1] = '\0';
         Strcpy(u.ushops, fakeshop);
         /* sets obj->unpaid if necessary */
         addtobill(otmp, TRUE, FALSE, FALSE);
         Strcpy(u.ushops, saveushops);
-        /* if you're outside the shop, make shk notice */
-        if (!index(u.ushops, *fakeshop))
-            remote_burglary(otmp->ox, otmp->oy);
+        robshop = otmp->unpaid && !index(u.ushops, *fakeshop);
     }
-    newsym(otmp->ox, otmp->oy);
-    return addinv(otmp); /* might merge it with other objects */
+
+    result = addinv(otmp);
+    /* if you're taking a shop item from outside the shop, make shk notice */
+    if (robshop)
+        remote_burglary(ox, oy);
+
+    return result;
 }
 
 /*
@@ -1711,7 +1818,7 @@ encumber_msg()
 }
 
 /* Is there a container at x,y. Optional: return count of containers at x,y */
-STATIC_OVL int
+int
 container_at(x, y, countem)
 int x, y;
 boolean countem;
@@ -1749,12 +1856,12 @@ boolean looting; /* loot vs tip */
     } else if ((is_pool(x, y) && (looting || !Underwater)) || is_lava(x, y)) {
         /* at present, can't loot in water even when Underwater;
            can tip underwater, but not when over--or stuck in--lava */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         You("cannot %s things that are deep in the %s.", verb,
-            is_lava(x, y) ? "lava" : "water");
+            hliquid(is_lava(x, y) ? "lava" : "water"));
 #else
         You("%s\82É\90[\82­\82É\92¾\82ñ\82¾\82à\82Ì\82ð%s\82±\82Æ\82Í\82Å\82«\82È\82¢\81D",
-            is_lava(u.ux, u.uy) ? "\97n\8aâ" : "\90\85", verb);
+            hliquid(is_lava(u.ux, u.uy) ? "\97n\8aâ" : "\90\85"), verb);
 #endif
         return FALSE;
     } else if (nolimbs(youmonst.data)) {
@@ -1779,6 +1886,7 @@ mon_beside(x, y)
 int x, y;
 {
     int i, j, nx, ny;
+
     for (i = -1; i <= 1; i++)
         for (j = -1; j <= 1; j++) {
             nx = x + i;
@@ -1790,19 +1898,27 @@ int x, y;
 }
 
 int
-do_loot_cont(cobjp)
+do_loot_cont(cobjp, cindex, ccount)
 struct obj **cobjp;
+int cindex, ccount; /* index of this container (1..N), number of them (N) */
 {
     struct obj *cobj = *cobjp;
+
     if (!cobj)
         return 0;
     if (cobj->olocked) {
-#if 0 /*JP*/
-        pline("%s locked.",
-              cobj->lknown ? "It is" : "Hmmm, it turns out to be");
+        if (ccount < 2)
+#if 0 /*JP:T*/
+            pline("%s locked.",
+                  cobj->lknown ? "It is" : "Hmmm, it turns out to be");
 #else
-        pline("%s\8c®\82ª\82©\82©\82Á\82Ä\82¢\82é\81D", cobj->lknown ? "" : "\82Þ\81[\82ñ\81C");
+            pline("%s\8c®\82ª\82©\82©\82Á\82Ä\82¢\82é\81D",
+                  cobj->lknown ? "" : "\82Þ\81[\82ñ\81C");
 #endif
+        else if (cobj->lknown)
+            pline("%s is locked.", The(xname(cobj)));
+        else
+            pline("Hmmm, %s turns out to be locked.", the(xname(cobj)));
         cobj->lknown = 1;
         return 0;
     }
@@ -1810,10 +1926,11 @@ struct obj **cobjp;
 
     if (cobj->otyp == BAG_OF_TRICKS) {
         int tmp;
+
 /*JP
-        You("carefully open the bag...");
+        You("carefully open %s...", the(xname(cobj)));
 */
-        You("\90T\8fd\82É\8a\93\82ð\8aJ\82¯\82½\81D\81D\81D");
+        You("\90T\8fd\82É%s\82ð\8aJ\82¯\82½\81D\81D\81D", xname(cobj));
 /*JP
         pline("It develops a huge set of teeth and bites you!");
 */
@@ -1824,6 +1941,7 @@ struct obj **cobjp;
 */
         losehp(Maybe_Half_Phys(tmp), "\90H\93÷\8a\93\82É\8a\9a\82Ü\82ê\82Ä", KILLED_BY_AN);
         makeknown(BAG_OF_TRICKS);
+        abort_looting = TRUE;
         return 1;
     }
 
@@ -1832,7 +1950,7 @@ struct obj **cobjp;
 */
     You("%s%s\82ð\8aJ\82¯\82½\81D\81D\81D", (!cobj->cknown || !cobj->lknown) ? "\90T\8fd\82É" : "",
         the(xname(cobj)));
-    return use_container(cobjp, 0);
+    return use_container(cobjp, 0, (boolean) (cindex < ccount));
 }
 
 /* loot a container on the floor or loot saddle from mon. */
@@ -1851,7 +1969,9 @@ doloot()
     char qbuf[BUFSZ];
     int prev_inquiry = 0;
     boolean prev_loot = FALSE;
-    int num_conts;
+    int num_conts = 0;
+
+    abort_looting = FALSE;
 
     if (check_capacity((char *) 0)) {
         /* "Can't do that while carrying so much stuff." */
@@ -1879,20 +1999,36 @@ doloot()
     cc.x = u.ux;
     cc.y = u.uy;
 
-lootcont:
+    if (iflags.menu_requested)
+        goto lootmon;
 
+ lootcont:
     if ((num_conts = container_at(cc.x, cc.y, TRUE)) > 0) {
         boolean anyfound = FALSE;
 
         if (!able_to_loot(cc.x, cc.y, TRUE))
             return 0;
 
+        if (Blind && !uarmg) {
+            /* if blind and without gloves, attempting to #loot at the
+               location of a cockatrice corpse is fatal before asking
+               whether to manipulate any containers */
+            for (nobj = sobj_at(CORPSE, cc.x, cc.y); nobj;
+                 nobj = nxtobj(nobj, CORPSE, TRUE))
+                if (will_feel_cockatrice(nobj, FALSE)) {
+                    feel_cockatrice(nobj, FALSE);
+                    /* if life-saved (or poly'd into stone golem),
+                       terminate attempt to loot */
+                    return 1;
+                }
+        }
+
         if (num_conts > 1) {
             /* use a menu to loot many containers */
             int n, i;
             winid win;
             anything any;
-            menu_item *pick_list = NULL;
+            menu_item *pick_list = (menu_item *) 0;
 
             any.a_void = 0;
             win = create_nhwindow(NHW_MENU);
@@ -1913,16 +2049,17 @@ lootcont:
             destroy_nhwindow(win);
 
             if (n > 0) {
-                for (i = 0; i < n; i++) {
-                    timepassed |= do_loot_cont(&pick_list[i].item.a_obj);
-                    if (multi < 0 || !pick_list[i].item.a_obj) {
+                for (i = 1; i <= n; i++) {
+                    cobj = pick_list[i - 1].item.a_obj;
+                    timepassed |= do_loot_cont(&cobj, i, n);
+                    if (abort_looting) {
+                        /* chest trap or magic bag explosion or <esc> */
                         free((genericptr_t) pick_list);
-                        return 1;
+                        return timepassed;
                     }
                 }
-            }
-            if (pick_list)
                 free((genericptr_t) pick_list);
+            }
             if (n != 0)
                 c = 'y';
         } else {
@@ -1945,11 +2082,10 @@ lootcont:
                         continue;
                     anyfound = TRUE;
 
-                    timepassed |= do_loot_cont(&cobj);
-                    /* might have triggered chest trap or magic bag explosion
-                     */
-                    if (multi < 0 || !cobj)
-                        return 1;
+                    timepassed |= do_loot_cont(&cobj, 1, 1);
+                    if (abort_looting)
+                        /* chest trap or magic bag explosion or <esc> */
+                        return timepassed;
                 }
             }
             if (anyfound)
@@ -1961,9 +2097,11 @@ lootcont:
 */
         You("\95æ\8dr\82ç\82µ\82ð\82·\82é\82É\82Í\8c@\82ç\82È\82­\82Ä\82Í\81D\81D\81D");
     }
+
     /*
      * 3.3.1 introduced directional looting for some things.
      */
+ lootmon:
     if (c != 'y' && mon_beside(u.ux, u.uy)) {
 /*JP
         if (!get_adjacent_loc("Loot in what direction?",
@@ -2116,8 +2254,8 @@ reverse_loot()
                 boxdummy = zeroobj, boxdummy.otyp = SPE_WIZARD_LOCK;
                 (void) boxlock(coffers, &boxdummy);
             }
-        } else if (levl[x][y].looted != T_LOOTED &&
-                   (mon = makemon(courtmon(), x, y, NO_MM_FLAGS)) != 0) {
+        } else if (levl[x][y].looted != T_LOOTED
+                   && (mon = makemon(courtmon(), x, y, NO_MM_FLAGS)) != 0) {
             freeinv(goldob);
             add_to_minv(mon, goldob);
 /*JP
@@ -2150,20 +2288,24 @@ boolean *prev_loot;
     struct obj *otmp;
     char qbuf[QBUFSZ];
 
-    /* 3.3.1 introduced the ability to remove saddle from a steed */
-    /*         *passed_info is set to TRUE if a loot query was given. */
-    /* *prev_loot is set to TRUE if something was actually acquired in here.
+    /* 3.3.1 introduced the ability to remove saddle from a steed.
+     *  *passed_info is set to TRUE if a loot query was given.
+     *  *prev_loot is set to TRUE if something was actually acquired in here.
      */
     if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) {
         long unwornmask;
+
         if (passed_info)
             *passed_info = 1;
-        Sprintf(
-/*JP
-            qbuf, "Do you want to remove the saddle from %s?",
-*/
-            qbuf, "%s\82©\82ç\88Æ\82ð\82Í\82¸\82µ\82Ü\82·\82©\81H",
-            x_monnam(mtmp, ARTICLE_THE, (char *) 0, SUPPRESS_SADDLE, FALSE));
+#if 0 /*JP*/
+        Sprintf(qbuf, "Do you want to remove the saddle from %s?",
+                x_monnam(mtmp, ARTICLE_THE, (char *) 0,
+                         SUPPRESS_SADDLE, FALSE));
+#else
+        Sprintf(qbuf, "%s\82©\82ç\88Æ\82ð\82Í\82¸\82µ\82Ü\82·\82©\81H",
+                x_monnam(mtmp, ARTICLE_THE, (char *) 0,
+                         SUPPRESS_SADDLE, FALSE));
+#endif
         if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
             if (nolimbs(youmonst.data)) {
 #if 0 /*JP*/
@@ -2178,8 +2320,8 @@ boolean *prev_loot;
                 You("can't.  The saddle seems to be stuck to %s.",
 */
                 pline("\88Æ\82Í%s\82É\82­\82Á\82Â\82¢\82Ä\82¢\82é\82æ\82¤\82¾\81D",
-                    x_monnam(mtmp, ARTICLE_THE, (char *) 0, SUPPRESS_SADDLE,
-                             FALSE));
+                    x_monnam(mtmp, ARTICLE_THE, (char *) 0,
+                             SUPPRESS_SADDLE, FALSE));
                 /* the attempt costs you time */
                 return 1;
             }
@@ -2201,10 +2343,10 @@ boolean *prev_loot;
             return 0;
         }
     }
-    /* 3.4.0 introduced the ability to pick things up from within swallower's
-     * stomach */
+    /* 3.4.0 introduced ability to pick things up from swallower's stomach */
     if (u.uswallow) {
         int count = passed_info ? *passed_info : 0;
+
         timepassed = pickup(count);
     }
     return timepassed;
@@ -2238,6 +2380,28 @@ int depthin;
     return FALSE;
 }
 
+STATIC_OVL long
+boh_loss(container, held)
+struct obj *container;
+int held;
+{
+    /* sometimes toss objects if a cursed magic bag */
+    if (Is_mbag(container) && container->cursed && Has_contents(container)) {
+        long loss = 0L;
+        struct obj *curr, *otmp;
+
+        for (curr = container->cobj; curr; curr = otmp) {
+            otmp = curr->nobj;
+            if (!rn2(13)) {
+                obj_extract_self(curr);
+                loss += mbag_item_gone(held, curr);
+            }
+        }
+        return loss;
+    }
+    return 0;
+}
+
 /* Returns: -1 to stop, 1 item was inserted, 0 item was not inserted. */
 STATIC_PTR int
 in_container(obj)
@@ -2303,16 +2467,16 @@ register struct obj *obj;
             return 0;
         }
         setuwep((struct obj *) 0);
+        /* This uwep check is obsolete.  It dates to 3.0 and earlier when
+         * unwielding Firebrand would be fatal in hell if hero had no other
+         * fire resistance.  Life-saving would force it to be re-wielded.
+         */
         if (uwep)
             return 0; /* unwielded, died, rewielded */
     } else if (obj == uswapwep) {
         setuswapwep((struct obj *) 0);
-        if (uswapwep)
-            return 0; /* unwielded, died, rewielded */
     } else if (obj == uquiver) {
         setuqwep((struct obj *) 0);
-        if (uquiver)
-            return 0; /* unwielded, died, rewielded */
     }
 
     if (fatal_corpse_mistake(obj, FALSE))
@@ -2341,14 +2505,14 @@ register struct obj *obj;
         (void) snuff_lit(obj);
 
     if (floor_container && costly_spot(u.ux, u.uy)) {
-        if (current_container->no_charge && !obj->unpaid) {
-            /* don't sell when putting the item into your own container */
-            obj->no_charge = 1;
-        } else if (obj->oclass != COIN_CLASS) {
-            /* sellobj() will take an unpaid item off the shop bill
-             * note: coins are handled later */
+        /* defer gold until after put-in message */
+        if (obj->oclass != COIN_CLASS) {
+            /* sellobj() will take an unpaid item off the shop bill */
             was_unpaid = obj->unpaid ? TRUE : FALSE;
-            sellobj_state(SELL_DELIBERATE);
+            /* don't sell when putting the item into your own container,
+             * but handle billing correctly */
+            sellobj_state(current_container->no_charge
+                          ? SELL_DONTSELL : SELL_DELIBERATE);
             sellobj(obj, u.ux, u.uy);
             sellobj_state(SELL_NORMAL);
         }
@@ -2358,6 +2522,7 @@ register struct obj *obj;
         /* stop any corpse timeouts when frozen */
         if (obj->otyp == CORPSE && obj->timed) {
             long rot_alarm = stop_timer(ROT_CORPSE, obj_to_any(obj));
+
             (void) stop_timer(REVIVE_MON, obj_to_any(obj));
             /* mark a non-reviving corpse as such */
             if (rot_alarm)
@@ -2407,15 +2572,19 @@ register struct obj *obj;
      * update status immediately.
      */
     bot();
-
     return (current_container ? 1 : -1);
 }
 
+/* askchain() filter used by in_container();
+ * returns True if the container is intact and 'obj' isn't it, False if
+ * container is gone (magic bag explosion) or 'obj' is the container itself;
+ * also used by getobj() when picking a single item to stash
+ */
 int
 ck_bag(obj)
 struct obj *obj;
 {
-    return current_container && obj != current_container;
+    return (current_container && obj != current_container);
 }
 
 /* Returns: -1 to stop, 1 item was removed, 0 item was not removed. */
@@ -2452,12 +2621,8 @@ register struct obj *obj;
     obj_extract_self(obj);
     current_container->owt = weight(current_container);
 
-    if (Icebox && !age_is_relative(obj)) {
-        obj->age = monstermoves - obj->age; /* actual age */
-        if (obj->otyp == CORPSE)
-            start_corpse_timeout(obj);
-    }
-    /* simulated point of time */
+    if (Icebox)
+        removed_from_icebox(obj);
 
     if (!obj->unpaid && !carried(current_container)
         && costly_spot(current_container->ox, current_container->oy)) {
@@ -2470,16 +2635,16 @@ register struct obj *obj;
 
     otmp = addinv(obj);
     loadlev = near_capacity();
-    prinv(loadlev
+    prinv(loadlev ? ((loadlev < MOD_ENCUMBER)
 /*JP
-              ? (loadlev < MOD_ENCUMBER ? "You have a little trouble removing"
+                        ? "You have a little trouble removing"
 */
-              ? (loadlev < MOD_ENCUMBER ? "\82ð\89^\82Ô\82Ì\82Í\8f­\81X\8d¢\93ï\82¾\81D"
+                        ? "\82ð\89^\82Ô\82Ì\82Í\8f­\81X\8d¢\93ï\82¾\81D"
 /*JP
                                         : "You have much trouble removing")
 */
                                         : "\82ð\89^\82Ô\82Ì\82Í\82©\82È\82è\8d¢\93ï\82¾\81D")
-              : (char *) 0,
+                  : (char *) 0,
           otmp, count);
 
     if (is_gold) {
@@ -2488,6 +2653,18 @@ register struct obj *obj;
     return 1;
 }
 
+/* taking a corpse out of an ice box needs a couple of adjustments */
+STATIC_OVL void
+removed_from_icebox(obj)
+struct obj *obj;
+{
+    if (!age_is_relative(obj)) {
+        obj->age = monstermoves - obj->age; /* actual age */
+        if (obj->otyp == CORPSE)
+            start_corpse_timeout(obj);
+    }
+}
+
 /* an object inside a cursed bag of holding is being destroyed */
 STATIC_OVL long
 mbag_item_gone(held, item)
@@ -2556,18 +2733,18 @@ struct obj *box;
             pline("\94 \82Ì\82È\82©\82Ì%s\82Í\82Ü\82¾\90\82«\82Ä\82¢\82é\81I", Monnam(livecat));
         (void) christen_monst(livecat, sc);
     } else {
-        deadcat =
-            mk_named_object(CORPSE, &mons[PM_HOUSECAT], box->ox, box->oy, sc);
+        deadcat = mk_named_object(CORPSE, &mons[PM_HOUSECAT],
+                                  box->ox, box->oy, sc);
         if (deadcat) {
             obj_extract_self(deadcat);
             (void) add_to_container(box, deadcat);
         }
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         pline_The("%s inside the box is dead!",
-                  Hallucination ? rndmonnam(NULL) : "housecat");
+                  Hallucination ? rndmonnam((char *) 0) : "housecat");
 #else
         pline_The("\94 \82Ì\92\86\82Ì%s\82Í\8e\80\82ñ\82Å\82¢\82é\81I",
-                  Hallucination ? rndmonnam(NULL) : "\94L");
+                  Hallucination ? rndmonnam((char *) 0) : "\94L");
 #endif
     }
     box->owt = weight(box);
@@ -2587,23 +2764,36 @@ int FDECL((*fn), (OBJ_P));
 }
 
 STATIC_OVL void
-explain_container_prompt()
+explain_container_prompt(more_containers)
+boolean more_containers;
 {
     static const char *const explaintext[] = {
 #if 0 /*JP*/
-        "Container actions:", "", " : -- Look: examine contents",
-        " o -- Out: take things out", " i -- In: put things in",
+        "Container actions:",
+        "",
+        " : -- Look: examine contents",
+        " o -- Out: take things out",
+        " i -- In: put things in",
         " b -- Both: first take things out, then put things in",
         " r -- Reversed: put things in, then take things out",
-        " s -- Stash: put one item in", " q -- Quit: do nothing",
-        " ? -- Help: display this text.", "", 0
+        " s -- Stash: put one item in", "",
+        " n -- Next: loot next selected container",
+        " q -- Quit: finished",
+        " ? -- Help: display this text.",
+        "", 0
 #else
-        "\93ü\82ê\95¨\82Ö\82Ì\8ds\93®\81F", "", " : -- Look: \92\86\90g\82ð\92²\82×\82é",
-        " o -- Out: \95¨\82ð\8fo\82·", " i -- In: \95¨\82ð\93ü\82ê\82é",
+        "\93ü\82ê\95¨\82Ö\82Ì\8ds\93®\81F",
+        "",
+        " : -- Look: \92\86\90g\82ð\92²\82×\82é",
+        " o -- Out: \95¨\82ð\8fo\82·",
+        " i -- In: \95¨\82ð\93ü\82ê\82é",
         " b -- Both: \82Ü\82¸\95¨\82ð\8fo\82µ\81A\82»\82ê\82©\82ç\95¨\82ð\93ü\82ê\82é",
         " r -- Reversed: \95¨\82ð\93ü\82ê\81A\82»\82ê\82©\82ç\95¨\82ð\8fo\82·",
-        " s -- Stash: \95¨\82ð\88ê\82Â\93ü\82ê\82é", " q -- Quit: \89½\82à\82µ\82È\82¢",
-        " ? -- Help: \82±\82ê\82ð\95\\8e¦\82·\82é", "", 0
+        " s -- Stash: \95¨\82ð\88ê\82Â\93ü\82ê\82é",
+        " n -- Next: \8e\9f\82É\91I\82ñ\82¾\93ü\82ê\95¨\82ð\92²\82×\82é",
+        " q -- Quit: \89½\82à\82µ\82È\82¢",
+        " ? -- Help: \82±\82ê\82ð\95\\8e¦\82·\82é",
+        "", 0
 #endif
     };
     const char *const *txtpp;
@@ -2611,8 +2801,11 @@ explain_container_prompt()
 
     /* "Do what with <container>? [:oibrsq or ?] (q)" */
     if ((win = create_nhwindow(NHW_TEXT)) != WIN_ERR) {
-        for (txtpp = explaintext; *txtpp; ++txtpp)
+        for (txtpp = explaintext; *txtpp; ++txtpp) {
+            if (!more_containers && !strncmp(*txtpp, " n ", 3))
+                continue;
             putstr(win, 0, *txtpp);
+        }
         display_nhwindow(win, FALSE);
         destroy_nhwindow(win);
     }
@@ -2641,16 +2834,19 @@ u_handsy()
 static const char stashable[] = { ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, 0 };
 
 int
-use_container(objp, held)
+use_container(objp, held, more_containers)
 struct obj **objp;
 int held;
+boolean more_containers; /* True iff #loot multiple and this isn't last one */
 {
-    struct obj *curr, *otmp, *obj = *objp;
+    struct obj *otmp, *obj = *objp;
     boolean quantum_cat, cursed_mbag, loot_out, loot_in, loot_in_first,
         stash_one, inokay, outokay, outmaybe;
     char c, emptymsg[BUFSZ], qbuf[QBUFSZ], pbuf[QBUFSZ], xbuf[QBUFSZ];
     int used = 0;
+    long loss;
 
+    abort_looting = FALSE;
     emptymsg[0] = '\0';
 
     if (!u_handsy())
@@ -2685,12 +2881,15 @@ int held;
             multi_reason = "\94 \82ð\8aJ\82¯\82Ä\82¢\82é\8e\9e\82É";
             nomovemsg = "";
         }
+        abort_looting = TRUE;
         return 1;
     }
     obj->lknown = 1;
 
     current_container = obj; /* for use by in/out_container */
-    /* from here on out, all early returns go through containerdone */
+    /*
+     * From here on out, all early returns go through 'containerdone:'.
+     */
 
     /* check for Schroedinger's Cat */
     quantum_cat = SchroedingersBox(current_container);
@@ -2698,21 +2897,13 @@ int held;
         observe_quantum_cat(current_container);
         used = 1;
     }
-    /* sometimes toss objects if a cursed magic bag */
-    cursed_mbag = (Is_mbag(current_container) && current_container->cursed
-                   && Has_contents(current_container));
-    if (cursed_mbag) {
-        long loss = 0L;
 
-        for (curr = current_container->cobj; curr; curr = otmp) {
-            otmp = curr->nobj;
-            if (!rn2(13)) {
-                obj_extract_self(curr);
-                loss += mbag_item_gone(held, curr);
-                used = 1;
-            }
-        }
-        if (loss)
+    cursed_mbag = Is_mbag(current_container)
+        && current_container->cursed
+        && Has_contents(current_container);
+    if (cursed_mbag
+        && (loss = boh_loss(current_container, held)) != 0) {
+        used = 1;
 /*JP
             You("owe %ld %s for lost merchandise.", loss, currency(loss));
 */
@@ -2744,17 +2935,20 @@ int held;
      * inventory is empty--taking out could alter that;
      * include do-both-reversed when 'i' is available,
      * even if container is empty--for similar reason;
-     * always include the quit choice ('q').
+     * include the next container choice ('n') when
+     * relevant, and make it the default;
+     * always include the quit choice ('q'), and make
+     * it the default if there's no next containter;
      * include the help choice (" or ?") if `cmdassist'
      * run-time option is set;
-     * (Player can pick any of (o,i,b,r,s,?) even when
+     * (Player can pick any of (o,i,b,r,n,s,?) even when
      * they're not listed among the available actions.)
      *
-     * Do what with <the/your/Shk's container>? [:oibrsq or ?] (q)
+     * Do what with <the/your/Shk's container>? [:oibrs nq or ?] (q)
      * or
-     * <The/Your/Shk's container> is empty.  Do what with it? [:irsq or ?]
+     * <The/Your/Shk's container> is empty.  Do what with it? [:irs nq or ?]
      */
-    for (;;) { /* repeats if '?' or ":' gets chosen */
+    for (;;) { /* repeats iff '?' or ":' gets chosen */
         outmaybe = (outokay || !current_container->cknown);
         if (!outmaybe)
 #if 0 /*JP*/
@@ -2775,34 +2969,39 @@ int held;
                              yname, ysimple_name, "\82±\82ê");
 #endif
         /* ask player about what to do with this container */
-        if (flags.menu_style == MENU_FULL) {
+        if (flags.menu_style == MENU_PARTIAL
+            || flags.menu_style == MENU_FULL) {
             if (!inokay && !outmaybe) {
                 /* nothing to take out, nothing to put in;
                    trying to do both will yield proper feedback */
                 c = 'b';
             } else {
                 c = in_or_out_menu(qbuf, current_container, outmaybe, inokay,
-                                   (used != 0));
+                                   (boolean) (used != 0), more_containers);
             }
-        } else {               /* TRADITIONAL, COMBINATION, or PARTIAL */
-            xbuf[0] = '\0';    /* list of extra acceptable responses */
-            Strcpy(pbuf, ":"); /* look inside */
+        } else { /* TRADITIONAL or COMBINATION */
+            xbuf[0] = '\0'; /* list of extra acceptable responses */
+            Strcpy(pbuf, ":");                   /* look inside */
             Strcat(outmaybe ? pbuf : xbuf, "o"); /* take out */
             Strcat(inokay ? pbuf : xbuf, "i");   /* put in */
             Strcat(outmaybe ? pbuf : xbuf, "b"); /* both */
             Strcat(inokay ? pbuf : xbuf, "rs");  /* reversed, stash */
+            Strcat(pbuf, " ");                   /* separator */
+            Strcat(more_containers ? pbuf : xbuf, "n"); /* next container */
             Strcat(pbuf, "q");                   /* quit */
             if (iflags.cmdassist)
+                /* this unintentionally allows user to answer with 'o' or
+                   'r'; fortunately, those are already valid choices here */
                 Strcat(pbuf, " or ?"); /* help */
             else
                 Strcat(xbuf, "?");
             if (*xbuf)
                 Strcat(strcat(pbuf, "\033"), xbuf);
-            c = yn_function(qbuf, pbuf, 'q');
-        } /* FULL vs other modes */
+            c = yn_function(qbuf, pbuf, more_containers ? 'n' : 'q');
+        } /* PARTIAL|FULL vs other modes */
 
         if (c == '?') {
-            explain_container_prompt();
+            explain_container_prompt(more_containers);
         } else if (c == ':') { /* note: will set obj->cknown */
             if (!current_container->cknown)
                 used = 1; /* gaining info */
@@ -2811,7 +3010,9 @@ int held;
             break;
     } /* loop until something other than '?' or ':' is picked */
 
-    if (c == 'q') /* [not strictly needed; falling through works] */
+    if (c == 'q')
+        abort_looting = TRUE;
+    if (c == 'n' || c == 'q') /* [not strictly needed; falling thru works] */
         goto containerdone;
     loot_out = (c == 'o' || c == 'b' || c == 'r');
     loot_in = (c == 'i' || c == 'b' || c == 'r');
@@ -2831,6 +3032,7 @@ int held;
                 used |= traditional_loot(FALSE);
             else
                 used |= (menu_loot(0, FALSE) > 0);
+            add_valid_menu_class(0);
         }
     }
 
@@ -2855,6 +3057,7 @@ int held;
             used |= traditional_loot(TRUE);
         else
             used |= (menu_loot(0, TRUE) > 0);
+        add_valid_menu_class(0);
     } else if (stash_one) {
         /* put one item into container */
         if ((otmp = getobj(stashable, "stash")) != 0) {
@@ -2863,11 +3066,7 @@ int held;
             } else {
                 /* couldn't put selected item into container for some
                    reason; might need to undo splitobj() */
-                for (curr = invent; curr; curr = curr->nobj)
-                    if (curr->nobj == otmp)
-                        break;
-                if (curr && curr->invlet == otmp->invlet)
-                    (void) merged(&curr, &otmp);
+                (void) unsplitobj(otmp);
             }
         }
     }
@@ -2888,6 +3087,7 @@ int held;
                 used |= traditional_loot(FALSE);
             else
                 used |= (menu_loot(0, FALSE) > 0);
+            add_valid_menu_class(0);
         }
     }
 
@@ -2903,7 +3103,10 @@ containerdone:
     }
 
     *objp = current_container; /* might have become null */
-    current_container = 0;     /* avoid hanging on to stale pointer */
+    if (current_container)
+        current_container = 0; /* avoid hanging on to stale pointer */
+    else
+        abort_looting = TRUE;
     return used;
 }
 
@@ -2914,7 +3117,7 @@ boolean put_in;
 {
     int FDECL((*actionfunc), (OBJ_P)), FDECL((*checkfunc), (OBJ_P));
     struct obj **objlist;
-    char selection[MAXOCLASSES + 1];
+    char selection[MAXOCLASSES + 10]; /* +10: room for B,U,C,X plus slop */
     const char *action;
     boolean one_by_one, allflag;
     int used = 0, menu_on_request = 0;
@@ -2974,9 +3177,9 @@ boolean put_in;
         Sprintf(buf, "%s what type of objects?", action);
 */
         Sprintf(buf, "\82Ç\82Ì\8eí\97Þ\82Ì\82à\82Ì\82ð%s\81H", action);
-        mflags = put_in
-                     ? ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN
-                     : ALL_TYPES | CHOOSE_ALL | BUC_ALLBKNOWN | BUC_UNKNOWN;
+        mflags = (ALL_TYPES | UNPAID_TYPES | BUCX_TYPES);
+        if (put_in)
+            mflags |= CHOOSE_ALL;
         n = query_category(buf, put_in ? invent : current_container->cobj,
                            mflags, &pick_list, PICK_ANY);
         if (!n)
@@ -3010,7 +3213,7 @@ boolean put_in;
         Sprintf(buf, "%s what?", action);
 */
         Sprintf(buf, "\89½\82ð%s\81H", action);
-        n = query_objlist(buf, put_in ? invent : current_container->cobj,
+        n = query_objlist(buf, put_in ? &invent : &(current_container->cobj),
                           mflags, &pick_list, PICK_ANY,
                           all_categories ? allow_all : allow_category);
         if (n) {
@@ -3042,13 +3245,13 @@ boolean put_in;
 }
 
 STATIC_OVL char
-in_or_out_menu(prompt, obj, outokay, inokay, alreadyused)
+in_or_out_menu(prompt, obj, outokay, inokay, alreadyused, more_containers)
 const char *prompt;
 struct obj *obj;
-boolean outokay, inokay, alreadyused;
+boolean outokay, inokay, alreadyused, more_containers;
 {
     /* underscore is not a choice; it's used to skip element [0] */
-    static const char lootchars[] = "_:oibrsq", abc_chars[] = "_:abcdeq";
+    static const char lootchars[] = "_:oibrsnq", abc_chars[] = "_:abcdenq";
     winid win;
     anything any;
     menu_item *pick_list;
@@ -3113,23 +3316,33 @@ boolean outokay, inokay, alreadyused;
         add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
                  buf, MENU_UNSELECTED);
     }
-    any.a_int = 7; /* 'q' */
+    any.a_int = 0;
+    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+    if (more_containers) {
+        any.a_int = 7; /* 'n' */
+        add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
+                 "loot next container", MENU_SELECTED);
+    }
+    any.a_int = 8; /* 'q' */
 /*JP
     Strcpy(buf, alreadyused ? "done" : "do nothing");
 */
     Strcpy(buf, alreadyused ? "\8fI\82í\82é" : "\89½\82à\82µ\82È\82¢");
     add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE, buf,
-             MENU_SELECTED);
+             more_containers ? MENU_UNSELECTED : MENU_SELECTED);
 
     end_menu(win, prompt);
     n = select_menu(win, PICK_ONE, &pick_list);
     destroy_nhwindow(win);
     if (n > 0) {
-        n = pick_list[0].item.a_int;
+        int k = pick_list[0].item.a_int;
+
+        if (n > 1 && k == (more_containers ? 7 : 8))
+            k = pick_list[1].item.a_int;
         free((genericptr_t) pick_list);
-        return lootchars[n]; /* :,o,i,b,r,s,q */
+        return lootchars[k]; /* :,o,i,b,r,s,n,q */
     }
-    return 'q'; /* quit */
+    return (n == 0 && more_containers) ? 'n' : 'q'; /* next or quit */
 }
 
 static const char tippables[] = { ALL_CLASSES, TOOL_CLASS, 0 };
@@ -3167,7 +3380,7 @@ dotip()
                 int n, i;
                 winid win;
                 anything any;
-                menu_item *pick_list = NULL;
+                menu_item *pick_list = (menu_item *) 0;
                 struct obj dummyobj, *otmp;
 
                 any = zeroany;
@@ -3333,20 +3546,27 @@ tipcontainer(box)
 struct obj *box; /* or bag */
 {
     xchar ox = u.ux, oy = u.uy; /* #tip only works at hero's location */
-    boolean empty_it = FALSE,
-            /* Shop handling:  can't rely on the container's own unpaid
-               or no_charge status because contents might differ with it.
-               A carried container's contents will be flagged as unpaid
-               or not, as appropriate, and need no special handling here.
-               Items owned by the hero get sold to the shop without
-               confirmation as with other uncontrolled drops.  A floor
-               container's contents will be marked no_charge if owned by
-               hero, otherwise they're owned by the shop.  By passing
-               the contents through shop billing, they end up getting
-               treated the same as in the carried case.   We do so one
-               item at a time instead of doing whole container at once
-               to reduce the chance of exhausting shk's billing capacity. */
-        maybeshopgoods = !carried(box) && costly_spot(ox, oy);
+    boolean empty_it = FALSE, maybeshopgoods;
+
+    /* box is either held or on floor at hero's spot; no need to check for
+       nesting; when held, we need to update its location to match hero's;
+       for floor, the coordinate updating is redundant */
+    if (get_obj_location(box, &ox, &oy, 0))
+        box->ox = ox, box->oy = oy;
+
+    /* Shop handling:  can't rely on the container's own unpaid
+       or no_charge status because contents might differ with it.
+       A carried container's contents will be flagged as unpaid
+       or not, as appropriate, and need no special handling here.
+       Items owned by the hero get sold to the shop without
+       confirmation as with other uncontrolled drops.  A floor
+       container's contents will be marked no_charge if owned by
+       hero, otherwise they're owned by the shop.  By passing
+       the contents through shop billing, they end up getting
+       treated the same as in the carried case.   We do so one
+       item at a time instead of doing whole container at once
+       to reduce the chance of exhausting shk's billing capacity. */
+    maybeshopgoods = !carried(box) && costly_spot(box->ox, box->oy);
 
     /* caveat: this assumes that cknown, lknown, olocked, and otrapped
        fields haven't been overloaded to mean something special for the
@@ -3412,7 +3632,7 @@ struct obj *box; /* or bag */
             pline("%sbox is now empty.", Shk_Your(yourbuf, box));
 */
             pline("%s\94 \82Í\8bó\82É\82È\82Á\82½\81D", Shk_Your(yourbuf, box));
-        else /* holds cat corpse or other random stuff */
+        else /* holds cat corpse */
             empty_it = TRUE;
         box->cknown = 1;
     } else if (!Has_contents(box)) {
@@ -3427,7 +3647,7 @@ struct obj *box; /* or bag */
 
     if (empty_it) {
         struct obj *otmp, *nobj;
-        boolean verbose = FALSE, highdrop = !can_reach_floor(TRUE),
+        boolean terse, highdrop = !can_reach_floor(TRUE),
                 altarizing = IS_ALTAR(levl[ox][oy].typ),
                 cursed_mbag = (Is_mbag(box) && box->cursed);
         int held = carried(box);
@@ -3435,11 +3655,17 @@ struct obj *box; /* or bag */
 
         if (u.uswallow)
             highdrop = altarizing = FALSE;
+        terse = !(highdrop || altarizing || costly_spot(box->ox, box->oy));
         box->cknown = 1;
-#if 0 /*JP*/
+        /* Terse formatting is
+         * "Objects spill out: obj1, obj2, obj3, ..., objN."
+         * If any other messages intervene between objects, we revert to
+         * "ObjK drops to the floor.", "ObjL drops to the floor.", &c.
+         */
+#if 0 /*JP:T*/
         pline("%s out%c",
               box->cobj->nobj ? "Objects spill" : "An object spills",
-              !(highdrop || altarizing) ? ':' : '.');
+              terse ? ':' : '.');
 #else
         pline("\92\86\90g\82ª\8fo\82Ä\82«\82½%s",
               !(highdrop || altarizing) ? "\81F" : "\81D");
@@ -3447,10 +3673,14 @@ struct obj *box; /* or bag */
         for (otmp = box->cobj; otmp; otmp = nobj) {
             nobj = otmp->nobj;
             obj_extract_self(otmp);
-            if (cursed_mbag && !rn2(13)) {
+            otmp->ox = box->ox, otmp->oy = box->oy;
+
+            if (box->otyp == ICE_BOX) {
+                removed_from_icebox(otmp); /* resume rotting for corpse */
+            } else if (cursed_mbag && !rn2(13)) {
                 loss += mbag_item_gone(held, otmp);
                 /* abbreviated drop format is no longer appropriate */
-                verbose = TRUE;
+                terse = FALSE;
                 continue;
             }
 
@@ -3463,22 +3693,26 @@ struct obj *box; /* or bag */
                 /* might break or fall down stairs; handles altars itself */
                 hitfloor(otmp);
             } else {
-                if (altarizing)
+                if (altarizing) {
                     doaltarobj(otmp);
-                else if (verbose)
-#if 0 /*JP*/
+                } else if (!terse) {
+#if 0 /*JP:T*/
                     pline("%s %s to the %s.", Doname2(otmp),
                           otense(otmp, "drop"), surface(ox, oy));
 #else
                     pline("%s\82Í%s\82Ì\8fã\82É\97\8e\82¿\82½\81D", Doname2(otmp),
                           surface(ox, oy));
 #endif
-                else
+                } else {
 /*JP
                     pline("%s%c", doname(otmp), nobj ? ',' : '.');
 */
                     pline("%s%s", doname(otmp), nobj ? "\81C" : "\81D");
+                    iflags.last_msg = PLNMSG_OBJNAM_ONLY;
+                }
                 dropy(otmp);
+                if (iflags.last_msg != PLNMSG_OBJNAM_ONLY)
+                    terse = FALSE; /* terse formatting has been interrupted */
             }
             if (maybeshopgoods)
                 iflags.suppress_price--; /* reset */
index 1c0aaa9..20b079f 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 pline.c $NHDT-Date: 1432512770 2015/05/25 00:12:50 $  $NHDT-Branch: master $:$NHDT-Revision: 1.42 $ */
+/* NetHack 3.6 pline.c $NHDT-Date: 1520964541 2018/03/13 18:09:01 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.66 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
                                        */
 #include "hack.h"
 
-static boolean no_repeat = FALSE;
+static unsigned pline_flags = 0;
 static char prevmsg[BUFSZ];
 
 static char *FDECL(You_buf, (int));
+#if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
+static void FDECL(execplinehandler, (const char *));
+#endif
+
+#ifdef DUMPLOG
+/* also used in end.c */
+unsigned saved_pline_index = 0; /* slot in saved_plines[] to use next */
+char *saved_plines[DUMPLOG_MSG_COUNT] = { (char *) 0 };
+
+/* keep the most recent DUMPLOG_MSG_COUNT messages */
+void
+dumplogmsg(line)
+const char *line;
+{
+    /*
+     * TODO:
+     *  This essentially duplicates message history, which is
+     *  currently implemented in an interface-specific manner.
+     *  The core should take responsibility for that and have
+     *  this share it.
+     */
+    unsigned indx = saved_pline_index; /* next slot to use */
+    char *oldest = saved_plines[indx]; /* current content of that slot */
+
+    if (oldest && strlen(oldest) >= strlen(line)) {
+        /* this buffer will gradually shrink until the 'else' is needed;
+           there's no pressing need to track allocation size instead */
+        Strcpy(oldest, line);
+    } else {
+        if (oldest)
+            free((genericptr_t) oldest);
+        saved_plines[indx] = dupstr(line);
+    }
+    saved_pline_index = (indx + 1) % DUMPLOG_MSG_COUNT;
+}
+
+/* called during save (unlike the interface-specific message history,
+   this data isn't saved and restored); end-of-game releases saved_pline[]
+   while writing its contents to the final dump log */
+void
+dumplogfreemessages()
+{
+    unsigned indx;
+
+    for (indx = 0; indx < DUMPLOG_MSG_COUNT; ++indx)
+        if (saved_plines[indx])
+            free((genericptr_t) saved_plines[indx]), saved_plines[indx] = 0;
+    saved_pline_index = 0;
+}
+#endif
 
 /*VARARGS1*/
 /* Note that these declarations rely on knowledge of the internals
@@ -51,9 +102,11 @@ void pline
 VA_DECL(const char *, line)
 #endif /* USE_STDARG | USE_VARARG */
 {       /* start of vpline() or of nested block in USE_OLDARG's pline() */
+    static int in_pline = 0;
     char pbuf[3 * BUFSZ];
     int ln;
-    xchar msgtyp;
+    int msgtyp;
+    boolean no_repeat;
     /* Do NOT use VA_START and VA_END in here... see above */
 
     if (!line || !*line)
@@ -83,27 +136,61 @@ VA_DECL(const char *, line)
         pbuf[BUFSZ - 1] = '\0';
         line = pbuf;
     }
-    if (!iflags.window_inited) {
+
+#ifdef DUMPLOG
+    /* We hook here early to have options-agnostic output.
+     * Unfortunately, that means Norep() isn't honored (general issue) and
+     * that short lines aren't combined into one longer one (tty behavior).
+     */
+    if ((pline_flags & SUPPRESS_HISTORY) == 0)
+        dumplogmsg(line);
+#endif
+    /* use raw_print() if we're called too early (or perhaps too late
+       during shutdown) or if we're being called recursively (probably
+       via debugpline() in the interface code) */
+    if (in_pline++ || !iflags.window_inited) {
+        /* [we should probably be using raw_printf("\n%s", line) here] */
         raw_print(line);
         iflags.last_msg = PLNMSG_UNKNOWN;
-        return;
+        goto pline_done;
     }
-#ifndef MAC
-    if (no_repeat && !strcmp(line, toplines))
-        return;
-#endif /* MAC */
+
+    msgtyp = MSGTYP_NORMAL;
+    no_repeat = (pline_flags & PLINE_NOREPEAT) ? TRUE : FALSE;
+    if ((pline_flags & OVERRIDE_MSGTYPE) == 0) {
+        msgtyp = msgtype_type(line, no_repeat);
+        if (msgtyp == MSGTYP_NOSHOW
+            || (msgtyp == MSGTYP_NOREP && !strcmp(line, prevmsg)))
+            /* FIXME: we need a way to tell our caller that this message
+             * was suppressed so that caller doesn't set iflags.last_msg
+             * for something that hasn't been shown, otherwise a subsequent
+             * message which uses alternate wording based on that would be
+             * doing so out of context and probably end up seeming silly.
+             * (Not an issue for no-repeat but matters for no-show.)
+             */
+            goto pline_done;
+    }
+
     if (vision_full_recalc)
         vision_recalc(0);
     if (u.ux)
         flush_screen(1); /* %% */
-    msgtyp = msgtype_type(line);
-    if (msgtyp == MSGTYP_NOSHOW) return;
-    if (msgtyp == MSGTYP_NOREP && !strcmp(line, prevmsg)) return;
+
     putstr(WIN_MESSAGE, 0, line);
+
+#if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
+    execplinehandler(line);
+#endif
+
     /* this gets cleared after every pline message */
     iflags.last_msg = PLNMSG_UNKNOWN;
-    strncpy(prevmsg, line, BUFSZ);
-    if (msgtyp == MSGTYP_STOP) display_nhwindow(WIN_MESSAGE, TRUE); /* --more-- */
+    (void) strncpy(prevmsg, line, BUFSZ), prevmsg[BUFSZ - 1] = '\0';
+    if (msgtyp == MSGTYP_STOP)
+        display_nhwindow(WIN_MESSAGE, TRUE); /* --more-- */
+
+ pline_done:
+    --in_pline;
+    return;
 
 #if !(defined(USE_STDARG) || defined(USE_VARARGS))
     /* provide closing brace for the nested block
@@ -112,15 +199,31 @@ VA_DECL(const char *, line)
 #endif
 }
 
+/* pline() variant which can override MSGTYPE handling or suppress
+   message history (tty interface uses pline() to issue prompts and
+   they shouldn't be blockable via MSGTYPE=hide) */
+/*VARARGS2*/
+void custompline
+VA_DECL2(unsigned, pflags, const char *, line)
+{
+    VA_START(line);
+    VA_INIT(line, const char *);
+    pline_flags = pflags;
+    vpline(line, VA_ARGS);
+    pline_flags = 0;
+    VA_END();
+    return;
+}
+
 /*VARARGS1*/
 void Norep
 VA_DECL(const char *, line)
 {
     VA_START(line);
     VA_INIT(line, const char *);
-    no_repeat = TRUE;
+    pline_flags = PLINE_NOREPEAT;
     vpline(line, VA_ARGS);
-    no_repeat = FALSE;
+    pline_flags = 0;
     VA_END();
     return;
 }
@@ -397,6 +500,9 @@ VA_DECL(const char *, line)
         pbuf[BUFSZ - 1] = '\0'; /* terminate strncpy or truncate vsprintf */
     }
     raw_print(line);
+#if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
+    execplinehandler(line);
+#endif
 #if !(defined(USE_STDARG) || defined(USE_VARARGS))
     VA_END(); /* (see vpline) */
 #endif
@@ -416,457 +522,57 @@ VA_DECL(const char *, s)
     Vsprintf(pbuf, s, VA_ARGS);
     pbuf[BUFSZ - 1] = '\0'; /* sanity */
     paniclog("impossible", pbuf);
-    pline("%s", pbuf);
-/*JP
-    pline("Program in disorder - perhaps you'd better #quit.");
-*/
-    pline("\83v\83\8d\83O\83\89\83\80\82É\8fá\8aQ\94­\90¶ - #quit\82µ\82½\82Ù\82¤\82ª\82æ\82³\82»\82¤\82¾\81D");
-    program_state.in_impossible = 0;
-    VA_END();
-}
-
-const char *
-align_str(alignment)
-aligntyp alignment;
-{
-    switch ((int) alignment) {
-    case A_CHAOTIC:
-/*JP
-        return "chaotic";
-*/
-        return "\8d¬\93×";
-    case A_NEUTRAL:
-/*JP
-        return "neutral";
-*/
-        return "\92\86\97§";
-    case A_LAWFUL:
-/*JP
-        return "lawful";
-*/
-        return "\92\81\8f\98";
-    case A_NONE:
-/*JP
-        return "unaligned";
-*/
-        return "\96³\90S";
-    }
-/*JP
-    return "unknown";
-*/
-    return "\95s\96¾";
-}
-
-void
-mstatusline(mtmp)
-register struct monst *mtmp;
-{
-    aligntyp alignment = mon_aligntyp(mtmp);
-    char info[BUFSZ], monnambuf[BUFSZ];
-
-    info[0] = 0;
-    if (mtmp->mtame) {
-/*JP
-        Strcat(info, ", tame");
-*/
-        Strcat(info, ", \8e\94\82¢\82È\82ç\82³\82ê\82Ä\82¢\82é");
-        if (wizard) {
-            Sprintf(eos(info), " (%d", mtmp->mtame);
-            if (!mtmp->isminion)
-                Sprintf(eos(info), "; hungry %ld; apport %d",
-                        EDOG(mtmp)->hungrytime, EDOG(mtmp)->apport);
-            Strcat(info, ")");
-        }
-    } else if (mtmp->mpeaceful)
-/*JP
-        Strcat(info, ", peaceful");
-*/
-        Strcat(info, ", \97F\8dD\93I");
-    if (mtmp->cham >= LOW_PM && mtmp->data != &mons[mtmp->cham])
-        /* don't reveal the innate form (chameleon, vampire, &c),
-           just expose the fact that this current form isn't it */
-/*JP
-        Strcat(info, ", shapechanger");
-*/
-        Strcat(info, ", \95Ï\89»");
-      
-    /* pets eating mimic corpses mimic while eating, so this comes first */
-    if (mtmp->meating)
-/*JP
-        Strcat(info, ", eating");
-*/
-        Strcat(info, ", \90H\8e\96\92\86");
-    /* a stethoscope exposes mimic before getting here so this
-       won't be relevant for it, but wand of probing doesn't */
-    if (mtmp->m_ap_type)
-#if 0 /*JP*/
-        Sprintf(eos(info), ", mimicking %s",
-                (mtmp->m_ap_type == M_AP_FURNITURE)
-                    ? an(defsyms[mtmp->mappearance].explanation)
-                    : (mtmp->m_ap_type == M_AP_OBJECT)
-                          ? ((mtmp->mappearance == GOLD_PIECE)
-                                 ? "gold"
-                                 : an(simple_typename(mtmp->mappearance)))
-                          : (mtmp->m_ap_type == M_AP_MONSTER)
-                                ? an(mons[mtmp->mappearance].mname)
-                                : something); /* impossible... */
-#else
-        Sprintf(eos(info), ", %s\82Ì\82Ü\82Ë\82ð\82µ\82Ä\82¢\82é",
-                (mtmp->m_ap_type == M_AP_FURNITURE)
-                    ? an(defsyms[mtmp->mappearance].explanation)
-                    : (mtmp->m_ap_type == M_AP_OBJECT)
-                          ? ((mtmp->mappearance == GOLD_PIECE)
-                                 ? "\8bà\89Ý"
-                                 : an(simple_typename(mtmp->mappearance)))
-                          : (mtmp->m_ap_type == M_AP_MONSTER)
-                                ? an(mons[mtmp->mappearance].mname)
-                                : something); /* impossible... */
-#endif
-    if (mtmp->mcan)
-/*JP
-        Strcat(info, ", cancelled");
-*/
-        Strcat(info, ", \96³\97Í");
-    if (mtmp->mconf)
-/*JP
-        Strcat(info, ", confused");
-*/
-        Strcat(info, ", \8d¬\97\90\8fó\91Ô");
-    if (mtmp->mblinded || !mtmp->mcansee)
-/*JP
-        Strcat(info, ", blind");
-*/
-        Strcat(info, ", \96Ó\96Ú");
-    if (mtmp->mstun)
-/*JP
-        Strcat(info, ", stunned");
-*/
-        Strcat(info, ", \82­\82ç\82­\82ç\8fó\91Ô");
-    if (mtmp->msleeping)
-/*JP
-        Strcat(info, ", asleep");
-*/
-        Strcat(info, ", \90\87\96°\8fó\91Ô");
-#if 0 /* unfortunately mfrozen covers temporary sleep and being busy \
-         (donning armor, for instance) as well as paralysis */
-       else if (mtmp->mfrozen)   Strcat(info, ", paralyzed");
-#else
-    else if (mtmp->mfrozen || !mtmp->mcanmove)
-/*JP
-        Strcat(info, ", can't move");
-*/
-        Strcat(info, ", \93®\82¯\82È\82¢");
-#endif
-    /* [arbitrary reason why it isn't moving] */
-    else if (mtmp->mstrategy & STRAT_WAITMASK)
-/*JP
-        Strcat(info, ", meditating");
-*/
-        Strcat(info, ", \96»\91z\92\86");
-    if (mtmp->mflee)
-/*JP
-        Strcat(info, ", scared");
-*/
-        Strcat(info, ", \8b¯\82¦\82Ä\82¢\82é");
-    if (mtmp->mtrapped)
-/*JP
-        Strcat(info, ", trapped");
-*/
-        Strcat(info, ", ã©\82É\82©\82©\82Á\82Ä\82¢\82é");
-    if (mtmp->mspeed)
-#if 0 /*JP:T*/
-        Strcat(info, mtmp->mspeed == MFAST ? ", fast" : mtmp->mspeed == MSLOW
-                                                            ? ", slow"
-                                                            : ", ???? speed");
-#else
-        Strcat(info, mtmp->mspeed == MFAST ? ", \91f\91\81\82¢" : mtmp->mspeed == MSLOW
-                                                            ? ", \92x\82¢"
-                                                            : ", \91¬\93x\95s\96¾");
-#endif
-    if (mtmp->mundetected)
-/*JP
-        Strcat(info, ", concealed");
-*/
-        Strcat(info, ", \89B\82ê\82Ä\82¢\82é");
-    if (mtmp->minvis)
-/*JP
-        Strcat(info, ", invisible");
-*/
-        Strcat(info, ", \95s\89Â\8e\8b");
-    if (mtmp == u.ustuck)
+    pline("%s", VA_PASS1(pbuf));
 #if 0 /*JP:T*/
-        Strcat(info, sticks(youmonst.data)
-                         ? ", held by you"
-                         : !u.uswallow ? ", holding you"
-                                       : attacktype_fordmg(u.ustuck->data,
-                                                           AT_ENGL, AD_DGST)
-                                             ? ", digesting you"
-                                             : is_animal(u.ustuck->data)
-                                                   ? ", swallowing you"
-                                                   : ", engulfing you");
+    pline(VA_PASS1(
+       "Program in disorder!  (Saving and reloading may fix this problem.)"));
 #else
-      Strcat(info,  sticks(youmonst.data)
-                         ? ", \82 \82È\82½\82ª\92Í\82Ü\82¦\82Ä\82¢\82é"
-                         : !u.uswallow ? ", \92Í\82Ü\82¦\82Ä\82¢\82é"
-                                       : attacktype_fordmg(u.ustuck->data,
-                                                           AT_ENGL, AD_DGST)
-                                             ? ", \8fÁ\89»\82µ\82Ä\82¢\82é"
-                                             : is_animal(u.ustuck->data)
-                                                   ? ", \88ù\82Ý\8d\9e\82ñ\82Å\82¢\82é"
-                                                   : ", \8aª\82«\8d\9e\82ñ\82Å\82¢\82é");
+    pline(VA_PASS1(
+       "\83v\83\8d\83O\83\89\83\80\82É\8fá\8aQ\94­\90\81I (\95Û\91\82µ\82Ä\8dÄ\93Ç\82Ý\8d\9e\82Ý\82·\82ê\82Î\96â\91è\89ð\8c\88\82·\82é\82©\82à\82µ\82ê\82È\82¢\81D)"));
 #endif
-    if (mtmp == u.usteed)
-/*JP
-        Strcat(info, ", carrying you");
-*/
-        Strcat(info, ", \82 \82È\82½\82ð\8fæ\82¹\82Ä\82¢\82é");
-
-    /* avoid "Status of the invisible newt ..., invisible" */
-    /* and unlike a normal mon_nam, use "saddled" even if it has a name */
-    Strcpy(monnambuf, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
-                               (SUPPRESS_IT | SUPPRESS_INVISIBLE), FALSE));
-
-/*JP
-    pline("Status of %s (%s):  Level %d  HP %d(%d)  AC %d%s.", monnambuf,
-*/
-    pline("%s\82Ì\8fó\91Ô (%s)\81F Level %d  HP %d(%d)  AC %d%s", monnambuf,
-          align_str(alignment), mtmp->m_lev, mtmp->mhp, mtmp->mhpmax,
-          find_mac(mtmp), info);
+    program_state.in_impossible = 0;
+    VA_END();
 }
 
-void
-ustatusline()
+#if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
+static boolean use_pline_handler = TRUE;
+static void
+execplinehandler(line)
+const char *line;
 {
-    char info[BUFSZ];
+    int f;
+    const char *args[3];
+    char *env;
 
-    info[0] = '\0';
-    if (Sick) {
-#if 0 /*JP*/
-        Strcat(info, ", dying from");
-        if (u.usick_type & SICK_VOMITABLE)
-            Strcat(info, " food poisoning");
-        if (u.usick_type & SICK_NONVOMITABLE) {
-            if (u.usick_type & SICK_VOMITABLE)
-                Strcat(info, " and");
-            Strcat(info, " illness");
-        }
-#else
-        Strcat(info, ", ");
-        if (u.usick_type & SICK_VOMITABLE)
-            Strcat(info, "\90H\92\86\93Å");
-        if (u.usick_type & SICK_NONVOMITABLE) {
-            if (u.usick_type & SICK_VOMITABLE)
-                Strcat(info, "\82Æ");
-            Strcat(info, "\95a\8bC");
-        }
-        Strcat(info, "\82Å\8e\80\82É\82Â\82Â\82 \82é");
-#endif
-    }
-    if (Stoned)
-/*JP
-        Strcat(info, ", solidifying");
-*/
-        Strcat(info, ", \90Î\89»\82µ\82Â\82Â\82 \82é");
-    if (Slimed)
-/*JP
-        Strcat(info, ", becoming slimy");
-*/
-        Strcat(info, ", \83X\83\89\83C\83\80\82É\82È\82è\82Â\82Â\82 \82é");
-    if (Strangled)
-/*JP
-        Strcat(info, ", being strangled");
-*/
-        Strcat(info, ", \8eñ\82ð\8di\82ß\82ç\82ê\82Ä\82¢\82é");
-    if (Vomiting)
-#if 0 /*JP*/
-        Strcat(info, ", nauseated"); /* !"nauseous" */
-#else
-        Strcat(info, ", \93f\82«\8bC\82ª\82·\82é");
-#endif
-    if (Confusion)
-/*JP
-        Strcat(info, ", confused");
-*/
-        Strcat(info, ", \8d¬\97\90\8fó\91Ô");
-    if (Blind) {
-#if 0 /*JP*/
-        Strcat(info, ", blind");
-        if (u.ucreamed) {
-            if ((long) u.ucreamed < Blinded || Blindfolded
-                || !haseyes(youmonst.data))
-                Strcat(info, ", cover");
-            Strcat(info, "ed by sticky goop");
-        } /* note: "goop" == "glop"; variation is intentional */
-#else
-        Strcat(info, ", ");
-        if (u.ucreamed) {
-            Strcat(info, "\82Ë\82Î\82Ë\82Î\82×\82Æ\82Â\82­\82à\82Ì\82Å");
-            if ((long)u.ucreamed < Blinded || Blindfolded
-                || !haseyes(youmonst.data))
-              Strcat(info, "\95¢\82í\82ê\82Ä");
-        }
-        Strcat(info, "\96Ó\96Ú\8fó\91Ô");
-#endif
-    }
-    if (Stunned)
-/*JP
-        Strcat(info, ", stunned");
-*/
-        Strcat(info, ", \82­\82ç\82­\82ç\8fó\91Ô");
-    if (!u.usteed && Wounded_legs) {
-        const char *what = body_part(LEG);
-        if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
-            what = makeplural(what);
-/*JP
-        Sprintf(eos(info), ", injured %s", what);
-*/
-        Sprintf(eos(info), ", %s\82É\82¯\82ª\82ð\82µ\82Ä\82¢\82é", what);
-    }
-    if (Glib)
-/*JP
-        Sprintf(eos(info), ", slippery %s", makeplural(body_part(HAND)));
-*/
-        Sprintf(eos(info), ", %s\82ª\82Ê\82é\82Ê\82é", makeplural(body_part(HAND)));
-    if (u.utrap)
-/*JP
-        Strcat(info, ", trapped");
-*/
-        Strcat(info, ", ã©\82É\82©\82©\82Á\82Ä\82¢\82é");
-    if (Fast)
-/*JP
-        Strcat(info, Very_fast ? ", very fast" : ", fast");
-*/
-        Strcat(info, Very_fast ? ", \82Æ\82Ä\82à\91f\91\81\82¢" : ", \91f\91\81\82¢");
-    if (u.uundetected)
-/*JP
-        Strcat(info, ", concealed");
-*/
-        Strcat(info, ", \89B\82ê\82Ä\82¢\82é");
-    if (Invis)
-/*JP
-        Strcat(info, ", invisible");
-*/
-        Strcat(info, ", \95s\89Â\8e\8b");
-    if (u.ustuck) {
-#if 0 /*JP*/
-        if (sticks(youmonst.data))
-            Strcat(info, ", holding ");
-        else
-            Strcat(info, ", held by ");
-        Strcat(info, mon_nam(u.ustuck));
-#else
-        Strcat(info, ", ");
-        Strcat(info, mon_nam(u.ustuck));
-        if (sticks(youmonst.data))
-            Strcat(info, "\82ð\92Í\82Ü\82¦\82Ä\82¢\82é");
-        else
-            Strcat(info, "\82É\92Í\82Ü\82¦\82ç\82ê\82Ä\82¢\82é");
-#endif
-    }
-
-/*JP
-    pline("Status of %s (%s%s):  Level %d  HP %d(%d)  AC %d%s.", plname,
-*/
-    pline("%s\82Ì\8fó\91Ô (%s %s)\81F Level %d  HP %d(%d)  AC %d%s", plname,
-          (u.ualign.record >= 20)
-/*JP
-              ? "piously "
-*/
-              ? "\8chåi" 
-              : (u.ualign.record > 13)
-/*JP
-                    ? "devoutly "
-*/
-                    ? "\90M\90S\90[\82¢" 
-                    : (u.ualign.record > 8)
-/*JP
-                          ? "fervently "
-*/
-                          ? "\94M\97ó" 
-                          : (u.ualign.record > 3)
-/*JP
-                                ? "stridently "
-*/
-                                ? "\90º\82Ì\82©\82ñ\8d\82\82¢" 
-                                : (u.ualign.record == 3)
-                                      ? ""
-                                      : (u.ualign.record >= 1)
-/*JP
-                                            ? "haltingly "
-*/
-                                            ? "\97L\96¼\96³\8eÀ" 
-                                            : (u.ualign.record == 0)
-/*JP
-                                                  ? "nominally "
-*/
-                                                  ? "\96À\98f" 
-/*JP
-                                                  : "insufficiently ",
-*/
-                                                  : "\95s\93K\93\96",
-          align_str(u.ualign.type),
-          Upolyd ? mons[u.umonnum].mlevel : u.ulevel, Upolyd ? u.mh : u.uhp,
-          Upolyd ? u.mhmax : u.uhpmax, u.uac, info);
-}
+    if (!use_pline_handler)
+        return;
 
-void
-self_invis_message()
-{
-#if 0 /*JP:T*/
-    pline("%s %s.",
-          Hallucination ? "Far out, man!  You" : "Gee!  All of a sudden, you",
-          See_invisible ? "can see right through yourself"
-                        : "can't see yourself");
-#else
-    pline("%s\82 \82È\82½\82Í%s\81D",
-          Hallucination ? "\83\8f\81[\83I\81I" : "\82°\81I\93Ë\91R",
-          See_invisible ? "\8e©\95ª\8e©\90g\82ª\82¿\82á\82ñ\82Æ\8c©\82¦\82È\82­\82È\82Á\82½"
-                        : "\8e©\95ª\8e©\90g\82ª\8c©\82¦\82È\82­\82È\82Á\82½");
-#endif
-}
+    if (!(env = nh_getenv("NETHACK_MSGHANDLER"))) {
+        use_pline_handler = FALSE;
+        return;
+    }
 
-void
-pudding_merge_message(otmp, otmp2)
-struct obj *otmp;
-struct obj *otmp2;
-{
-    boolean visible =
-        cansee(otmp->ox, otmp->oy) || cansee(otmp2->ox, otmp2->oy);
-    boolean onfloor = otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR;
-    boolean inpack = carried(otmp) || carried(otmp2);
-
-    /* the player will know something happened inside his own inventory */
-    if ((!Blind && visible) || inpack) {
-        if (Hallucination) {
-            if (onfloor) {
-/*JP
-                You_see("parts of the floor melting!");
-*/
-                You_see("\8f°\82Ì\88ê\95\94\82ª\97n\82¯\82Ä\82¢\82é\82Ì\82ð\8c©\82½\81I");
-            } else if (inpack) {
-/*JP
-                Your("pack reaches out and grabs something!");
-*/
-                Your("\82©\82Î\82ñ\82ª\8eè\82ð\90L\82Î\82µ\82Ä\89½\82©\82ð\82Â\82©\82ñ\82¾\81I");
-            }
-            /* even though we can see where they should be,
-             * they'll be out of our view (minvent or container)
-             * so don't actually show anything */
-        } else if (onfloor || inpack) {
-#if 0 /*JP*/
-            pline("The %s coalesce%s.", makeplural(obj_typename(otmp->otyp)),
-                  inpack ? " inside your pack" : "");
-#else
-            pline("%s\82ª%s\8d\87\91Ì\82µ\82½\81D", obj_typename(otmp->otyp),
-                  inpack ? "\82 \82È\82½\82Ì\82©\82Î\82ñ\82Ì\92\86\82Å" : "");
-#endif
-        }
-    } else {
-/*JP
-        You_hear("a faint sloshing sound.");
-*/
-        You_hear("\82©\82·\82©\82È\83o\83V\83\83\83o\83V\83\83\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
+    f = fork();
+    if (f == 0) { /* child */
+        args[0] = env;
+        args[1] = line;
+        args[2] = NULL;
+        (void) setgid(getgid());
+        (void) setuid(getuid());
+        (void) execv(args[0], (char *const *) args);
+        perror((char *) 0);
+        (void) fprintf(stderr, "Exec to message handler %s failed.\n", env);
+        nh_terminate(EXIT_FAILURE);
+    } else if (f > 0) {
+        int status;
+
+        waitpid(f, &status, 0);
+    } else if (f == -1) {
+        perror((char *) 0);
+        use_pline_handler = FALSE;
+        pline("%s", VA_PASS1("Fork to message handler failed."));
     }
 }
+#endif /* defined(POSIX_TYPES) || defined(__GNUC__) */
 
 /*pline.c*/
index 2692853..ca8f308 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 polyself.c      $NHDT-Date: 1448496566 2015/11/26 00:09:26 $  $NHDT-Branch: master $:$NHDT-Revision: 1.104 $ */
+/* NetHack 3.6 polyself.c      $NHDT-Date: 1520797126 2018/03/11 19:38:46 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.117 $ */
 /*      Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -33,7 +33,7 @@ STATIC_DCL void FDECL(drop_weapon, (int));
 STATIC_DCL void NDECL(uunstick);
 STATIC_DCL int FDECL(armor_to_dragon, (int));
 STATIC_DCL void NDECL(newman);
-STATIC_DCL boolean FDECL(polysense, (struct permonst *));
+STATIC_DCL void NDECL(polysense);
 
 STATIC_VAR const char no_longer_petrify_resistant[] =
 /*JP
@@ -50,6 +50,7 @@ void
 set_uasmon()
 {
     struct permonst *mdat = &mons[u.umonnum];
+    int new_speed, old_speed = youmonst.data ? youmonst.data->mmove : 0;
 
     set_mon_data(&youmonst, mdat, 0);
 
@@ -100,12 +101,21 @@ set_uasmon()
     PROPSET(PASSES_WALLS, passes_walls(mdat));
     PROPSET(REGENERATION, regenerates(mdat));
     PROPSET(REFLECTING, (mdat == &mons[PM_SILVER_DRAGON]));
+#undef PROPSET
 
     float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
+    polysense();
 
-#undef PROPSET
+    if (youmonst.movement) {
+        new_speed = mdat->mmove;
+        /* prorate unused movement if new form is slower so that
+           it doesn't get extra moves leftover from previous form;
+           if new form is faster, leave unused movement as is */
+        if (new_speed < old_speed)
+            youmonst.movement = new_speed * youmonst.movement / old_speed;
+    }
 
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
     status_initialize(REASSESS_ONLY);
 #endif
 }
@@ -120,6 +130,7 @@ float_vs_flight()
         BFlying |= I_SPECIAL;
     else
         BFlying &= ~I_SPECIAL;
+    context.botl = TRUE;
 }
 
 /* for changing into form that's immune to strangulation */
@@ -133,6 +144,8 @@ boolean on;
            vulnerable form into another causes the counter to be reset */
         if (uamul && uamul->otyp == AMULET_OF_STRANGULATION
             && can_be_strangled(&youmonst)) {
+            Strangled = 6L;
+            context.botl = TRUE;
 #if 0 /*JP*/
             Your("%s %s your %s!", simpleonames(uamul),
                  Strangled ? "still constricts" : "begins constricting",
@@ -143,7 +156,6 @@ boolean on;
                  body_part(NECK),
                  Strangled ? "\82Ä\82¢\82é" : "\82Í\82\82ß\82½");
 #endif
-            Strangled = 6L;
             makeknown(AMULET_OF_STRANGULATION);
         }
 
@@ -151,6 +163,7 @@ boolean on;
     } else {
         if (Strangled && !can_be_strangled(&youmonst)) {
             Strangled = 0L;
+            context.botl = TRUE;
 /*JP
             You("are no longer being strangled.");
 */
@@ -194,12 +207,7 @@ const char *fmt, *arg;
 
     You(fmt, arg);
     /* check whether player foolishly genocided self while poly'd */
-    if ((mvitals[urole.malenum].mvflags & G_GENOD)
-        || (urole.femalenum != NON_PM
-            && (mvitals[urole.femalenum].mvflags & G_GENOD))
-        || (mvitals[urace.malenum].mvflags & G_GENOD)
-        || (urace.femalenum != NON_PM
-            && (mvitals[urace.femalenum].mvflags & G_GENOD))) {
+    if (ugenocided()) {
         /* intervening activity might have clobbered genocide info */
         struct kinfo *kptr = find_delayed_killer(POLYMORPH);
 
@@ -374,7 +382,6 @@ newman()
             Strcpy(killer.name, "\95Ï\89»\82Ì\8e¸\94s\82Å");
             done(DIED);
             newuhs(FALSE);
-            (void) polysense(youmonst.data);
             return; /* lifesaved */
         }
     }
@@ -384,9 +391,11 @@ newman()
 */
     polyman("%s\82Æ\82µ\82Ä\90\82Ü\82ê\82©\82í\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81I",
             /* use saved gender we're about to revert to, not current */
-            (u.mfemale && urace.individual.f)
+            ((Upolyd ? u.mfemale : flags.female) && urace.individual.f)
                 ? urace.individual.f
-                : (urace.individual.m) ? urace.individual.m : urace.noun);
+                : (urace.individual.m)
+                   ? urace.individual.m
+                   : urace.noun);
     if (Slimed) {
 /*JP
         Your("body transforms, but there is still slime on you.");
@@ -395,7 +404,6 @@ newman()
         make_slimed(10L, (const char *) 0);
     }
 
-    (void) polysense(youmonst.data);
     context.botl = 1;
     see_monsters();
     (void) encumber_msg();
@@ -409,7 +417,7 @@ void
 polyself(psflags)
 int psflags;
 {
-    char buf[BUFSZ];
+    char buf[BUFSZ] = DUMMY;
     int old_light, new_light, mntmp, class, tryct;
     boolean forcecontrol = (psflags == 1), monsterpoly = (psflags == 2),
             draconian = (uarm && Is_dragon_armor(uarm)),
@@ -649,6 +657,7 @@ int
 polymon(mntmp)
 int mntmp;
 {
+    char buf[BUFSZ];
     boolean sticky = sticks(youmonst.data) && u.ustuck && !u.uswallow,
             was_blind = !!Blind, dochange = FALSE;
     int mlvl;
@@ -703,35 +712,28 @@ int mntmp;
         if (sex_change_ok && !rn2(10))
             dochange = TRUE;
     }
+
+#if 0 /*JP*/
+    Strcpy(buf, (u.umonnum != mntmp) ? "" : "new ");
+#else /*\93ú\96{\8cê\82Æ\82µ\82Ä\95s\8e©\91R\82É\82È\82é\82Ì\82Å\88ê\92U\82»\82Ì\82Ü\82Ü\82É\82·\82é*/
+    Strcpy(buf, "");
+#endif
     if (dochange) {
         flags.female = !flags.female;
 #if 0 /*JP*/
-        You("%s %s%s!",
-            (u.umonnum != mntmp) ? "turn into a" : "feel like a new",
-            (is_male(&mons[mntmp]) || is_female(&mons[mntmp]))
-                ? ""
-                : flags.female ? "female " : "male ",
-            mons[mntmp].mname);
+        Strcat(buf, (is_male(&mons[mntmp]) || is_female(&mons[mntmp]))
+                       ? "" : flags.female ? "female " : "male ");
 #else
-        You("%s%s\82É\82È\82Á\82½%s\81I",
-            (is_male(&mons[mntmp]) || is_female(&mons[mntmp]))
-                ? ""
-                : flags.female ? "\8f\97\82Ì" : "\92j\82Ì",
-            mons[mntmp].mname,
-            (u.umonnum != mntmp) ? "" : "\82æ\82¤\82È\8bC\82ª\82µ\82½");
+        Strcat(buf, (is_male(&mons[mntmp]) || is_female(&mons[mntmp]))
+                       ? "" : flags.female ? "\8f\97\82Ì" : "\92j\82Ì");
 #endif
-    } else {
-        if (u.umonnum != mntmp)
-/*JP
-            You("turn into %s!", an(mons[mntmp].mname));
-*/
-            You("%s\82É\82È\82Á\82½\81I", mons[mntmp].mname);
-        else
+    }
+    Strcat(buf, mons[mntmp].mname);
 /*JP
-            You_feel("like a new %s!", mons[mntmp].mname);
+    You("%s %s!", (u.umonnum != mntmp) ? "turn into" : "feel like", an(buf));
 */
-            You("\95Ê\82Ì%s\82É\82È\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81I", mons[mntmp].mname);
-    }
+    You("%s%s\81I", an(buf), (u.umonnum != mntmp) ? "\82É\82È\82Á\82½" : "\82Ì\82æ\82¤\82È\8bC\82ª\82µ\82½");
+
     if (Stoned && poly_when_stoned(&mons[mntmp])) {
         /* poly_when_stoned already checked stone golem genocide */
         mntmp = PM_STONE_GOLEM;
@@ -833,9 +835,7 @@ int mntmp;
         uunstick();
     if (u.usteed) {
         if (touch_petrifies(u.usteed->data) && !Stone_resistance && rnl(3)) {
-            char buf[BUFSZ];
-
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             pline("%s touch %s.", no_longer_petrify_resistant,
                   mon_nam(u.usteed));
 #else
@@ -956,9 +956,9 @@ int mntmp;
                && u.utraptype == TT_LAVA) {
         u.utrap = 0;
 /*JP
-        pline_The("lava now feels soothing.");
+        pline_The("%s now feels soothing.", hliquid("lava"));
 */
-        pline("\97n\8aâ\82ª\90¸\90_\82ð\97\8e\82¿\82Â\82©\82¹\82Ä\82­\82ê\82é\81D");
+        pline_The("%s\82ª\90¸\90_\82ð\97\8e\82¿\82Â\82©\82¹\82Ä\82­\82ê\82é\81D", hliquid("\97n\8aâ"));
     }
     if (amorphous(youmonst.data) || is_whirly(youmonst.data)
         || unsolid(youmonst.data)) {
@@ -998,7 +998,6 @@ int mntmp;
         u.utrap = 0;
     }
     check_strangling(TRUE); /* maybe start strangling */
-    (void) polysense(youmonst.data);
 
     context.botl = 1;
     vision_full_recalc = 1;
@@ -1192,7 +1191,7 @@ int alone;
 #else
     const char *which, *whichtoo;
 #endif
-    boolean candropwep, candropswapwep;
+    boolean candropwep, candropswapwep, updateinv = TRUE;
 
     if (uwep) {
         /* !alone check below is currently superfluous but in the
@@ -1234,17 +1233,26 @@ int alone;
                 You("%s\82ð\97\8e\82Æ\82µ\82½\82±\82Æ\82É\8bC\82Ã\82¢\82½\81I", which);
 #endif
             }
+            /* if either uwep or wielded uswapwep is flagged as 'in_use'
+               then don't drop it or explicitly update inventory; leave
+               those actions to caller (or caller's caller, &c) */
             if (u.twoweap) {
                 otmp = uswapwep;
                 uswapwepgone();
-                if (candropswapwep)
+                if (otmp->in_use)
+                    updateinv = FALSE;
+                else if (candropswapwep)
                     dropx(otmp);
             }
             otmp = uwep;
             uwepgone();
-            if (candropwep)
+            if (otmp->in_use)
+                updateinv = FALSE;
+            else if (candropwep)
                 dropx(otmp);
-            update_inventory();
+
+            if (updateinv)
+                update_inventory();
         } else if (!could_twoweap(youmonst.data)) {
             untwoweapon();
         }
@@ -1255,15 +1263,21 @@ void
 rehumanize()
 {
     /* You can't revert back while unchanging */
-    if (Unchanging && (u.mh < 1)) {
+    if (Unchanging) {
+        if (u.mh < 1) {
 #if 0 /*JP*/
-        killer.format = NO_KILLER_PREFIX;
-        Strcpy(killer.name, "killed while stuck in creature form");
+            killer.format = NO_KILLER_PREFIX;
+            Strcpy(killer.name, "killed while stuck in creature form");
 #else
-        killer.format = KILLED_BY;
-        Strcpy(killer.name, "\8c³\82Ì\8ep\82Ö\96ß\82ê\82¸\82É");
+            killer.format = KILLED_BY;
+            Strcpy(killer.name, "\8c³\82Ì\8ep\82Ö\96ß\82ê\82¸\82É");
 #endif
-        done(DIED);
+            done(DIED);
+        } else if (uamul && uamul->otyp == AMULET_OF_UNCHANGING) {
+            Your("%s %s!", simpleonames(uamul), otense(uamul, "fail"));
+            uamul->dknown = 1;
+            makeknown(AMULET_OF_UNCHANGING);
+        }
     }
 
     if (emits_light(youmonst.data))
@@ -1665,8 +1679,8 @@ dogaze()
 #endif
                     if (yn(qbuf) != 'y')
                         continue;
-                    setmangry(mtmp);
                 }
+                setmangry(mtmp, TRUE);
                 if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleeping
                     || !mtmp->mcansee || !haseyes(mtmp->data)) {
                     looked--;
@@ -1721,11 +1735,13 @@ dogaze()
 
                 if (mtmp->data == &mons[PM_FLOATING_EYE] && !mtmp->mcan) {
                     if (!Free_action) {
-/*JP
+#if 0 /*JP*/
                         You("are frozen by %s gaze!",
-*/
-                        You("%s\82Ì\82É\82ç\82Ý\82Å\93®\82¯\82È\82­\82È\82Á\82½\81I", 
                             s_suffix(mon_nam(mtmp)));
+#else
+                        You("%s\82Ì\82É\82ç\82Ý\82Å\93®\82¯\82È\82­\82È\82Á\82½\81I", 
+                            mon_nam(mtmp));
+#endif
                         nomul((u.ulevel > 6 || rn2(4))
                                   ? -d((int) mtmp->m_lev + 1,
                                        (int) mtmp->data->mattk[0].damd)
@@ -1737,11 +1753,13 @@ dogaze()
                         nomovemsg = 0;
                         return 1;
                     } else
-/*JP
+#if 0 /*JP*/
                         You("stiffen momentarily under %s gaze.",
-*/
-                        You("%s\82Ì\82É\82ç\82Ý\82Å\88ê\8fu\8dd\92¼\82µ\82½\81D",
                             s_suffix(mon_nam(mtmp)));
+#else
+                        You("%s\82Ì\82É\82ç\82Ý\82Å\88ê\8fu\8dd\92¼\82µ\82½\81D",
+                            mon_nam(mtmp));
+#endif
                 }
                 /* Technically this one shouldn't affect you at all because
                  * the Medusa gaze is an active monster attack that only
@@ -1786,20 +1804,21 @@ dohide()
     /* can't hide while being held (or holding) or while trapped
        (except for floor hiders [trapper or mimic] in pits) */
     if (u.ustuck || (u.utrap && (u.utraptype != TT_PIT || on_ceiling))) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         You_cant("hide while you're %s.",
-                 !u.ustuck ? "trapped" : !sticks(youmonst.data)
-                                             ? "being held"
-                                             : humanoid(u.ustuck->data)
-                                                   ? "holding someone"
-                                                   : "holding that creature");
+                 !u.ustuck ? "trapped"
+                   : u.uswallow ? (is_animal(u.ustuck->data) ? "swallowed"
+                                                             : "engulfed")
+                     : !sticks(youmonst.data) ? "being held"
+                       : (humanoid(u.ustuck->data) ? "holding someone"
+                                                   : "holding that creature"));
 #else
         You_cant("%s\8aÔ\82Í\89B\82ê\82ç\82ê\82È\82¢\81D",
-                 !u.ustuck ? "\95ß\82Ü\82Á\82Ä\82¢\82é" : !sticks(youmonst.data)
-                                             ? "\95ß\82Ü\82¦\82ç\82ê\82Ä\82¢\82é"
-                                             : humanoid(u.ustuck->data)
-                                                   ? "\92N\82©\82ð\82Â\82©\82ñ\82Å\82¢\82é"
-                                                   : "\89ö\95¨\82ð\82Â\82©\82ñ\82Å\82¢\82é");
+                 !u.ustuck ? "\95ß\82Ü\82Á\82Ä\82¢\82é"
+                   : u.uswallow ? "\88ù\82Ý\8d\9e\82Ü\82ê\82Ä\82¢\82é"
+                   : !sticks(youmonst.data) ? "\95ß\82Ü\82¦\82ç\82ê\82Ä\82¢\82é"
+                     : humanoid(u.ustuck->data) ? "\92N\82©\82ð\82Â\82©\82ñ\82Å\82¢\82é"
+                                                : "\89ö\95¨\82ð\82Â\82©\82ñ\82Å\82¢\82é");
 #endif
         if (u.uundetected
             || (ismimic && youmonst.m_ap_type != M_AP_NOTHING)) {
@@ -1819,9 +1838,9 @@ dohide()
             The("\90ò\82Í\89B\82ê\82ç\82ê\82é\82Ù\82Ç\90[\82­\82È\82¢\81D");
         else
 /*JP
-            There("is no water to hide in here.");
+            There("is no %s to hide in here.", hliquid("water"));
 */
-            There("\82±\82±\82É\82Í\89B\82ê\82é\82½\82ß\82Ì\90\85\82ª\82È\82¢\81D");
+            There("\82±\82±\82É\82Í\89B\82ê\82é\82½\82ß\82Ì%s\82ª\82È\82¢\81D", hliquid("\90\85"));
         u.uundetected = 0;
         return 0;
     }
@@ -2351,20 +2370,18 @@ int atyp;
     }
 }
 
-/*
- * Some species have awareness of other species
- */
-static boolean
-polysense(mptr)
-struct permonst *mptr;
+/* some species have awareness of other species */
+static void
+polysense()
 {
-    short warnidx = 0;
+    short warnidx = NON_PM;
 
-    context.warntype.speciesidx = 0;
+    context.warntype.speciesidx = NON_PM;
     context.warntype.species = 0;
     context.warntype.polyd = 0;
+    HWarn_of_mon &= ~FROMRACE;
 
-    switch (monsndx(mptr)) {
+    switch (u.umonnum) {
     case PM_PURPLE_WORM:
         warnidx = PM_SHRIEKER;
         break;
@@ -2372,18 +2389,48 @@ struct permonst *mptr;
     case PM_VAMPIRE_LORD:
         context.warntype.polyd = M2_HUMAN | M2_ELF;
         HWarn_of_mon |= FROMRACE;
-        return TRUE;
+        return;
     }
-    if (warnidx) {
+    if (warnidx >= LOW_PM) {
         context.warntype.speciesidx = warnidx;
         context.warntype.species = &mons[warnidx];
         HWarn_of_mon |= FROMRACE;
-        return TRUE;
     }
-    context.warntype.speciesidx = 0;
-    context.warntype.species = 0;
-    HWarn_of_mon &= ~FROMRACE;
-    return FALSE;
+}
+
+/* True iff hero's role or race has been genocided */
+boolean
+ugenocided()
+{
+    return (boolean) ((mvitals[urole.malenum].mvflags & G_GENOD)
+                      || (urole.femalenum != NON_PM
+                          && (mvitals[urole.femalenum].mvflags & G_GENOD))
+                      || (mvitals[urace.malenum].mvflags & G_GENOD)
+                      || (urace.femalenum != NON_PM
+                          && (mvitals[urace.femalenum].mvflags & G_GENOD)));
+}
+
+/* how hero feels "inside" after self-genocide of role or race */
+const char *
+udeadinside()
+{
+    /* self-genocide used to always say "you feel dead inside" but that
+       seems silly when you're polymorphed into something undead;
+       monkilled() distinguishes between living (killed) and non (destroyed)
+       for monster death message; we refine the nonliving aspect a bit */
+#if 0 /*JP*/
+    return !nonliving(youmonst.data)
+             ? "dead"          /* living, including demons */
+             : !weirdnonliving(youmonst.data)
+                 ? "condemned" /* undead plus manes */
+                 : "empty";    /* golems plus vortices */
+#else
+    return !nonliving(youmonst.data)
+             ? "\8e\80\82ñ\82¾"          /* living, including demons */
+             : !weirdnonliving(youmonst.data)
+                 ? "\94j\89ó\82³\82ê\82½" /* undead plus manes */
+                 : "\82È\82­\82È\82Á\82½";    /* golems plus vortices */
+#endif
 }
 
 /*polyself.c*/
index 483ecbd..7c5bbb7 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 potion.c        $NHDT-Date: 1446861768 2015/11/07 02:02:48 $  $NHDT-Branch: master $:$NHDT-Revision: 1.121 $ */
+/* NetHack 3.6 potion.c        $NHDT-Date: 1520797133 2018/03/11 19:38:53 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.144 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -196,12 +197,12 @@ const char *msg;
     if (Unaware)
         msg = 0;
 #endif
-    if ((!xtime && old) || (xtime && !old)) {
+    set_itimeout(&Slimed, xtime);
+    if ((xtime != 0L) ^ (old != 0L)) {
+        context.botl = TRUE;
         if (msg)
             pline1(msg);
-        context.botl = 1;
     }
-    set_itimeout(&Slimed, xtime);
     if (!Slimed)
         dealloc_killer(find_delayed_killer(SLIMED));
 }
@@ -220,12 +221,12 @@ const char *killername;
     if (Unaware)
         msg = 0;
 #endif
-    if ((!xtime && old) || (xtime && !old)) {
+    set_itimeout(&Stoned, xtime);
+    if ((xtime != 0L) ^ (old != 0L)) {
+        context.botl = TRUE;
         if (msg)
             pline1(msg);
-        /* context.botl = 1;   --- Stoned is not a status line item */
     }
-    set_itimeout(&Stoned, xtime);
     if (!Stoned)
         dealloc_killer(find_delayed_killer(STONED));
     else if (!old)
@@ -242,14 +243,14 @@ boolean talk;
     if (Unaware)
         talk = FALSE;
 
+    set_itimeout(&Vomiting, xtime);
+    context.botl = TRUE;
     if (!xtime && old)
         if (talk)
 /*JP
             You_feel("much less nauseated now.");
 */
             You("\93f\82«\8bC\82ª\82¨\82³\82Ü\82Á\82½\81D");
-
-    set_itimeout(&Vomiting, xtime);
 }
 
 /*JP
@@ -360,7 +361,7 @@ boolean talk;
     set_itimeout(&Blinded, xtime);
 
     if (u_could_see ^ can_see_now) { /* one or the other but not both */
-        context.botl = 1;
+        context.botl = TRUE;
         vision_full_recalc = 1; /* blindness just got toggled */
         /* this vision recalculation used to be deferred until
            moveloop(), but that made it possible for vision
@@ -466,7 +467,7 @@ long mask; /* nonzero if resistance status should change by mask */
         (eg. Qt windowport's equipped items display) */
         update_inventory();
 
-        context.botl = 1;
+        context.botl = TRUE;
         if (talk)
             pline(message, verb);
     }
@@ -479,32 +480,36 @@ long xtime;
 boolean talk;
 {
     long old = HDeaf;
-    boolean toggled = FALSE;
 
     if (Unaware)
         talk = FALSE;
 
-    if (!xtime && old) {
-        if (talk)
-/*JP
-            You("can hear again.");
-*/
-            You("\82Ü\82½\95·\82±\82¦\82é\82æ\82¤\82É\82È\82Á\82½\81D");
-        toggled = TRUE;
-    } else if (xtime && !old) {
+    set_itimeout(&HDeaf, xtime);
+    if ((xtime != 0L) ^ (old != 0L)) {
+        context.botl = TRUE;
         if (talk)
 /*JP
-            You("are unable to hear anything.");
+            You(old ? "can hear again." : "are unable to hear anything.");
 */
-            You("\89½\82à\95·\82±\82¦\82È\82­\82È\82Á\82½\81D");
-        toggled = TRUE;
+            You(old ? "\82Ü\82½\95·\82±\82¦\82é\82æ\82¤\82É\82È\82Á\82½\81D" : "\89½\82à\95·\82±\82¦\82È\82­\82È\82Á\82½\81D");
     }
-    /* deafness isn't presently shown on status line, but
-       request a status update in case that changes someday */
-    if (toggled)
-        context.botl = TRUE;
+}
 
-    set_itimeout(&HDeaf, xtime);
+void
+self_invis_message()
+{
+#if 0 /*JP*/
+    pline("%s %s.",
+          Hallucination ? "Far out, man!  You"
+                        : "Gee!  All of a sudden, you",
+          See_invisible ? "can see right through yourself"
+                        : "can't see yourself");
+#else
+    pline("%s\82 \82È\82½\82Í%s\81D",
+          Hallucination ? "\83\8f\81[\83I\81I" : "\82°\81I\93Ë\91R",
+          See_invisible ? "\8e©\95ª\8e©\90g\82ª\82¿\82á\82ñ\82Æ\8c©\82¦\82È\82­\82È\82Á\82½"
+                        : "\8e©\95ª\8e©\90g\82ª\8c©\82¦\82È\82­\82È\82Á\82½");
+#endif
 }
 
 STATIC_OVL void
@@ -710,8 +715,8 @@ register struct obj *otmp;
             i = rn2(A_MAX); /* start at a random point */
             for (ii = 0; ii < A_MAX; ii++) {
                 lim = AMAX(i);
-                if (i == A_STR && u.uhs >= 3)
-                    --lim; /* WEAK */
+                /* this used to adjust 'lim' for A_STR when u.uhs was
+                   WEAK or worse, but that's handled via ATEMP(A_STR) now */
                 if (ABASE(i) < lim) {
                     ABASE(i) = lim;
                     context.botl = 1;
@@ -722,6 +727,18 @@ register struct obj *otmp;
                 if (++i >= A_MAX)
                     i = 0;
             }
+
+            /* when using the potion (not the spell) also restore lost levels,
+               to make the potion more worth keeping around for players with
+               the spell or with a unihorn; this is better than full healing
+               in that it can restore all of them, not just half, and a
+               blessed potion restores them all at once */
+            if (otmp->otyp == POT_RESTORE_ABILITY &&
+                u.ulevel < u.ulevelmax) {
+                do {
+                    pluslvl(FALSE);
+                } while (u.ulevel < u.ulevelmax && otmp->blessed);
+            }
         }
         break;
     case POT_HALLUCINATION:
@@ -734,9 +751,9 @@ register struct obj *otmp;
     case POT_WATER:
         if (!otmp->blessed && !otmp->cursed) {
 /*JP
-            pline("This tastes like water.");
+            pline("This tastes like %s.", hliquid("water"));
 */
-            pline("\90\85\82Ì\82æ\82¤\82È\96¡\82ª\82·\82é\81D");
+            pline("%s\82Ì\82æ\82¤\82È\96¡\82ª\82·\82é\81D", hliquid("\90\85"));
             u.uhunger += rnd(10);
             newuhs(FALSE);
             break;
@@ -746,9 +763,9 @@ register struct obj *otmp;
             || u.ualign.type == A_CHAOTIC) {
             if (otmp->blessed) {
 /*JP
-                pline("This burns like acid!");
+                pline("This burns like %s!", hliquid("acid"));
 */
-                pline("\8e_\82Ì\82æ\82¤\82É\90ã\82ª\82Ð\82è\82Ð\82è\82·\82é\81I");
+                pline("%s\82Ì\82æ\82¤\82É\90ã\82ª\82Ð\82è\82Ð\82è\82·\82é\81I", hliquid("\8e_"));
                 exercise(A_CON, FALSE);
                 if (u.ulycn >= LOW_PM) {
 /*JP
@@ -758,7 +775,7 @@ register struct obj *otmp;
                          makeplural(mons[u.ulycn].mname));
                     if (youmonst.data == &mons[u.ulycn])
                         you_unwere(FALSE);
-                    u.ulycn = NON_PM; /* cure lycanthropy */
+                    set_ulycn(NON_PM); /* cure lycanthropy */
                 }
 /*JP
                 losehp(Maybe_Half_Phys(d(2, 6)), "potion of holy water",
@@ -790,9 +807,9 @@ register struct obj *otmp;
             } else {
                 if (u.ualign.type == A_LAWFUL) {
 /*JP
-                    pline("This burns like acid!");
+                    pline("This burns like %s!", hliquid("acid"));
 */
-                    pline("\8e_\82Ì\82æ\82¤\82É\90ã\82ª\82Ð\82è\82Ð\82è\82·\82é\81I");
+                    pline("%s\82Ì\82æ\82¤\82É\90ã\82ª\82Ð\82è\82Ð\82è\82·\82é\81I", hliquid("\8e_"));
 /*JP
                     losehp(Maybe_Half_Phys(d(2, 6)), "potion of unholy water",
 */
@@ -1265,47 +1282,67 @@ register struct obj *otmp;
         break;
     case POT_LEVITATION:
     case SPE_LEVITATION:
-        if (otmp->cursed)
-            HLevitation &= ~I_SPECIAL;
+        /*
+         * BLevitation will be set if levitation is blocked due to being
+         * inside rock (currently or formerly in phazing xorn form, perhaps)
+         * but it doesn't prevent setting or incrementing Levitation timeout
+         * (which will take effect after escaping from the rock if it hasn't
+         * expired by then).
+         */
         if (!Levitation && !BLevitation) {
             /* kludge to ensure proper operation of float_up() */
             set_itimeout(&HLevitation, 1L);
             float_up();
-            /* reverse kludge */
-            set_itimeout(&HLevitation, 0L);
-            if (otmp->cursed) {
-                if ((u.ux == xupstair && u.uy == yupstair)
-                    || (sstairs.up && u.ux == sstairs.sx
-                        && u.uy == sstairs.sy)
-                    || (xupladder && u.ux == xupladder
-                        && u.uy == yupladder)) {
-                    (void) doup();
-                } else if (has_ceiling(&u.uz)) {
-                    int dmg = uarmh ? 1 : rnd(10);
+            /* This used to set timeout back to 0, then increment it below
+               for blessed and uncursed effects.  But now we leave it so
+               that cursed effect yields "you float down" on next turn.
+               Blessed and uncursed get one extra turn duration. */
+        } else /* already levitating, or can't levitate */
+            nothing++;
 
-#if 0 /*JP*/
-                    You("hit your %s on the %s.", body_part(HEAD),
-                        ceiling(u.ux, u.uy));
+        if (otmp->cursed) {
+            /* 'already levitating' used to block the cursed effect(s)
+               aside from ~I_SPECIAL; it was not clear whether that was
+               intentional; either way, it no longer does (as of 3.6.1) */
+            HLevitation &= ~I_SPECIAL; /* can't descend upon demand */
+            if (BLevitation) {
+                ; /* rising via levitation is blocked */
+            } else if ((u.ux == xupstair && u.uy == yupstair)
+                    || (sstairs.up && u.ux == sstairs.sx && u.uy == sstairs.sy)
+                    || (xupladder && u.ux == xupladder && u.uy == yupladder)) {
+                (void) doup();
+                /* in case we're already Levitating, which would have
+                   resulted in incrementing 'nothing' */
+                nothing = 0; /* not nothing after all */
+            } else if (has_ceiling(&u.uz)) {
+                int dmg = rnd(!uarmh ? 10 : !is_metallic(uarmh) ? 6 : 3);
+
+#if 0 /*JP:T*/
+                You("hit your %s on the %s.", body_part(HEAD),
+                    ceiling(u.ux, u.uy));
 #else
-                    You("%s\82ð%s\82É\82Ô\82Â\82¯\82½\81D", body_part(HEAD),
-                        ceiling(u.ux,u.uy));
+                You("%s\82ð%s\82É\82Ô\82Â\82¯\82½\81D", body_part(HEAD),
+                    ceiling(u.ux,u.uy));
 #endif
 /*JP
                     losehp(Maybe_Half_Phys(dmg), "colliding with the ceiling",
 */
                     losehp(Maybe_Half_Phys(dmg), "\93V\88ä\82É\93ª\82ð\82Ô\82Â\82¯\82Ä",
-                           KILLED_BY);
-                }
-            } /*cursed*/
-        } else
-            nothing++;
-        if (otmp->blessed) {
+                       KILLED_BY);
+                nothing = 0; /* not nothing after all */
+            }
+        } else if (otmp->blessed) {
+            /* at this point, timeout is already at least 1 */
             incr_itimeout(&HLevitation, rn1(50, 250));
+            /* can descend at will (stop levitating via '>') provided timeout
+               is the only factor (ie, not also wearing Lev ring or boots) */
             HLevitation |= I_SPECIAL;
-        } else
+        } else /* timeout is already at least 1 */
             incr_itimeout(&HLevitation, rn1(140, 10));
-        if (Levitation)
-            spoteffects(FALSE); /* for sinks */
+
+        if (Levitation && IS_SINK(levl[u.ux][u.uy].typ))
+            spoteffects(FALSE);
+        /* levitating blocks flying */
         float_vs_flight();
         break;
     case POT_GAIN_ENERGY: { /* M. Stephenson */
@@ -1460,8 +1497,12 @@ register boolean curesick, cureblind;
                 u.uhp = (u.uhpmax += nxtra);
         }
     }
-    if (cureblind)
+    if (cureblind) {
+        /* 3.6.1: it's debatible whether healing magic should clean off
+           mundane 'dirt', but if it doesn't, blindness isn't cured */
+        u.ucreamed = 0;
         make_blinded(0L, TRUE);
+    }
     if (curesick) {
         make_vomiting(0L, TRUE);
         make_sick(0L, (char *) 0, TRUE, SICK_ALL);
@@ -1601,32 +1642,39 @@ const char *objphrase; /* "Your widget glows" or "Steed's saddle glows" */
     return res;
 }
 
+/* potion obj hits monster mon, which might be youmonst; obj always used up */
 void
-potionhit(mon, obj, your_fault)
-register struct monst *mon;
-register struct obj *obj;
-boolean your_fault;
+potionhit(mon, obj, how)
+struct monst *mon;
+struct obj *obj;
+int how;
 {
     const char *botlnam = bottlename();
     boolean isyou = (mon == &youmonst);
-    int distance;
+    int distance, tx, ty;
     struct obj *saddle = (struct obj *) 0;
-    boolean hit_saddle = FALSE;
+    boolean hit_saddle = FALSE, your_fault = (how <= POTHIT_HERO_THROW);
 
     if (isyou) {
+        tx = u.ux, ty = u.uy;
         distance = 0;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         pline_The("%s crashes on your %s and breaks into shards.", botlnam,
                   body_part(HEAD));
 #else
         pline("%s\82ª\82 \82È\82½\82Ì%s\82Ì\8fã\82Å\89ó\82ê\94j\95Ð\82Æ\82È\82Á\82½\81D", botlnam,
-              body_part(HEAD));
+                  body_part(HEAD));
 #endif
-/*JP
-        losehp(Maybe_Half_Phys(rnd(2)), "thrown potion", KILLED_BY_AN);
-*/
+#if 0 /*JP*/
+        losehp(Maybe_Half_Phys(rnd(2)),
+               (how == POTHIT_OTHER_THROW) ? "propelled potion" /* scatter */
+                                           : "thrown potion",
+               KILLED_BY_AN);
+#else /*\82Ç\82¿\82ç\82à\81u\93\8a\82°\82ç\82ê\82½\81v\82Å\82æ\82¢*/
         losehp(Maybe_Half_Phys(rnd(2)), "\93\8a\82°\82ç\82ê\82½\96ò\82Å", KILLED_BY_AN);
+#endif
     } else {
+        tx = mon->mx, ty = mon->my;
         /* sometimes it hits the saddle */
         if (((mon->misc_worn_check & W_SADDLE)
              && (saddle = which_armor(mon, W_SADDLE)))
@@ -1635,30 +1683,34 @@ boolean your_fault;
                     && ((rnl(10) > 7 && obj->cursed)
                         || (rnl(10) < 4 && obj->blessed) || !rn2(3)))))
             hit_saddle = TRUE;
-        distance = distu(mon->mx, mon->my);
-        if (!cansee(mon->mx, mon->my))
+        distance = distu(tx, ty);
+        if (!cansee(tx, ty)) {
 /*JP
             pline("Crash!");
 */
             pline("\83K\83V\83\83\83\93\81I");
-        else {
+        else {
             char *mnam = mon_nam(mon);
             char buf[BUFSZ];
 
             if (hit_saddle && saddle) {
-/*JP
+#if 0 /*JP*/
                 Sprintf(buf, "%s saddle",
-*/
-                Sprintf(buf, "%s\82Ì\88Æ",
                         s_suffix(x_monnam(mon, ARTICLE_THE, (char *) 0,
                                           (SUPPRESS_IT | SUPPRESS_SADDLE),
                                           FALSE)));
+#else
+                Sprintf(buf, "%s\82Ì\88Æ",
+                        x_monnam(mon, ARTICLE_THE, (char *) 0,
+                                          (SUPPRESS_IT | SUPPRESS_SADDLE),
+                                          FALSE));
+#endif
             } else if (has_head(mon->data)) {
 #if 0 /*JP*/
                 Sprintf(buf, "%s %s", s_suffix(mnam),
                         (notonhead ? "body" : "head"));
 #else
-                Sprintf(buf, "%s\82Ì%s", s_suffix(mnam),
+                Sprintf(buf, "%s\82Ì%s", mnam,
                         (notonhead ? "\91Ì" : "\93ª"));
 #endif
             } else {
@@ -1677,7 +1729,7 @@ boolean your_fault;
     }
 
     /* oil doesn't instantly evaporate; Neither does a saddle hit */
-    if (obj->otyp != POT_OIL && !hit_saddle && cansee(mon->mx, mon->my))
+    if (obj->otyp != POT_OIL && !hit_saddle && cansee(tx, ty))
 /*JP
         pline("%s.", Tobjnam(obj, "evaporate"));
 */
@@ -1700,7 +1752,8 @@ boolean your_fault;
         case POT_ACID:
             if (!Acid_resistance) {
                 int dmg;
-#if 0 /*JP*/
+
+#if 0 /*JP:T*/
                 pline("This burns%s!",
                       obj->blessed ? " a little"
                                    : obj->cursed ? " a lot" : "");
@@ -1720,7 +1773,7 @@ boolean your_fault;
     } else if (hit_saddle && saddle) {
         char *mnam, buf[BUFSZ], saddle_glows[BUFSZ];
         boolean affected = FALSE;
-        boolean useeit = !Blind && canseemon(mon) && cansee(mon->mx, mon->my);
+        boolean useeit = !Blind && canseemon(mon) && cansee(tx, ty);
 
         mnam = x_monnam(mon, ARTICLE_THE, (char *) 0,
                         (SUPPRESS_IT | SUPPRESS_SADDLE), FALSE);
@@ -1744,17 +1797,22 @@ boolean your_fault;
 */
             pline("%s\82Í\94G\82ê\82½\81D", buf);
     } else {
-        boolean angermon = TRUE;
+        boolean angermon = your_fault, cureblind = FALSE;
 
-        if (!your_fault)
-            angermon = FALSE;
         switch (obj->otyp) {
-        case POT_HEALING:
-        case POT_EXTRA_HEALING:
         case POT_FULL_HEALING:
+            cureblind = TRUE;
+            /*FALLTHRU*/
+        case POT_EXTRA_HEALING:
+            if (!obj->cursed)
+                cureblind = TRUE;
+            /*FALLTHRU*/
+        case POT_HEALING:
+            if (obj->blessed)
+                cureblind = TRUE;
             if (mon->data == &mons[PM_PESTILENCE])
                 goto do_illness;
-        /*FALLTHRU*/
+            /*FALLTHRU*/
         case POT_RESTORE_ABILITY:
         case POT_GAIN_ABILITY:
         do_healing:
@@ -1767,6 +1825,8 @@ boolean your_fault;
 */
                     pline("%s\82Í\8c³\8bC\82É\82È\82Á\82½\82æ\82¤\82É\8c©\82¦\82é\81D", Monnam(mon));
             }
+            if (cureblind)
+                mcureblindness(mon, canseemon(mon));
             break;
         case POT_SICKNESS:
             if (mon->data == &mons[PM_PESTILENCE])
@@ -1802,10 +1862,15 @@ boolean your_fault;
             if (!resist(mon, POTION_CLASS, 0, NOTELL))
                 mon->mconf = TRUE;
             break;
-        case POT_INVISIBILITY:
+        case POT_INVISIBILITY: {
+            boolean sawit = canspotmon(mon);
+
             angermon = FALSE;
             mon_set_minvis(mon);
+            if (sawit && !canspotmon(mon) && cansee(mon->mx, mon->my))
+                map_invisible(mon->mx, mon->my);
             break;
+        }
         case POT_SLEEPING:
             /* wakeup() doesn't rouse victims of temporary sleep */
             if (sleep_monst(mon, rnd(12), POTION_CLASS)) {
@@ -1830,7 +1895,7 @@ boolean your_fault;
             break;
         case POT_BLINDNESS:
             if (haseyes(mon->data)) {
-                register int btmp = 64 + rn2(32)
+                int btmp = 64 + rn2(32)
                             + rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL);
 
                 btmp += mon->mblinded;
@@ -1850,7 +1915,7 @@ boolean your_fault;
                           is_silent(mon->data) ? "\82É\90g\82à\82¾\82¦\82µ\82½" : "\82Ì\8b©\82Ñ\90º\82ð\82 \82°\82½");
 #endif
                     if (!is_silent(mon->data))
-                        wake_nearto(mon->mx, mon->my, mon->data->mlevel * 10);
+                        wake_nearto(tx, ty, mon->data->mlevel * 10);
                     mon->mhp -= d(2, 6);
                     /* should only be by you */
                     if (mon->mhp < 1)
@@ -1888,7 +1953,7 @@ boolean your_fault;
             break;
         case POT_OIL:
             if (obj->lamplit)
-                explode_oil(obj, mon->mx, mon->my);
+                explode_oil(obj, tx, ty);
             break;
         case POT_ACID:
             if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) {
@@ -1900,7 +1965,7 @@ boolean your_fault;
                       is_silent(mon->data) ? "\82É\90g\82à\82¾\82¦\82µ\82½" : "\82Ì\8b©\82Ñ\90º\82ð\82 \82°\82½");
 #endif
                 if (!is_silent(mon->data))
-                    wake_nearto(mon->mx, mon->my, mon->data->mlevel * 10);
+                    wake_nearto(tx, ty, mon->data->mlevel * 10);
                 mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8);
                 if (mon->mhp < 1) {
                     if (your_fault)
@@ -1922,27 +1987,36 @@ boolean your_fault;
             break;
         */
         }
-        if (angermon)
-            wakeup(mon);
-        else
-            mon->msleeping = 0;
+        /* target might have been killed */
+        if (mon->mhp > 0) {
+            if (angermon)
+                wakeup(mon, TRUE);
+            else
+                mon->msleeping = 0;
+        }
     }
 
     /* Note: potionbreathe() does its own docall() */
-    if ((distance == 0 || ((distance < 3) && rn2(5)))
+    if ((distance == 0 || (distance < 3 && rn2(5)))
         && (!breathless(youmonst.data) || haseyes(youmonst.data)))
         potionbreathe(obj);
     else if (obj->dknown && !objects[obj->otyp].oc_name_known
-             && !objects[obj->otyp].oc_uname && cansee(mon->mx, mon->my))
+             && !objects[obj->otyp].oc_uname && cansee(tx, ty))
         docall(obj);
+
     if (*u.ushops && obj->unpaid) {
         struct monst *shkp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
 
-        if (shkp)
+        /* neither of the first two cases should be able to happen;
+           only the hero should ever have an unpaid item, and only
+           when inside a tended shop */
+        if (!shkp) /* if shkp was killed, unpaid ought to cleared already */
+            obj->unpaid = 0;
+        else if (context.mon_moving) /* obj thrown by monster */
+            subfrombill(obj, shkp);
+        else /* obj thrown by hero */
             (void) stolen_value(obj, u.ux, u.uy, (boolean) shkp->mpeaceful,
                                 FALSE);
-        else
-            obj->unpaid = 0;
     }
     obfree(obj, (struct obj *) 0);
 }
@@ -1952,7 +2026,13 @@ void
 potionbreathe(obj)
 register struct obj *obj;
 {
-    register int i, ii, isdone, kn = 0;
+    int i, ii, isdone, kn = 0;
+    boolean cureblind = FALSE;
+
+    /* potion of unholy water might be wielded; prevent
+       you_were() -> drop_weapon() from dropping it so that it
+       remains in inventory where our caller expects it to be */
+    obj->in_use = 1;
 
     switch (obj->otyp) {
     case POT_RESTORE_ABILITY:
@@ -1994,18 +2074,25 @@ register struct obj *obj;
             u.mh++, context.botl = 1;
         if (u.uhp < u.uhpmax)
             u.uhp++, context.botl = 1;
+        cureblind = TRUE;
         /*FALLTHRU*/
     case POT_EXTRA_HEALING:
         if (Upolyd && u.mh < u.mhmax)
             u.mh++, context.botl = 1;
         if (u.uhp < u.uhpmax)
             u.uhp++, context.botl = 1;
+        if (!obj->cursed)
+            cureblind = TRUE;
         /*FALLTHRU*/
     case POT_HEALING:
         if (Upolyd && u.mh < u.mhmax)
             u.mh++, context.botl = 1;
         if (u.uhp < u.uhpmax)
             u.uhp++, context.botl = 1;
+        if (obj->blessed)
+            cureblind = TRUE;
+        if (cureblind)
+            make_blinded(0L, !u.ucreamed);
         exercise(A_CON, TRUE);
         break;
     case POT_SICKNESS:
@@ -2141,7 +2228,7 @@ register struct obj *obj;
         break;
      */
     }
-    /* note: no obfree() */
+    /* note: no obfree() -- that's our caller's responsibility */
     if (obj->dknown) {
         if (kn)
             makeknown(obj->otyp);
@@ -2224,6 +2311,7 @@ register struct obj *o1, *o2;
         switch (o2->otyp) {
         case POT_SICKNESS:
             return POT_SICKNESS;
+        case POT_ENLIGHTENMENT:
         case POT_SPEED:
             return POT_BOOZE;
         case POT_GAIN_LEVEL:
@@ -2245,19 +2333,24 @@ register struct obj *o1, *o2;
         break;
     }
 
-    return 0;
+    return STRANGE_OBJECT;
 }
 
 /* #dip command */
 int
 dodip()
 {
+/*JP
+    static const char Dip_[] = "Dip ";
+*/
+    static const char Dip_[] = "\90Z\82·";
     register struct obj *potion, *obj;
     struct obj *singlepotion;
     uchar here;
     char allowall[2];
     short mixture;
-    char qbuf[QBUFSZ], qtoo[QBUFSZ];
+    char qbuf[QBUFSZ], obuf[QBUFSZ];
+    const char *shortestname; /* last resort obj name for prompt */
 
     allowall[0] = ALL_CLASSES;
     allowall[1] = '\0';
@@ -2269,34 +2362,50 @@ dodip()
     if (inaccessible_equipment(obj, "\82ð\90Z\82·", FALSE))
         return 0;
 
-#if 0 /*JP*/
-    Sprintf(qbuf, "dip %s into", thesimpleoname(obj));
-#else /*JP:\89p\8cê\82Å\82Í\89½\82ð\90Z\82·\82©\82ð\8aÜ\82ß\82Ä\82¢\82é\82ª\93ú\96{\8cê\82Å\82Í\8f\88\97\9d\82Ì\93s\8d\87\82Å\82Æ\82è\82 \82¦\82¸\8fÈ\97ª*/
-    Sprintf(qbuf, "dip into");
+#if 0 /*JP:T*/
+    shortestname = (is_plural(obj) || pair_of(obj)) ? "them" : "it";
+#else
+    shortestname = "\82»\82ê";
 #endif
+    /*
+     * Bypass safe_qbuf() since it doesn't handle varying suffix without
+     * an awful lot of support work.  Format the object once, even though
+     * the fountain and pool prompts offer a lot more room for it.
+     * 3.6.0 used thesimpleoname() unconditionally, which posed no risk
+     * of buffer overflow but drew bug reports because it omits user-
+     * supplied type name.
+     * getobj: "What do you want to dip <the object> into? [xyz or ?*] "
+     */
+    Strcpy(obuf, short_oname(obj, doname, thesimpleoname,
+                             /* 128 - (24 + 54 + 1) leaves 49 for <object> */
+                             QBUFSZ - sizeof "What do you want to dip \
+ into? [abdeghjkmnpqstvwyzBCEFHIKLNOQRTUWXZ#-# or ?*] "));
+
     here = levl[u.ux][u.uy].typ;
     /* Is there a fountain to dip into here? */
     if (IS_FOUNTAIN(here)) {
-        /* "Dip <the object> into the fountain?" */
 #if 0 /*JP*/
-        Sprintf(qtoo, "%s the fountain?", qbuf);
+        Sprintf(qbuf, "%s%s into the fountain?", Dip_,
+                flags.verbose ? obuf : shortestname);
 #else
-        Sprintf(qtoo, "\90ò\82É%s\81H", qbuf);
+        Sprintf(qbuf, "\90ò\82É%s\81H", Dip_);
 #endif
-        if (yn(upstart(qtoo)) == 'y') {
+        /* "Dip <the object> into the fountain?" */
+        if (yn(qbuf) == 'y') {
             dipfountain(obj);
             return 1;
         }
     } else if (is_pool(u.ux, u.uy)) {
         const char *pooltype = waterbody_name(u.ux, u.uy);
 
-        /* "Dip <the object> into the {pool, moat, &c}?" */
 #if 0 /*JP*/
-        Sprintf(qtoo, "%s the %s?", qbuf, pooltype);
-#else
-        Sprintf(qtoo, "%s\82É%s\81H", pooltype, qbuf);
+        Sprintf(qbuf, "%s%s into the %s?", Dip_,
+                flags.verbose ? obuf : shortestname, pooltype);
+#else /*JP:\89p\8cê\82Å\82Í\89½\82ð\90Z\82·\82©\82ð\8aÜ\82ß\82Ä\82¢\82é\82ª\93ú\96{\8cê\82Å\82Í\8f\88\97\9d\82Ì\93s\8d\87\82Å\82Æ\82è\82 \82¦\82¸\8fÈ\97ª*/
+        Sprintf(qbuf, "%s\82É%s\81H", pooltype, Dip_);
 #endif
-        if (yn(upstart(qtoo)) == 'y') {
+        /* "Dip <the object> into the {pool, moat, &c}?" */
+        if (yn(qbuf) == 'y') {
             if (Levitation) {
                 floating_above(pooltype);
             } else if (u.usteed && !is_swimmer(u.usteed->data)
@@ -2312,8 +2421,14 @@ dodip()
         }
     }
 
-    /* "What do you want to dip <the object> into?" */
-    potion = getobj(beverages, qbuf); /* "dip into" */
+#if 0 /*JP*/
+    /* "What do you want to dip <the object> into? [xyz or ?*] " */
+    Sprintf(qbuf, "dip %s into", flags.verbose ? obuf : shortestname);
+#else
+    /* "What do you want to dip into? [xyz or ?*] " */
+    Sprintf(qbuf, "dip into");
+#endif
+    potion = getobj(beverages, qbuf);
     if (!potion)
         return 0;
     if (potion == obj && potion->quan == 1L) {
@@ -2378,23 +2493,29 @@ dodip()
         potion->in_use = FALSE; /* didn't go poof */
         return 1;
     } else if (obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
-        long amt = obj->quan;
+        int amt = (int) obj->quan;
+        boolean magic;
+
+        mixture = mixtype(obj, potion);
 
+        magic = (mixture != STRANGE_OBJECT) ? objects[mixture].oc_magic
+            : (objects[obj->otyp].oc_magic || objects[potion->otyp].oc_magic);
 #if 0 /*JP*/
-        Strcpy(qbuf, "The");
+        Strcpy(qbuf, "The"); /* assume full stack */
 #else
         Strcpy(qbuf, "");
 #endif
-        if (amt > (objects[potion->otyp].oc_magic ? 2L : 9L)) {
+        if (amt > (magic ? 3 : 7)) {
             /* trying to dip multiple potions will usually affect only a
-               subset; pick an amount between 2 and min(N,9), inclusive */
-            amt -= 1L;
-            do {
-                amt = (long) rnd((int) amt);
-            } while (amt >= 9L);
-            amt += 1L;
-            if (amt < obj->quan) {
-                obj = splitobj(obj, amt);
+               subset; pick an amount between 3 and 8, inclusive, for magic
+               potion result, between 7 and N for non-magic */
+            if (magic)
+                amt = rnd(min(amt, 8) - (3 - 1)) + (3 - 1); /* 1..6 + 2 */
+            else
+                amt = rnd(amt - (7 - 1)) + (7 - 1); /* 1..(N-6) + 6 */
+
+            if ((long) amt < obj->quan) {
+                obj = splitobj(obj, (long) amt);
 #if 0 /*JP*/
                 Sprintf(qbuf, "%ld of the", obj->quan);
 #else
@@ -2430,7 +2551,7 @@ dodip()
                 potionbreathe(obj);
             useupall(obj);
             useup(potion);
-            losehp((int) (amt + rnd(9)), /* not physical damage */
+            losehp(amt + rnd(9), /* not physical damage */
 /*JP
                    "alchemic blast", KILLED_BY_AN);
 */
@@ -2442,7 +2563,7 @@ dodip()
         if (Blind || Hallucination)
             obj->dknown = 0;
 
-        if ((mixture = mixtype(obj, potion)) != 0) {
+        if (mixture != STRANGE_OBJECT) {
             obj->otyp = mixture;
         } else {
             switch (obj->odiluted ? 1 : rnd(8)) {
@@ -2655,7 +2776,7 @@ more_dips:
 
     potion->in_use = FALSE; /* didn't go poof */
     if ((obj->otyp == UNICORN_HORN || obj->otyp == AMETHYST)
-        && (mixture = mixtype(obj, potion)) != 0) {
+        && (mixture = mixtype(obj, potion)) != STRANGE_OBJECT) {
         char oldbuf[BUFSZ], newbuf[BUFSZ];
         short old_otyp = potion->otyp;
         boolean old_dknown = FALSE;
@@ -2874,7 +2995,7 @@ struct monst *mon,  /* monster being split */
 #else
         Sprintf(reason, "%s\82Ì\94M\82Å",
                 (mtmp == &youmonst) ? the_your[1]
-                                    : (const char *) s_suffix(mon_nam(mtmp)));
+                                    : (const char *) mon_nam(mtmp));
 #endif
 
     if (mon == &youmonst) {
index edcbbfc..04439fa 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 pray.c  $NHDT-Date: 1446854232 2015/11/06 23:57:12 $  $NHDT-Branch: master $:$NHDT-Revision: 1.87 $ */
+/* NetHack 3.6 pray.c  $NHDT-Date: 1519662898 2018/02/26 16:34:58 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.96 $ */
 /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -151,6 +151,31 @@ boolean only_if_injured; /* determines whether maxhp <= 5 matters */
     return (boolean) (curhp <= 5 || curhp * divisor <= maxhp);
 }
 
+/* return True if surrounded by impassible rock, regardless of the state
+   of your own location (for example, inside a doorless closet) */
+boolean
+stuck_in_wall()
+{
+    int i, j, x, y, count = 0;
+
+    if (Passes_walls)
+        return FALSE;
+    for (i = -1; i <= 1; i++) {
+        x = u.ux + i;
+        for (j = -1; j <= 1; j++) {
+            if (!i && !j)
+                continue;
+            y = u.uy + j;
+            if (!isok(x, y)
+                || (IS_ROCK(levl[x][y].typ)
+                    && (levl[x][y].typ != SDOOR || levl[x][y].typ != SCORR))
+                || (blocked_boulder(i, j) && !throws_rocks(youmonst.data)))
+                ++count;
+        }
+    }
+    return (count == 8) ? TRUE : FALSE;
+}
+
 /*
  * Return 0 if nothing particular seems wrong, positive numbers for
  * serious trouble, and negative numbers for comparative annoyances.
@@ -169,7 +194,7 @@ STATIC_OVL int
 in_trouble()
 {
     struct obj *otmp;
-    int i, j, count = 0;
+    int i;
 
     /*
      * major troubles
@@ -194,19 +219,8 @@ in_trouble()
         return TROUBLE_LYCANTHROPE;
     if (near_capacity() >= EXT_ENCUMBER && AMAX(A_STR) - ABASE(A_STR) > 3)
         return TROUBLE_COLLAPSING;
-
-    for (i = -1; i <= 1; i++)
-        for (j = -1; j <= 1; j++) {
-            if (!i && !j)
-                continue;
-            if (!isok(u.ux + i, u.uy + j)
-                || IS_ROCK(levl[u.ux + i][u.uy + j].typ)
-                || (blocked_boulder(i, j) && !throws_rocks(youmonst.data)))
-                count++;
-        }
-    if (count == 8 && !Passes_walls)
+    if (stuck_in_wall())
         return TROUBLE_STUCK_IN_WALL;
-
     if (Cursed_obj(uarmf, LEVITATION_BOOTS)
         || stuck_ring(uleft, RIN_LEVITATION)
         || stuck_ring(uright, RIN_LEVITATION))
@@ -276,18 +290,21 @@ worst_cursed_item()
        with taking off a ring or putting on a shield */
     if (welded(uwep) && (uright || bimanual(uwep))) { /* weapon */
         otmp = uwep;
-        /* gloves come next, due to rings */
+    /* gloves come next, due to rings */
     } else if (uarmg && uarmg->cursed) { /* gloves */
         otmp = uarmg;
-        /* then shield due to two handed weapons and spells */
+    /* then shield due to two handed weapons and spells */
     } else if (uarms && uarms->cursed) { /* shield */
         otmp = uarms;
-        /* then cloak due to body armor */
+    /* then cloak due to body armor */
     } else if (uarmc && uarmc->cursed) { /* cloak */
         otmp = uarmc;
     } else if (uarm && uarm->cursed) { /* suit */
         otmp = uarm;
-    } else if (uarmh && uarmh->cursed) { /* helmet */
+    /* if worn helmet of opposite alignment is making you an adherent
+       of the current god, he/she/it won't uncurse that for you */
+    } else if (uarmh && uarmh->cursed /* helmet */
+               && uarmh->otyp != HELM_OF_OPPOSITE_ALIGNMENT) {
         otmp = uarmh;
     } else if (uarmf && uarmf->cursed) { /* boots */
         otmp = uarmf;
@@ -300,14 +317,14 @@ worst_cursed_item()
     } else if (uright && uright->cursed) { /* right ring */
         otmp = uright;
     } else if (ublindf && ublindf->cursed) { /* eyewear */
-        otmp = ublindf;                      /* must be non-blinding lenses */
-        /* if weapon wasn't handled above, do it now */
+        otmp = ublindf; /* must be non-blinding lenses */
+    /* if weapon wasn't handled above, do it now */
     } else if (welded(uwep)) { /* weapon */
         otmp = uwep;
-        /* active secondary weapon even though it isn't welded */
+    /* active secondary weapon even though it isn't welded */
     } else if (uswapwep && uswapwep->cursed && u.twoweap) {
         otmp = uswapwep;
-        /* all worn items ought to be handled by now */
+    /* all worn items ought to be handled by now */
     } else {
         for (otmp = invent; otmp; otmp = otmp->nobj) {
             if (!otmp->cursed)
@@ -367,14 +384,12 @@ int trouble;
         You("are back on solid ground.");
 */
         You("\8cÅ\82¢\92n\96Ê\82É\96ß\82Á\82½\81D");
-        /* teleport should always succeed, but if not,
-         * just untrap them.
-         */
+        /* teleport should always succeed, but if not, just untrap them */
         if (!safe_teleds(FALSE))
             u.utrap = 0;
         break;
     case TROUBLE_STARVING:
-        losestr(-1);
+        /* temporarily lost strength recovery now handled by init_uhunger() */
         /*FALLTHRU*/
     case TROUBLE_HUNGRY:
 /*JP
@@ -431,8 +446,7 @@ int trouble;
             if ((otmp = stuck_ring(uleft, RIN_SUSTAIN_ABILITY)) != 0) {
                 if (otmp == uleft)
                     what = leftglow;
-            } else if ((otmp = stuck_ring(uright, RIN_SUSTAIN_ABILITY))
-                       != 0) {
+            } else if ((otmp = stuck_ring(uright, RIN_SUSTAIN_ABILITY)) != 0) {
                 if (otmp == uright)
                     what = rightglow;
             }
@@ -441,12 +455,25 @@ int trouble;
         }
         break;
     case TROUBLE_STUCK_IN_WALL:
+        /* no control, but works on no-teleport levels */
+        if (safe_teleds(FALSE)) {
 /*JP
         Your("surroundings change.");
 */
         Your("\8aÂ\8b«\82ª\95Ï\89»\82µ\82½\81D");
-        /* no control, but works on no-teleport levels */
-        (void) safe_teleds(FALSE);
+        } else {
+            /* safe_teleds() couldn't find a safe place; perhaps the
+               level is completely full.  As a last resort, confer
+               intrinsic wall/rock-phazing.  Hero might get stuck
+               again fairly soon....
+               Without something like this, fix_all_troubles can get
+               stuck in an infinite loop trying to fix STUCK_IN_WALL
+               and repeatedly failing. */
+            set_itimeout(&HPasses_walls, (long) (d(4, 4) + 4)); /* 8..20 */
+            /* how else could you move between packed rocks or among
+               lattice forming "solid" rock? */
+            You_feel("much slimmer.");
+        }
         break;
     case TROUBLE_CURSED_LEVITATION:
         if (Cursed_obj(uarmf, LEVITATION_BOOTS)) {
@@ -527,7 +554,7 @@ int trouble;
                  jconj_adj(hcolor(NH_AMBER)));
 #endif
             iflags.last_msg = PLNMSG_OBJ_GLOWS;
-            otmp->bknown = TRUE;
+            otmp->bknown = !Hallucination;
         }
         uncurse(otmp);
         update_inventory();
@@ -596,9 +623,8 @@ int trouble;
     }
 }
 
-/* "I am sometimes shocked by...  the nuns who never take a bath without
- * wearing a bathrobe all the time.  When asked why, since no man can see
- * them,
+/* "I am sometimes shocked by... the nuns who never take a bath without
+ * wearing a bathrobe all the time.  When asked why, since no man can see them,
  * they reply 'Oh, but you forget the good God'.  Apparently they conceive of
  * the Deity as a Peeping Tom, whose omnipotence enables Him to see through
  * bathroom walls, but who is foiled by bathrobes." --Bertrand Russell, 1943
@@ -625,8 +651,10 @@ aligntyp resp_god;
             pline("%s\82Í\83p\83\8a\83p\83\8a\82É\82È\82Á\82½\81I", Monnam(u.ustuck));
             /* Yup, you get experience.  It takes guts to successfully
              * pull off this trick on your god, anyway.
+             * Other credit/blame applies (luck or alignment adjustments),
+             * but not direct kill count (pacifist conduct).
              */
-            xkilled(u.ustuck, 0);
+            xkilled(u.ustuck, XKILL_NOMSG | XKILL_NOCONDUCT);
         } else
 /*JP
             pline("%s seems unaffected.", Monnam(u.ustuck));
@@ -674,7 +702,7 @@ aligntyp resp_god;
             pline("%s disintegrates into a pile of dust!", Monnam(u.ustuck));
 */
             pline("%s\82Í\82¿\82è\82Ì\8eR\82É\82È\82Á\82½\81I", Monnam(u.ustuck));
-            xkilled(u.ustuck, 2); /* no corpse */
+            xkilled(u.ustuck, XKILL_NOMSG | XKILL_NOCORPSE | XKILL_NOCONDUCT);
         } else
 /*JP
             pline("%s seems unaffected.", Monnam(u.ustuck));
@@ -700,9 +728,9 @@ aligntyp resp_god;
             (void) destroy_arm(uarm);
         if (uarmu && !uarm && !uarmc)
             (void) destroy_arm(uarmu);
-        if (!Disint_resistance)
+        if (!Disint_resistance) {
             fry_by_god(resp_god, TRUE);
-        else {
+        else {
 /*JP
             You("bask in its %s glow for a minute...", NH_BLACK);
 */
@@ -1148,6 +1176,7 @@ aligntyp g_align;
         switch (min(action, 5)) {
         case 5:
             pat_on_head = 1;
+            /*FALLTHRU*/
         case 4:
             do
                 fix_worst_trouble(trouble);
@@ -1292,7 +1321,7 @@ aligntyp g_align;
                     break;
                 }
             }
-        /* Otherwise, falls into next case */
+            /*FALLTHRU*/
         case 2:
             if (!Blind)
 /*JP
@@ -1315,8 +1344,15 @@ aligntyp g_align;
             ABASE(A_STR) = AMAX(A_STR);
             if (u.uhunger < 900)
                 init_uhunger();
+            /* luck couldn't have been negative at start of prayer because
+               the prayer would have failed, but might have been decremented
+               due to a timed event (delayed death of peaceful monster hit
+               by hero-created stinking cloud) during the praying interval */
             if (u.uluck < 0)
                 u.uluck = 0;
+            /* superfluous; if hero was blinded we'd be handling trouble
+               rather than issuing a pat-on-head */
+            u.ucreamed = 0;
             make_blinded(0L, TRUE);
             context.botl = 1;
             break;
@@ -1335,7 +1371,9 @@ aligntyp g_align;
 */
                 You("%s\83I\81[\83\89\82É\82Â\82Â\82Ü\82ê\82½\81D", an(hcolor(NH_LIGHT_BLUE)));
             for (otmp = invent; otmp; otmp = otmp->nobj) {
-                if (otmp->cursed) {
+                if (otmp->cursed
+                    && (otmp != uarmh /* [see worst_cursed_item()] */
+                        || uarmh->otyp != HELM_OF_OPPOSITE_ALIGNMENT)) {
                     if (!Blind) {
 #if 0 /*JP*/
                         pline("%s %s.", Yobjnam2(otmp, "softly glow"),
@@ -1410,7 +1448,8 @@ aligntyp g_align;
             if (u.ualign.record >= PIOUS && !u.uevent.uhand_of_elbereth) {
                 gcrownu();
                 break;
-            } /* else FALLTHRU */
+            }
+            /*FALLTHRU*/
         case 6: {
             struct obj *otmp;
             int sp_no, trycnt = u.ulevel + 1;
@@ -1933,15 +1972,15 @@ dosacrifice()
 */
                 "\82Ç\82±\82©\82ç\82Æ\82à\82È\82­\90¹\89Ì\91à\82Ì\89Ì\82ª\95·\82±\82¦\81C\82 \82È\82½\82Í\8cõ\82É\95ï\82Ü\82ê\82½\81D\81D\81D");
 /*JP
-                godvoice(altaralign, "Congratulations, mortal!");
+                godvoice(altaralign, "Mortal, thou hast done well!");
 */
-                godvoice(altaralign, "\82æ\82­\82â\82Á\82½\81I\92è\96½\82Ì\8eÒ\82æ\81I");
+                godvoice(altaralign, "\92è\96½\82Ì\8eÒ\82æ\81C\82æ\82­\82â\82Á\82½\81I");
                 display_nhwindow(WIN_MESSAGE, FALSE);
                 verbalize(
 /*JP
           "In return for thy service, I grant thee the gift of Immortality!");
 */
-          "\93ð\82Ì\88Ì\8bÆ\82É\91Î\82µ\81C\95s\8e\80\82Ì\91Ì\82ð\95ù\82°\82æ\82¤\82¼\81I");
+          "\93ð\82Ì\88Ì\8bÆ\82É\91Î\82µ\81C\95s\8e\80\82Ì\91Ì\82ð\8eö\82¯\82æ\82¤\82¼\81I");
 #if 0 /*JP*/
                 You("ascend to the status of Demigod%s...",
                     flags.female ? "dess" : "");
@@ -2578,7 +2617,7 @@ doturn()
             }
         }
     }
-    nomul(-5);
+    nomul(-(5 - ((u.ulevel - 1) / 6))); /* -5 .. -1 */
 /*JP
     multi_reason = "trying to turn the monsters";
 */
index b58f1a1..74e0be9 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 priest.c        $NHDT-Date: 1446892452 2015/11/07 10:34:12 $  $NHDT-Branch: master $:$NHDT-Revision: 1.41 $ */
+/* NetHack 3.6 priest.c        $NHDT-Date: 1501725407 2017/08/03 01:56:47 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.44 $ */
 /* Copyright (c) Izchak Miller, Steve Linhart, 1989.              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -586,14 +586,17 @@ int roomno;
         if (!rn2(5)
             && (mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS))
                    != 0) {
-            /* [TODO: alter this (at a minimum, by switching from
-               an exclamation to a simple declaration) if hero has
-               already killed enough ghosts.] */
+            int ngen = mvitals[PM_GHOST].born;
             if (canspotmon(mtmp))
-/*JP
-                pline("An enormous ghost appears next to you!");
-*/
-                pline("\8b\90\91å\82È\97H\97ì\82ª\82 \82È\82½\82Ì\82·\82®\82»\82Î\82É\8c»\82í\82ê\82½\81I");
+#if 0 /*JP:T*/
+                pline("A%s ghost appears next to you%c",
+                      ngen < 5 ? "n enormous" : "",
+                      ngen < 10 ? '!' : '.');
+#else
+                pline("%s\97H\97ì\82ª\82 \82È\82½\82Ì\82·\82®\82»\82Î\82É\8c»\82í\82ê\82½%s",
+                      ngen < 5 ? "\8b\90\91å\82È" : "",
+                      ngen < 10 ? "\81I" : "\81D");
+#endif
             else
 /*JP
                 You("sense a presence close by!");
@@ -608,9 +611,9 @@ int roomno;
                 You("\82Ü\82Á\82³\82¨\82É\82È\82Á\82Ä\8bÁ\82«\81C\93®\82¯\82È\82­\82È\82Á\82½\81D");
             nomul(-3);
 /*JP
-            multi_reason = "being terrified of a demon";
+            multi_reason = "being terrified of a ghost";
 */
-            multi_reason = "\88«\97ì\82É\8b°\95|\82µ\82Ä\82¢\82é\8e\9e\82É";
+            multi_reason = "\97H\97ì\82É\8b°\95|\82µ\82Ä\82¢\82é\8e\9e\82É";
 /*JP
             nomovemsg = "You regain your composure.";
 */
@@ -939,11 +942,13 @@ struct monst *priest;
               a_gname_at(ax, ay));
         break;
     case 1:
-/*JP
+#if 0 /*JP*/
         pline("%s voice booms:  \"How darest thou harm my servant!\"",
-*/
-        pline("%s\82Ì\90º\82ª\8b¿\82¢\82½\81F\81u\82í\82ª\89º\96l\82É\8bê\82µ\82Þ\82ª\82æ\82¢\81I\81v",
               s_suffix(a_gname_at(ax, ay)));
+#else
+        pline("%s\82Ì\90º\82ª\8b¿\82¢\82½\81F\81u\82í\82ª\89º\96l\82É\8bê\82µ\82Þ\82ª\82æ\82¢\81I\81v",
+              a_gname_at(ax, ay));
+#endif
         break;
     default:
 /*JP
@@ -968,7 +973,8 @@ angry_priest()
     if ((priest = findpriest(temple_occupied(u.urooms))) != 0) {
         struct epri *eprip = EPRI(priest);
 
-        wakeup(priest);
+        wakeup(priest, FALSE);
+        setmangry(priest, FALSE);
         /*
          * If the altar has been destroyed or converted, let the
          * priest run loose.
@@ -1024,4 +1030,422 @@ boolean ghostly;
     }
 }
 
+/*
+ * align_str(), piousness(), mstatusline() and ustatusline() used to be
+ * in pline.c, presumeably because the latter two generate one line of
+ * output.  The USE_OLDARGS config gets warnings from 2016ish-vintage
+ * gcc (for -Wint-to-pointer-cast, activated by -Wall or -W) when they
+ * follow pline() itself.  Fixing up the variadic calls like is done for
+ * lev_comp would be needlessly messy there.
+ *
+ * They don't belong here.  If/when enlightenment ever gets split off
+ * from cmd.c (which definitely doesn't belong there), they should go
+ * with it.
+ */
+
+const char *
+align_str(alignment)
+aligntyp alignment;
+{
+    switch ((int) alignment) {
+    case A_CHAOTIC:
+/*JP
+        return "chaotic";
+*/
+        return "\8d¬\93×";
+    case A_NEUTRAL:
+/*JP
+        return "neutral";
+*/
+        return "\92\86\97§";
+    case A_LAWFUL:
+/*JP
+        return "lawful";
+*/
+        return "\92\81\8f\98";
+    case A_NONE:
+/*JP
+        return "unaligned";
+*/
+        return "\96³\90S";
+    }
+/*JP
+    return "unknown";
+*/
+    return "\95s\96¾";
+}
+
+/* used for self-probing */
+char *
+piousness(showneg, suffix)
+boolean showneg;
+const char *suffix;
+{
+    static char buf[32]; /* bigger than "insufficiently neutral" */
+    const char *pio;
+
+    /* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
+    if (u.ualign.record >= 20)
+/*JP
+        pio = "piously";
+*/
+        pio = "\8chåi\82È";
+    else if (u.ualign.record > 13)
+/*JP
+        pio = "devoutly";
+*/
+        pio = "\90M\90S\90[\82¢";
+    else if (u.ualign.record > 8)
+/*JP
+        pio = "fervently";
+*/
+        pio = "\94M\90S\82È";
+    else if (u.ualign.record > 3)
+/*JP
+        pio = "stridently";
+*/
+        pio = "\91å\82°\82³\82È";
+    else if (u.ualign.record == 3)
+        pio = "";
+    else if (u.ualign.record > 0)
+/*JP
+        pio = "haltingly";
+*/
+        pio = "\95s\8a®\91S\82È";
+    else if (u.ualign.record == 0)
+/*JP
+        pio = "nominally";
+*/
+        pio = "\8c`\82¾\82¯\82Ì";
+    else if (!showneg)
+/*JP
+        pio = "insufficiently";
+*/
+        pio = "\95s\8f\\95ª\82È";
+    else if (u.ualign.record >= -3)
+/*JP
+        pio = "strayed";
+*/
+        pio = "\96À\82¢\82ð\8e\9d\82Á\82½";
+    else if (u.ualign.record >= -8)
+/*JP
+        pio = "sinned";
+*/
+        pio = "\8dß\82ð\95\89\82Á\82½";
+    else
+/*JP
+        pio = "transgressed";
+*/
+        pio = "\88í\92E\82µ\82½";
+
+    Sprintf(buf, "%s", pio);
+    if (suffix && (!showneg || u.ualign.record >= 0)) {
+        if (u.ualign.record != 3)
+            Strcat(buf, " ");
+        Strcat(buf, suffix);
+    }
+    return buf;
+}
+
+/* stethoscope or probing applied to monster -- one-line feedback */
+void
+mstatusline(mtmp)
+struct monst *mtmp;
+{
+    aligntyp alignment = mon_aligntyp(mtmp);
+    char info[BUFSZ], monnambuf[BUFSZ];
+
+    info[0] = 0;
+    if (mtmp->mtame) {
+/*JP
+        Strcat(info, ", tame");
+*/
+        Strcat(info, ", \8e\94\82¢\82È\82ç\82³\82ê\82Ä\82¢\82é");
+        if (wizard) {
+            Sprintf(eos(info), " (%d", mtmp->mtame);
+            if (!mtmp->isminion)
+                Sprintf(eos(info), "; hungry %ld; apport %d",
+                        EDOG(mtmp)->hungrytime, EDOG(mtmp)->apport);
+            Strcat(info, ")");
+        }
+    } else if (mtmp->mpeaceful)
+/*JP
+        Strcat(info, ", peaceful");
+*/
+        Strcat(info, ", \97F\8dD\93I");
+
+    if (mtmp->data == &mons[PM_LONG_WORM]) {
+        int segndx, nsegs = count_wsegs(mtmp);
+
+        /* the worm code internals don't consider the head of be one of
+           the worm's segments, but we count it as such when presenting
+           worm feedback to the player */
+        if (!nsegs) {
+            Strcat(info, ", single segment");
+        } else {
+            ++nsegs; /* include head in the segment count */
+            segndx = wseg_at(mtmp, bhitpos.x, bhitpos.y);
+            Sprintf(eos(info), ", %d%s of %d segments",
+                    segndx, ordin(segndx), nsegs);
+        }
+    }
+    if (mtmp->cham >= LOW_PM && mtmp->data != &mons[mtmp->cham])
+        /* don't reveal the innate form (chameleon, vampire, &c),
+           just expose the fact that this current form isn't it */
+/*JP
+        Strcat(info, ", shapechanger");
+*/
+        Strcat(info, ", \95Ï\89»");
+    /* pets eating mimic corpses mimic while eating, so this comes first */
+    if (mtmp->meating)
+/*JP
+        Strcat(info, ", eating");
+*/
+        Strcat(info, ", \90H\8e\96\92\86");
+    /* a stethoscope exposes mimic before getting here so this
+       won't be relevant for it, but wand of probing doesn't */
+    if (mtmp->mundetected || mtmp->m_ap_type)
+        mhidden_description(mtmp, TRUE, eos(info));
+    if (mtmp->mcan)
+/*JP
+        Strcat(info, ", cancelled");
+*/
+        Strcat(info, ", \96³\97Í");
+    if (mtmp->mconf)
+/*JP
+        Strcat(info, ", confused");
+*/
+        Strcat(info, ", \8d¬\97\90\8fó\91Ô");
+    if (mtmp->mblinded || !mtmp->mcansee)
+/*JP
+        Strcat(info, ", blind");
+*/
+        Strcat(info, ", \96Ó\96Ú");
+    if (mtmp->mstun)
+/*JP
+        Strcat(info, ", stunned");
+*/
+        Strcat(info, ", \82­\82ç\82­\82ç\8fó\91Ô");
+    if (mtmp->msleeping)
+/*JP
+        Strcat(info, ", asleep");
+*/
+        Strcat(info, ", \90\87\96°\8fó\91Ô");
+#if 0 /* unfortunately mfrozen covers temporary sleep and being busy \
+         (donning armor, for instance) as well as paralysis */
+    else if (mtmp->mfrozen)
+        Strcat(info, ", paralyzed");
+#else
+    else if (mtmp->mfrozen || !mtmp->mcanmove)
+/*JP
+        Strcat(info, ", can't move");
+*/
+        Strcat(info, ", \93®\82¯\82È\82¢");
+#endif
+    /* [arbitrary reason why it isn't moving] */
+    else if (mtmp->mstrategy & STRAT_WAITMASK)
+/*JP
+        Strcat(info, ", meditating");
+*/
+        Strcat(info, ", \96»\91z\92\86");
+    if (mtmp->mflee)
+/*JP
+        Strcat(info, ", scared");
+*/
+        Strcat(info, ", \8b¯\82¦\82Ä\82¢\82é");
+    if (mtmp->mtrapped)
+/*JP
+        Strcat(info, ", trapped");
+*/
+        Strcat(info, ", ã©\82É\82©\82©\82Á\82Ä\82¢\82é");
+    if (mtmp->mspeed)
+#if 0 /*JP:T*/
+        Strcat(info, (mtmp->mspeed == MFAST) ? ", fast"
+                      : (mtmp->mspeed == MSLOW) ? ", slow"
+                         : ", [? speed]");
+#else
+        Strcat(info, (mtmp->mspeed == MFAST) ? ", \91f\91\81\82¢"
+                      : (mtmp->mspeed == MSLOW) ? ", \92x\82¢"
+                         : ", \91¬\93x\95s\96¾");
+#endif
+    if (mtmp->minvis)
+/*JP
+        Strcat(info, ", invisible");
+*/
+        Strcat(info, ", \95s\89Â\8e\8b");
+    if (mtmp == u.ustuck)
+#if 0 /*JP*/
+        Strcat(info, sticks(youmonst.data) ? ", held by you"
+                      : !u.uswallow ? ", holding you"
+                         : attacktype_fordmg(u.ustuck->data, AT_ENGL, AD_DGST)
+                            ? ", digesting you"
+                            : is_animal(u.ustuck->data) ? ", swallowing you"
+                               : ", engulfing you");
+#else
+        Strcat(info, sticks(youmonst.data) ? ", \82 \82È\82½\82ª\92Í\82Ü\82¦\82Ä\82¢\82é"
+                      : !u.uswallow ? ", \92Í\82Ü\82¦\82Ä\82¢\82é"
+                         : attacktype_fordmg(u.ustuck->data, AT_ENGL, AD_DGST)
+                            ? ", \8fÁ\89»\82µ\82Ä\82¢\82é"
+                            : is_animal(u.ustuck->data) ? ", \88ù\82Ý\8d\9e\82ñ\82Å\82¢\82é"
+                               : ", \8aª\82«\8d\9e\82ñ\82Å\82¢\82é");
+#endif
+    if (mtmp == u.usteed)
+/*JP
+        Strcat(info, ", carrying you");
+*/
+        Strcat(info, ", \82 \82È\82½\82ð\8fæ\82¹\82Ä\82¢\82é");
+
+    /* avoid "Status of the invisible newt ..., invisible" */
+    /* and unlike a normal mon_nam, use "saddled" even if it has a name */
+    Strcpy(monnambuf, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
+                               (SUPPRESS_IT | SUPPRESS_INVISIBLE), FALSE));
+
+/*JP
+    pline("Status of %s (%s):  Level %d  HP %d(%d)  AC %d%s.", monnambuf,
+*/
+    pline("%s\82Ì\8fó\91Ô (%s)\81F Level %d  HP %d(%d)  AC %d%s", monnambuf,
+          align_str(alignment), mtmp->m_lev, mtmp->mhp, mtmp->mhpmax,
+          find_mac(mtmp), info);
+}
+
+/* stethoscope or probing applied to hero -- one-line feedback */
+void
+ustatusline()
+{
+    char info[BUFSZ];
+
+    info[0] = '\0';
+    if (Sick) {
+#if 0 /*JP*/
+        Strcat(info, ", dying from");
+        if (u.usick_type & SICK_VOMITABLE)
+            Strcat(info, " food poisoning");
+        if (u.usick_type & SICK_NONVOMITABLE) {
+            if (u.usick_type & SICK_VOMITABLE)
+                Strcat(info, " and");
+            Strcat(info, " illness");
+        }
+#else
+        Strcat(info, ", ");
+        if (u.usick_type & SICK_VOMITABLE)
+            Strcat(info, "\90H\92\86\93Å");
+        if (u.usick_type & SICK_NONVOMITABLE) {
+            if (u.usick_type & SICK_VOMITABLE)
+                Strcat(info, "\82Æ");
+            Strcat(info, "\95a\8bC");
+        }
+        Strcat(info, "\82Å\8e\80\82É\82Â\82Â\82 \82é");
+#endif
+    }
+    if (Stoned)
+/*JP
+        Strcat(info, ", solidifying");
+*/
+        Strcat(info, ", \90Î\89»\82µ\82Â\82Â\82 \82é");
+    if (Slimed)
+/*JP
+        Strcat(info, ", becoming slimy");
+*/
+        Strcat(info, ", \83X\83\89\83C\83\80\82É\82È\82è\82Â\82Â\82 \82é");
+    if (Strangled)
+/*JP
+        Strcat(info, ", being strangled");
+*/
+        Strcat(info, ", \8eñ\82ð\8di\82ß\82ç\82ê\82Ä\82¢\82é");
+    if (Vomiting)
+#if 0 /*JP*/
+        Strcat(info, ", nauseated"); /* !"nauseous" */
+#else
+        Strcat(info, ", \93f\82«\8bC\82ª\82·\82é");
+#endif
+    if (Confusion)
+/*JP
+        Strcat(info, ", confused");
+*/
+        Strcat(info, ", \8d¬\97\90\8fó\91Ô");
+    if (Blind) {
+#if 0 /*JP*/
+        Strcat(info, ", blind");
+        if (u.ucreamed) {
+            if ((long) u.ucreamed < Blinded || Blindfolded
+                || !haseyes(youmonst.data))
+                Strcat(info, ", cover");
+            Strcat(info, "ed by sticky goop");
+        } /* note: "goop" == "glop"; variation is intentional */
+#else
+        Strcat(info, ", ");
+        if (u.ucreamed) {
+            Strcat(info, "\82Ë\82Î\82Ë\82Î\82×\82Æ\82Â\82­\82à\82Ì\82Å");
+            if ((long)u.ucreamed < Blinded || Blindfolded
+                || !haseyes(youmonst.data))
+              Strcat(info, "\95¢\82í\82ê\82Ä");
+        }
+        Strcat(info, "\96Ó\96Ú\8fó\91Ô");
+#endif
+    }
+    if (Stunned)
+/*JP
+        Strcat(info, ", stunned");
+*/
+        Strcat(info, ", \82­\82ç\82­\82ç\8fó\91Ô");
+    if (!u.usteed && Wounded_legs) {
+        const char *what = body_part(LEG);
+        if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
+            what = makeplural(what);
+/*JP
+        Sprintf(eos(info), ", injured %s", what);
+*/
+        Sprintf(eos(info), ", %s\82É\82¯\82ª\82ð\82µ\82Ä\82¢\82é", what);
+    }
+    if (Glib)
+/*JP
+        Sprintf(eos(info), ", slippery %s", makeplural(body_part(HAND)));
+*/
+        Sprintf(eos(info), ", %s\82ª\82Ê\82é\82Ê\82é", makeplural(body_part(HAND)));
+    if (u.utrap)
+/*JP
+        Strcat(info, ", trapped");
+*/
+        Strcat(info, ", ã©\82É\82©\82©\82Á\82Ä\82¢\82é");
+    if (Fast)
+/*JP
+        Strcat(info, Very_fast ? ", very fast" : ", fast");
+*/
+        Strcat(info, Very_fast ? ", \82Æ\82Ä\82à\91f\91\81\82¢" : ", \91f\91\81\82¢");
+    if (u.uundetected)
+/*JP
+        Strcat(info, ", concealed");
+*/
+        Strcat(info, ", \89B\82ê\82Ä\82¢\82é");
+    if (Invis)
+/*JP
+        Strcat(info, ", invisible");
+*/
+        Strcat(info, ", \95s\89Â\8e\8b");
+    if (u.ustuck) {
+#if 0 /*JP*/
+        if (sticks(youmonst.data))
+            Strcat(info, ", holding ");
+        else
+            Strcat(info, ", held by ");
+        Strcat(info, mon_nam(u.ustuck));
+#else
+        Strcat(info, ", ");
+        Strcat(info, mon_nam(u.ustuck));
+        if (sticks(youmonst.data))
+            Strcat(info, "\82ð\92Í\82Ü\82¦\82Ä\82¢\82é");
+        else
+            Strcat(info, "\82É\92Í\82Ü\82¦\82ç\82ê\82Ä\82¢\82é");
+#endif
+    }
+
+/*JP
+    pline("Status of %s (%s):  Level %d  HP %d(%d)  AC %d%s.", plname,
+*/
+    pline("%s\82Ì\8fó\91Ô (%s)\81F Level %d  HP %d(%d)  AC %d%s", plname,
+          piousness(FALSE, align_str(u.ualign.type)),
+          Upolyd ? mons[u.umonnum].mlevel : u.ulevel, Upolyd ? u.mh : u.uhp,
+          Upolyd ? u.mhmax : u.uhpmax, u.uac, info);
+}
+
 /*priest.c*/
index 7bbd1d8..ae95ee9 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 quest.c $NHDT-Date: 1446191878 2015/10/30 07:57:58 $  $NHDT-Branch: master $:$NHDT-Revision: 1.20 $ */
+/* NetHack 3.6 quest.c $NHDT-Date: 1505170343 2017/09/11 22:52:23 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */
 /*      Copyright 1991, M. Stephenson             */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -73,7 +73,20 @@ on_goal()
         qt_pager(QT_FIRSTGOAL);
         Qstat(made_goal) = 1;
     } else {
-        qt_pager(QT_NEXTGOAL);
+        /*
+         * Some QT_NEXTGOAL messages reference the quest artifact;
+         * find out if it is still present.  If not, request an
+         * alternate message (qt_pager() will revert to delivery
+         * of QT_NEXTGOAL if current role doesn't have QT_ALTGOAL).
+         * Note: if hero is already carrying it, it is treated as
+         * being absent from the level for quest message purposes.
+         */
+        unsigned whichobjchains = ((1 << OBJ_FLOOR)
+                                   | (1 << OBJ_MINVENT)
+                                   | (1 << OBJ_BURIED));
+        struct obj *qarti = find_quest_artifact(whichobjchains);
+
+        qt_pager(qarti ? QT_NEXTGOAL : QT_ALTGOAL);
         if (Qstat(made_goal) < 7)
             Qstat(made_goal)++;
     }
@@ -203,6 +216,7 @@ boolean seal;
     schedule_goto(dest, FALSE, FALSE, portal_flag, (char *) 0, (char *) 0);
     if (seal) { /* remove the portal to the quest - sealing it off */
         int reexpelled = u.uevent.qexpelled;
+
         u.uevent.qexpelled = 1;
         remdun_mapseen(quest_dnum);
         /* Delete the near portal now; the far (main dungeon side)
index 65a79a1..05bae87 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 questpgr.c      $NHDT-Date: 1448541043 2015/11/26 12:30:43 $  $NHDT-Branch: master $:$NHDT-Revision: 1.36 $ */
+/* NetHack 3.6 questpgr.c      $NHDT-Date: 1505172128 2017/09/11 23:22:08 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.38 $ */
 /*      Copyright 1991, M. Stephenson                             */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -27,6 +27,7 @@ static void NDECL(dump_qtlist);
 static void FDECL(Fread, (genericptr_t, int, int, dlb *));
 STATIC_DCL struct qtmsg *FDECL(construct_qtlist, (long));
 STATIC_DCL const char *NDECL(intermed);
+STATIC_DCL struct obj *FDECL(find_qarti, (struct obj *));
 STATIC_DCL const char *NDECL(neminame);
 STATIC_DCL const char *NDECL(guardname);
 STATIC_DCL const char *NDECL(homebase);
@@ -205,6 +206,58 @@ struct obj *otmp;
     return (boolean) (otmp->oartifact == urole.questarti);
 }
 
+STATIC_OVL struct obj *
+find_qarti(ochain)
+struct obj *ochain;
+{
+    struct obj *otmp, *qarti;
+
+    for (otmp = ochain; otmp; otmp = otmp->nobj) {
+        if (is_quest_artifact(otmp))
+            return otmp;
+        if (Has_contents(otmp) && (qarti = find_qarti(otmp->cobj)) != 0)
+            return qarti;
+    }
+    return (struct obj *) 0;
+}
+
+/* check several object chains for the quest artifact to determine
+   whether it is present on the current level */
+struct obj *
+find_quest_artifact(whichchains)
+unsigned whichchains;
+{
+    struct monst *mtmp;
+    struct obj *qarti = 0;
+
+    if ((whichchains & (1 << OBJ_INVENT)) != 0)
+        qarti = find_qarti(invent);
+    if (!qarti && (whichchains & (1 << OBJ_FLOOR)) != 0)
+        qarti = find_qarti(fobj);
+    if (!qarti && (whichchains & (1 << OBJ_MINVENT)) != 0)
+        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+            if (DEADMONSTER(mtmp))
+                continue;
+            if ((qarti = find_qarti(mtmp->minvent)) != 0)
+                break;
+        }
+    if (!qarti && (whichchains & (1 << OBJ_MIGRATING)) != 0) {
+        /* check migrating objects and minvent of migrating monsters */
+        for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
+            if (DEADMONSTER(mtmp))
+                continue;
+            if ((qarti = find_qarti(mtmp->minvent)) != 0)
+                break;
+        }
+        if (!qarti)
+            qarti = find_qarti(migrating_objs);
+    }
+    if (!qarti && (whichchains & (1 << OBJ_BURIED)) != 0)
+        qarti = find_qarti(level.buriedobjlist);
+
+    return qarti;
+}
+
 /* return your role nemesis' name */
 STATIC_OVL const char *
 neminame()
@@ -457,6 +510,7 @@ char *in_line, *out_line;
 #if 0 /*JP*/
                     cvt_buf[0] = highc(cvt_buf[0]);
 #endif
+                    /*FALLTHRU*/
                 case 'p':
                     Strcpy(cvt_buf, makeplural(cvt_buf));
                     break;
@@ -466,8 +520,11 @@ char *in_line, *out_line;
 #if 0 /*JP*/
                     cvt_buf[0] = highc(cvt_buf[0]);
 #endif
+                    /*FALLTHRU*/
                 case 's':
+#if 0 /*JP*/
                     Strcpy(cvt_buf, s_suffix(cvt_buf));
+#endif
                     break;
 
                 /* strip any "the" prefix */
@@ -616,7 +673,18 @@ int msgnum;
     if (skip_pager(FALSE))
         return;
 
-    if (!(qt_msg = msg_in(qt_list.chrole, msgnum))) {
+    qt_msg = msg_in(qt_list.chrole, msgnum);
+    if (!qt_msg) {
+        /* some roles have an alternate message for return to the goal
+           level when the quest artifact is absent (handled by caller)
+           but some don't; for the latter, use the normal goal message;
+           note: for first visit, artifact is assumed to always be
+           present which might not be true for wizard mode but we don't
+           worry about quest message references in that situation */
+        if (msgnum == QT_ALTGOAL)
+            qt_msg = msg_in(qt_list.chrole, QT_NEXTGOAL);
+    }
+    if (!qt_msg) {
         impossible("qt_pager: message %d not found.", msgnum);
         return;
     }
index ec39cf6..c798fbc 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 read.c  $NHDT-Date: 1448862378 2015/11/30 05:46:18 $  $NHDT-Branch: master $:$NHDT-Revision: 1.125 $ */
+/* NetHack 3.6 read.c  $NHDT-Date: 1515802375 2018/01/13 00:12:55 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.150 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -34,6 +35,7 @@ STATIC_DCL void FDECL(forget, (int));
 STATIC_DCL int FDECL(maybe_tame, (struct monst *, struct obj *));
 STATIC_DCL boolean FDECL(is_valid_stinking_cloud_pos, (int, int, BOOLEAN_P));
 STATIC_DCL void FDECL(display_stinking_cloud_positions, (int));
+STATIC_DCL boolean FDECL(get_valid_stinking_cloud_pos, (int, int));
 STATIC_PTR void FDECL(set_lit, (int, int, genericptr));
 
 STATIC_OVL boolean
@@ -65,6 +67,7 @@ struct obj *otmp;
 char *buf;
 {
     int erosion = greatest_erosion(otmp);
+
     if (erosion)
         wipeout_text(buf, (int) (strlen(buf) * erosion / (2 * MAX_ERODE)),
                      otmp->o_id ^ (unsigned) ubirthday);
@@ -125,10 +128,10 @@ char *buf;
         "Go team ant!",
         "Got newt?",
         "Hello, my darlings!", /* Charlie Drake */
-        "Hey! Nymphs! Steal This T-Shirt!",
+        "Hey!  Nymphs!  Steal This T-Shirt!",
         "I <3 Dungeon of Doom",
         "I <3 Maud",
-        "I am a Valkyrie. If you see me running, try to keep up.",
+        "I am a Valkyrie.  If you see me running, try to keep up.",
         "I am not a pack rat - I am a collector",
         "I bounced off a rubber tree",         /* Monkey Island */
         "Plunder Island Brimstone Beach Club", /* Monkey Island */
@@ -202,6 +205,16 @@ char *buf;
         "Pudding farmer",
         "Vegetarian",
         "Hello, I'm War!",
+        "It is better to light a candle than to curse the darkness",
+        "It is easier to curse the darkness than to light a candle",
+        /* expanded "rock--paper--scissors" featured in TV show "Big Bang
+           Theory" although they didn't create it (and an actual T-shirt
+           with pentagonal diagram showing which choices defeat which) */
+        "rock--paper--scissors--lizard--Spock!",
+        /* "All men must die -- all men must serve" challange and response
+           from book series _A_Song_of_Ice_and_Fire_ by George R.R. Martin,
+           TV show "Game of Thrones" (probably an actual T-shirt too...) */
+        "/Valar morghulis/ -- /Valar dohaeris/",
 #else
         "\83[\83C\81E\83}\83C\83g\81E\83r\81[\81E\83X\83g\81[\83\80\81E\83W\83\83\83C\83A\83\93\83c",
         "\95\90\8aí\82ª\90l\82ð\8eE\82·\82Ì\82Å\82Í\82È\82¢\81C\8e\84\82ª\90l\82ð\8eE\82·\82Ì\82¾",
@@ -220,6 +233,16 @@ char *buf;
         "\83v\83\8a\83\93\94_\89Æ",
         "\83x\83W\83^\83\8a\83A\83\93",
         "\82â\82 \81C\8e\84\82ª\81w\90í\91\88\81x\82¾\81I",
+        "It is better to light a candle than to curse the darkness",
+        "It is easier to curse the darkness than to light a candle",
+        /* expanded "rock--paper--scissors" featured in TV show "Big Bang
+           Theory" although they didn't create it (and an actual T-shirt
+           with pentagonal diagram showing which choices defeat which) */
+        "rock--paper--scissors--lizard--Spock!",
+        /* "All men must die -- all men must serve" challange and response
+           from book series _A_Song_of_Ice_and_Fire_ by George R.R. Martin,
+           TV show "Game of Thrones" (probably an actual T-shirt too...) */
+        "/Valar morghulis/ -- /Valar dohaeris/",
 #endif
     };
 
@@ -274,7 +297,9 @@ doread()
         useup(scroll);
         return 1;
     } else if (scroll->otyp == T_SHIRT || scroll->otyp == ALCHEMY_SMOCK) {
-        char buf[BUFSZ];
+        char buf[BUFSZ], *mesg;
+        const char *endpunct;
+
         if (Blind) {
 /*JP
             You_cant("feel any Braille writing.");
@@ -295,24 +320,33 @@ doread()
             return 0;
         }
         u.uconduct.literate++;
-        if (flags.verbose)
+        /* populate 'buf[]' */
+        mesg = (scroll->otyp == T_SHIRT) ? tshirt_text(scroll, buf)
+                                         : apron_text(scroll, buf);
+        endpunct = "";
+        if (flags.verbose) {
+            int ln = (int) strlen(mesg);
+
+            /* we will be displaying a sentence; need ending punctuation */
+            if (ln > 0 && !index(".!?", mesg[ln - 1]))
+                endpunct = ".";
 /*JP
             pline("It reads:");
 */
             pline("\82»\82ê\82ð\93Ç\82ñ\82¾\81F");
+        }
 #if 0 /*JP*/
-        pline("\"%s\"", (scroll->otyp == T_SHIRT) ? tshirt_text(scroll, buf)
-                                                  : apron_text(scroll, buf));
+        pline("\"%s\"%s", mesg, endpunct);
 #else
-        pline("\81u%s\81v", (scroll->otyp == T_SHIRT) ? tshirt_text(scroll, buf)
-                                                  : apron_text(scroll, buf));
+        pline("\81u%s\81v", mesg);
 #endif
         return 1;
     } else if (scroll->otyp == CREDIT_CARD) {
         static const char *card_msgs[] = {
 #if 0 /*JP*/
             "Leprechaun Gold Tru$t - Shamrock Card",
-            "Magic Memory Vault Charge Card", "Larn National Bank", /* Larn */
+            "Magic Memory Vault Charge Card",
+            "Larn National Bank",                /* Larn */
             "First Bank of Omega",               /* Omega */
             "Bank of Zork - Frobozz Magic Card", /* Zork */
             "Ankh-Morpork Merchant's Guild Barter Card",
@@ -361,10 +395,14 @@ doread()
                       : card_msgs[scroll->o_id % (SIZE(card_msgs) - 1)]);
         }
         /* Make a credit card number */
-        pline("\"%d0%d %d%d1 0%d%d0\"", ((scroll->o_id % 89) + 10),
-              (scroll->o_id % 4), (((scroll->o_id * 499) % 899999) + 100000),
-              (scroll->o_id % 10), (!(scroll->o_id % 3)),
-              ((scroll->o_id * 7) % 10));
+        pline("\"%d0%d %ld%d1 0%d%d0\"%s",
+              (((int) scroll->o_id % 89) + 10),
+              ((int) scroll->o_id % 4),
+              ((((long) scroll->o_id * 499L) % 899999L) + 100000L),
+              ((int) scroll->o_id % 10),
+              (!((int) scroll->o_id % 3)),
+              (((int) scroll->o_id * 7) % 10),
+              (flags.verbose || Blind) ? "." : "");
         u.uconduct.literate++;
         return 1;
     } else if (scroll->otyp == CAN_OF_GREASE) {
@@ -387,7 +425,7 @@ doread()
 */
             pline("\82»\82ê\82ð\93Ç\82ñ\82¾\81F");
 /*JP
-        pline("\"Magic Marker(TM) Red Ink Marker Pen. Water Soluble.\"");
+        pline("\"Magic Marker(TM) Red Ink Marker Pen.  Water Soluble.\"");
 */
         pline("\81u\96\82\96@\82Ì\83}\81[\83J(TM) \90Ô\83C\83\93\83N\83}\81[\83J\83y\83\93\81D\90\85\90«\81D\81v");
         u.uconduct.literate++;
@@ -403,7 +441,7 @@ doread()
             You("read:");
 */
             pline("\82»\82ê\82ð\93Ç\82ñ\82¾\81F");
-        pline("\"1 Zorkmid. 857 GUE. In Frobs We Trust.\"");
+        pline("\"1 Zorkmid.  857 GUE.  In Frobs We Trust.\"");
         u.uconduct.literate++;
         return 1;
     } else if (scroll->oartifact == ART_ORB_OF_FATE) {
@@ -441,11 +479,13 @@ doread()
             pline("\93_\8e\9a\82Í\82Ç\82¤\82à\8f\91\82¢\82Ä\82È\82¢\82æ\82¤\82¾\81D");
             return 0;
         }
-/*JP
-        pline("The wrapper reads: \"%s\"",
-*/
-        pline("\95ï\82Ý\8e\86\82Ì\95\8e\9a\82ð\93Ç\82ñ\82¾\81F\81u%s\81v",
+#if 0 /*JP:T*/
+        pline("The wrapper reads: \"%s\".",
               wrapper_msgs[scroll->o_id % SIZE(wrapper_msgs)]);
+#else
+        pline("\95ï\82Ý\8e\86\82Ì\95\8e\9a\82ð\93Ç\82ñ\82¾\81F\81u%s\81v.",
+              wrapper_msgs[scroll->o_id % SIZE(wrapper_msgs)]);
+#endif
         u.uconduct.literate++;
         return 1;
     } else if (scroll->oclass != SCROLL_CLASS
@@ -508,6 +548,8 @@ doread()
     }
     scroll->in_use = TRUE; /* scroll, not spellbook, now being read */
     if (scroll->otyp != SCR_BLANK_PAPER) {
+        boolean silently = !can_chant(&youmonst);
+
         /* a few scroll feedback messages describe something happening
            to the scroll itself, so avoid "it disappears" for those */
         nodisappear = (scroll->otyp == SCR_FIRE
@@ -518,12 +560,12 @@ doread()
             pline(nodisappear
                       ? "You %s the formula on the scroll."
                       : "As you %s the formula on it, the scroll disappears.",
-                  is_silent(youmonst.data) ? "cogitate" : "pronounce");
+                  silently ? "cogitate" : "pronounce");
 #else
             pline(nodisappear
                       ? "\82 \82È\82½\82Í\8eô\95\82ð%s\82½\81D"
                       : "\8eô\95\82ð%s\82é\82Æ\81C\8aª\95¨\82Í\8fÁ\82¦\82½\81D",
-                  is_silent(youmonst.data) ? "\94O\82¶" : "\8f¥\82¦");
+                  silently ? "\94O\82¶" : "\8f¥\82¦");
 #endif
         else
 #if 0 /*JP*/
@@ -542,8 +584,7 @@ doread()
             else
 #if 0 /*JP*/
                 pline("Being confused, you %s the magic words...",
-                      is_silent(youmonst.data) ? "misunderstand"
-                                               : "mispronounce");
+                      silently ? "misunderstand" : "mispronounce");
 #else
                 pline("\8d¬\97\90\82µ\82Ä\82¢\82é\82Ì\82Å\81C\8eô\95\82ð\8aÔ\88á\82Á\82Ä\82µ\82Ü\82Á\82½\81D\81D\81D");
 #endif
@@ -1124,7 +1165,7 @@ struct obj *sobj;
     unsigned was_peaceful = mtmp->mpeaceful;
 
     if (sobj->cursed) {
-        setmangry(mtmp);
+        setmangry(mtmp, FALSE);
         if (was_peaceful && !mtmp->mpeaceful)
             return -1;
     } else {
@@ -1138,12 +1179,21 @@ struct obj *sobj;
     return 0;
 }
 
+STATIC_OVL boolean
+get_valid_stinking_cloud_pos(x,y)
+int x,y;
+{
+    return (!(!isok(x,y) || !cansee(x, y)
+              || !ACCESSIBLE(levl[x][y].typ)
+              || distu(x, y) >= 32));
+}
+
 boolean
 is_valid_stinking_cloud_pos(x, y, showmsg)
 int x, y;
 boolean showmsg;
 {
-    if (!cansee(x, y) || !ACCESSIBLE(levl[x][y].typ) || distu(x, y) >= 32) {
+    if (!get_valid_stinking_cloud_pos(x,y)) {
         if (showmsg)
 /*JP
             You("smell rotten eggs.");
@@ -1168,7 +1218,7 @@ int state;
             for (dy = -dist; dy <= dist; dy++) {
                 x = u.ux + dx;
                 y = u.uy + dy;
-                if (isok(x, y) && is_valid_stinking_cloud_pos(x, y, FALSE))
+                if (get_valid_stinking_cloud_pos(x,y))
                     tmp_at(x, y);
             }
     } else {
@@ -1197,15 +1247,19 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
 #ifdef MAIL
     case SCR_MAIL:
         known = TRUE;
-        if (sobj->spe)
+        if (sobj->spe == 2)
+            /* "stamped scroll" created via magic marker--without a stamp */
+            pline("This scroll is marked \"postage due\".");
+        else if (sobj->spe)
+            /* scroll of mail obtained from bones file or from wishing;
+             * note to the puzzled: the game Larn actually sends you junk
+             * mail if you win!
+             */
             pline(
 /*JP
     "This seems to be junk mail addressed to the finder of the Eye of Larn.");
 */
     "Eye of Larn\82Ì\94­\8c©\8eÒ\82É\88\82Ä\82ç\82ê\82½\83S\83~\83\81\83C\83\8b\82Ì\82æ\82¤\82¾\81D");
-        /* note to the puzzled: the game Larn actually sends you junk
-         * mail if you win!
-         */
         else
             readmail(sobj);
         break;
@@ -1308,9 +1362,12 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
             useup(otmp);
             break;
         }
-        s = scursed ? -1 : otmp->spe >= 9
-                               ? (rn2(otmp->spe) == 0)
-                               : sblessed ? rnd(3 - otmp->spe / 3) : 1;
+        s = scursed ? -1
+                    : (otmp->spe >= 9)
+                       ? (rn2(otmp->spe) == 0)
+                       : sblessed
+                          ? rnd(3 - otmp->spe / 3)
+                          : 1;
         if (s >= 0 && Is_dragon_scales(otmp)) {
             /* dragon scales get turned into dragon scale mail */
 /*JP
@@ -1337,8 +1394,8 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
               s == 0 ? "violently " : "",
               otense(otmp, Blind ? "vibrate" : "glow"),
               (!Blind && !same_color) ? " " : "",
-              (Blind || same_color) ? ""
-                                    : hcolor(scursed ? NH_BLACK : NH_SILVER),
+              (Blind || same_color)
+                 ? "" : hcolor(scursed ? NH_BLACK : NH_SILVER),
               (s * s > 1) ? "while" : "moment");
 #else
         Your("%s\82Í%s%s%s%s\81D", xname(otmp),
@@ -1356,6 +1413,8 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
             curse(otmp);
         else if (sblessed && !otmp->blessed)
             bless(otmp);
+        else if (!scursed && otmp->cursed)
+            uncurse(otmp);
         if (s) {
             otmp->spe += s;
             adj_abon(otmp, s);
@@ -1569,6 +1628,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
         } else {
             for (obj = invent; obj; obj = obj->nobj) {
                 long wornmask;
+
                 /* gold isn't subject to cursing and blessing */
                 if (obj->oclass == COIN_CLASS)
                     continue;
@@ -1601,8 +1661,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
                 if (sblessed || wornmask || obj->otyp == LOADSTONE
                     || (obj->otyp == LEASH && obj->leashmon)) {
                     /* water price varies by curse/bless status */
-                    boolean shop_h2o =
-                        (obj->unpaid && obj->otyp == POT_WATER);
+                    boolean shop_h2o = (obj->unpaid && obj->otyp == POT_WATER);
 
                     if (confused) {
                         blessorcurse(obj, 2);
@@ -1647,8 +1706,11 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
          */
         break;
     case SCR_ENCHANT_WEAPON:
+        /* [What about twoweapon mode?  Proofing/repairing/enchanting both
+           would be too powerful, but shouldn't we choose randomly between
+           primary and secondary instead of always acting on primary?] */
         if (confused && uwep
-            && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))) {
+            && erosion_matters(uwep) && uwep->oclass != ARMOR_CLASS) {
             old_erodeproof = (uwep->oerodeproof != 0);
             new_erodeproof = !scursed;
             uwep->oerodeproof = 0; /* for messages */
@@ -1689,13 +1751,11 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
             uwep->oerodeproof = new_erodeproof ? 1 : 0;
             break;
         }
-        if (!chwepon(sobj,
-                     scursed
-                         ? -1
-                         : !uwep ? 1 : (uwep->spe >= 9)
-                                           ? !rn2(uwep->spe)
-                                           : sblessed ? rnd(3 - uwep->spe / 3)
-                                                      : 1))
+        if (!chwepon(sobj, scursed ? -1
+                             : !uwep ? 1
+                               : (uwep->spe >= 9) ? !rn2(uwep->spe)
+                                 : sblessed ? rnd(3 - uwep->spe / 3)
+                                   : 1))
             sobj = 0; /* nothing enchanted: strange_feeling -> useup */
         break;
     case SCR_TAMING:
@@ -1747,7 +1807,8 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
             if (vis_results > 0)
                 known = TRUE;
         }
-    } break;
+        break;
+    }
     case SCR_GENOCIDE:
         if (!already_known)
 /*JP
@@ -1758,7 +1819,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
         if (sblessed)
             do_class_genocide();
         else
-            do_genocide(!scursed | (2 * !!Confusion));
+            do_genocide((!scursed) | (2 * !!Confusion));
         break;
     case SCR_LIGHT:
         if (!confused || rn2(5)) {
@@ -1774,8 +1835,6 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
             (void) create_critters(1, !scursed ? &mons[PM_YELLOW_LIGHT]
                                                : &mons[PM_BLACK_LIGHT],
                                    TRUE);
-            if (!objects[sobj->otyp].oc_uname)
-                docall(sobj);
         }
         break;
     case SCR_TELEPORTATION:
@@ -1903,6 +1962,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
             /* do_mapping() already reveals secret passages */
         }
         known = TRUE;
+        /*FALLTHRU*/
     case SPE_MAGIC_MAPPING:
         if (level.flags.nommap) {
 #if 0 /*JP*/
@@ -1957,8 +2017,14 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
             pline("Maud\82ð\8dl\82¦\82é\82±\82Æ\88È\8aO\81C\82 \82È\82½\82Í\91S\82Ä\82ð\96Y\82ê\82Ä\82µ\82Ü\82Á\82½\81D");
         exercise(A_WIS, FALSE);
         break;
-    case SCR_FIRE:
+    case SCR_FIRE: {
+        coord cc;
+        int dam;
+
+        cc.x = u.ux;
+        cc.y = u.uy;
         cval = bcsign(sobj);
+        dam = (2 * (rn1(3, 3) + 2 * cval) + 1) / 3;
         useup(sobj);
         sobj = 0; /* it's gone */
         if (!already_known)
@@ -1993,20 +2059,35 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
         }
         if (Underwater) {
 /*JP
-            pline_The("water around you vaporizes violently!");
+            pline_The("%s around you vaporizes violently!", hliquid("water"));
 */
-            pline("\82 \82È\82½\82Ì\89ñ\82è\82Ì\90\85\82Í\95¦\93«\82µ\82½\81I");
+            pline_The("\82 \82È\82½\82Ì\89ñ\82è\82Ì%s\82Í\82Í\82°\82µ\82­\95¦\93«\82µ\82½\81I", hliquid("\90\85"));
         } else {
+            if (sblessed) {
+                if (!already_known)
+                    pline("This is a scroll of fire!");
+                dam *= 5;
+                pline("Where do you want to center the explosion?");
+                getpos_sethilite(display_stinking_cloud_positions, get_valid_stinking_cloud_pos);
+                (void) getpos(&cc, TRUE, "the desired position");
+                if (!is_valid_stinking_cloud_pos(cc.x, cc.y, FALSE)) {
+                    /* try to reach too far, get burned */
+                    cc.x = u.ux;
+                    cc.y = u.uy;
+                }
+            }
+            if (cc.x == u.ux && cc.y == u.uy) {
 /*JP
             pline_The("scroll erupts in a tower of flame!");
 */
             pline("\8aª\95¨\82©\82ç\89Î\92\8c\82ª\97§\82¿\8f¸\82Á\82½\81I");
-            iflags.last_msg = PLNMSG_TOWER_OF_FLAME; /* for explode() */
-            burn_away_slime();
+                iflags.last_msg = PLNMSG_TOWER_OF_FLAME; /* for explode() */
+                burn_away_slime();
+            }
         }
-        explode(u.ux, u.uy, 11, (2 * (rn1(3, 3) + 2 * cval) + 1) / 3,
-                SCROLL_CLASS, EXPL_FIERY);
+        explode(cc.x, cc.y, 11, dam, SCROLL_CLASS, EXPL_FIERY);
         break;
+    }
     case SCR_EARTH:
         /* TODO: handle steeds */
         if (!Is_rogue_level(&u.uz) && has_ceiling(&u.uz)
@@ -2083,7 +2164,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
 #endif
         cc.x = u.ux;
         cc.y = u.uy;
-        getpos_sethilite(display_stinking_cloud_positions);
+        getpos_sethilite(display_stinking_cloud_positions, get_valid_stinking_cloud_pos);
 /*JP
         if (getpos(&cc, TRUE, "the desired position") < 0) {
 */
@@ -2145,6 +2226,7 @@ boolean confused, helmet_protects, byu, skip_uswallow;
         }
     } else
         dmg = 0;
+    wake_nearto(u.ux, u.uy, 4 * 4);
     /* Must be before the losehp(), for bones files */
 /*JP
     if (!flooreffects(otmp2, u.ux, u.uy, "fall")) {
@@ -2198,7 +2280,7 @@ boolean confused, byu;
 #else
             You_hear("\89½\82©\82ª\82 \82È\82½\82Ì%s\82Ì\8fã\82Ì%s\82Ì%s\82É\93\96\82½\82Á\82½\89¹\82ð\95·\82¢\82½\81I",
                      body_part(HEAD),
-                     s_suffix(mon_nam(mtmp)), mbodypart(mtmp, STOMACH));
+                     mon_nam(mtmp), mbodypart(mtmp, STOMACH));
 #endif
 
         mdmg = dmgval(otmp2, mtmp) * otmp2->quan;
@@ -2230,16 +2312,19 @@ boolean confused, byu;
         }
         mtmp->mhp -= mdmg;
         if (mtmp->mhp <= 0) {
-            if (byu)
-                xkilled(mtmp, 1);
-            else {
+            if (byu) {
+                killed(mtmp);
+            else {
 /*JP
                 pline("%s is killed.", Monnam(mtmp));
 */
                 pline("%s\82Í\8e\80\82ñ\82¾\81D", Monnam(mtmp));
                 mondied(mtmp);
             }
+        } else {
+            wakeup(mtmp, byu);
         }
+        wake_nearto(x, y, 4 * 4);
     } else if (u.uswallow && mtmp == u.ustuck) {
         obfree(otmp2, (struct obj *) 0);
         /* fall through to player */
@@ -2482,7 +2567,7 @@ STATIC_OVL void
 do_class_genocide()
 {
     int i, j, immunecnt, gonecnt, goodcnt, class, feel_dead = 0;
-    char buf[BUFSZ];
+    char buf[BUFSZ] = DUMMY;
     boolean gameover = FALSE; /* true iff killed self */
 
     for (j = 0;; j++) {
@@ -2603,9 +2688,9 @@ do_class_genocide()
                         if (Upolyd) {
                             if (!feel_dead++)
 /*JP
-                                You_feel("dead inside.");
+                                You_feel("%s inside.", udeadinside());
 */
-                                You("\8d°\82ª\8e\80\82ñ\82¾\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
+                                You("\8d°\82ª%s\82æ\82¤\82È\8bC\82ª\82µ\82½\81D", udeadinside());
                         } else {
                             if (!feel_dead++)
 /*JP
@@ -2678,7 +2763,7 @@ int how;
 /* 3 = forced genocide of player */
 /* 5 (4 | 1) = normal genocide from throne */
 {
-    char buf[BUFSZ];
+    char buf[BUFSZ] = DUMMY;
     register int i, killplayer = 0;
     register int mndx;
     register struct permonst *ptr;
@@ -2692,6 +2777,10 @@ int how;
     } else {
         for (i = 0;; i++) {
             if (i >= 5) {
+                /* cursed effect => no free pass (unless rndmonst() fails) */
+                if (!(how & REALLY) && (ptr = rndmonst()) != 0)
+                    break;
+
                 pline1(thats_enough_tries);
                 return;
             }
@@ -2702,19 +2791,18 @@ int how;
                    buf);
             (void) mungspaces(buf);
             /* choosing "none" preserves genocideless conduct */
-/*JP
-            if (!strcmpi(buf, "none") || !strcmpi(buf, "nothing")) {
-*/
-            if (!strcmpi(buf, "\82È\82µ") || !strcmpi(buf, "\96³\82µ")) {
+#if 0 /*JP:T*/
+            if (*buf == '\033' || !strcmpi(buf, "none")
+                || !strcmpi(buf, "nothing")) {
+#else
+            if (*buf == '\033' || !strcmpi(buf, "\82È\82µ")
+                || !strcmpi(buf, "\96³\82µ")) {
+#endif
                 /* ... but no free pass if cursed */
-                if (!(how & REALLY)) {
-                    ptr = rndmonst();
-                    if (!ptr)
-                        return; /* no message, like normal case */
-                    mndx = monsndx(ptr);
+                if (!(how & REALLY) && (ptr = rndmonst()) != 0)
                     break; /* remaining checks don't apply */
-                } else
-                    return;
+
+                return;
             }
 
             mndx = name_to_mon(buf);
@@ -2743,14 +2831,15 @@ int how;
 
             if (!(ptr->geno & G_GENO)) {
                 if (!Deaf) {
-                    /* fixme: unconditional "caverns" will be silly in some
-                     * circumstances */
+                    /* FIXME: unconditional "caverns" will be silly in some
+                     * circumstances.  Who's speaking?  Divine pronouncements
+                     * aren't supposed to be hampered by deafness....
+                     */
                     if (flags.verbose)
-                        pline(
 /*JP
-                            "A thunderous voice booms through the caverns:");
+                        pline("A thunderous voice booms through the caverns:");
 */
-                            "\97\8b\82Ì\82æ\82¤\82È\90º\82ª\93´\8cA\82É\8b¿\82¢\82½\81F");
+                        pline("\97\8b\82Ì\82æ\82¤\82È\90º\82ª\93´\8cA\82É\8b¿\82¢\82½\81F");
 /*JP
                     verbalize("No, mortal!  That will not be done.");
 */
@@ -2763,6 +2852,7 @@ int how;
                 killplayer++;
             break;
         }
+        mndx = monsndx(ptr); /* needed for the 'no free pass' cases */
     }
 
 /*JP
@@ -2835,9 +2925,9 @@ int how;
             if (Upolyd && ptr != youmonst.data) {
                 delayed_killer(POLYMORPH, killer.format, killer.name);
 /*JP
-                You_feel("dead inside.");
+                You_feel("%s inside.", udeadinside());
 */
-                You("\8d°\82ª\8e\80\82ñ\82¾\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
+                You_feel("\8d°\82ª%s\82æ\82¤\82È\8bC\82ª\82µ\82½\81D", udeadinside());
             } else
                 done(GENOCIDED);
         } else if (ptr == youmonst.data) {
@@ -2891,7 +2981,7 @@ struct obj *sobj;
         Your("iron ball gets heavier.");
 */
         Your("\93S\8b\85\82Í\82³\82ç\82É\8fd\82­\82È\82Á\82½\81D");
-        uball->owt += 160 * (1 + sobj->cursed);
+        uball->owt += IRON_BALL_W_INCR * (1 + sobj->cursed);
         return;
     }
     if (amorphous(youmonst.data) || is_whirly(youmonst.data)
@@ -2984,19 +3074,23 @@ struct obj *from_obj;
 boolean
 create_particular()
 {
-    char buf[BUFSZ], *bufp, monclass;
+    char buf[BUFSZ] = DUMMY, *bufp, monclass;
+    char *tmpp;
     int which, tryct, i, firstchoice = NON_PM;
     struct permonst *whichpm = NULL;
     struct monst *mtmp;
-    boolean madeany = FALSE;
-    boolean maketame, makepeaceful, makehostile;
-    boolean randmonst = FALSE;
+    boolean madeany = FALSE, randmonst = FALSE,
+        maketame, makepeaceful, makehostile, saddled, invisible,
+        sleeping;
+    int fem;
 
     tryct = 5;
     do {
         monclass = MAXMCLASSES;
         which = urole.malenum; /* an arbitrary index into mons[] */
         maketame = makepeaceful = makehostile = FALSE;
+        sleeping = saddled = invisible = FALSE;
+        fem = -1; /* gender not specified */
 /*JP
         getlin("Create what kind of monster? [type the name or symbol]", buf);
 */
@@ -3004,6 +3098,28 @@ create_particular()
         bufp = mungspaces(buf);
         if (*bufp == '\033')
             return FALSE;
+        if ((tmpp = strstri(bufp, "saddled ")) != 0) {
+            saddled = TRUE;
+            (void) memset(tmpp, ' ', sizeof "saddled " - 1);
+        }
+        if ((tmpp = strstri(bufp, "sleeping ")) != 0) {
+            sleeping = TRUE;
+            (void) memset(tmpp, ' ', sizeof "sleeping " - 1);
+        }
+        if ((tmpp = strstri(bufp, "invisible ")) != 0) {
+            invisible = TRUE;
+            (void) memset(tmpp, ' ', sizeof "invisible " - 1);
+        }
+        /* check "female" before "male" to avoid false hit mid-word */
+        if ((tmpp = strstri(bufp, "female ")) != 0) {
+            fem = 1;
+            (void) memset(tmpp, ' ', sizeof "female " - 1);
+        }
+        if ((tmpp = strstri(bufp, "male ")) != 0) {
+            fem = 0;
+            (void) memset(tmpp, ' ', sizeof "male " - 1);
+        }
+        bufp = mungspaces(bufp); /* after potential memset(' ') */
         /* allow the initial disposition to be specified */
 #if 0 /*JP*/
         if (!strncmpi(bufp, "tame ", 5)) {
@@ -3088,6 +3204,9 @@ create_particular()
                 /* otherwise try again */
                 continue;
             }
+            /* 'is_FOO()' ought to be called 'always_FOO()' */
+            if (fem != -1 && !is_male(mtmp->data) && !is_female(mtmp->data))
+                mtmp->female = fem; /* ignored for is_neuter() */
             if (maketame) {
                 (void) tamedog(mtmp, (struct obj *) 0);
             } else if (makepeaceful || makehostile) {
@@ -3095,6 +3214,15 @@ create_particular()
                 mtmp->mpeaceful = makepeaceful ? 1 : 0;
                 set_malign(mtmp);
             }
+            if (saddled && can_saddle(mtmp) && !which_armor(mtmp, W_SADDLE)) {
+                struct obj *otmp = mksobj(SADDLE, TRUE, FALSE);
+
+                put_saddle_on_mon(otmp, mtmp);
+            }
+            if (invisible)
+                mon_set_minvis(mtmp);
+            if (sleeping)
+                mtmp->msleeping = 1;
             madeany = TRUE;
             /* in case we got a doppelganger instead of what was asked
                for, make it start out looking like what was asked for */
index 5107bf1..e8f2b5a 100644 (file)
@@ -1,5 +1,5 @@
 /* NetHack 3.6 rect.c  $NHDT-Date: 1432512774 2015/05/25 00:12:54 $  $NHDT-Branch: master $:$NHDT-Revision: 1.11 $ */
-/* Copyright (c) 1990 by Jean-Christophe Collet         */
+/* Copyright (c) 1990 by Jean-Christophe Collet                   */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
index 16faa36..9f57b53 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 region.c        $NHDT-Date: 1446892454 2015/11/07 10:34:14 $  $NHDT-Branch: master $:$NHDT-Revision: 1.36 $ */
+/* NetHack 3.6 region.c        $NHDT-Date: 1496087244 2017/05/29 19:47:24 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.40 $ */
 /* Copyright (c) 1996 by Jean-Christophe Collet  */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -96,18 +96,18 @@ int nrect;
     NhRegion *reg;
 
     reg = (NhRegion *) alloc(sizeof(NhRegion));
+    (void) memset((genericptr_t)reg, 0, sizeof(NhRegion));
     /* Determines bounding box */
     if (nrect > 0) {
         reg->bounding_box = rects[0];
     } else {
-        reg->bounding_box.lx = 99;
-        reg->bounding_box.ly = 99;
-        reg->bounding_box.hx = 0;
+        reg->bounding_box.lx = COLNO;
+        reg->bounding_box.ly = ROWNO;
+        reg->bounding_box.hx = 0; /* 1 */
         reg->bounding_box.hy = 0;
     }
     reg->nrects = nrect;
-    reg->rects =
-        nrect > 0 ? (NhRect *) alloc((sizeof(NhRect)) * nrect) : (NhRect *) 0;
+    reg->rects = (nrect > 0) ? (NhRect *) alloc(nrect * sizeof (NhRect)) : 0;
     for (i = 0; i < nrect; i++) {
         if (rects[i].lx < reg->bounding_box.lx)
             reg->bounding_box.lx = rects[i].lx;
@@ -150,10 +150,10 @@ NhRect *rect;
 {
     NhRect *tmp_rect;
 
-    tmp_rect = (NhRect *) alloc(sizeof(NhRect) * (reg->nrects + 1));
+    tmp_rect = (NhRect *) alloc((reg->nrects + 1) * sizeof (NhRect));
     if (reg->nrects > 0) {
         (void) memcpy((genericptr_t) tmp_rect, (genericptr_t) reg->rects,
-                      (sizeof(NhRect) * reg->nrects));
+                      reg->nrects * sizeof (NhRect));
         free((genericptr_t) reg->rects);
     }
     tmp_rect[reg->nrects] = *rect;
@@ -182,7 +182,7 @@ struct monst *mon;
     unsigned *tmp_m;
 
     if (reg->max_monst <= reg->n_monst) {
-        tmp_m = (unsigned *) alloc(sizeof(unsigned)
+        tmp_m = (unsigned *) alloc(sizeof (unsigned)
                                    * (reg->max_monst + MONST_INC));
         if (reg->max_monst > 0) {
             for (i = 0; i < reg->max_monst; i++)
@@ -302,10 +302,10 @@ NhRegion *reg;
     if (max_regions <= n_regions) {
         tmp_reg = regions;
         regions =
-            (NhRegion **) alloc(sizeof(NhRegion *) * (max_regions + 10));
+            (NhRegion **) alloc((max_regions + 10) * sizeof (NhRegion *));
         if (max_regions > 0) {
             (void) memcpy((genericptr_t) regions, (genericptr_t) tmp_reg,
-                          max_regions * sizeof(NhRegion *));
+                          max_regions * sizeof (NhRegion *));
             free((genericptr_t) tmp_reg);
         }
         max_regions += 10;
@@ -768,6 +768,32 @@ boolean ghostly; /* If a bones file restore */
             reset_region_mids(regions[i]);
 }
 
+/* to support '#stats' wizard-mode command */
+void
+region_stats(hdrfmt, hdrbuf, count, size)
+const char *hdrfmt;
+char *hdrbuf;
+long *count, *size;
+{
+    NhRegion *rg;
+    int i;
+
+    /* other stats formats take one parameter; this takes two */
+    Sprintf(hdrbuf, hdrfmt, (long) sizeof (NhRegion), (long) sizeof (NhRect));
+    *count = (long) n_regions; /* might be 0 even though max_regions isn't */
+    *size = (long) max_regions * (long) sizeof (NhRegion);
+    for (i = 0; i < n_regions; ++i) {
+        rg = regions[i];
+        *size += (long) rg->nrects * (long) sizeof (NhRect);
+        if (rg->enter_msg)
+            *size += (long) (strlen(rg->enter_msg) + 1);
+        if (rg->leave_msg)
+            *size += (long) (strlen(rg->leave_msg) + 1);
+        *size += (long) rg->max_monst * (long) sizeof *rg->monsters;
+    }
+    /* ? */
+}
+
 /* update monster IDs for region being loaded from bones; `ghostly' implied */
 STATIC_OVL void
 reset_region_mids(reg)
@@ -961,16 +987,22 @@ genericptr_t p2;
     } else { /* A monster is inside the cloud */
         mtmp = (struct monst *) p2;
 
-        /* Non living and non breathing monsters are not concerned */
+        /* Non living and non breathing monsters are not concerned;
+           adult green dragon is not affected by gas cloud, baby one is */
         if (!(nonliving(mtmp->data) || is_vampshifter(mtmp))
-            && !breathless(mtmp->data)) {
+            && !breathless(mtmp->data)
+            /* exclude monsters with poison gas breath attack:
+               adult green dragon and Chromatic Dragon (and iron golem,
+               but nonliving() and breathless() tests also catch that) */
+            && !(attacktype_fordmg(mtmp->data, AT_BREA, AD_DRST)
+                 || attacktype_fordmg(mtmp->data, AT_BREA, AD_RBRE))) {
             if (cansee(mtmp->mx, mtmp->my))
 /*JP
                 pline("%s coughs!", Monnam(mtmp));
 */
                 pline("%s\82Í\8aP\82«\82±\82ñ\82¾\81I", Monnam(mtmp));
             if (heros_fault(reg))
-                setmangry(mtmp);
+                setmangry(mtmp, TRUE);
             if (haseyes(mtmp->data) && mtmp->mcansee) {
                 mtmp->mblinded = 1;
                 mtmp->mcansee = 0;
index 3ece4f1..cda3e8f 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 restore.c       $NHDT-Date: 1446892455 2015/11/07 10:34:15 $  $NHDT-Branch: master $:$NHDT-Revision: 1.101 $ */
+/* NetHack 3.6 restore.c       $NHDT-Date: 1451082255 2015/12/25 22:24:15 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.103 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2009. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -542,7 +543,7 @@ unsigned int *stuckid, *steedid;
             return FALSE;
     }
     mread(fd, (genericptr_t) &context, sizeof(struct context_info));
-    if (context.warntype.speciesidx)
+    if (context.warntype.speciesidx >= LOW_PM)
         context.warntype.species = &mons[context.warntype.speciesidx];
 
     /* we want to be able to revert to command line/environment/config
@@ -579,20 +580,10 @@ unsigned int *stuckid, *steedid;
     foo = time_from_yyyymmddhhmmss(timebuf);
 
     ReadTimebuf(ubirthday);
-#if 0 /*C360-19*/
-    mread(fd, &urealtime.realtime, sizeof(urealtime.realtime));
-    ReadTimebuf(urealtime.restored);
-#if defined(BSD) && !defined(POSIX_TYPES)
-    (void) time((long *) &urealtime.restored);
-#else
-    (void) time(&urealtime.restored);
-#endif
-#else
     mread(fd, &urealtime.realtime, sizeof urealtime.realtime);
     ReadTimebuf(urealtime.start_timing); /** [not used] **/
     /* current time is the time to use for next urealtime.realtime update */
     urealtime.start_timing = getnow();
-#endif
 
     set_uasmon();
 #ifdef CLIPPING
@@ -775,7 +766,7 @@ xchar ltmp;
         pline("Be seeing you...");
 */
         pline("\82Ü\82½\89ï\82¢\82Ü\82µ\82å\82¤\81D\81D\81D");
-        terminate(EXIT_SUCCESS);
+        nh_terminate(EXIT_SUCCESS);
     }
 #endif /* MFLOPPY */
     bufon(nfd);
index 2ca5cad..f63c04e 100644 (file)
--- a/src/rip.c
+++ b/src/rip.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 rip.c   $NHDT-Date: 1436753522 2015/07/13 02:12:02 $  $NHDT-Branch: master $:$NHDT-Revision: 1.18 $ */
+/* NetHack 3.6 rip.c   $NHDT-Date: 1488788514 2017/03/06 08:21:54 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.23 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2017. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -12,7 +13,7 @@
 STATIC_DCL void FDECL(center, (int, char *));
 
 #if defined(TTY_GRAPHICS) || defined(X11_GRAPHICS) || defined(GEM_GRAPHICS) \
-    || defined(MSWIN_GRAPHICS)
+    || defined(MSWIN_GRAPHICS) || defined(DUMPLOG)
 #define TEXT_TOMBSTONE
 #endif
 #if defined(mac) || defined(__BEOS__) || defined(WIN32_GRAPHICS)
@@ -117,7 +118,7 @@ time_t when;
     center(GOLD_LINE, buf);
 
     /* Put together death description */
-    formatkiller(buf, sizeof buf, how);
+    formatkiller(buf, sizeof buf, how, FALSE);
 
     /* Put death type on stone */
     for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; line++) {
@@ -172,12 +173,21 @@ time_t when;
     Sprintf(buf, "%4ld", year);
     center(YEAR_LINE, buf);
 
-    putstr(tmpwin, 0, "");
+#ifdef DUMPLOG
+    if (tmpwin == 0)
+        dump_forward_putstr(0, 0, "Game over:", TRUE);
+    else
+#endif
+        putstr(tmpwin, 0, "");
+
     for (; *dp; dp++)
         putstr(tmpwin, 0, *dp);
 
     putstr(tmpwin, 0, "");
-    putstr(tmpwin, 0, "");
+#ifdef DUMPLOG
+    if (tmpwin != 0)
+#endif
+        putstr(tmpwin, 0, "");
 
     for (x = 0; rip_txt[x]; x++) {
         free((genericptr_t) rip[x]);
index 8c15f22..c3627e8 100644 (file)
--- a/src/rnd.c
+++ b/src/rnd.c
@@ -1,4 +1,5 @@
-/* NetHack 3.6 rnd.c   $NHDT-Date: 1446883921 2015/11/07 08:12:01 $  $NHDT-Branch: master $:$NHDT-Revision: 1.16 $ */
+/* NetHack 3.6 rnd.c   $NHDT-Date: 1524689470 2018/04/25 20:51:10 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.18 $ */
+/*      Copyright (c) 2004 by Robert Patrick Rankin               */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
index ee5915b..f1deb1e 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 role.c  $NHDT-Date: 1446861770 2015/11/07 02:02:50 $  $NHDT-Branch: master $:$NHDT-Revision: 1.34 $ */
+/* NetHack 3.6 role.c  $NHDT-Date: 1463561393 2016/05/18 08:49:53 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.38 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -1071,7 +1072,7 @@ const struct Align aligns[] = {
 static struct {
     boolean roles[SIZE(roles)];
     short mask;
-} filter;
+} rfilter;
 
 STATIC_DCL int NDECL(randrole_filtered);
 STATIC_DCL char *FDECL(promptsep, (char *, int));
@@ -1352,7 +1353,7 @@ int rolenum, racenum, gendnum, alignnum;
     short allow;
 
     if (rolenum >= 0 && rolenum < SIZE(roles) - 1) {
-        if (filter.roles[rolenum])
+        if (rfilter.roles[rolenum])
             return FALSE;
         allow = roles[rolenum].allow;
         if (racenum >= 0 && racenum < SIZE(races) - 1
@@ -1368,7 +1369,7 @@ int rolenum, racenum, gendnum, alignnum;
     } else {
         /* random; check whether any selection is possible */
         for (i = 0; i < SIZE(roles) - 1; i++) {
-            if (filter.roles[i])
+            if (rfilter.roles[i])
                 continue;
             allow = roles[i].allow;
             if (racenum >= 0 && racenum < SIZE(races) - 1
@@ -1420,7 +1421,7 @@ int rolenum, racenum, gendnum, alignnum;
     short allow;
 
     if (racenum >= 0 && racenum < SIZE(races) - 1) {
-        if (filter.mask & races[racenum].selfmask)
+        if (rfilter.mask & races[racenum].selfmask)
             return FALSE;
         allow = races[racenum].allow;
         if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1436,7 +1437,7 @@ int rolenum, racenum, gendnum, alignnum;
     } else {
         /* random; check whether any selection is possible */
         for (i = 0; i < SIZE(races) - 1; i++) {
-            if (filter.mask & races[i].selfmask)
+            if (rfilter.mask & races[i].selfmask)
                 continue;
             allow = races[i].allow;
             if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1454,9 +1455,9 @@ int rolenum, racenum, gendnum, alignnum;
     }
 }
 
-/* pick a random race subject to any rolenum/gendnum/alignnum constraints */
-/* If pickhow == PICK_RIGID a race is returned only if there is  */
-/* a single possibility */
+/* Pick a random race subject to any rolenum/gendnum/alignnum constraints.
+   If pickhow == PICK_RIGID a race is returned only if there is
+   a single possibility. */
 int
 pick_race(rolenum, gendnum, alignnum, pickhow)
 int rolenum, gendnum, alignnum, pickhow;
@@ -1493,7 +1494,7 @@ int alignnum UNUSED;
     short allow;
 
     if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
-        if (filter.mask & genders[gendnum].allow)
+        if (rfilter.mask & genders[gendnum].allow)
             return FALSE;
         allow = genders[gendnum].allow;
         if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1506,7 +1507,7 @@ int alignnum UNUSED;
     } else {
         /* random; check whether any selection is possible */
         for (i = 0; i < ROLE_GENDERS; i++) {
-            if (filter.mask & genders[i].allow)
+            if (rfilter.mask & genders[i].allow)
                 continue;
             allow = genders[i].allow;
             if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1562,7 +1563,7 @@ int alignnum;
     short allow;
 
     if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
-        if (filter.mask & aligns[alignnum].allow)
+        if (rfilter.mask & aligns[alignnum].allow)
             return FALSE;
         allow = aligns[alignnum].allow;
         if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1575,7 +1576,7 @@ int alignnum;
     } else {
         /* random; check whether any selection is possible */
         for (i = 0; i < ROLE_ALIGNS; i++) {
-            if (filter.mask & aligns[i].allow)
+            if (rfilter.mask & aligns[i].allow)
                 return FALSE;
             allow = aligns[i].allow;
             if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1590,11 +1591,10 @@ int alignnum;
     }
 }
 
-/* pick a random alignment subject to any rolenum/racenum/gendnum constraints
- */
-/* alignment and gender are not comparable (and also not constrainable) */
-/* If pickhow == PICK_RIGID an alignment is returned only if there is  */
-/* a single possibility */
+/* Pick a random alignment subject to any rolenum/racenum/gendnum constraints;
+   alignment and gender are not comparable (and also not constrainable).
+   If pickhow == PICK_RIGID an alignment is returned only if there is
+   a single possibility. */
 int
 pick_align(rolenum, racenum, gendnum, pickhow)
 int rolenum, racenum, gendnum, pickhow;
@@ -1623,6 +1623,8 @@ int rolenum, racenum, gendnum, pickhow;
 void
 rigid_role_checks()
 {
+    int tmp;
+
     /* Some roles are limited to a single race, alignment, or gender and
      * calling this routine prior to XXX_player_selection() will help
      * prevent an extraneous prompt that actually doesn't allow
@@ -1633,14 +1635,27 @@ rigid_role_checks()
      */
     if (flags.initrole == ROLE_RANDOM) {
         /* If the role was explicitly specified as ROLE_RANDOM
-         * via -uXXXX-@ then choose the role in here to narrow down
-         * later choices. Pick a random role in this case.
+         * via -uXXXX-@ or OPTIONS=role:random then choose the role
+         * in here to narrow down later choices.
          */
         flags.initrole = pick_role(flags.initrace, flags.initgend,
                                    flags.initalign, PICK_RANDOM);
         if (flags.initrole < 0)
             flags.initrole = randrole_filtered();
     }
+    if (flags.initrace == ROLE_RANDOM
+        && (tmp = pick_race(flags.initrole, flags.initgend,
+                            flags.initalign, PICK_RANDOM)) != ROLE_NONE)
+        flags.initrace = tmp;
+    if (flags.initalign == ROLE_RANDOM
+        && (tmp = pick_align(flags.initrole, flags.initrace,
+                             flags.initgend, PICK_RANDOM)) != ROLE_NONE)
+        flags.initalign = tmp;
+    if (flags.initgend == ROLE_RANDOM
+        && (tmp = pick_gend(flags.initrole, flags.initrace,
+                            flags.initalign, PICK_RANDOM)) != ROLE_NONE)
+        flags.initgend = tmp;
+
     if (flags.initrole != ROLE_NONE) {
         if (flags.initrace == ROLE_NONE)
             flags.initrace = pick_race(flags.initrole, flags.initgend,
@@ -1662,13 +1677,13 @@ const char *bufp;
     boolean reslt = TRUE;
 
     if ((i = str2role(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
-        filter.roles[i] = TRUE;
+        rfilter.roles[i] = TRUE;
     else if ((i = str2race(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
-        filter.mask |= races[i].selfmask;
+        rfilter.mask |= races[i].selfmask;
     else if ((i = str2gend(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
-        filter.mask |= genders[i].allow;
+        rfilter.mask |= genders[i].allow;
     else if ((i = str2align(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
-        filter.mask |= aligns[i].allow;
+        rfilter.mask |= aligns[i].allow;
     else
         reslt = FALSE;
     return reslt;
@@ -1679,10 +1694,10 @@ gotrolefilter()
 {
     int i;
 
-    if (filter.mask)
+    if (rfilter.mask)
         return TRUE;
     for (i = 0; i < SIZE(roles); ++i)
-        if (filter.roles[i])
+        if (rfilter.roles[i])
             return TRUE;
     return FALSE;
 }
@@ -1693,8 +1708,8 @@ clearrolefilter()
     int i;
 
     for (i = 0; i < SIZE(roles); ++i)
-        filter.roles[i] = FALSE;
-    filter.mask = 0;
+        rfilter.roles[i] = FALSE;
+    rfilter.mask = 0;
 }
 
 #define BP_ALIGN 0
@@ -1992,7 +2007,20 @@ int buflen, rolenum, racenum, gendnum, alignnum;
      * Now append the post attributes to it
      */
     num_post_attribs = post_attribs;
-    if (post_attribs) {
+    if (!num_post_attribs) {
+        /* some constraints might have been mutually exclusive, in which case
+           some prompting that would have been omitted is needed after all */
+        if (flags.initrole == ROLE_NONE && !pa[BP_ROLE])
+            pa[BP_ROLE] = ++post_attribs;
+        if (flags.initrace == ROLE_NONE && !pa[BP_RACE])
+            pa[BP_RACE] = ++post_attribs;
+        if (flags.initalign == ROLE_NONE && !pa[BP_ALIGN])
+            pa[BP_ALIGN] = ++post_attribs;
+        if (flags.initgend == ROLE_NONE && !pa[BP_GEND])
+            pa[BP_GEND] = ++post_attribs;
+        num_post_attribs = post_attribs;
+    }
+    if (num_post_attribs) {
         if (pa[BP_RACE]) {
             (void) promptsep(eos(buf), num_post_attribs);
 /*
@@ -2041,22 +2069,21 @@ plnamesuffix()
     char *sptr, *eptr;
     int i;
 
-#ifdef GENERIC_USERNAMES
-    {
-        /* some generic user names will be ignored in favor of prompting */
-        const char *uptr = GENERIC_USERNAMES;
-
-        i = (int) strlen(plname);
-        if ((sptr = strstri(uptr, plname)) != 0
-            && (sptr == uptr || sptr[-1] == ' ')
-            && (sptr[i] == ' ' || sptr[i] == '\0'))
-            *plname = '\0'; /* call askname() */
+    /* some generic user names will be ignored in favor of prompting */
+    if (sysopt.genericusers) {
+       if (*sysopt.genericusers == '*') *plname = '\0';
+       else {
+           i = (int)strlen(plname);
+           if ((sptr = strstri(sysopt.genericusers, plname)) != 0
+               && (sptr == sysopt.genericusers || sptr[-1] == ' ')
+               && (sptr[i] == ' ' || sptr[i] == '\0'))
+               *plname = '\0'; /* call askname() */
+       }
     }
-#endif
 
     do {
         if (!*plname)
-            askname(); /* fill plname[] if necessary */
+            askname(); /* fill plname[] if necessary, or set defer_plname */
 
         /* Look for tokens delimited by '-' */
         if ((eptr = index(plname, '-')) != (char *) 0)
@@ -2077,7 +2104,7 @@ plnamesuffix()
             else if ((i = str2align(sptr)) != ROLE_NONE)
                 flags.initalign = i;
         }
-    } while (!*plname);
+    } while (!*plname && !iflags.defer_plname);
 
     /* commas in the plname confuse the record file, convert to spaces */
     for (sptr = plname; *sptr; sptr++) {
@@ -2205,9 +2232,10 @@ winid where;
 
 /* add a "pick alignment first"-type entry to the specified menu */
 void
-role_menu_extra(which, where)
+role_menu_extra(which, where, preselect)
 int which;
 winid where;
+boolean preselect;
 {
     static NEARDATA const char RS_menu_let[] = {
         '=',  /* name */
@@ -2237,7 +2265,7 @@ winid where;
         what = "\90E\8bÆ";
         f = r;
         for (i = 0; i < SIZE(roles); ++i)
-            if (i != f && !filter.roles[i])
+            if (i != f && !rfilter.roles[i])
                 break;
         if (i == SIZE(roles)) {
 /*JP
@@ -2268,7 +2296,7 @@ winid where;
                 constrainer = "\90E\8bÆ";
                 forcedvalue = races[c].noun;
             } else if (f >= 0
-                       && (allowmask & ~filter.mask) == races[f].selfmask) {
+                       && (allowmask & ~rfilter.mask) == races[f].selfmask) {
                 /* if there is only one race choice available due to user
                    options disallowing others, race menu entry is disabled */
 /*JP
@@ -2302,7 +2330,7 @@ winid where;
                 constrainer = "\90E\8bÆ";
                 forcedvalue = genders[g].adj;
             } else if (f >= 0
-                       && (allowmask & ~filter.mask) == genders[f].allow) {
+                       && (allowmask & ~rfilter.mask) == genders[f].allow) {
                 /* if there is only one gender choice available due to user
                    options disallowing other, gender menu entry is disabled */
 /*JP
@@ -2352,7 +2380,7 @@ winid where;
                 constrainer = "\8eí\91°";
         }
         if (f >= 0 && !constrainer
-            && (ROLE_ALIGNMASK & ~filter.mask) == aligns[f].allow) {
+            && (ROLE_ALIGNMASK & ~rfilter.mask) == aligns[f].allow) {
             /* if there is only one alignment choice available due to user
                options disallowing others, algn menu entry is disabled */
 /*JP
@@ -2381,7 +2409,7 @@ winid where;
         Sprintf(buf, "%4s%s forces %s", "", constrainer, forcedvalue);
 */
         Sprintf(buf, "%4s\82±\82Ì%s\82Å\82Í%s\82Ì\82Ý", "", constrainer, forcedvalue);
-        add_menu(where, NO_GLYPH, &any, ' ', 0, ATR_NONE, buf,
+        add_menu(where, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
                  MENU_UNSELECTED);
     } else if (what) {
         any.a_int = RS_menu_arg(which);
@@ -2393,7 +2421,7 @@ winid where;
                  MENU_UNSELECTED);
     } else if (which == RS_filter) {
         any.a_int = RS_menu_arg(RS_filter);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         add_menu(where, NO_GLYPH, &any, '~', 0, ATR_NONE,
                  "Reset role/race/&c filtering", MENU_UNSELECTED);
 #else
@@ -2402,18 +2430,18 @@ winid where;
 #endif
     } else if (which == ROLE_RANDOM) {
         any.a_int = ROLE_RANDOM;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
-                 MENU_UNSELECTED);
+                 preselect ? MENU_SELECTED : MENU_UNSELECTED);
 #else
         add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "\83\89\83\93\83_\83\80",
                  MENU_UNSELECTED);
 #endif
     } else if (which == ROLE_NONE) {
         any.a_int = ROLE_NONE;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         add_menu(where, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
-                 MENU_UNSELECTED);
+                 preselect ? MENU_SELECTED : MENU_UNSELECTED);
 #else
         add_menu(where, NO_GLYPH, &any, 'q', 0, ATR_NONE, "\94²\82¯\82é",
                  MENU_UNSELECTED);
index f0a4f08..6fa7921 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 rumors.c        $NHDT-Date: 1446713640 2015/11/05 08:54:00 $  $NHDT-Branch: master $:$NHDT-Revision: 1.27 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
index a20b2ea..47fbe26 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 save.c  $NHDT-Date: 1448241784 2015/11/23 01:23:04 $  $NHDT-Branch: master $:$NHDT-Revision: 1.95 $ */
+/* NetHack 3.6 save.c  $NHDT-Date: 1489192905 2017/03/11 00:41:45 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.101 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2009. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -69,8 +70,6 @@ static struct save_procs {
 #endif
 };
 
-static long nulls[sizeof(struct trap) + sizeof(struct fruit)];
-
 #if defined(UNIX) || defined(VMS) || defined(__EMX__) || defined(WIN32)
 #define HUP if (!program_state.done_hup)
 #else
@@ -108,7 +107,7 @@ dosave()
             exit_nhwindows("Be seeing you...");
 */
             exit_nhwindows("\82Ü\82½\89ï\82¢\82Ü\82µ\82å\82¤\81D\81D\81D");
-            terminate(EXIT_SUCCESS);
+            nh_terminate(EXIT_SUCCESS);
         } else
             (void) doredraw();
     }
@@ -129,6 +128,8 @@ dosave0()
        a few of things before saving so that they won't be restored in
        an improper state; these will be no-ops for normal save sequence */
     u.uinvulnerable = 0;
+    if (iflags.save_uswallow)
+        u.uswallow = 1, iflags.save_uswallow = 0;
     if (iflags.save_uinwater)
         u.uinwater = 1, iflags.save_uinwater = 0;
     if (iflags.save_uburied)
@@ -309,14 +310,6 @@ register int fd, mode;
 #ifdef SYSFLAGS
     bwrite(fd, (genericptr_t) &sysflags, sizeof(struct sysflag));
 #endif
-#if 0 /*C360-19*/
-    urealtime.realtime += (long) (getnow() - urealtime.restored);
-    bwrite(fd, (genericptr_t) &u, sizeof(struct you));
-    bwrite(fd, yyyymmddhhmmss(ubirthday), 14);
-    bwrite(fd, (genericptr_t) &urealtime.realtime,
-           sizeof(urealtime.realtime));
-    bwrite(fd, yyyymmddhhmmss(urealtime.restored), 14);
-#else
     urealtime.finish_time = getnow();
     urealtime.realtime += (long) (urealtime.finish_time
                                   - urealtime.start_timing);
@@ -326,7 +319,6 @@ register int fd, mode;
     bwrite(fd, yyyymmddhhmmss(urealtime.start_timing), 14);  /** Why? **/
     /* this is the value to use for the next update of urealtime.realtime */
     urealtime.start_timing = urealtime.finish_time;
-#endif
     save_killers(fd, mode);
 
     /* must come before migrating_objs and migrating_mons are freed */
@@ -761,7 +753,7 @@ register unsigned num;
     if (failed) {
 #if defined(UNIX) || defined(VMS) || defined(__EMX__)
         if (program_state.done_hup)
-            terminate(EXIT_FAILURE);
+            nh_terminate(EXIT_FAILURE);
         else
 #endif
             panic("cannot write %u bytes to file #%d", num, fd);
@@ -867,7 +859,7 @@ register int fd;
         if (write(fd, outbuf, outbufp) != outbufp) {
 #if defined(UNIX) || defined(VMS) || defined(__EMX__)
             if (program_state.done_hup)
-                terminate(EXIT_FAILURE);
+                nh_terminate(EXIT_FAILURE);
             else
 #endif
                 zerocomp_bclose(fd); /* panic (outbufp != 0) */
@@ -893,7 +885,7 @@ register unsigned num;
         if ((unsigned) write(fd, loc, num) != num) {
 #if defined(UNIX) || defined(VMS) || defined(__EMX__)
             if (program_state.done_hup)
-                terminate(EXIT_FAILURE);
+                nh_terminate(EXIT_FAILURE);
             else
 #endif
                 panic("cannot write %u bytes to file #%d", num, fd);
@@ -1208,23 +1200,26 @@ register struct monst *mtmp;
         bwrite(fd, (genericptr_t) &minusone, sizeof(int));
 }
 
+/* save traps; ftrap is the only trap chain so the 2nd arg is superfluous */
 STATIC_OVL void
 savetrapchn(fd, trap, mode)
-register int fd, mode;
+int fd;
 register struct trap *trap;
+int mode;
 {
+    static struct trap zerotrap;
     register struct trap *trap2;
 
     while (trap) {
         trap2 = trap->ntrap;
         if (perform_bwrite(mode))
-            bwrite(fd, (genericptr_t) trap, sizeof(struct trap));
+            bwrite(fd, (genericptr_t) trap, sizeof (struct trap));
         if (release_data(mode))
             dealloc_trap(trap);
         trap = trap2;
     }
     if (perform_bwrite(mode))
-        bwrite(fd, (genericptr_t) nulls, sizeof(struct trap));
+        bwrite(fd, (genericptr_t) &zerotrap, sizeof zerotrap);
 }
 
 /* save all the fruit names and ID's; this is used only in saving whole games
@@ -1234,21 +1229,22 @@ register struct trap *trap;
  */
 void
 savefruitchn(fd, mode)
-register int fd, mode;
+int fd, mode;
 {
+    static struct fruit zerofruit;
     register struct fruit *f2, *f1;
 
     f1 = ffruit;
     while (f1) {
         f2 = f1->nextf;
         if (f1->fid >= 0 && perform_bwrite(mode))
-            bwrite(fd, (genericptr_t) f1, sizeof(struct fruit));
+            bwrite(fd, (genericptr_t) f1, sizeof (struct fruit));
         if (release_data(mode))
             dealloc_fruit(f1);
         f1 = f2;
     }
     if (perform_bwrite(mode))
-        bwrite(fd, (genericptr_t) nulls, sizeof(struct fruit));
+        bwrite(fd, (genericptr_t) &zerofruit, sizeof zerofruit);
     if (release_data(mode))
         ffruit = 0;
 }
@@ -1258,6 +1254,7 @@ store_plname_in_file(fd)
 int fd;
 {
     int plsiztmp = PL_NSIZ;
+
     bufoff(fd);
     /* bwrite() before bufon() uses plain write() */
     bwrite(fd, (genericptr_t) &plsiztmp, sizeof(plsiztmp));
@@ -1367,6 +1364,9 @@ free_dungeons()
 void
 freedynamicdata()
 {
+#if defined(UNIX) && defined(MAIL)
+    free_maildata();
+#endif
     unload_qtlist();
     free_menu_coloring();
     free_invbuf();           /* let_to_name (invent.c) */
@@ -1440,9 +1440,12 @@ freedynamicdata()
     /* free_pickinv_cache();  --  now done from really_done()... */
     free_symsets();
 #endif /* FREE_ALL_MEMORY */
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
     status_finish();
 #endif
+#ifdef DUMPLOG
+    dumplogfreemessages();
+#endif
 
     /* last, because it frees data that might be used by panic() to provide
        feedback to the user; conceivably other freeing might trigger panic */
index ddad293..b415be3 100644 (file)
--- a/src/shk.c
+++ b/src/shk.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 shk.c   $NHDT-Date: 1446854234 2015/11/06 23:57:14 $  $NHDT-Branch: master $:$NHDT-Revision: 1.116 $ */
+/* NetHack 3.6 shk.c   $NHDT-Date: 1515144230 2018/01/05 09:23:50 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.136 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -39,7 +40,6 @@ STATIC_VAR const char the_contents_of[] = "the contents of ";
 #endif
 
 STATIC_DCL void FDECL(append_honorific, (char *));
-STATIC_DCL void FDECL(setpaid, (struct monst *));
 STATIC_DCL long FDECL(addupbill, (struct monst *));
 STATIC_DCL void FDECL(pacify_shk, (struct monst *));
 STATIC_DCL struct bill_x *FDECL(onbill, (struct obj *, struct monst *,
@@ -48,7 +48,8 @@ STATIC_DCL struct monst *FDECL(next_shkp, (struct monst *, BOOLEAN_P));
 STATIC_DCL long FDECL(shop_debt, (struct eshk *));
 STATIC_DCL char *FDECL(shk_owns, (char *, struct obj *));
 STATIC_DCL char *FDECL(mon_owns, (char *, struct obj *));
-STATIC_DCL void FDECL(clear_unpaid, (struct obj *));
+STATIC_DCL void FDECL(clear_unpaid_obj, (struct monst *, struct obj *));
+STATIC_DCL void FDECL(clear_unpaid, (struct monst *, struct obj *));
 STATIC_DCL long FDECL(check_credit, (long, struct monst *));
 STATIC_DCL void FDECL(pay, (long, struct monst *));
 STATIC_DCL long FDECL(get_cost, (struct obj *, struct monst *));
@@ -92,6 +93,8 @@ STATIC_DCL const char *FDECL(cad, (BOOLEAN_P));
                     obj->quan <= bp->bquan
  */
 
+static const char *angrytexts[] = { "quite upset", "ticked off", "furious" };
+
 /*
  *  Transfer money from inventory to monster when paying
  *  shopkeepers, priests, oracle, succubus, and other demons.
@@ -273,41 +276,49 @@ boolean ghostly;
     }
 }
 
+/* Clear the unpaid bit on a single object and its contents. */
+STATIC_OVL void
+clear_unpaid_obj(shkp, otmp)
+struct monst *shkp;
+struct obj *otmp;
+{
+    if (Has_contents(otmp))
+        clear_unpaid(shkp, otmp->cobj);
+    if (onbill(otmp, shkp, TRUE))
+        otmp->unpaid = 0;
+}
+
 /* Clear the unpaid bit on all of the objects in the list. */
 STATIC_OVL void
-clear_unpaid(list)
-register struct obj *list;
+clear_unpaid(shkp, list)
+struct monst *shkp;
+struct obj *list;
 {
     while (list) {
-        if (Has_contents(list))
-            clear_unpaid(list->cobj);
-        list->unpaid = 0;
+        clear_unpaid_obj(shkp, list);
         list = list->nobj;
     }
 }
 
 /* either you paid or left the shop or the shopkeeper died */
-STATIC_OVL void
+void
 setpaid(shkp)
 register struct monst *shkp;
 {
     register struct obj *obj;
     register struct monst *mtmp;
 
-    /* FIXME: object handling should be limited to
-       items which are on this particular shk's bill */
-
-    clear_unpaid(invent);
-    clear_unpaid(fobj);
-    clear_unpaid(level.buriedobjlist);
+    clear_unpaid(shkp, invent);
+    clear_unpaid(shkp, fobj);
+    clear_unpaid(shkp, level.buriedobjlist);
     if (thrownobj)
-        thrownobj->unpaid = 0;
+        clear_unpaid_obj(shkp, thrownobj);
     if (kickedobj)
-        kickedobj->unpaid = 0;
+        clear_unpaid_obj(shkp, kickedobj);
     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
-        clear_unpaid(mtmp->minvent);
+        clear_unpaid(shkp, mtmp->minvent);
     for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon)
-        clear_unpaid(mtmp->minvent);
+        clear_unpaid(shkp, mtmp->minvent);
 
     while ((obj = billobjs) != 0) {
         obj_extract_self(obj);
@@ -410,9 +421,8 @@ register xchar x, y;
 
     rno = levl[x][y].roomno;
     if ((rno < ROOMOFFSET) || levl[x][y].edge || !IS_SHOP(rno - ROOMOFFSET))
-        return NO_ROOM;
-    else
-        return rno;
+        rno = NO_ROOM;
+    return rno;
 }
 
 void
@@ -446,15 +456,21 @@ boolean newlev;
          * Player just stepped onto shop-boundary (known from above logic).
          * Try to intimidate him into paying his bill
          */
-#if 0 /*JP*/
-        verbalize(NOTANGRY(shkp) ? "%s!  Please pay before leaving."
+        if (!Deaf && !muteshk(shkp))
+#if 0 /*JP:T*/
+            verbalize(NOTANGRY(shkp) ? "%s!  Please pay before leaving."
                                  : "%s!  Don't you leave without paying!",
-                  plname);
+                      plname);
 #else
-        verbalize(NOTANGRY(shkp) ? "%s\82³\82ñ\81I\8bA\82é\91O\82É\81C\82¨\8bà\82ð\95¥\82Á\82Ä\82¢\82½\82¾\82¯\82Ü\82¹\82ñ\82©\81D"
+            verbalize(NOTANGRY(shkp) ? "%s\82³\82ñ\81I\8bA\82é\91O\82É\81C\82¨\8bà\82ð\95¥\82Á\82Ä\82¢\82½\82¾\82¯\82Ü\82¹\82ñ\82©\81D"
                                  : "%s\81I\8bA\82é\91O\82É\81C\8bà\82ð\95¥\82¦\81I",
                       plname);
 #endif
+        else
+            pline("%s %s that you need to pay before leaving%s",
+                Shknam(shkp),
+                NOTANGRY(shkp) ? "points out" : "makes it clear",
+                NOTANGRY(shkp) ? "." : "!");
         return;
     }
 
@@ -617,38 +633,63 @@ char *enterstring;
         pline("%s senses your presence.", shkname(shkp));
 */
         pline("%s\82Í\82 \82È\82½\82Ì\91\8dÝ\82É\8bC\82ª\82Â\82¢\82½\81D", shkname(shkp));
+        if (!Deaf && !muteshk(shkp))
 /*JP
         verbalize("Invisible customers are not welcome!");
 */
         verbalize("\93§\96¾\82È\82¨\8bq\82³\82ñ\82Æ\82Í\8a´\90S\82µ\82È\82¢\82È\81I");
+        else
+            pline("%s stands firm as if %s knows you are there.",
+                  Shknam(shkp), mhe(shkp));
         return;
     }
 
     rt = rooms[*enterstring - ROOMOFFSET].rtype;
 
     if (ANGRY(shkp)) {
-#if 0 /*JP*/
-        verbalize("So, %s, you dare return to %s %s?!", plname,
+        if (!Deaf && !muteshk(shkp))
+#if 0 /*JP:T*/
+            verbalize("So, %s, you dare return to %s %s?!", plname,
                   s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
 #else
-        verbalize("%s\81I\82í\82´\82í\82´%s\82Ì%s\82É\96ß\82Á\82Ä\82«\82½\82Ì\82©\81H\81I", plname,
-                  s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
+            verbalize("%s\81I\82í\82´\82í\82´%s\82Ì%s\82É\96ß\82Á\82Ä\82«\82½\82Ì\82©\81H\81I", plname,
+                  shkname(shkp), shtypes[rt - SHOPBASE].name);
 #endif
+        else
+            pline("%s seems %s over your return to %s %s!",
+                  Shknam(shkp),
+                  angrytexts[rn2(SIZE(angrytexts))],
+                  mhis(shkp),
+                  shtypes[rt - SHOPBASE].name);
     } else if (eshkp->robbed) {
-/*JP
-        pline("%s mutters imprecations against shoplifters.", shkname(shkp));
-*/
-        pline("%s\82Í\93D\96_\82ð\82Ì\82Ì\82µ\82Á\82½\81D", shkname(shkp));
-    } else {
+        if (!Deaf)
 #if 0 /*JP*/
-        verbalize("%s, %s!  Welcome%s to %s %s!", Hello(shkp), plname,
-                  eshkp->visitct++ ? " again" : "", s_suffix(shkname(shkp)),
-                  shtypes[rt - SHOPBASE].name);
+            pline("%s mutters imprecations against shoplifters.",
+                  shkname(shkp));
+#else
+            pline("%s\82Í\93D\96_\82ð\82Ì\82Ì\82µ\82Á\82½\81D",
+                  shkname(shkp));
+#endif
+        else
+            pline("%s is combing through %s inventory list.",
+                  Shknam(shkp),
+                  mhis(shkp));
+    } else {
+        if (!Deaf && !muteshk(shkp))
+#if 0 /*JP:T*/
+            verbalize("%s, %s!  Welcome%s to %s %s!", Hello(shkp), plname,
+                      eshkp->visitct++ ? " again" : "",
+                      s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
 #else
-        verbalize("%s\81I%s\82Ì%s\82É%s\81I", Hello(shkp), shkname(shkp),
-                  shtypes[rt - SHOPBASE].name,
-                  eshkp->visitct++ ? "\82Ü\82½\97\88\82Ü\82µ\82½\82Ë" : "\82æ\82¤\82±\82»");
+            verbalize("%s\81I%s\82Ì%s\82É%s\81I", Hello(shkp),
+                      shkname(shkp), shtypes[rt - SHOPBASE].name,
+                      eshkp->visitct++ ? "\82Ü\82½\97\88\82Ü\82µ\82½\82Ë" : "\82æ\82¤\82±\82»");
 #endif
+        else
+            You("enter %s %s%s!",
+                s_suffix(shkname(shkp)),
+                shtypes[rt - SHOPBASE].name,
+                eshkp->visitct++ ? " again" : "");
     }
     /* can't do anything about blocking if teleported in */
     if (!inside_shop(u.ux, u.uy)) {
@@ -687,28 +728,40 @@ char *enterstring;
                 if (!Blind)
                     makeknown(DWARVISH_MATTOCK);
             }
-#if 0 /*JP*/
-            verbalize(NOTANGRY(shkp)
-                          ? "Will you please leave your %s%s outside?"
-                          : "Leave the %s%s outside.",
-                      tool, plur(cnt));
+            if (!Deaf && !muteshk(shkp))
+#if 0 /*JP:T*/
+                verbalize(NOTANGRY(shkp)
+                              ? "Will you please leave your %s%s outside?"
+                              : "Leave the %s%s outside.",
+                          tool, plur(cnt));
 #else
-            verbalize(NOTANGRY(shkp)
-                          ? "%s\82ð\8aO\82É\92u\82¢\82Ä\82«\82Ä\82¢\82½\82¾\82¯\82Ü\82¹\82ñ\82©\81H"
-                          : "%s\82ð\8aO\82Ö\92u\82¢\82Ä\82±\82¢\81I",
-                      tool);
+                verbalize(NOTANGRY(shkp)
+                              ? "%s\82ð\8aO\82É\92u\82¢\82Ä\82«\82Ä\82¢\82½\82¾\82¯\82Ü\82¹\82ñ\82©\81H"
+                              : "%s\82ð\8aO\82Ö\92u\82¢\82Ä\82±\82¢\81I",
+                          tool);
 #endif
+            else
+                pline("%s %s to let you in with your %s%s.",
+                        Shknam(shkp),
+                        NOTANGRY(shkp) ? "is hesitant" : "refuses",
+                        tool, plur(cnt));
             should_block = TRUE;
         } else if (u.usteed) {
-#if 0 /*JP*/
-            verbalize(NOTANGRY(shkp) ? "Will you please leave %s outside?"
+            if (!Deaf && !muteshk(shkp))
+#if 0 /*JP:T*/
+                verbalize(NOTANGRY(shkp) ? "Will you please leave %s outside?"
                                      : "Leave %s outside.",
                       y_monnam(u.usteed));
 #else
-            verbalize(NOTANGRY(shkp) ? "%s\82ð\8aO\82É\92u\82¢\82Ä\82«\82Ä\82¢\82½\82¾\82¯\82Ü\82¹\82ñ\82©\81H"
+                verbalize(NOTANGRY(shkp) ? "%s\82ð\8aO\82É\92u\82¢\82Ä\82«\82Ä\82¢\82½\82¾\82¯\82Ü\82¹\82ñ\82©\81H"
                                      : "%s\82ð\8aO\82Ö\92u\82¢\82Ä\82±\82¢\81I",
                       y_monnam(u.usteed));
 #endif
+            else
+                pline("%s %s to let you in while you're riding %s.",
+                        Shknam(shkp),
+                        NOTANGRY(shkp) ? "doesn't want" : "refuses",
+                        y_monnam(u.usteed));
             should_block = TRUE;
         } else {
             should_block =
@@ -731,18 +784,25 @@ struct obj *obj;
     if (obj->unpaid || !is_pick(obj))
         return;
     shkp = shop_keeper(*u.ushops);
-    if (shkp && inhishop(shkp) && !muteshk(shkp)) {
+    if (shkp && inhishop(shkp)) {
         static NEARDATA long pickmovetime = 0L;
 
         /* if you bring a sack of N picks into a shop to sell,
            don't repeat this N times when they're taken out */
-        if (moves != pickmovetime)
+        if (moves != pickmovetime) {
+            if (!Deaf && !muteshk(shkp))
 #if 0 /*JP*/
-            verbalize("You sneaky %s!  Get out of here with that pick!",
+                verbalize("You sneaky %s!  Get out of here with that pick!",
                       cad(FALSE));
 #else
-            verbalize("\82Ð\82«\82å\82¤\8eÒ\82ß\81I\82Â\82é\82Í\82µ\82ð\8e\9d\82Á\82Ä\8aO\82É\8fo\82ë\81I");
+                verbalize("\82Ð\82«\82å\82¤\8eÒ\82ß\81I\82Â\82é\82Í\82µ\82ð\8e\9d\82Á\82Ä\8aO\82É\8fo\82ë\81I");
 #endif
+            else
+                pline("%s %s your pick!",
+                      Shknam(shkp),
+                      haseyes(shkp->data) ? "glares at"
+                                          : "is dismayed because of");
+        }
         pickmovetime = moves;
     }
 }
@@ -867,18 +927,33 @@ register struct monst *mtmp;
 
 struct monst *
 shop_keeper(rmno)
-register char rmno;
+char rmno;
 {
-    struct monst *shkp =
-        rmno >= ROOMOFFSET ? rooms[rmno - ROOMOFFSET].resident : 0;
+    struct monst *shkp;
 
+    shkp = (rmno >= ROOMOFFSET) ? rooms[rmno - ROOMOFFSET].resident : 0;
     if (shkp) {
-        if (NOTANGRY(shkp)) {
-            if (ESHK(shkp)->surcharge)
-                pacify_shk(shkp);
+        if (has_eshk(shkp)) {
+            if (NOTANGRY(shkp)) {
+                if (ESHK(shkp)->surcharge)
+                    pacify_shk(shkp);
+            } else {
+                if (!ESHK(shkp)->surcharge)
+                    rile_shk(shkp);
+            }
         } else {
-            if (!ESHK(shkp)->surcharge)
-                rile_shk(shkp);
+            /* would have segfaulted on ESHK dereference previously */
+            impossible("%s? (rmno=%d, rtype=%d, mnum=%d, \"%s\")",
+                       shkp->isshk ? "shopkeeper career change"
+                                   : "shop resident not shopkeeper",
+                       (int) rmno,
+                       (int) rooms[rmno - ROOMOFFSET].rtype,
+                       shkp->mnum,
+                       /* [real shopkeeper name is kept in ESHK, not MNAME] */
+                       has_mname(shkp) ? MNAME(shkp) : "anonymous");
+            /* not sure if this is appropriate, because it does nothing to
+               correct the underlying rooms[].resident issue but... */
+            return (struct monst *) 0;
         }
     }
     return shkp;
@@ -886,21 +961,18 @@ register char rmno;
 
 boolean
 tended_shop(sroom)
-register struct mkroom *sroom;
+struct mkroom *sroom;
 {
-    register struct monst *mtmp = sroom->resident;
+    struct monst *mtmp = sroom->resident;
 
-    if (!mtmp)
-        return FALSE;
-    else
-        return (boolean) inhishop(mtmp);
+    return !mtmp ? FALSE : (boolean) inhishop(mtmp);
 }
 
 STATIC_OVL struct bill_x *
 onbill(obj, shkp, silent)
-register struct obj *obj;
-register struct monst *shkp;
-register boolean silent;
+struct obj *obj;
+struct monst *shkp;
+boolean silent;
 {
     if (shkp) {
         register struct bill_x *bp = ESHK(shkp)->bill_p;
@@ -917,7 +989,7 @@ register boolean silent;
             } else
                 bp++;
     }
-    if (obj->unpaid & !silent)
+    if (obj->unpaid && !silent)
 /*JP
         pline("onbill: unpaid obj not on bill?");
 */
@@ -1146,8 +1218,8 @@ boolean verbosely;
     if (!shkp->mcanmove || shkp->msleeping) {
         /* greed induced recovery... */
         if (verbosely && canspotmon(shkp))
-#if 0 /*JP*/
-            pline("%s %s.", Monnam(shkp),
+#if 0 /*JP:T*/
+            pline("%s %s.", Shknam(shkp),
                   shkp->msleeping ? "wakes up" : "can move again");
 #else
             pline("%s\82Í%s\81D", Monnam(shkp),
@@ -1176,7 +1248,7 @@ register boolean silentkops;
         char shk_nam[BUFSZ];
         boolean vanished = canseemon(shkp);
 
-        Strcpy(shk_nam, mon_nam(shkp));
+        Strcpy(shk_nam, shkname(shkp));
         if (on_level(&eshkp->shoplevel, &u.uz)) {
             home_shk(shkp, FALSE);
             /* didn't disappear if shk can still be seen */
@@ -1202,9 +1274,9 @@ register boolean silentkops;
             pline("%s\82Í\96\9e\91«\82·\82é\82Æ\81C\93Ë\91R\8fÁ\82¦\82½\81I", shk_nam);
     } else if (wasmad)
 /*JP
-        pline("%s calms down.", Monnam(shkp));
+        pline("%s calms down.", Shknam(shkp));
 */
-        pline("%s\82Í\97\8e\92\85\82¢\82½\81D", Monnam(shkp));
+        pline("%s\82Í\97\8e\92\85\82¢\82½\81D", Shknam(shkp));
 
     make_happy_shoppers(silentkops);
 }
@@ -1232,17 +1304,16 @@ register struct monst *shkp;
     ESHK(shkp)->following = 1;
 }
 
-/* used when the shkp is teleported or falls (ox == 0) out of his shop,
- * or when the player is not on a costly_spot and he
- * damages something inside the shop.  these conditions
- * must be checked by the calling function.
- */
+/* Used when the shkp is teleported or falls (ox == 0) out of his shop, or
+   when the player is not on a costly_spot and he damages something inside
+   the shop.  These conditions must be checked by the calling function. */
+/*ARGSUSED*/
 void
 make_angry_shk(shkp, ox, oy)
-register struct monst *shkp;
-register xchar ox, oy;
+struct monst *shkp;
+xchar ox UNUSED; /* <ox,oy> predate 'noit_Monnam()', let alone Shknam() */
+xchar oy UNUSED;
 {
-    xchar sx, sy;
     struct eshk *eshkp = ESHK(shkp);
 
     /* all pending shop transactions are now "past due" */
@@ -1255,33 +1326,26 @@ register xchar ox, oy;
         setpaid(shkp);
     }
 
-    /* If you just used a wand of teleportation to send the shk away, you
-       might not be able to see her any more.  Monnam would yield "it",
-       which makes this message look pretty silly, so temporarily restore
-       her original location during the call to Monnam. */
-    sx = shkp->mx, sy = shkp->my;
-    if (isok(ox, oy) && cansee(ox, oy) && !cansee(sx, sy))
-        shkp->mx = ox, shkp->my = oy;
 /*JP
-    pline("%s %s!", Monnam(shkp), !ANGRY(shkp) ? "gets angry" : "is furious");
+    pline("%s %s!", Shknam(shkp), !ANGRY(shkp) ? "gets angry" : "is furious");
 */
-    pline("%s\82Í%s\81I", Monnam(shkp), !ANGRY(shkp) ? "\93{\82Á\82½" : "\93{\82è\8b\82Á\82½");
-    shkp->mx = sx, shkp->my = sy;
+    pline("%s\82Í%s\81I", Shknam(shkp), !ANGRY(shkp) ? "\93{\82Á\82½" : "\93{\82è\8b\82Á\82½");
     hot_pursuit(shkp);
 }
 
+STATIC_VAR const char
 /*JP
-STATIC_VAR const char no_money[] = "Moreover, you%s have no money.";
+        no_money[] = "Moreover, you%s have no money.",
 */
-STATIC_VAR const char no_money[] = "\82µ\82©\82à\81C\82 \82È\82½\82Í\82¨\8bà\82ª\82È\82¢%s\81D";
-STATIC_VAR const char not_enough_money[] =
+        no_money[] = "\82µ\82©\82à\81C\82 \82È\82½\82Í\82¨\8bà\82ª\82È\82¢%s\81D",
 /*JP
-    "Besides, you don't have enough to interest %s.";
+        not_enough_money[] = "Besides, you don't have enough to interest %s.";
 */
-    "\82µ\82©\82à\81C\82 \82È\82½\82Í%s\82ª\8b»\96¡\82ð\8e\9d\82Â\82Ù\82Ç\82¨\8bà\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81I";
+        not_enough_money[] = "\82µ\82©\82à\81C\82 \82È\82½\82Í%s\82ª\8b»\96¡\82ð\8e\9d\82Â\82Ù\82Ç\82¨\8bà\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81I";
 
+/* delivers the cheapest item on the list */
 STATIC_OVL long
-cheapest_item(shkp) /* delivers the cheapest item on the list */
+cheapest_item(shkp)
 register struct monst *shkp;
 {
     register int ct = ESHK(shkp)->billct;
@@ -1363,7 +1427,7 @@ dopay()
             pline("%s is not near enough to receive your payment.",
 */
             pline("%s\82Í\89\93\82­\82É\82¢\82é\82Ì\82Å\8ex\95¥\82¦\82È\82¢\81D",
-                  Monnam(shkp));
+                  Shknam(shkp));
             return 0;
         }
     } else {
@@ -1399,6 +1463,10 @@ dopay()
             return 0;
         }
         mtmp = m_at(cx, cy);
+        if (!cansee(cx, cy) && (!mtmp || !canspotmon(mtmp))) {
+            You("can't %s anyone there.", !Blind ? "see" : "sense");
+            return 0;
+        }
         if (!mtmp) {
 /*JP
             There("is no one there to receive your payment.");
@@ -1415,9 +1483,9 @@ dopay()
         }
         if (mtmp != resident && distu(mtmp->mx, mtmp->my) > 2) {
 /*JP
-            pline("%s is too far to receive your payment.", Monnam(mtmp));
+            pline("%s is too far to receive your payment.", Shknam(mtmp));
 */
-            pline("%s\82Í\8ex\95¥\82¢\82É\8b»\96¡\82ð\8e¦\82³\82È\82¢\81D", Monnam(mtmp));
+            pline("%s\82Í\8ex\95¥\82¢\82É\8b»\96¡\82ð\8e¦\82³\82È\82¢\81D", Shknam(mtmp));
             return 0;
         }
         shkp = mtmp;
@@ -1437,11 +1505,11 @@ proceed:
 
     if (!shkp->mcanmove || shkp->msleeping) { /* still asleep/paralyzed */
 #if 0 /*JP:T*/
-        pline("%s %s.", Monnam(shkp),
+        pline("%s %s.", Shknam(shkp),
               rn2(2) ? "seems to be napping" : "doesn't respond");
 #else
-                pline("%s\82Í%s\81D", Monnam(shkp),
-                      rn2(2) ? "\8b\8f\96°\82è\82ð\82µ\82Ä\82¢\82é\82æ\82¤\82¾" : "\94½\89\9e\82ª\82È\82¢");
+        pline("%s\82Í%s\81D", Shknam(shkp),
+              rn2(2) ? "\8b\8f\96°\82è\82ð\82µ\82Ä\82¢\82é\82æ\82¤\82¾" : "\94½\89\9e\82ª\82È\82¢");
 #endif
         return 0;
     }
@@ -1450,9 +1518,9 @@ proceed:
         umoney = money_cnt(invent);
         if (!ltmp)
 /*JP
-            You("do not owe %s anything.", mon_nam(shkp));
+            You("do not owe %s anything.", shkname(shkp));
 */
-            You("%s\82É\8eØ\82è\82Í\82È\82¢\81D", mon_nam(shkp));
+            You("%s\82É\8eØ\82è\82Í\82È\82¢\81D", shkname(shkp));
         else if (!umoney) {
 /*JP
             You("%shave no money.", stashed_gold ? "seem to " : "");
@@ -1545,9 +1613,9 @@ proceed:
             /* shopkeeper is angry, but has not been robbed --
              * door broken, attacked, etc. */
 /*JP
-            pline("%s is after your hide, not your money!", Monnam(shkp));
+            pline("%s is after your hide, not your money!", Shknam(shkp));
 */
-            pline("%s\82Í\82 \82È\82½\82Ì\96½\82ð\91_\82Á\82Ä\82¢\82é\81C\82¨\8bà\82Ç\82±\82ë\82\82á\82È\82¢\81I", Monnam(shkp));
+            pline("%s\82Í\82 \82È\82½\82Ì\96½\82ð\91_\82Á\82Ä\82¢\82é\81C\82¨\8bà\82Ç\82±\82ë\82\82á\82È\82¢\81I", Shknam(shkp));
             if (umoney < 1000L) {
                 if (!umoney)
 /*JP
@@ -1587,6 +1655,7 @@ proceed:
         long dtmp = eshkp->debit;
         long loan = eshkp->loan;
         char sbuf[BUFSZ];
+
         umoney = money_cnt(invent);
 #if 0 /*JP*//*\96\96\94ö\82É\89ñ\82·*/
         Sprintf(sbuf, "You owe %s %ld %s ", shkname(shkp), dtmp,
@@ -1667,6 +1736,7 @@ proceed:
     if (eshkp->billct) {
         register boolean itemize;
         int iprompt;
+
         umoney = money_cnt(invent);
         if (!umoney && !eshkp->credit) {
 #if 0 /*JP*/
@@ -1756,14 +1826,21 @@ proceed:
         if (!itemize)
             update_inventory(); /* Done in dopayobj() if itemize. */
     }
-    if (!ANGRY(shkp) && paid && !muteshk(shkp))
+    if (!ANGRY(shkp) && paid) {
+        if (!Deaf && !muteshk(shkp))
 #if 0 /*JP*/
-        verbalize("Thank you for shopping in %s %s!", s_suffix(shkname(shkp)),
+            verbalize("Thank you for shopping in %s %s!", s_suffix(shkname(shkp)),
                   shtypes[eshkp->shoptype - SHOPBASE].name);
 #else
-        verbalize("%s\82Ì%s\82Ö\82Ü\82½\82Ç\82¤\82¼\81I", shkname(shkp),
+            verbalize("%s\82Ì%s\82Ö\82Ü\82½\82Ç\82¤\82¼\81I", shkname(shkp),
                   shtypes[eshkp->shoptype - SHOPBASE].name);
 #endif
+        else
+            pline("%s nods appreciatively at you for shopping in %s %s!",
+                    Shknam(shkp),
+                    mhis(shkp),
+                    shtypes[eshkp->shoptype - SHOPBASE].name);
+    }
     return 1;
 }
 
@@ -1839,16 +1916,24 @@ boolean itemize;
             buy = PAY_SKIP;                         /* don't want to buy */
         } else if (quan < bp->bquan && !consumed) { /* partly used goods */
             obj->quan = bp->bquan - save_quan;      /* used up amount */
+            if (!Deaf && !muteshk(shkp)) {
 #if 0 /*JP*/
-            verbalize("%s for the other %s before buying %s.",
+                verbalize("%s for the other %s before buying %s.",
                       ANGRY(shkp) ? "Pay" : "Please pay",
                       simpleonames(obj), /* short name suffices */
                       save_quan > 1L ? "these" : "this one");
 #else
-            verbalize("\82»\82ê\82ð\94\83\82¤\82Ü\82¦\82É\91¼\82Ì%s\82ð%s",
+                verbalize("\82»\82ê\82ð\94\83\82¤\82Ü\82¦\82É\91¼\82Ì%s\82ð%s",
                       simpleonames(obj),
                       ANGRY(shkp) ? "\95¥\82¦\81I" : "\95¥\82Á\82Ä\82­\82¾\82³\82¢\81D");
 #endif
+            } else {
+                pline("%s %s%s your bill for the other %s first.",
+                      Shknam(shkp),
+                      ANGRY(shkp) ? "angrily " : "",
+                      nolimbs(shkp->data) ? "motions to" : "points out",
+                      simpleonames(obj));
+            }
             buy = PAY_SKIP; /* shk won't sell */
         }
     }
@@ -2029,11 +2114,11 @@ int croaked;
                 Strcpy(takes, "\8eñ\82ð\90U\82è\81C");
 #endif
 #if 0 /*JP*/
-            pline("%s %slooks at your corpse%s and %s.", Monnam(shkp),
+            pline("%s %slooks at your corpse%s and %s.", Shknam(shkp),
                   (!shkp->mcanmove || shkp->msleeping) ? "wakes up, " : "",
                   takes, !inhishop(shkp) ? "disappears" : "sighs");
 #else
-            pline("%s\82Í%s\82 \82È\82½\82Ì\8e\80\91Ì\82ð\8c©\82Ä%s%s\81D", Monnam(shkp),
+            pline("%s\82Í%s\82 \82È\82½\82Ì\8e\80\91Ì\82ð\8c©\82Ä%s%s\81D", Shknam(shkp),
                   (!shkp->mcanmove || shkp->msleeping) ? "\96Ú\82ð\82³\82Ü\82·\82Æ" : "",
                   takes, !inhishop(shkp) ? "\8ep\82ð\8fÁ\82µ\82½" : "\97­\91§\82ð\82Â\82¢\82½");
 #endif
@@ -2047,7 +2132,7 @@ int croaked;
     /* shopkeeper is peaceful, nothing stolen, nothing owed. */
     if (roomno == eshkp->shoproom && inhishop(shkp) && !eshkp->billct
         && !eshkp->robbed && !eshkp->debit && NOTANGRY(shkp)
-        && !eshkp->following) {
+        && !eshkp->following && u.ugrave_arise < LOW_PM) {
         taken = (invent != 0);
         if (taken)
 /*JP
@@ -2104,14 +2189,14 @@ int croaked;
             money2mon(shkp, loss);
             context.botl = 1;
 #if 0 /*JP*/
-            pline("%s %s the %ld %s %sowed %s.", Monnam(shkp), takes, loss,
-                  currency(loss),
+            pline("%s %s the %ld %s %sowed %s.", Shknam(shkp),
+                  takes, loss, currency(loss),
                   strncmp(eshkp->customer, plname, PL_NSIZ) ? "" : "you ",
-                  shkp->female ? "her" : "him");
+                  mhim(shkp));
 #else
-            pline("%s\82Í%s%s\8eØ\82è\82Ä\82¢\82é%ld%s\82ð\8eó\82¯\82Æ\82Á\82½\81D", Monnam(shkp), takes,
-                  strncmp(eshkp->customer, plname, PL_NSIZ) ?
-                  "" : "\82 \82È\82½\82ª",
+            pline("%s\82Í%s%s\8eØ\82è\82Ä\82¢\82é%ld%s\82ð\8eó\82¯\82Æ\82Á\82½\81D", Shknam(shkp),
+                  takes,
+                  strncmp(eshkp->customer, plname, PL_NSIZ) ? "" : "\82 \82È\82½\82ª",
                   loss, currency(loss));
 #endif
             /* shopkeeper has now been paid in full */
@@ -2405,9 +2490,10 @@ boolean unpaid_only;
     return price;
 }
 
+/* count amount of gold inside container 'obj' and any nested containers */
 long
 contained_gold(obj)
-register struct obj *obj;
+struct obj *obj;
 {
     register struct obj *otmp;
     register long value = 0L;
@@ -2473,28 +2559,40 @@ boolean quietly;
         && obj->otyp == CANDELABRUM_OF_INVOCATION) {
         if (!quietly) {
             if (is_izchak(shkp, TRUE) && !u.uevent.invoked) {
+                if (Deaf || muteshk(shkp)) {
+                    pline("%s seems %s that you want to sell that.",
+                          Shknam(shkp),
+                          (obj->spe < 7) ? "horrified" : "concerned");
+                } else {
 /*JP
                 verbalize("No thanks, I'd hang onto that if I were you.");
 */
                 verbalize("\82¢\82â\81C\82¢\82ç\82È\82¢\81D\8e\84\82È\82ç\82»\82ê\82ð\8eè\95ú\82³\82È\82¢\82Ë\81D");
-                if (obj->spe < 7)
-#if 0 /*JP*/
-                    verbalize(
+                    if (obj->spe < 7)
+#if 0 /*JP:T*/
+                        verbalize(
                              "You'll need %d%s candle%s to go along with it.",
-                              (7 - obj->spe), (obj->spe > 0) ? " more" : "",
-                              plur(7 - obj->spe));
+                                (7 - obj->spe), (obj->spe > 0) ? " more" : "",
+                                  plur(7 - obj->spe));
 #else
-                    verbalize(
+                        verbalize(
                              "\82»\82ê\82ð\8eg\82¤\82É\82Í%s%d\96{\82Ì\82ë\82¤\82»\82­\82ª\95K\97v\82¾\81D",
                               (obj->spe > 0) ? "\82 \82Æ" : "", (7 - obj->spe));
 #endif
-                /* [what if hero is already carrying enough candles?
-                   should Izchak explain how to attach them instead] */
+                    /* [what if hero is already carrying enough candles?
+                       should Izchak explain how to attach them instead?] */
+                }
             } else {
+                if (!Deaf && !muteshk(shkp))
 /*JP
                 verbalize("I won't stock that.  Take it out of here!");
 */
                 verbalize("\82»\82ê\82Í\8ed\93ü\82ê\82È\82¢\82æ\81D\8e\9d\82Á\82Ä\82¢\82«\82È\82³\82¢\81I");
+                else
+                    pline("%s shakes %s %s in refusal.",
+                            Shknam(shkp),
+                            mhis(shkp),
+                            mbodypart(shkp, HEAD));
             }
         }
         return TRUE;
@@ -2528,7 +2626,7 @@ register struct monst *shkp;
                 tmp = (obj->otyp % (6 - shkp->m_id % 3));
                 tmp = (tmp + 3) * obj->quan;
             }
-        } else if (tmp > 1L && !rn2(4))
+        } else if (tmp > 1L && !(shkp->m_id % 4))
             multiplier *= 3L, divisor *= 4L;
     }
 
@@ -2632,6 +2730,12 @@ struct monst *shkp;
         return;
     }
 
+    /* normally bill_p gets set up whenever you enter the shop, but obj
+       might be going onto the bill because hero just snagged it with
+       a grappling hook from outside without ever having been inside */
+    if (!eshkp->bill_p)
+        eshkp->bill_p = &(eshkp->bill[0]);
+
     bct = eshkp->billct;
     bp = &(eshkp->bill_p[bct]);
     bp->bo_id = obj->o_id;
@@ -2826,14 +2930,14 @@ boolean ininv, dummy, silent;
         contentscount = 0;
     }
 
-    if (!muteshk(shkp) && !silent) {
+    if (!Deaf && !muteshk(shkp) && !silent) {
         char buf[BUFSZ];
 
         if (!ltmp) {
 /*JP
-            pline("%s has no interest in %s.", Monnam(shkp), the(xname(obj)));
+            pline("%s has no interest in %s.", Shknam(shkp), the(xname(obj)));
 */
-            pline("%s\82Í%s\82É\8b»\96¡\82ð\8e¦\82³\82È\82¢\81D", Monnam(shkp), xname(obj));
+            pline("%s\82Í%s\82É\8b»\96¡\82ð\8e¦\82³\82È\82¢\81D", Shknam(shkp), the(xname(obj)));
             return;
         }
         if (!ininv) {
@@ -2867,9 +2971,10 @@ boolean ininv, dummy, silent;
             obj->quan = 1L; /* fool xname() into giving singular */
 #if 0 /*JP*/
             pline("%s %ld %s %s %s%s.\"", buf, ltmp, currency(ltmp),
-                  (save_quan > 1L) ? "per" : (contentscount && !obj->unpaid)
-                                                 ? "for the contents of this"
-                                                 : "for this",
+                  (save_quan > 1L) ? "per"
+                                   : (contentscount && !obj->unpaid)
+                                       ? "for the contents of this"
+                                       : "for this",
                   xname(obj),
                   (contentscount && obj->unpaid) ? and_its_contents : "");
 #else
@@ -2898,9 +3003,9 @@ boolean ininv, dummy, silent;
 #endif
         else
 /*JP
-            pline("%s does not notice.", Monnam(shkp));
+            pline("%s does not notice.", Shknam(shkp));
 */
-            pline("%s\82Í\8bC\82ª\82Â\82¢\82Ä\82¢\82È\82¢\81D", Monnam(shkp));
+            pline("%s\82Í\8bC\82ª\82Â\82¢\82Ä\82¢\82È\82¢\81D", Shknam(shkp));
     }
 }
 
@@ -3164,16 +3269,16 @@ boolean peaceful, silent;
             }
             if (obj->oclass == COIN_CLASS)
 #if 0 /*JP*/
-                You("%sowe %s %ld %s!", still, mon_nam(shkp), value,
+                You("%sowe %s %ld %s!", still, shkname(shkp), value,
                     currency(value));
 #else
-                You("%s%s\82É%ld%s\82Ì\8eØ\82è\82ð\82Â\82­\82Á\82½\81I", still, mon_nam(shkp), value,
+                You("%s%s\82É%ld%s\82Ì\8eØ\82è\82ð\82Â\82­\82Á\82½\81I", still, shkname(shkp), value,
                     currency(value));
 #endif
             else
 #if 0 /*JP*/
-                You("%sowe %s %ld %s for %s!", still, mon_nam(shkp), value,
-                    currency(value), obj->quan > 1L ? "them" : "it");
+                You("%sowe %s %ld %s for %s!", still, shkname(shkp),
+                    value, currency(value), (obj->quan > 1L) ? "them" : "it");
 #else
                 You("%s%s\82É%ld%s\82Ì\8eØ\82è\82ð\82Â\82­\82Á\82½\81I", still, mon_nam(shkp), value,
                     currency(value));
@@ -3183,13 +3288,13 @@ boolean peaceful, silent;
         ESHK(shkp)->robbed += value;
 
         if (!silent) {
-            if (cansee(shkp->mx, shkp->my)) {
+            if (canseemon(shkp)) {
 #if 0 /*JP*/
-                Norep("%s booms: \"%s, you are a thief!\"", Monnam(shkp),
-                      plname);
+                Norep("%s booms: \"%s, you are a thief!\"",
+                      Shknam(shkp), plname);
 #else
-                Norep("%s\82Í\8b©\82ñ\82¾\81F\81u%s\81C\91Ò\82Ä\81I\82±\82Ì\82Ç\82ë\82Ú\82¤\82ß\81I\81v", Monnam(shkp),
-                      plname);
+                Norep("%s\82Í\8b©\82ñ\82¾\81F\81u%s\81C\91Ò\82Ä\81I\82±\82Ì\82Ç\82ë\82Ú\82¤\82ß\81I\81v",
+                      Shknam(shkp),  plname);
 #endif
             } else
 /*JP
@@ -3237,12 +3342,12 @@ xchar x, y;
     boolean isgold = (obj->oclass == COIN_CLASS);
     boolean only_partially_your_contents = FALSE;
 
+    if (!*u.ushops) /* do cheapest exclusion test first */
+        return;
     if (!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp))
         return;
     if (!costly_spot(x, y))
         return;
-    if (!*u.ushops)
-        return;
 
     if (obj->unpaid && !container && !isgold) {
         sub_one_frombill(obj, shkp);
@@ -3263,12 +3368,13 @@ xchar x, y;
     offer = ltmp + cltmp;
 
     /* get one case out of the way: nothing to sell, and no gold */
-    if (!isgold && ((offer + gltmp) == 0L || sell_how == SELL_DONTSELL)) {
+    if (!(isgold || cgold)
+        && ((offer + gltmp) == 0L || sell_how == SELL_DONTSELL)) {
         boolean unpaid = is_unpaid(obj);
 
         if (container) {
             dropped_container(obj, shkp, FALSE);
-            if (!obj->unpaid && !saleitem)
+            if (!obj->unpaid)
                 obj->no_charge = 1;
             if (unpaid)
                 subfrombill(obj, shkp);
@@ -3278,9 +3384,9 @@ xchar x, y;
         if (!unpaid && (sell_how != SELL_DONTSELL)
             && !special_stock(obj, shkp, FALSE))
 /*JP
-            pline("%s seems uninterested.", Monnam(shkp));
+            pline("%s seems uninterested.", Shknam(shkp));
 */
-            pline("%s\82Í\8b»\96¡\82ª\82È\82¢\82æ\82¤\82¾\81D", Monnam(shkp));
+            pline("%s\82Í\8b»\96¡\82ª\82È\82¢\82æ\82¤\82¾\81D", Shknam(shkp));
         return;
     }
 
@@ -3289,11 +3395,13 @@ xchar x, y;
     eshkp = ESHK(shkp);
 
     if (ANGRY(shkp)) { /* they become shop-objects, no pay */
-        if (!muteshk(shkp))
+        if (!Deaf && !muteshk(shkp))
 /*JP
             verbalize("Thank you, scum!");
 */
             verbalize("\82 \82è\82ª\82Æ\82æ\81C\82±\82Ì\83N\83\\82Á\82½\82ê\81I");
+        else
+            pline("%s smirks with satisfaction.", Shknam(shkp));
         subfrombill(obj, shkp);
         return;
     }
@@ -3305,7 +3413,7 @@ xchar x, y;
             offer += cgold;
         if ((eshkp->robbed -= offer < 0L))
             eshkp->robbed = 0L;
-        if (offer && !muteshk(shkp))
+        if (offer && !Deaf && !muteshk(shkp))
             verbalize(
 /*JP
   "Thank you for your contribution to restock this recently plundered shop.");
@@ -3363,11 +3471,11 @@ xchar x, y;
 #endif
         }
 
-        if (!offer) {
+        if (!offer || sell_how == SELL_DONTSELL) {
             if (!isgold) {
                 if (container)
                     dropped_container(obj, shkp, FALSE);
-                if (!obj->unpaid && !saleitem)
+                if (!obj->unpaid)
                     obj->no_charge = 1;
                 subfrombill(obj, shkp);
             }
@@ -3380,11 +3488,11 @@ xchar x, y;
         || offer == 0L || (obj->oclass == FOOD_CLASS && obj->oeaten)
         || (Is_candle(obj)
             && obj->age < 20L * (long) objects[obj->otyp].oc_cost)) {
-#if 0 /*JP*/
-        pline("%s seems uninterested%s.", Monnam(shkp),
+#if 0 /*JP:T*/
+        pline("%s seems uninterested%s.", Shknam(shkp),
               cgold ? " in the rest" : "");
 #else
-        pline("%s\82Í%s\8b»\96¡\82ª\82È\82¢\82æ\82¤\82¾\81D", Monnam(shkp),
+        pline("%s\82Í%s\8b»\96¡\82ª\82È\82¢\82æ\82¤\82¾\81D", Shknam(shkp),
               cgold ? "\8ec\82è\95¨\82É\82Í" : "");
 #endif
         if (container)
@@ -3531,6 +3639,7 @@ xchar x, y;
         switch (sell_response ? sell_response : ynaq(qbuf)) {
         case 'q':
             sell_response = 'n';
+            /*FALLTHRU*/
         case 'n':
             if (container)
                 dropped_container(obj, shkp, FALSE);
@@ -3540,6 +3649,7 @@ xchar x, y;
             break;
         case 'a':
             sell_response = 'y';
+            /*FALLTHRU*/
         case 'y':
             if (container)
                 dropped_container(obj, shkp, TRUE);
@@ -3662,8 +3772,6 @@ quit:
     return 0;
 }
 
-#define HUNGRY 2
-
 STATIC_OVL long
 getprice(obj, shk_buying)
 register struct obj *obj;
@@ -3722,18 +3830,18 @@ register xchar x, y;
         && dist2(shkp->mx, shkp->my, x, y) < 3
         /* if it is the shk's pos, you hit and anger him */
         && (shkp->mx != x || shkp->my != y)) {
-        if (mnearto(shkp, x, y, TRUE) && !muteshk(shkp))
+        if (mnearto(shkp, x, y, TRUE) && !Deaf && !muteshk(shkp))
 /*JP
             verbalize("Out of my way, scum!");
 */
                     verbalize("\82Ç\82¯\81C\83N\83\\82Á\82½\82ê\81I");
         if (cansee(x, y)) {
-#if 0 /*JP*/
-            pline("%s nimbly%s catches %s.", Monnam(shkp),
+#if 0 /*JP:T*/
+            pline("%s nimbly%s catches %s.", Shknam(shkp),
                   (x == shkp->mx && y == shkp->my) ? "" : " reaches over and",
                   the(xname(obj)));
 #else
-            pline("%s\82Í\82·\82Î\82â\82­%s%s\82ð\82Â\82©\82Ü\82¦\82½\81D", Monnam(shkp),
+            pline("%s\82Í\82·\82Î\82â\82­%s%s\82ð\82Â\82©\82Ü\82¦\82½\81D", Shknam(shkp),
                   (x == shkp->mx && y == shkp->my) ? "" : "\8bß\82Ã\82¢\82Ä",
                   xname(obj));
 #endif
@@ -3774,6 +3882,7 @@ long cost;
             return;
         }
     tmp_dam = (struct damage *) alloc((unsigned) sizeof(struct damage));
+    (void) memset((genericptr_t)tmp_dam, 0, sizeof(struct damage));
     tmp_dam->when = monstermoves;
     tmp_dam->place.x = x;
     tmp_dam->place.y = y;
@@ -4036,7 +4145,7 @@ boolean catchup; /* restoring a level */
              *
              * Take the easy way out and put ball&chain under hero.
              */
-            if (!muteshk(shkp))
+            if (!Deaf && !muteshk(shkp))
 /*JP
                 verbalize("Get your junk out of my wall!");
 */
@@ -4112,16 +4221,16 @@ register struct monst *shkp;
         if (ANGRY(shkp) || (Conflict && !resist(shkp, RING_CLASS, 0, 0))) {
             if (Displaced)
 /*JP
-                Your("displaced image doesn't fool %s!", mon_nam(shkp));
+                Your("displaced image doesn't fool %s!", shkname(shkp));
 */
-                pline("%s\82Í\82 \82È\82½\82Ì\8c\89e\82É\82¾\82Ü\82³\82ê\82È\82©\82Á\82½\81I", mon_nam(shkp));
+                pline("%s\82Í\82 \82È\82½\82Ì\8c\89e\82É\82¾\82Ü\82³\82ê\82È\82©\82Á\82½\81I", shkname(shkp));
             (void) mattacku(shkp);
             return 0;
         }
         if (eshkp->following) {
             if (strncmp(eshkp->customer, plname, PL_NSIZ)) {
-                if (!muteshk(shkp))
-#if 0 /*JP*/
+                if (!Deaf && !muteshk(shkp))
+#if 0 /*JP:T*/
                     verbalize("%s, %s!  I was looking for %s.", Hello(shkp),
                               plname, eshkp->customer);
 #else
@@ -4132,22 +4241,27 @@ register struct monst *shkp;
                 return 0;
             }
             if (moves > followmsg + 4) {
-                if (!muteshk(shkp))
-#if 0 /*JP*/
+                if (!Deaf && !muteshk(shkp))
+#if 0 /*JP:T*/
                     verbalize("%s, %s!  Didn't you forget to pay?",
                               Hello(shkp), plname);
 #else
                     verbalize("%s\81I\8ex\95¥\82¢\82ð\96Y\82ê\82Ä\82¢\82Ü\82¹\82ñ\82©\81H",
                               Hello(shkp));
 #endif
+                else
+                    pline("%s holds out %s upturned %s.",
+                          Shknam(shkp),
+                          mhis(shkp),
+                          mbodypart(shkp, HAND));
                 followmsg = moves;
                 if (!rn2(9)) {
 #if 0 /*JP*/
                     pline("%s doesn't like customers who don't pay.",
-                          Monnam(shkp));
+                          Shknam(shkp));
 #else
-                    pline ("%s\82Í\8bà\82ð\95¥\82í\82È\82¢\8bq\82ª\8c\99\82¢\82Ý\82½\82¢\82¾\81D",
-                           Monnam(shkp));
+                    pline("%s\82Í\8bà\82ð\95¥\82í\82È\82¢\8bq\82ª\8c\99\82¢\82Ý\82½\82¢\82¾\81D",
+                          Shknam(shkp));
 #endif
                     rile_shk(shkp);
                 }
@@ -4276,23 +4390,26 @@ register int fall;
 
     if (!fall) {
         if (lang == 2) {
-            if (u.utraptype == TT_PIT)
+            if (!Deaf && !muteshk(shkp)) {
+                if (u.utraptype == TT_PIT)
 #if 0 /*JP*/
-                verbalize(
-                    "Be careful, %s, or you might fall through the floor.",
-                    flags.female ? "madam" : "sir");
+                    verbalize(
+                        "Be careful, %s, or you might fall through the floor.",
+                        flags.female ? "madam" : "sir");
 #else
-                verbalize("\92\8d\88Ó\82µ\82Ä\82­\82¾\82³\82¢%s\81C\8f°\82©\82ç\97\8e\82¿\82Ü\82·\82æ\81D",
-                          flags.female ? "\82¨\8fì\82³\82ñ" : "\82¨\8bq\82³\82ñ");
+                    verbalize(
+                        "\92\8d\88Ó\82µ\82Ä\82­\82¾\82³\82¢%s\81C\8f°\82©\82ç\97\8e\82¿\82Ü\82·\82æ\81D",
+                        flags.female ? "\82¨\8fì\82³\82ñ" : "\82¨\8bq\82³\82ñ");
 #endif
-            else
+                else
 #if 0 /*JP*/
-                verbalize("%s, do not damage the floor here!",
-                          flags.female ? "Madam" : "Sir");
+                    verbalize("%s, do not damage the floor here!",
+                        flags.female ? "Madam" : "Sir");
 #else
-                verbalize("%s\81C\8f°\82É\8f\9d\82ð\82Â\82¯\82È\82¢\82Å\82­\82¾\82³\82¢\81I",
-                          flags.female ? "\82¨\8fì\82³\82ñ" : "\82¨\8bq\82³\82ñ");
+                    verbalize("%s\81C\8f°\82É\8f\9d\82ð\82Â\82¯\82È\82¢\82Å\82­\82¾\82³\82¢\81I",
+                        flags.female ? "\82¨\8fì\82³\82ñ" : "\82¨\8bq\82³\82ñ");
 #endif
+            }
         }
         if (Role_if(PM_KNIGHT)) {
 /*JP
@@ -4505,7 +4622,8 @@ boolean cant_mollify;
          * yanked the hapless critter out of the way.
          */
         if (MON_AT(x, y)) {
-            if (!Deaf && !animal) {
+            if (!animal) {
+                if (!Deaf && !muteshk(shkp)) {
 /*JP
                 You_hear("an angry voice:");
 */
@@ -4514,6 +4632,7 @@ boolean cant_mollify;
                 verbalize("Out of my way, scum!");
 */
                 verbalize("\82Ç\82¯\81I\83N\83\\82Á\82½\82ê\81I");
+                }
                 wait_synch();
 #if defined(UNIX) || defined(VMS)
 #if defined(SYSV) || defined(ULTRIX) || defined(VMS)
@@ -4536,29 +4655,40 @@ boolean cant_mollify;
             if (animal && shkp->mcanmove && !shkp->msleeping)
                 yelp(shkp);
         } else if (pursue || uinshp || !um_dist(x, y, 1)) {
+            if (!Deaf)
 #if 0 /*JP*/
-            verbalize("How dare you %s my %s?", dmgstr,
-                      dugwall ? "shop" : "door");
+                verbalize("How dare you %s my %s?", dmgstr,
+                          dugwall ? "shop" : "door");
 #else
-            verbalize("\82Ç\82¤\82µ\82Ä%s%s%s\82è\82µ\82½\82ñ\82¾\81H",
-                      dugwall ? "\93X" : "\94à",
-                      ni_wo ? "\82É" : "\82ð",
-                      jpast(dmgstr));
+                verbalize("\82Ç\82¤\82µ\82Ä%s%s%s\82è\82µ\82½\82ñ\82¾\81H",
+                          dugwall ? "\93X" : "\94à",
+                          ni_wo ? "\82É" : "\82ð",
+                          jpast(dmgstr));
 #endif
+            else
+                pline("%s is %s that you decided to %s %s %s!",
+                      Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
+                      dmgstr, mhis(shkp), dugwall ? "shop" : "door");
         } else {
+            if (!Deaf) {
 /*JP
             pline("%s shouts:", shkname(shkp));
 */
             pline("%s\82Í\82³\82¯\82ñ\82¾\81F", shkname(shkp));
 #if 0 /*JP*/
-            verbalize("Who dared %s my %s?", dmgstr,
-                      dugwall ? "shop" : "door");
+                verbalize("Who dared %s my %s?", dmgstr,
+                          dugwall ? "shop" : "door");
 #else
-            verbalize("\92N\82ª%s%s%s\82è\82µ\82½\82ñ\82¾\82ë\82¤\81H",
-                      dugwall ? "\93X" : "\94à",
-                      ni_wo ? "\82É" : "\82ð",
-                      jpast(dmgstr));
+                verbalize("\92N\82ª%s%s%s\82è\82µ\82½\82ñ\82¾\82ë\82¤\81H",
+                          dugwall ? "\93X" : "\94à",
+                          ni_wo ? "\82É" : "\82ð",
+                          jpast(dmgstr));
 #endif
+            } else {
+                pline("%s is %s that someone decided to %s %s %s!",
+                      Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
+                      dmgstr, mhis(shkp), dugwall ? "shop" : "door");
+            }
         }
         hot_pursuit(shkp);
         return;
@@ -4589,12 +4719,19 @@ boolean cant_mollify;
         home_shk(shkp, FALSE);
         pacify_shk(shkp);
     } else {
-        if (!animal)
+        if (!animal) {
+            if (!Deaf && !muteshk(shkp))
 /*JP
             verbalize("Oh, yes!  You'll pay!");
 */
             verbalize("\82³\82 \81C\95¥\82¤\82ñ\82¾\81I");
-        else
+            else
+                pline("%s lunges %s %s toward your %s!",
+                    Shknam(shkp),
+                    mhis(shkp),
+                    mbodypart(shkp, HAND),
+                    body_part(NECK));
+        } else
             growl(shkp);
         hot_pursuit(shkp);
         adjalign(-sgn(u.ualign.type));
@@ -4739,6 +4876,7 @@ long cost;
 {
     if (!rn2(3)) {
         register int o, choice = rn2(5);
+
         if (choice == 0)
             choice = (cost < 100L ? 1 : cost < 500L ? 2 : 3);
         switch (choice) {
@@ -4841,6 +4979,7 @@ struct monst *shkp;
 {
     struct eshk *eshk;
     long shkmoney;
+
     if (!shkp->isshk) {
         /* The monster type is shopkeeper, but this monster is
            not actually a shk, which could happen if someone
@@ -4861,51 +5000,65 @@ struct monst *shkp;
     eshk = ESHK(shkp);
     if (ANGRY(shkp)) {
 #if 0 /*JP*/
-        pline("%s mentions how much %s dislikes %s customers.",
-              shkname(shkp), mhe(shkp), eshk->robbed ? "non-paying" : "rude");
+        pline("%s %s how much %s dislikes %s customers.",
+              shkname(shkp),
+              (!Deaf && !muteshk(shkp)) ? "mentions" : "indicates",
+              mhe(shkp), eshk->robbed ? "non-paying" : "rude");
 #else
-        pline("%s\82Í%s\8bq\82Í\91å\8c\99\82¢\82¾\82Æ\8c¾\82Á\82½\81D",
-              shkname(shkp),  eshk->robbed ? "\8bà\82ð\8ex\95¥\82í\82È\82¢" : "\96³\97ç\82È");
+        pline("%s\82Í%s\8bq\82Í\91å\8c\99\82¢\82¾\82Æ%s\81D",
+              shkname(shkp),
+              eshk->robbed ? "\8bà\82ð\8ex\95¥\82í\82È\82¢" : "\96³\97ç\82È",
+              (!Deaf && !muteshk(shkp)) ? "\8c¾\82Á\82½" : "\8e¦\82µ\82½");
 #endif
     } else if (eshk->following) {
         if (strncmp(eshk->customer, plname, PL_NSIZ)) {
+            if (!Deaf && !muteshk(shkp))
 #if 0 /*JP*/
-            verbalize("%s %s!  I was looking for %s.",
+                verbalize("%s %s!  I was looking for %s.",
                       Hello(shkp), plname, eshk->customer);
 #else
-            verbalize("%s\81I\8e\84\82Í%s\82ð\92T\82µ\82Ä\82¢\82Ü\82·\81D",
+                verbalize("%s\81I\8e\84\82Í%s\82ð\92T\82µ\82Ä\82¢\82Ü\82·\81D",
                       Hello(shkp), eshk->customer);
 #endif
             eshk->following = 0;
         } else {
+            if (!Deaf && !muteshk(shkp))
 #if 0 /*JP*/
-            verbalize("%s %s!  Didn't you forget to pay?",
-                      Hello(shkp), plname);
+                verbalize("%s %s!  Didn't you forget to pay?",
+                          Hello(shkp), plname);
 #else
-            verbalize("%s\81I\8ex\95¥\82¢\82ð\96Y\82ê\82Ä\82¢\82Ü\82¹\82ñ\82©\81H", 
-                      Hello(shkp));
+                verbalize("%s\81I\8ex\95¥\82¢\82ð\96Y\82ê\82Ä\82¢\82Ü\82¹\82ñ\82©\81H", 
+                          Hello(shkp));
 #endif
+            else
+                pline("%s taps you on the %s.",
+                      Shknam(shkp), body_part(ARM));
         }
     } else if (eshk->billct) {
         register long total = addupbill(shkp) + eshk->debit;
 
 #if 0 /*JP*/
-        pline("%s says that your bill comes to %ld %s.",
-              shkname(shkp), total, currency(total));
+        pline("%s %s that your bill comes to %ld %s.",
+              shkname(shkp),
+              (!Deaf && !muteshk(shkp)) ? "says" : "indicates",
+              total, currency(total));
 #else
-        pline("%s\82Í\8a¨\92è\82ª%ld%s\82É\82È\82é\82Æ\8c¾\82Á\82½\81D",
-              shkname(shkp), total, currency(total));
+        pline("%s\82Í\8a¨\92è\82ª%ld%s\82É\82È\82é\82Æ%s\81D",
+              shkname(shkp), total, currency(total),
+              (!Deaf && !muteshk(shkp)) ? "\8c¾\82Á\82½" : "\8e¦\82µ\82½");
 #endif
     } else if (eshk->debit) {
 #if 0 /*JP*/
-        pline("%s reminds you that you owe %s %ld %s.",
-              shkname(shkp), mhim(shkp), eshk->debit, currency(eshk->debit));
+        pline("%s %s that you owe %s %ld %s.",
+              shkname(shkp),
+              (!Deaf && !muteshk(shkp)) ? "reminds you" : "indicates",
+              mhim(shkp), eshk->debit, currency(eshk->debit));
 #else
         pline("\82 \82È\82½\82Í%s\82É%ld%s\82Ì\8eØ\82è\82ª\82 \82é\82±\82Æ\82ð\8ev\82¢\82¾\82µ\82½\81D",
               shkname(shkp), eshk->debit, currency(eshk->debit));
 #endif
     } else if (eshk->credit) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         pline("%s encourages you to use your %ld %s of credit.",
               shkname(shkp), eshk->credit, currency(eshk->credit));
 #else
@@ -4913,23 +5066,40 @@ struct monst *shkp;
               shkname(shkp), eshk->credit, currency(eshk->credit));
 #endif
     } else if (eshk->robbed) {
-/*JP
-        pline("%s complains about a recent robbery.", shkname(shkp));
-*/
-        pline("%s\82Í\8dÅ\8bß\82Ì\8b­\93\90\82É\82Â\82¢\82Ä\8bð\92s\82ð\82±\82Ú\82µ\82½\81D", shkname(shkp));
-    } else if ((shkmoney = money_cnt(shkp->minvent)) < 50) {
-/*JP
-        pline("%s complains that business is bad.", shkname(shkp));
-*/
-        pline("%s\82Í\8f¤\94\84\82ª\8e|\82­\82¢\82Á\82Ä\82È\82¢\82Æ\8bð\92s\82ð\82±\82Ú\82µ\82½\81D", shkname(shkp));
+#if 0 /*JP*/
+        pline("%s %s about a recent robbery.",
+              Shknam(shkp),
+              (!Deaf && !muteshk(shkp)) ? "complains" : "indicates concern");
+#else
+        pline("%s\82Í\8dÅ\8bß\82Ì\8b­\93\90\82É\82Â\82¢\82Ä%s\81D",
+              Shknam(shkp),
+              (!Deaf && !muteshk(shkp)) ? "\8bð\92s\82ð\82±\82Ú\82µ\82½" : "\8c\9c\94O\82ð\8e¦\82µ\82½");
+#endif
+    } else if ((shkmoney = money_cnt(shkp->minvent)) < 50L) {
+#if 0 /*JP*/
+        pline("%s %s that business is bad.",
+              shkname(shkp),
+              (!Deaf && !muteshk(shkp)) ? "complains" : "indicates");
+#else
+        pline("%s\82Í\8f¤\94\84\82ª\8e|\82­\82¢\82Á\82Ä\82È\82¢\82Æ%s\81D",
+              shkname(shkp),
+              (!Deaf && !muteshk(shkp)) ? "\8bð\92s\82ð\82±\82Ú\82µ\82½" : "\8e¦\82µ\82½");
+#endif
     } else if (shkmoney > 4000) {
-/*JP
-        pline("%s says that business is good.", shkname(shkp));
-*/
-        pline("%s\82Í\8f¤\94\84\82ª\8e|\82­\82¢\82Á\82Ä\82¢\82é\82Æ\8c¾\82Á\82½\81D", shkname(shkp));
+#if 0 /*JP*/
+        pline("%s %s that business is good.",
+              shkname(shkp),
+              (!Deaf && !muteshk(shkp)) ? "says" : "indicates");
+#else
+        pline("%s\82Í\8f¤\94\84\82ª\8e|\82­\82¢\82Á\82Ä\82¢\82é\82Æ%s\81D",
+              shkname(shkp),
+              (!Deaf && !muteshk(shkp)) ? "\8c¾\82Á\82½" : "\8e¦\82µ\82½");
+#endif
     } else if (is_izchak(shkp, FALSE)) {
-        pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))], shkname(shkp));
+        if (!Deaf && !muteshk(shkp))
+            pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))], shkname(shkp));
     } else {
+        if (!Deaf && !muteshk(shkp))
 /*JP
         pline("%s talks about the problem of shoplifters.", shkname(shkp));
 */
@@ -5091,7 +5261,7 @@ boolean altusage;
             arg2 = "\83S\83z\83\93\81D";
     }
 
-    if (!muteshk(shkp)) {
+    if (!Deaf && !muteshk(shkp)) {
         verbalize(fmt, arg1, arg2, tmp, currency(tmp));
         exercise(A_WIS, TRUE); /* you just got info */
     }
index 6835508..488e973 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 shknam.c        $NHDT-Date: 1448094342 2015/11/21 08:25:42 $  $NHDT-Branch: master $:$NHDT-Revision: 1.38 $ */
+/* NetHack 3.6 shknam.c        $NHDT-Date: 1454485432 2016/02/03 07:43:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.41 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* shknam.c -- initialize a shop */
@@ -11,6 +12,7 @@
 
 #include "hack.h"
 
+STATIC_DCL boolean FDECL(stock_room_goodpos, (struct mkroom *, int, int, int, int));
 STATIC_DCL boolean FDECL(veggy_item, (struct obj * obj, int));
 STATIC_DCL int NDECL(shkveg);
 STATIC_DCL void FDECL(mkveggy_at, (int, int));
@@ -118,12 +120,13 @@ static const char *const shkweapons[] = {
 
 static const char *const shktools[] = {
     /* Spmi */
-    "Ymla", "Eed-morra", "Cubask", "Nieb", "Bnowr Falr", "Telloc Cyaj",
+    "Ymla", "Eed-morra", "Elan Lapinski", "Cubask", "Nieb", "Bnowr Falr",
     "Sperc", "Noskcirdneh", "Yawolloh", "Hyeghu", "Niskal", "Trahnil",
     "Htargcm", "Enrobwem", "Kachzi Rellim", "Regien", "Donmyar", "Yelpur",
-    "Nosnehpets", "Stewe", "Renrut", "-Zlaw", "Nosalnef", "Rewuorb",
-    "Rellenk", "Yad", "Cire Htims", "Y-crad", "Nenilukah", "Corsh", "Aned",
-    "Niknar", "Lapu", "Lechaim", "Rebrol-nek", "AlliWar Wickson", "Oguhmk",
+    "Nosnehpets", "Stewe", "Renrut", "Senna Hut", "-Zlaw", "Nosalnef",
+    "Rewuorb", "Rellenk", "Yad", "Cire Htims", "Y-crad", "Nenilukah",
+    "Corsh", "Aned", "Dark Eery", "Niknar", "Lapu", "Lechaim",
+    "Rebrol-nek", "AlliWar Wickson", "Oguhmk", "Telloc Cyaj",
 #ifdef OVERLAY
     "Erreip", "Nehpets", "Mron", "Snivek", "Kahztiy",
 #endif
@@ -495,7 +498,7 @@ boolean mkspecl;
     struct permonst *ptr;
     int atype;
 
-    /* 3.6.0 tribute */
+    /* 3.6 tribute */
 #if 0 /*JP*/
     if (mkspecl && (!strcmp(shp->name, "rare books")
                     || !strcmp(shp->name, "second-hand bookstore"))) {
@@ -721,6 +724,24 @@ struct mkroom *sroom;
     return sh;
 }
 
+STATIC_OVL boolean
+stock_room_goodpos(sroom, rmno, sh, sx, sy)
+struct mkroom *sroom;
+int rmno, sh, sx,sy;
+{
+    if (sroom->irregular) {
+        if (levl[sx][sy].edge
+            || (int) levl[sx][sy].roomno != rmno
+            || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
+            return FALSE;
+    } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
+               || (sx == sroom->hx && doors[sh].x == sx + 1)
+               || (sy == sroom->ly && doors[sh].y == sy - 1)
+               || (sy == sroom->hy && doors[sh].y == sy + 1))
+        return FALSE;
+    return TRUE;
+}
+
 /* stock a newly-created room with objects */
 void
 stock_room(shp_indx, sroom)
@@ -781,39 +802,20 @@ register struct mkroom *sroom;
          * going to put stuff, randomly single out one in particular.
          */
         for (sx = sroom->lx; sx <= sroom->hx; sx++)
-            for (sy = sroom->ly; sy <= sroom->hy; sy++) {
-                if (sroom->irregular) {
-                    if (levl[sx][sy].edge
-                        || (int) levl[sx][sy].roomno != rmno
-                        || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
-                        continue;
-                } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
-                           || (sx == sroom->hx && doors[sh].x == sx + 1)
-                           || (sy == sroom->ly && doors[sh].y == sy - 1)
-                           || (sy == sroom->hy && doors[sh].y == sy + 1))
-                    continue;
-                stockcount++;
-            }
+            for (sy = sroom->ly; sy <= sroom->hy; sy++)
+                if (stock_room_goodpos(sroom, rmno, sh, sx,sy))
+                    stockcount++;
         specialspot = rnd(stockcount);
         stockcount = 0;
     }
 
     for (sx = sroom->lx; sx <= sroom->hx; sx++)
-        for (sy = sroom->ly; sy <= sroom->hy; sy++) {
-            if (sroom->irregular) {
-                if (levl[sx][sy].edge
-                    || (int) levl[sx][sy].roomno != rmno
-                    || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
-                    continue;
-            } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
-                       || (sx == sroom->hx && doors[sh].x == sx + 1)
-                       || (sy == sroom->ly && doors[sh].y == sy - 1)
-                       || (sy == sroom->hy && doors[sh].y == sy + 1))
-                continue;
-            stockcount++;
-            mkshobj_at(shp, sx, sy,
-                       ((stockcount) && (stockcount == specialspot)));
-        }
+        for (sy = sroom->ly; sy <= sroom->hy; sy++)
+            if (stock_room_goodpos(sroom, rmno, sh, sx,sy)) {
+                stockcount++;
+                mkshobj_at(shp, sx, sy,
+                           ((stockcount) && (stockcount == specialspot)));
+            }
 
     /*
      * Special monster placements (if any) should go here: that way,
@@ -863,35 +865,64 @@ int type;
     return shp->iprobs[i].itype;
 }
 
-const char *
-shkname(mtmp)
+/* version of shkname() for beginning of sentence */
+char *
+Shknam(mtmp)
 struct monst *mtmp;
 {
-    const char *shknm = ESHK(mtmp)->shknam;
+    char *nam = shkname(mtmp);
 
-    if (Hallucination && !program_state.gameover) {
-        const char *const *nlp;
-        int num;
+    /* 'nam[]' is almost certainly already capitalized, but be sure */
+    nam[0] = highc(nam[0]);
+    return nam;
+}
 
-        /* count the number of non-unique shop types;
-           pick one randomly, ignoring shop generation probabilities;
-           pick a name at random from that shop type's list */
-        for (num = 0; num < SIZE(shtypes); num++)
-            if (shtypes[num].prob == 0)
-                break;
-        if (num > 0) {
-            nlp = shtypes[rn2(num)].shknms;
-            for (num = 0; nlp[num]; num++)
-                continue;
-            if (num > 0)
-                shknm = nlp[rn2(num)];
+/* shopkeeper's name, without any visibility constraint; if hallucinating,
+   will yield some other shopkeeper's name (not necessarily one residing
+   in the current game's dungeon, or who keeps same type of shop) */
+char *
+shkname(mtmp)
+struct monst *mtmp;
+{
+    char *nam;
+    unsigned save_isshk = mtmp->isshk;
+
+    mtmp->isshk = 0; /* don't want mon_nam() calling shkname() */
+    /* get a modifiable name buffer along with fallback result */
+    nam = noit_mon_nam(mtmp);
+    mtmp->isshk = save_isshk;
+
+    if (!mtmp->isshk) {
+        impossible("shkname: \"%s\" is not a shopkeeper.", nam);
+    } else if (!has_eshk(mtmp)) {
+        panic("shkname: shopkeeper \"%s\" lacks 'eshk' data.", nam);
+    } else {
+        const char *shknm = ESHK(mtmp)->shknam;
+
+        if (Hallucination && !program_state.gameover) {
+            const char *const *nlp;
+            int num;
+
+            /* count the number of non-unique shop types;
+               pick one randomly, ignoring shop generation probabilities;
+               pick a name at random from that shop type's list */
+            for (num = 0; num < SIZE(shtypes); num++)
+                if (shtypes[num].prob == 0)
+                    break;
+            if (num > 0) {
+                nlp = shtypes[rn2(num)].shknms;
+                for (num = 0; nlp[num]; num++)
+                    continue;
+                if (num > 0)
+                    shknm = nlp[rn2(num)];
+            }
         }
+        /* strip prefix if present */
+        if (!letter(*shknm))
+            ++shknm;
+        Strcpy(nam, shknm);
     }
-
-    /* strip prefix if present */
-    if (!letter(*shknm))
-        ++shknm;
-    return shknm;
+    return nam;
 }
 
 boolean
index 0c47c8e..3dc0d0a 100644 (file)
--- a/src/sit.c
+++ b/src/sit.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 sit.c   $NHDT-Date: 1445906863 2015/10/27 00:47:43 $  $NHDT-Branch: master $:$NHDT-Revision: 1.51 $ */
+/* NetHack 3.6 sit.c   $NHDT-Date: 1458341129 2016/03/18 22:45:29 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.53 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -160,9 +161,9 @@ dosit()
             } else if (u.utraptype == TT_LAVA) {
                 /* Must have fire resistance or they'd be dead already */
 /*JP
-                You("sit in the lava!");
+                You("sit in the %s!", hliquid("lava"));
 */
-                You("\97n\8aâ\82Ì\92\86\82É\8dÀ\82Á\82½\81I");
+                You("%s\82Ì\92\86\82É\8dÀ\82Á\82½\81I", hliquid("\97n\8aâ"));
                 if (Slimed)
                     burn_away_slime();
                 u.utrap += rnd(4);
@@ -184,7 +185,7 @@ dosit()
             You("sit down.");
 */
             You("\8dÀ\82Á\82½\81D");
-            dotrap(trap, 0);
+            dotrap(trap, VIASITTING);
         }
     } else if (Underwater || Is_waterlevel(&u.uz)) {
         if (Is_waterlevel(&u.uz))
@@ -200,9 +201,9 @@ dosit()
     } else if (is_pool(u.ux, u.uy)) {
     in_water:
 /*JP
-        You("sit in the water.");
+        You("sit in the %s.", hliquid("water"));
 */
-        You("\90\85\82Ì\92\86\82Å\8dÀ\82Á\82½\81D");
+        You("%s\82Ì\92\86\82Å\8dÀ\82Á\82½\81D", hliquid("\90\85"));
         if (!rn2(10) && uarm)
 /*JP
             (void) water_damage(uarm, "armor", TRUE);
@@ -237,21 +238,21 @@ dosit()
     } else if (is_lava(u.ux, u.uy)) {
         /* must be WWalking */
 /*JP
-        You(sit_message, "lava");
+        You(sit_message, hliquid("lava"));
 */
-        You(sit_message, "\97n\8aâ");
+        You(sit_message, hliquid("\97n\8aâ"));
         burn_away_slime();
         if (likes_lava(youmonst.data)) {
 /*JP
-            pline_The("lava feels warm.");
+            pline_The("%s feels warm.", hliquid("lava"));
 */
-            pline("\97n\8aâ\82Í\92g\82©\82¢\81D");
+            pline_The("%s\82Í\92g\82©\82¢\81D", hliquid("\97n\8aâ"));
             return 1;
         }
 /*JP
-        pline_The("lava burns you!");
+        pline_The("%s burns you!", hliquid("lava"));
 */
-        You("\97n\8aâ\82Å\94R\82¦\82½\81I");
+        pline_The("%s\82Å\94R\82¦\82½\81I", hliquid("\97n\8aâ"));
         losehp(d((Fire_resistance ? 2 : 10), 10), /* lava damage */
 /*JP
                "sitting on lava", KILLED_BY);
@@ -311,6 +312,7 @@ dosit()
                 if (u.uhp >= (u.uhpmax - 5))
                     u.uhpmax += 4;
                 u.uhp = u.uhpmax;
+                u.ucreamed = 0;
                 make_blinded(0L, TRUE);
                 make_sick(0L, (char *) 0, FALSE, SICK_ALL);
                 heal_legs();
@@ -377,6 +379,7 @@ dosit()
                  "\90¹\82È\82é\8bÊ\8dÀ\82É\8dÀ\82è\82µ\93ð\82É\8eô\82¢\82 \82ê\81I");
                 if (Luck > 0) {
                     make_blinded(Blinded + rn1(100, 250), TRUE);
+                    change_luck((Luck > 1) ? -rnd(2) : -1);
                 } else
                     rndcurse();
                 break;
@@ -612,6 +615,7 @@ attrcurse()
             You("\92g\82©\82³\82ð\8a´\82\82½\81D");
             break;
         }
+        /*FALLTHRU*/
     case 2:
         if (HTeleportation & INTRINSIC) {
             HTeleportation &= ~INTRINSIC;
@@ -621,6 +625,7 @@ attrcurse()
             You("\82¿\82å\82Á\82Æ\97\8e\82¿\82Â\82¢\82½\81D");
             break;
         }
+        /*FALLTHRU*/
     case 3:
         if (HPoison_resistance & INTRINSIC) {
             HPoison_resistance &= ~INTRINSIC;
@@ -630,6 +635,7 @@ attrcurse()
             You("\8f­\82µ\8bC\95ª\82ª\88«\82­\82È\82Á\82½\81I");
             break;
         }
+        /*FALLTHRU*/
     case 4:
         if (HTelepat & INTRINSIC) {
             HTelepat &= ~INTRINSIC;
@@ -641,6 +647,7 @@ attrcurse()
             Your("\8cÜ\8a´\82Í\96\83á\83\82µ\82½\81I");
             break;
         }
+        /*FALLTHRU*/
     case 5:
         if (HCold_resistance & INTRINSIC) {
             HCold_resistance &= ~INTRINSIC;
@@ -650,6 +657,7 @@ attrcurse()
             You("\97Á\82µ\82³\82ð\8a´\82\82½\81D");
             break;
         }
+        /*FALLTHRU*/
     case 6:
         if (HInvis & INTRINSIC) {
             HInvis &= ~INTRINSIC;
@@ -659,6 +667,7 @@ attrcurse()
             You("\96Ï\91z\82ð\95ø\82¢\82½\81D");
             break;
         }
+        /*FALLTHRU*/
     case 7:
         if (HSee_invisible & INTRINSIC) {
             HSee_invisible &= ~INTRINSIC;
@@ -673,6 +682,7 @@ attrcurse()
 #endif
             break;
         }
+        /*FALLTHRU*/
     case 8:
         if (HFast & INTRINSIC) {
             HFast &= ~INTRINSIC;
@@ -682,6 +692,7 @@ attrcurse()
             You("\92x\82­\82È\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
             break;
         }
+        /*FALLTHRU*/
     case 9:
         if (HStealth & INTRINSIC) {
             HStealth &= ~INTRINSIC;
@@ -691,6 +702,7 @@ attrcurse()
             You("\95s\8aí\97p\82É\82È\82Á\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
             break;
         }
+        /*FALLTHRU*/
     case 10:
         /* intrinsic protection is just disabled, not set back to 0 */
         if (HProtection & INTRINSIC) {
@@ -701,6 +713,7 @@ attrcurse()
             You("\96³\96h\94õ\82É\82È\82Á\82½\8bC\82ª\82µ\82½\81D");
             break;
         }
+        /*FALLTHRU*/
     case 11:
         if (HAggravate_monster & INTRINSIC) {
             HAggravate_monster &= ~INTRINSIC;
@@ -710,6 +723,7 @@ attrcurse()
             You("\96£\97Í\82ª\8e¸\82¹\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
             break;
         }
+        /*FALLTHRU*/
     default:
         break;
     }
index 17cbaf6..25f9060 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 sounds.c        $NHDT-Date: 1446713641 2015/11/05 08:54:01 $  $NHDT-Branch: master $:$NHDT-Revision: 1.74 $ */
+/* NetHack 3.6 sounds.c        $NHDT-Date: 1452992329 2016/01/17 00:58:49 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.78 $ */
 /*      Copyright (c) 1989 Janet Walz, Mike Threepoint */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -155,8 +155,8 @@ dosounds()
                         You_hear("\92N\82©\82ª\91{\8dõ\82µ\82Ä\82¢\82é\89¹\82ð\95·\82¢\82½\81D");
                     break;
                 }
-                /* fall into... (yes, even for hallucination) */
             }
+                /*FALLTHRU*/
             case 0:
 /*JP
                 You_hear("the footsteps of a guard on patrol.");
@@ -571,40 +571,40 @@ register struct monst *mtmp;
         switch (mtmp->data->msound) {
         case MS_MEW:
 /*JP
-            yelp_verb = "yowl";
+            yelp_verb = (!Deaf) ? "yowl" : "arch";
 */
-            yelp_verb = "\94ß\82µ\82­\96Â\82¢\82½";
+            yelp_verb = (!Deaf) ? "\94ß\82µ\82­\96Â\82¢\82½" : "arch";
             break;
         case MS_BARK:
         case MS_GROWL:
 /*JP
-            yelp_verb = "yelp";
+            yelp_verb = (!Deaf) ? "yelp" : "recoil";
 */
-            yelp_verb = "\83L\83\83\83\93\83L\83\83\83\93\96Â\82¢\82½";
+            yelp_verb = (!Deaf) ? "\83L\83\83\83\93\83L\83\83\83\93\96Â\82¢\82½" : "\90K\8d\9e\82Ý\82µ\82½";
             break;
         case MS_ROAR:
 /*JP
-            yelp_verb = "snarl";
+            yelp_verb = (!Deaf) ? "snarl" : "bluff";
 */
-            yelp_verb = "\82¤\82È\82Á\82½";
+            yelp_verb = (!Deaf) ? "\82¤\82È\82Á\82½" : "\82â\82¹\89ä\96\9d\82µ\82½";
             break;
         case MS_SQEEK:
 /*JP
-            yelp_verb = "squeal";
+            yelp_verb = (!Deaf) ? "squeal" : "quiver";
 */
-            yelp_verb = "\83L\81[\83L\81[\96Â\82¢\82½";
+            yelp_verb = (!Deaf) ? "\83L\81[\83L\81[\96Â\82¢\82½" : "\90k\82¦\82½";
             break;
         case MS_SQAWK:
 /*JP
-            yelp_verb = "screak";
+            yelp_verb = (!Deaf) ? "screak" : "thrash";
 */
-            yelp_verb = "\8bà\90Ø\82è\90º\82ð\97§\82Ä\82½";
+            yelp_verb = (!Deaf) ? "\8bà\90Ø\82è\90º\82ð\97§\82Ä\82½" : "\82Ì\82½\82¤\82¿\89ñ\82Á\82½";
             break;
         case MS_WAIL:
 /*JP
-            yelp_verb = "wail";
+            yelp_verb = (!Deaf) ? "wail" : "cringe";
 */
-            yelp_verb = "\94ß\82µ\82­\96Â\82¢\82½";
+            yelp_verb = (!Deaf) ? "\94ß\82µ\82­\96Â\82¢\82½" : "\90g\82ð\82·\82­\82ß\82½";
             break;
         }
     if (yelp_verb) {
@@ -713,7 +713,7 @@ register struct monst *mtmp;
     char verbuf[BUFSZ];
     register const char *pline_msg = 0, /* Monnam(mtmp) will be prepended */
         *verbl_msg = 0,                 /* verbalize() */
-            *verbl_msg_mcan = 0;        /* verbalize() if cancelled */
+        *verbl_msg_mcan = 0;            /* verbalize() if cancelled */
     struct permonst *ptr = mtmp->data;
     int msound = ptr->msound;
 
@@ -963,7 +963,8 @@ register struct monst *mtmp;
 */
                 pline_msg = "\83j\83\83\81[\83j\83\83\81[\96Â\82¢\82½\81D";
             break;
-        } /* else FALLTHRU */
+        }
+        /*FALLTHRU*/
     case MS_GROWL:
 /*JP
         pline_msg = mtmp->mpeaceful ? "snarls." : "growls!";
@@ -1150,7 +1151,7 @@ register struct monst *mtmp;
             }
             break;
         }
-    /* else FALLTHRU */
+        /*FALLTHRU*/
     case MS_HUMANOID:
         if (!mtmp->mpeaceful) {
             if (In_endgame(&u.uz) && is_mplayer(ptr))
@@ -1261,6 +1262,7 @@ register struct monst *mtmp;
         break;
     case MS_SEDUCE: {
         int swval;
+
         if (SYSOPT_SEDUCE) {
             if (ptr->mlet != S_NYMPH
                 && could_seduce(mtmp, &youmonst, (struct attack *) 0) == 1) {
@@ -1419,66 +1421,63 @@ register struct monst *mtmp;
                                     : soldier_foe_msg[rn2(3)];
         break;
     }
-    case MS_RIDER:
-        /* 3.6.0 tribute */
-        if (ptr == &mons[PM_DEATH]
-            && !context.tribute.Deathnotice && u_have_novel()) {
-            struct obj *book = u_have_novel();
-            const char *tribtitle = (char *)0;
-
-            if (book) {
-                int novelidx = book->novelidx;
+    case MS_RIDER: {
+        const char *tribtitle;
+        struct obj *book = 0;
+        boolean ms_Death = (ptr == &mons[PM_DEATH]);
 
-                tribtitle = noveltitle(&novelidx);
-            }
-            if (tribtitle) {
+        /* 3.6 tribute */
+        if (ms_Death && !context.tribute.Deathnotice
+            && (book = u_have_novel()) != 0) {
+            if ((tribtitle = noveltitle(&book->novelidx)) != 0) {
 /*JP
                 Sprintf(verbuf, "Ah, so you have a copy of /%s/.", tribtitle);
 */
                 Sprintf(verbuf, "\82 \82 \81A/%s/\82ð\8e\9d\82Á\82Ä\82¢\82é\82Ì\82©\81D", tribtitle);
                 /* no Death featured in these two, so exclude them */
-                if (!(strcmpi(tribtitle, "Snuff") == 0
-                      || strcmpi(tribtitle, "The Wee Free Men") == 0))
+                if (strcmpi(tribtitle, "Snuff")
+                    && strcmpi(tribtitle, "The Wee Free Men"))
 /*JP
-                    Strcat(verbuf, " I may have been misquoted there.");
+                    Strcat(verbuf, "  I may have been misquoted there.");
 */
-                    Strcat(verbuf, "\82±\82±\82Å\82Í\88ø\97p\82ª\8aÔ\88á\82Á\82Ä\82¢\82é\82©\82à\82µ\82ê\82È\82¢\81D");
+                    Strcat(verbuf, "  \82±\82±\82Å\82Í\88ø\97p\82ª\8aÔ\88á\82Á\82Ä\82¢\82é\82©\82à\82µ\82ê\82È\82¢\81D");
                 verbl_msg = verbuf;
-                context.tribute.Deathnotice = 1;
             }
-        } else if (ptr == &mons[PM_DEATH]
-                   && !rn2(2) && Death_quote(verbuf, BUFSZ)) {
-                verbl_msg = verbuf;
-        }
+            context.tribute.Deathnotice = 1;
+        } else if (ms_Death && rn2(3) && Death_quote(verbuf, sizeof verbuf)) {
+            verbl_msg = verbuf;
         /* end of tribute addition */
-        else if (ptr == &mons[PM_DEATH] && !rn2(10))
+
+        } else if (ms_Death && !rn2(10)) {
 /*JP
             pline_msg = "is busy reading a copy of Sandman #8.";
 */
             pline_msg = "\81u\83T\83\93\83h\83}\83\93\81v\82Ì8\8aª\82ð\93Ç\82Þ\82Ì\82É\96Z\82µ\82¢\81D";
-        else
+        else
 /*JP
             verbl_msg = "Who do you think you are, War?";
 */
             verbl_msg = "\83E\83H\81[\82æ\81C\8e©\95ª\82ª\89½\8eÒ\82©\8dl\82¦\82½\82±\82Æ\82ª\82 \82é\82©\81H";
         break;
-    }
+    } /* case MS_RIDER */
+    } /* switch */
 
-    if (pline_msg)
+    if (pline_msg) {
 /*JP
         pline("%s %s", Monnam(mtmp), pline_msg);
 */
         pline("%s\82Í%s", Monnam(mtmp), pline_msg);
-    else if (mtmp->mcan && verbl_msg_mcan)
+    } else if (mtmp->mcan && verbl_msg_mcan) {
         verbalize1(verbl_msg_mcan);
-    else if (verbl_msg) {
+    else if (verbl_msg) {
 #if 0 /*JP*//*\83f\83X\82ð\93Á\95Ê\88µ\82¢\82µ\82È\82¢*/
+        /* more 3.6 tribute */
         if (ptr == &mons[PM_DEATH]) {
             /* Death talks in CAPITAL LETTERS
                and without quotation marks */
             char tmpbuf[BUFSZ];
-            Sprintf(tmpbuf, "%s", verbl_msg);
-            pline1(ucase(tmpbuf));
+
+            pline1(ucase(strcpy(tmpbuf, verbl_msg)));
         } else {
             verbalize1(verbl_msg);
         }
index dc45412..a1b1f6d 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 sp_lev.c        $NHDT-Date: 1449269920 2015/12/04 22:58:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.77 $ */
+/* NetHack 3.6 sp_lev.c        $NHDT-Date: 1524287226 2018/04/21 05:07:06 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */
 /*      Copyright (c) 1989 by Jean-Christophe Collet */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -36,7 +36,6 @@ STATIC_DCL struct opvar *FDECL(opvar_new_coord, (int, int));
 #if 0
 STATIC_DCL struct opvar * FDECL(opvar_new_region, (int,int, int,int));
 #endif /*0*/
-STATIC_DCL void FDECL(opvar_free_x, (struct opvar *));
 STATIC_DCL struct opvar *FDECL(opvar_clone, (struct opvar *));
 STATIC_DCL struct opvar *FDECL(opvar_var_conversion, (struct sp_coder *,
                                                       struct opvar *));
@@ -53,6 +52,7 @@ STATIC_DCL void FDECL(set_wall_property, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P,
 STATIC_DCL void NDECL(shuffle_alignments);
 STATIC_DCL void NDECL(count_features);
 STATIC_DCL void NDECL(remove_boundary_syms);
+STATIC_DCL void FDECL(set_door_orientation, (int, int));
 STATIC_DCL void FDECL(maybe_add_door, (int, int, struct mkroom *));
 STATIC_DCL void NDECL(link_doors_rooms);
 STATIC_DCL void NDECL(fill_rooms);
@@ -69,9 +69,10 @@ STATIC_DCL void FDECL(get_free_room_loc, (schar *, schar *,
 STATIC_DCL boolean FDECL(create_subroom, (struct mkroom *, XCHAR_P, XCHAR_P,
                                           XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P));
 STATIC_DCL void FDECL(create_door, (room_door *, struct mkroom *));
-STATIC_DCL void FDECL(create_trap, (trap *, struct mkroom *));
+STATIC_DCL void FDECL(create_trap, (spltrap *, struct mkroom *));
 STATIC_DCL int FDECL(noncoalignment, (ALIGNTYP_P));
 STATIC_DCL boolean FDECL(m_bad_boulder_spot, (int, int));
+STATIC_DCL int FDECL(pm_to_humidity, (struct permonst *));
 STATIC_DCL void FDECL(create_monster, (monster *, struct mkroom *));
 STATIC_DCL void FDECL(create_object, (object *, struct mkroom *));
 STATIC_DCL void FDECL(create_altar, (altar *, struct mkroom *));
@@ -113,8 +114,6 @@ STATIC_DCL void FDECL(spo_altar, (struct sp_coder *));
 STATIC_DCL void FDECL(spo_trap, (struct sp_coder *));
 STATIC_DCL void FDECL(spo_gold, (struct sp_coder *));
 STATIC_DCL void FDECL(spo_corridor, (struct sp_coder *));
-STATIC_DCL struct opvar *FDECL(selection_opvar, (char *));
-STATIC_DCL xchar FDECL(selection_getpoint, (int, int, struct opvar *));
 STATIC_DCL void FDECL(selection_setpoint, (int, int, struct opvar *, XCHAR_P));
 STATIC_DCL struct opvar *FDECL(selection_not, (struct opvar *));
 STATIC_DCL struct opvar *FDECL(selection_logical_oper, (struct opvar *,
@@ -125,11 +124,8 @@ STATIC_DCL void FDECL(selection_filter_percent, (struct opvar *, int));
 STATIC_DCL int FDECL(selection_rndcoord, (struct opvar *, schar *, schar *,
                                           BOOLEAN_P));
 STATIC_DCL void FDECL(selection_do_grow, (struct opvar *, int));
-STATIC_DCL void FDECL(set_selection_floodfillchk, (int FDECL((*), (int,int))));
 STATIC_DCL int FDECL(floodfillchk_match_under, (int, int));
 STATIC_DCL int FDECL(floodfillchk_match_accessible, (int, int));
-STATIC_DCL void FDECL(selection_floodfill, (struct opvar *, int, int,
-                                            BOOLEAN_P));
 STATIC_DCL void FDECL(selection_do_ellipse, (struct opvar *, int, int,
                                              int, int, int));
 STATIC_DCL long FDECL(line_dist_coord, (long, long, long, long, long, long));
@@ -203,13 +199,14 @@ static NEARDATA char xsize, ysize;
 char *lev_message = 0;
 lev_region *lregions = 0;
 int num_lregions = 0;
-boolean splev_init_present = FALSE;
-boolean icedpools = FALSE;
 
-struct obj *container_obj[MAX_CONTAINMENT];
-int container_idx = 0;
+static boolean splev_init_present = FALSE;
+static boolean icedpools = FALSE;
+static int mines_prize_count = 0, soko_prize_count = 0; /* achievements */
 
-struct monst *invent_carrying_monster = NULL;
+static struct obj *container_obj[MAX_CONTAINMENT];
+static int container_idx = 0;
+static struct monst *invent_carrying_monster = NULL;
 
 #define SPLEV_STACK_RESERVE 128
 
@@ -611,8 +608,8 @@ schar filling;
             if (level.flags.corrmaze)
                 levl[x][y].typ = STONE;
             else
-                levl[x][y].typ =
-                    (y < 2 || ((x % 2) && (y % 2))) ? STONE : filling;
+                levl[x][y].typ = (y < 2 || ((x % 2) && (y % 2))) ? STONE
+                                                                 : filling;
         }
 }
 
@@ -706,7 +703,55 @@ remove_boundary_syms()
     }
 }
 
-void
+/* used by sel_set_door() and link_doors_rooms() */
+STATIC_OVL void
+set_door_orientation(x, y)
+int x, y;
+{
+    boolean wleft, wright, wup, wdown;
+
+    /* If there's a wall or door on either the left side or right
+     * side (or both) of this secret door, make it be horizontal.
+     *
+     * It is feasible to put SDOOR in a corner, tee, or crosswall
+     * position, although once the door is found and opened it won't
+     * make a lot sense (diagonal access required).  Still, we try to
+     * handle that as best as possible.  For top or bottom tee, using
+     * horizontal is the best we can do.  For corner or crosswall,
+     * either horizontal or vertical are just as good as each other;
+     * we produce horizontal for corners and vertical for crosswalls.
+     * For left or right tee, using vertical is best.
+     *
+     * A secret door with no adjacent walls is also feasible and makes
+     * even less sense.  It will be displayed as a vertical wall while
+     * hidden and become a vertical door when found.  Before resorting
+     * to that, we check for solid rock which hasn't been wallified
+     * yet (cf lower leftside of leader's room in Cav quest).
+     */
+    wleft  = (isok(x - 1, y) && (IS_WALL(levl[x - 1][y].typ)
+                                 || IS_DOOR(levl[x - 1][y].typ)
+                                 || levl[x - 1][y].typ == SDOOR));
+    wright = (isok(x + 1, y) && (IS_WALL(levl[x + 1][y].typ)
+                                 || IS_DOOR(levl[x + 1][y].typ)
+                                 || levl[x + 1][y].typ == SDOOR));
+    wup    = (isok(x, y - 1) && (IS_WALL(levl[x][y - 1].typ)
+                                 || IS_DOOR(levl[x][y - 1].typ)
+                                 || levl[x][y - 1].typ == SDOOR));
+    wdown  = (isok(x, y + 1) && (IS_WALL(levl[x][y + 1].typ)
+                                 || IS_DOOR(levl[x][y + 1].typ)
+                                 || levl[x][y + 1].typ == SDOOR));
+    if (!wleft && !wright && !wup && !wdown) {
+        /* out of bounds is treated as implicit wall; should be academic
+           because we don't expect to have doors so near the level's edge */
+        wleft  = (!isok(x - 1, y) || IS_DOORJOIN(levl[x - 1][y].typ));
+        wright = (!isok(x + 1, y) || IS_DOORJOIN(levl[x + 1][y].typ));
+        wup    = (!isok(x, y - 1) || IS_DOORJOIN(levl[x][y - 1].typ));
+        wdown  = (!isok(x, y + 1) || IS_DOORJOIN(levl[x][y + 1].typ));
+    }
+    levl[x][y].horizontal = ((wleft || wright) && !(wup && wdown)) ? 1 : 0;
+}
+
+STATIC_OVL void
 maybe_add_door(x, y, droom)
 int x, y;
 struct mkroom *droom;
@@ -715,7 +760,7 @@ struct mkroom *droom;
         add_door(x, y, droom);
 }
 
-void
+STATIC_OVL void
 link_doors_rooms()
 {
     int x, y;
@@ -724,6 +769,11 @@ link_doors_rooms()
     for (y = 0; y < ROWNO; y++)
         for (x = 0; x < COLNO; x++)
             if (IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR) {
+                /* in case this door was a '+' or 'S' from the
+                   MAP...ENDMAP section without an explicit DOOR
+                   directive, set/clear levl[][].horizontal for it */
+                set_door_orientation(x, y);
+
                 for (tmpi = 0; tmpi < nroom; tmpi++) {
                     maybe_add_door(x, y, &rooms[tmpi]);
                     for (m = 0; m < rooms[tmpi].nsubrooms; m++) {
@@ -895,6 +945,8 @@ register int humidity;
             || typ == CORR)
             return TRUE;
     }
+    if ((humidity & SPACELOC) && SPACE_POS(levl[x][y].typ))
+        return TRUE;
     if ((humidity & WET) && is_pool(x, y))
         return TRUE;
     if ((humidity & HOT) && is_lava(x, y))
@@ -1434,10 +1486,10 @@ xchar walls; /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */
  */
 STATIC_OVL void
 create_trap(t, croom)
-trap *t;
+spltrap *t;
 struct mkroom *croom;
 {
-    schar x, y;
+    schar x = -1, y = -1;
     coord tm;
 
     if (croom)
@@ -1495,6 +1547,24 @@ int x, y;
     return FALSE;
 }
 
+STATIC_OVL int
+pm_to_humidity(pm)
+struct permonst *pm;
+{
+    int loc = DRY;
+    if (!pm)
+        return loc;
+    if (pm->mlet == S_EEL || amphibious(pm) || is_swimmer(pm))
+        loc = WET;
+    if (is_flyer(pm) || is_floater(pm))
+        loc |= (HOT | WET);
+    if (passes_walls(pm) || noncorporeal(pm))
+        loc |= SOLID;
+    if (flaming(pm))
+        loc |= HOT;
+    return loc;
+}
+
 STATIC_OVL void
 create_monster(m, croom)
 monster *m;
@@ -1543,15 +1613,7 @@ struct mkroom *croom;
         pm = (struct permonst *) 0;
 
     if (pm) {
-        int loc = DRY;
-        if (pm->mlet == S_EEL || amphibious(pm) || is_swimmer(pm))
-            loc = WET;
-        if (is_flyer(pm) || is_floater(pm))
-            loc |= (HOT | WET);
-        if (passes_walls(pm) || noncorporeal(pm))
-            loc |= SOLID;
-        if (flaming(pm))
-            loc |= HOT;
+        int loc = pm_to_humidity(pm);
         /* If water-liking monster, first try is without DRY */
         get_location_coord(&x, &y, loc | NO_LOC_WARN, croom, m->coord);
         if (x == -1 && y == -1) {
@@ -1581,11 +1643,15 @@ struct mkroom *croom;
             mtmp = christen_monst(mtmp, m->name.str);
 
         /*
-         * This is currently hardwired for mimics only.  It should
-         * eventually be expanded.
+         * This doesn't complain if an attempt is made to give a
+         * non-mimic/non-shapechanger an appearance or to give a
+         * shapechanger a non-monster shape, it just refuses to comply.
          */
         if (m->appear_as.str
-            && ((mtmp->data->mlet == S_MIMIC) || mtmp->cham)) {
+            && ((mtmp->data->mlet == S_MIMIC)
+                /* shapechanger (chameleons, et al, and vampires) */
+                || (mtmp->cham >= LOW_PM && m->appear == M_AP_MONSTER))
+            && !Protection_from_shape_changers) {
             int i;
 
             switch (m->appear) {
@@ -1649,7 +1715,29 @@ struct mkroom *croom;
                     mndx = select_newcham_form(mtmp);
                 else
                     mndx = name_to_mon(m->appear_as.str);
-                if ((mndx != NON_PM) && (&mons[mndx] != mtmp->data)) {
+
+                if (mndx == NON_PM || (is_vampshifter(mtmp)
+                                       && !validvamp(mtmp, &mndx, S_HUMAN))) {
+                    impossible("create_monster: invalid %s (\"%s\")",
+                               (mtmp->data->mlet == S_MIMIC)
+                                 ? "mimic appearance"
+                                 : (mtmp->data == &mons[PM_WIZARD_OF_YENDOR])
+                                     ? "Wizard appearance"
+                                     : is_vampshifter(mtmp)
+                                         ? "vampire shape"
+                                         : "chameleon shape",
+                               m->appear_as.str);
+                } else if (&mons[mndx] == mtmp->data) {
+                    /* explicitly forcing a mimic to appear as itself */
+                    mtmp->m_ap_type = M_AP_NOTHING;
+                    mtmp->mappearance = 0;
+                } else if (mtmp->data->mlet == S_MIMIC
+                           || mtmp->data == &mons[PM_WIZARD_OF_YENDOR]) {
+                    /* this is ordinarily only used for Wizard clones
+                       and hasn't been exhaustively tested for mimics */
+                    mtmp->m_ap_type = M_AP_MONSTER;
+                    mtmp->mappearance = mndx;
+                } else { /* chameleon or vampire */
                     struct permonst *mdat = &mons[mndx];
                     struct permonst *olddata = mtmp->data;
 
@@ -1823,8 +1911,8 @@ struct mkroom *croom;
         otmp->obroken = 1;
         otmp->olocked = 0; /* obj generation may set */
     }
-    if (o->trapped)
-        otmp->otrapped = 1;
+    if (o->trapped == 0 || o->trapped == 1)
+        otmp->otrapped = o->trapped;
     if (o->greased)
         otmp->greased = 1;
 #ifdef INVISIBLE_OBJECTS
@@ -1872,11 +1960,13 @@ struct mkroom *croom;
                 }
             }
         } else {
+            struct obj *cobj = container_obj[container_idx - 1];
+
             remove_object(otmp);
-            if (container_obj[container_idx - 1])
-                (void) add_to_container(container_obj[container_idx - 1],
-                                        otmp);
-            else {
+            if (cobj) {
+                (void) add_to_container(cobj, otmp);
+                cobj->owt = weight(cobj);
+            else {
                 obj_extract_self(otmp);
                 obfree(otmp, NULL);
                 return;
@@ -1932,16 +2022,31 @@ struct mkroom *croom;
         }
     }
 
-    /* Nasty hack here: try to determine if this is the Mines or Sokoban
-     * "prize" and then set record_achieve_special (maps to corpsenm)
-     * for the object.  That field will later be checked to find out if
-     * the player obtained the prize. */
-    if (otmp->otyp == LUCKSTONE && Is_mineend_level(&u.uz)) {
-        otmp->record_achieve_special = 1;
-    } else if ((otmp->otyp == AMULET_OF_REFLECTION
-                || otmp->otyp == BAG_OF_HOLDING)
-               && Is_sokoend_level(&u.uz)) {
-        otmp->record_achieve_special = 1;
+    if (o->id != -1) {
+        static const char prize_warning[] = "multiple prizes on %s level";
+
+        /* if this is a specific item of the right type and it is being
+           created on the right level, flag it as the designated item
+           used to detect a special achievement (to whit, reaching and
+           exploring the target level, although the exploration part
+           might be short-circuited if a monster brings object to hero) */
+        if (Is_mineend_level(&u.uz)) {
+            if (otmp->otyp == iflags.mines_prize_type) {
+                otmp->record_achieve_special = MINES_PRIZE;
+                if (++mines_prize_count > 1)
+                    impossible(prize_warning, "mines end");
+            }
+        } else if (Is_sokoend_level(&u.uz)) {
+            if (otmp->otyp == iflags.soko_prize_type1) {
+                otmp->record_achieve_special = SOKO_PRIZE1;
+                if (++soko_prize_count > 1)
+                    impossible(prize_warning, "sokoban end");
+            } else if (otmp->otyp == iflags.soko_prize_type2) {
+                otmp->record_achieve_special = SOKO_PRIZE2;
+                if (++soko_prize_count > 1)
+                    impossible(prize_warning, "sokoban end");
+            }
+        }
     }
 
     stackobj(otmp);
@@ -1968,7 +2073,7 @@ create_altar(a, croom)
 altar *a;
 struct mkroom *croom;
 {
-    schar sproom, x, y;
+    schar sproom, x = -1, y = -1;
     aligntyp amask;
     boolean croom_is_temple = TRUE;
     int oldtyp;
@@ -3023,7 +3128,7 @@ struct sp_coder *coder;
     tmpobj.lit = 0;
     tmpobj.eroded = 0;
     tmpobj.locked = 0;
-    tmpobj.trapped = 0;
+    tmpobj.trapped = -1;
     tmpobj.recharged = 0;
     tmpobj.invis = 0;
     tmpobj.greased = 0;
@@ -3039,6 +3144,7 @@ struct sp_coder *coder;
     while ((nparams++ < (SP_O_V_END + 1)) && (OV_typ(varparam) == SPOVAR_INT)
            && (OV_i(varparam) >= 0) && (OV_i(varparam) < SP_O_V_END)) {
         struct opvar *parm;
+
         OV_pop(parm);
         switch (OV_i(varparam)) {
         case SP_O_V_NAME:
@@ -3050,11 +3156,12 @@ struct sp_coder *coder;
                 char monclass = SP_MONST_CLASS(OV_i(parm));
                 int monid = SP_MONST_PM(OV_i(parm));
 
-                if (monid >= 0 && monid < NUMMONS) {
+                if (monid >= LOW_PM && monid < NUMMONS) {
                     tmpobj.corpsenm = monid;
                     break; /* we're done! */
                 } else {
                     struct permonst *pm = (struct permonst *) 0;
+
                     if (def_char_to_monclass(monclass) != MAXMCLASSES) {
                         pm = mkclass(def_char_to_monclass(monclass), G_NOGEN);
                     } else {
@@ -3467,7 +3574,7 @@ struct sp_coder *coder;
     static const char nhFunc[] = "spo_trap";
     struct opvar *type;
     struct opvar *tcoord;
-    trap tmptrap;
+    spltrap tmptrap;
 
     if (!OV_pop_i(type) || !OV_pop_c(tcoord))
         return;
@@ -3763,7 +3870,7 @@ int dir;
 STATIC_VAR int FDECL((*selection_flood_check_func), (int, int));
 STATIC_VAR schar floodfillchk_match_under_typ;
 
-STATIC_OVL void
+void
 set_selection_floodfillchk(f)
 int FDECL((*f), (int, int));
 {
@@ -3786,7 +3893,7 @@ int x, y;
             || levl[x][y].typ == SCORR);
 }
 
-STATIC_OVL void
+void
 selection_floodfill(ov, x, y, diagonals)
 struct opvar *ov;
 int x, y;
@@ -4087,8 +4194,8 @@ struct opvar *ov;
         my = ((y1 + y2) / 2);
     } else {
         do {
-            dx = (Rand() % rough) - (rough / 2);
-            dy = (Rand() % rough) - (rough / 2);
+            dx = rn2(rough) - (rough / 2);
+            dy = rn2(rough) - (rough / 2);
             mx = ((x1 + x2) / 2) + dx;
             my = ((y1 + y2) / 2) + dy;
         } while ((mx > COLNO - 1 || mx < 0 || my < 0 || my > ROWNO - 1));
@@ -4153,8 +4260,7 @@ int dx, dy;
 genericptr_t arg;
 {
     xchar typ = *(xchar *) arg;
-    xchar x = dx;
-    xchar y = dy;
+    xchar x = dx, y = dy;
 
     if (!IS_DOOR(levl[x][y].typ) && levl[x][y].typ != SDOOR)
         levl[x][y].typ = (typ & D_SECRET) ? SDOOR : DOOR;
@@ -4163,6 +4269,7 @@ genericptr_t arg;
         if (typ < D_CLOSED)
             typ = D_CLOSED;
     }
+    set_door_orientation(x, y); /* set/clear levl[x][y].horizontal */
     levl[x][y].doormask = typ;
     SpLev_Map[x][y] = 1;
 }
@@ -4386,7 +4493,7 @@ void
 spo_levregion(coder)
 struct sp_coder *coder;
 {
-    static const char nhFunc[] = "spot_levregion";
+    static const char nhFunc[] = "spo_levregion";
     struct opvar *rname, *padding, *rtype, *del_islev, *dy2, *dx2, *dy1, *dx1,
         *in_islev, *iy2, *ix2, *iy1, *ix1;
 
@@ -4745,7 +4852,8 @@ struct sp_coder *coder;
         dy1 = (xchar) SP_REGION_Y1(OV_i(r));
         dx2 = (xchar) SP_REGION_X2(OV_i(r));
         dy2 = (xchar) SP_REGION_Y2(OV_i(r));
-        wallify_map(dx1 < 0 ? (xstart-1) : dx1, dy1 < 0 ? (ystart-1) : dy1,
+        wallify_map(dx1 < 0 ? (xstart - 1) : dx1,
+                    dy1 < 0 ? (ystart - 1) : dy1,
                     dx2 < 0 ? (xstart + xsize + 1) : dx2,
                     dy2 < 0 ? (ystart + ysize + 1) : dy2);
         break;
@@ -4844,7 +4952,7 @@ struct sp_coder *coder;
         ystart = valign;
         break;
     }
-    if ((ystart < 0) || (ystart + ysize > ROWNO)) {
+    if (ystart < 0 || ystart + ysize > ROWNO) {
         /* try to move the start a bit */
         ystart += (ystart > 0) ? -2 : 2;
         if (ysize == ROWNO)
@@ -4858,13 +4966,13 @@ struct sp_coder *coder;
         xsize = COLNO - 1;
         ysize = ROWNO;
     } else {
-        xchar x, y;
+        xchar x, y, mptyp;
+
         /* Load the map */
         for (y = ystart; y < ystart + ysize; y++)
             for (x = xstart; x < xstart + xsize; x++) {
-                xchar mptyp =
-                    (mpmap->vardata.str[(y - ystart) * xsize + (x - xstart)]
-                     - 1);
+                mptyp = (mpmap->vardata.str[(y - ystart) * xsize
+                                                  + (x - xstart)] - 1);
                 if (mptyp >= MAX_TYPE)
                     continue;
                 levl[x][y].typ = mptyp;
@@ -5172,7 +5280,7 @@ sp_lev *lvl;
     long room_stack = 0;
     unsigned long max_execution = SPCODER_MAX_RUNTIME;
     struct sp_coder *coder =
-        (struct sp_coder *) alloc(sizeof(struct sp_coder));
+        (struct sp_coder *) alloc(sizeof (struct sp_coder));
 
     coder->frame = frame_new(0);
     coder->stack = NULL;
@@ -5186,9 +5294,14 @@ sp_lev *lvl;
 
     splev_init_present = FALSE;
     icedpools = FALSE;
+    /* achievement tracking; static init would suffice except we need to
+       reset if #wizmakemap is used to recreate mines' end or sokoban end;
+       once either level is created, these values can be forgotten */
+    mines_prize_count = soko_prize_count = 0;
 
     if (wizard) {
         char *met = nh_getenv("SPCODER_MAX_RUNTIME");
+
         if (met && met[0] == '1')
             max_execution = (1 << 30) - 1;
     }
@@ -5862,11 +5975,16 @@ sp_lev *lvl;
 
     count_features();
 
-    if (coder->premapped)
-        sokoban_detect();
     if (coder->solidify)
         solidify_map();
 
+    /* This must be done before sokoban_detect(),
+     * otherwise branch stairs won't be premapped. */
+    fixup_special();
+
+    if (coder->premapped)
+        sokoban_detect();
+
     if (coder->frame) {
         struct sp_frame *tmpframe;
         do {
@@ -5900,7 +6018,8 @@ const char *name;
         (void) dlb_fclose(fd);
         goto give_up;
     }
-    lvl = (sp_lev *) alloc(sizeof(sp_lev));
+
+    lvl = (sp_lev *) alloc(sizeof (sp_lev));
     result = sp_level_loader(fd, lvl);
     (void) dlb_fclose(fd);
     if (result)
index 6e4eb4b..bed45e7 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 spell.c $NHDT-Date: 1447653429 2015/11/16 05:57:09 $  $NHDT-Branch: master $:$NHDT-Revision: 1.72 $ */
+/* NetHack 3.6 spell.c $NHDT-Date: 1508479722 2017/10/20 06:08:42 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.84 $ */
 /*      Copyright (c) M. Stephenson 1988                          */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -48,6 +48,7 @@ STATIC_DCL int NDECL(throwspell);
 STATIC_DCL void NDECL(cast_protection);
 STATIC_DCL void FDECL(spell_backfire, (int));
 STATIC_DCL const char *FDECL(spelltypemnemonic, (int));
+STATIC_DCL boolean FDECL(spell_aim_step, (genericptr_t, int, int));
 
 /* The roles[] table lists the role-specific values for tuning
  * percent_success().
@@ -127,6 +128,7 @@ STATIC_OVL boolean
 cursed_book(bp)
 struct obj *bp;
 {
+    boolean was_in_use;
     int lev = objects[bp->otyp].oc_level;
     int dmg = 0;
 
@@ -172,6 +174,7 @@ struct obj *bp;
             break;
         }
         /* temp disable in_use; death should not destroy the book */
+        was_in_use = bp->in_use;
         bp->in_use = FALSE;
         losestr(Poison_resistance ? rn1(2, 1) : rn1(4, 3));
 #if 0 /*JP*/
@@ -181,7 +184,7 @@ struct obj *bp;
         losehp(rnd(Poison_resistance ? 6 : 10), "\90Ú\90G\93Å\82Ì\96\82\96@\8f\91\82Å",
                KILLED_BY_AN);
 #endif
-        bp->in_use = TRUE;
+        bp->in_use = was_in_use;
         break;
     case 6:
         if (Antimagic) {
@@ -406,6 +409,17 @@ struct obj *book2;
     return;
 }
 
+/* 'book' has just become cursed; if we're reading it and realize it is
+   now cursed, interrupt */
+void
+book_cursed(book)
+struct obj *book;
+{
+    if (occupation == learn && context.spbook.book == book
+        && book->cursed && book->bknown && multi >= 0)
+        stop_occupation();
+}
+
 STATIC_PTR int
 learn(VOID_ARGS)
 {
@@ -431,9 +445,8 @@ learn(VOID_ARGS)
         context.spbook.delay = 0;
         return 0;
     }
-    if (context
-            .spbook.delay) { /* not if (context.spbook.delay++), so at end
-                                delay == 0 */
+    if (context.spbook.delay) {
+        /* not if (context.spbook.delay++), so at end delay == 0 */
         context.spbook.delay++;
         return 1; /* still busy */
     }
@@ -540,7 +553,7 @@ register struct obj *spellbook;
     boolean too_hard = FALSE;
 
     /* attempting to read dull book may make hero fall asleep */
-    if (!confused && booktype != SPE_BLANK_PAPER
+    if (!confused && !Sleep_resistance
 /*JP
         && !strcmp(OBJ_DESCR(objects[booktype]), "dull")) {
 */
@@ -589,7 +602,7 @@ register struct obj *spellbook;
             return 1;
         }
 
-        /* 3.6.0 tribute */
+        /* 3.6 tribute */
         if (booktype == SPE_NOVEL) {
             /* Obtain current Terry Pratchett book title */
             const char *tribtitle = noveltitle(&spellbook->novelidx);
@@ -598,6 +611,7 @@ register struct obj *spellbook;
                              spellbook->o_id)) {
                 u.uconduct.literate++;
                 check_unpaid(spellbook);
+                makeknown(booktype);
                 if (!u.uevent.read_tribute) {
                     /* give bonus of 20 xp and 4*20+0 pts */
                     more_experienced(20, 0);
@@ -639,19 +653,21 @@ register struct obj *spellbook;
                 too_hard = TRUE;
             } else {
                 /* uncursed - chance to fail */
-                int read_ability =
-                    ACURR(A_INT) + 4 + u.ulevel / 2
-                    - 2 * objects[booktype].oc_level
-                    + ((ublindf && ublindf->otyp == LENSES) ? 2 : 0);
+                int read_ability = ACURR(A_INT) + 4 + u.ulevel / 2
+                                   - 2 * objects[booktype].oc_level
+                             + ((ublindf && ublindf->otyp == LENSES) ? 2 : 0);
+
                 /* only wizards know if a spell is too difficult */
                 if (Role_if(PM_WIZARD) && read_ability < 20 && !confused) {
                     char qbuf[QBUFSZ];
-                    Sprintf(qbuf,
+
 #if 0 /*JP*/
-                     "This spellbook is %sdifficult to comprehend. Continue?",
+                    Sprintf(qbuf,
+                    "This spellbook is %sdifficult to comprehend.  Continue?",
                             (read_ability < 12 ? "very " : ""));
 #else
-                     "\82±\82Ì\96\82\96@\8f\91\82ð\97\9d\89ð\82·\82é\82Ì\82Í%s\8d¢\93ï\82¾\81D\91±\82¯\82Ü\82·\82©\81H",
+                    Sprintf(qbuf,
+                    "\82±\82Ì\96\82\96@\8f\91\82ð\97\9d\89ð\82·\82é\82Ì\82Í%s\8d¢\93ï\82¾\81D\91±\82¯\82Ü\82·\82©\81H",
                             (read_ability < 12 ? "\82Æ\82Ä\82à" : ""));
 #endif
                     if (yn(qbuf) != 'y') {
@@ -778,6 +794,9 @@ rejectcasting()
 */
         You("\96\82\96@\82ð\8f¥\82¦\82ç\82ê\82È\82¢\81D");
         return TRUE;
+    } else if (!can_chant(&youmonst)) {
+        You("are unable to chant the incantation.");
+        return TRUE;
     } else if (!freehand()) {
         /* Note: !freehand() occurs when weapon and shield (or two-handed
          * weapon) are welded to hands, so "arms" probably doesn't need
@@ -999,9 +1018,9 @@ cast_protection()
                                          : "\82Ë\82Î\82Ë\82Î")
                                 : (u.uinwater
 /*JP
-                                   ? "water"
+                                   ? hliquid("water")
 */
-                                   ? "\90\85"
+                                   ? hliquid("\90\85")
                                    : (rmtyp == CLOUD)
 /*JP
                                       ? "cloud"
@@ -1009,7 +1028,7 @@ cast_protection()
                                       ? "\89_"
                                       : IS_TREE(rmtyp)
 /*JP
-                                         ? "vegitation"
+                                         ? "vegetation"
 */
                                          ? "\96Ø"
                                          : IS_STWALL(rmtyp)
@@ -1075,8 +1094,8 @@ int spell;
         break;
     case 7:
     case 8:
-        make_stunned(old_conf + 2L * duration / 3L, FALSE); /* 20% */
-        make_confused(old_stun + duration / 3L, FALSE);
+        make_stunned(old_stun + 2L * duration / 3L, FALSE); /* 20% */
+        make_confused(old_conf + duration / 3L, FALSE);
         break;
     case 9:
         make_stunned(old_stun + duration, FALSE); /* 10% */
@@ -1091,7 +1110,7 @@ int spell;
 boolean atme;
 {
     int energy, damage, chance, n, intell;
-    int skill, role_skill;
+    int skill, role_skill, res = 0;
     boolean confused = (Confusion != 0);
     boolean physical_damage = FALSE;
     struct obj *pseudo;
@@ -1168,19 +1187,35 @@ boolean atme;
         return 1;
     }
 
-    if (u.uhave.amulet) {
+    /* if the cast attempt is already going to fail due to insufficient
+       energy (ie, u.uen < energy), the Amulet's drain effect won't kick
+       in and no turn will be consumed; however, when it does kick in,
+       the attempt may fail due to lack of energy after the draining, in
+       which case a turn will be used up in addition to the energy loss */
+    if (u.uhave.amulet && u.uen >= energy) {
 /*JP
         You_feel("the amulet draining your energy away.");
 */
         pline("\96\82\8f\9c\82¯\82ª\82 \82È\82½\82Ì\83G\83l\83\8b\83M\81[\82ð\8bz\82¢\82Æ\82Á\82Ä\82¢\82é\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
-        energy += rnd(2 * energy);
+        /* this used to be 'energy += rnd(2 * energy)' (without 'res'),
+           so if amulet-induced cost was more than u.uen, nothing
+           (except the "don't have enough energy" message) happened
+           and player could just try again (and again and again...);
+           now we drain some energy immediately, which has a
+           side-effect of not increasing the hunger aspect of casting */
+        u.uen -= rnd(2 * energy);
+        if (u.uen < 0)
+            u.uen = 0;
+        context.botl = 1;
+        res = 1; /* time is going to elapse even if spell doesn't get cast */
     }
+
     if (energy > u.uen) {
 /*JP
         You("don't have enough energy to cast that spell.");
 */
         pline("\96\82\96@\82ð\8f¥\82¦\82é\82¾\82¯\82Ì\8f\\95ª\82È\83G\83l\83\8b\83M\81[\82ª\82È\82¢\81D");
-        return 0;
+        return res;
     } else {
         if (spellid(spell) != SPE_DETECT_FOOD) {
             int hungr = energy * 2;
@@ -1396,6 +1431,7 @@ boolean atme;
     case SPE_INVISIBILITY:
         (void) peffects(pseudo);
         break;
+    /* end of potion-like spells */
 
     case SPE_CURE_BLINDNESS:
         healup(0, 0, FALSE, TRUE);
@@ -1417,10 +1453,12 @@ boolean atme;
         (void) make_familiar((struct obj *) 0, u.ux, u.uy, FALSE);
         break;
     case SPE_CLAIRVOYANCE:
-        if (!BClairvoyant)
-            do_vicinity_map();
+        if (!BClairvoyant) {
+            if (role_skill >= P_SKILLED)
+                pseudo->blessed = 1; /* detect monsters as well as map */
+            do_vicinity_map(pseudo);
         /* at present, only one thing blocks clairvoyance */
-        else if (uarmh && uarmh->otyp == CORNUTHAUM)
+        else if (uarmh && uarmh->otyp == CORNUTHAUM)
 /*JP
             You("sense a pointy hat on top of your %s.", body_part(HEAD));
 */
@@ -1446,11 +1484,25 @@ boolean atme;
     return 1;
 }
 
+/*ARGSUSED*/
+STATIC_OVL boolean
+spell_aim_step(arg, x, y)
+genericptr_t arg UNUSED;
+int x, y;
+{
+    if (!isok(x,y))
+        return FALSE;
+    if (!ZAP_POS(levl[x][y].typ)
+        && !(IS_DOOR(levl[x][y].typ) && (levl[x][y].doormask & D_ISOPEN)))
+        return FALSE;
+    return TRUE;
+}
+
 /* Choose location where spell takes effect. */
 STATIC_OVL int
 throwspell()
 {
-    coord cc;
+    coord cc, uc;
     struct monst *mtmp;
 
     if (u.uinwater) {
@@ -1504,6 +1556,11 @@ throwspell()
         return 0;
     }
 
+    uc.x = u.ux;
+    uc.y = u.uy;
+
+    walk_path(&uc, &cc, spell_aim_step, (genericptr_t) 0);
+
     u.dx = cc.x;
     u.dy = cc.y;
     return 1;
@@ -1591,53 +1648,58 @@ losespells()
  *      are learned, they get inserted into sorted order rather than be
  *      appended to the end of the list?
  */
-static const char *spl_sortchoices[] = {
+enum spl_sort_types {
+    SORTBY_LETTER = 0,
+    SORTBY_ALPHA,
+    SORTBY_LVL_LO,
+    SORTBY_LVL_HI,
+    SORTBY_SKL_AL,
+    SORTBY_SKL_LO,
+    SORTBY_SKL_HI,
+    SORTBY_CURRENT,
+    SORTRETAINORDER,
+
+    NUM_SPELL_SORTBY
+};
+
+static const char *spl_sortchoices[NUM_SPELL_SORTBY] = {
 /*JP
     "by casting letter",
 */
     "\91I\91ð\82·\82é\95\8e\9a\8f\87",
-#define SORTBY_LETTER 0
 /*JP
     "alphabetically",
 */
     "\95\8e\9a\83R\81[\83h\8f\87",
-#define SORTBY_ALPHA 1
 /*JP
     "by level, low to high",
 */
     "\83\8c\83x\83\8b\8f¸\8f\87",
-#define SORTBY_LVL_LO 2
 /*JP
     "by level, high to low",
 */
     "\83\8c\83x\83\8b\8d~\8f\87",
-#define SORTBY_LVL_HI 3
 /*JP
     "by skill group, alphabetized within each group",
 */
     "\83X\83L\83\8b\83O\83\8b\81[\83v\96\88\82É\95\8e\9a\83R\81[\83h\8f\87",
-#define SORTBY_SKL_AL 4
 /*JP
     "by skill group, low to high level within group",
 */
     "\83X\83L\83\8b\83O\83\8b\81[\83v\96\88\82É\83\8c\83x\83\8b\8f¸\8f\87",
-#define SORTBY_SKL_LO 5
 /*JP
     "by skill group, high to low level within group",
 */
     "\83X\83L\83\8b\83O\83\8b\81[\83v\96\88\82É\83\8c\83x\83\8b\8d~\8f\87",
-#define SORTBY_SKL_HI 6
 /*JP
     "maintain current ordering",
 */
     "\8c»\8dÝ\82Ì\8f\87\8f\98\82ð\88Û\8e\9d",
-#define SORTBY_CURRENT 7
     /* a menu choice rather than a sort choice */
 /*JP
     "reassign casting letters to retain current order",
 */
     "\8c»\8dÝ\82Ì\8f\87\8f\98\82ð\95Ï\82¦\82¸\82É\91I\91ð\82·\82é\95\8e\9a\82ð\8dÄ\8a\84\82è\93\96\82Ä",
-#define SORTRETAINORDER 8
 };
 static int spl_sortmode = 0;   /* index into spl_sortchoices[] */
 static int *spl_orderindx = 0; /* array of spl_book[] indices */
index b48dd9a..2483734 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 steal.c $NHDT-Date: 1446713643 2015/11/05 08:54:03 $  $NHDT-Branch: master $:$NHDT-Revision: 1.65 $ */
+/* NetHack 3.6 steal.c $NHDT-Date: 1496614914 2017/06/04 22:21:54 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.69 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -579,53 +580,86 @@ register struct obj *otmp;
     return freed_otmp;
 }
 
+/* called for AD_SAMU (the Wizard and quest nemeses) */
 void
 stealamulet(mtmp)
 struct monst *mtmp;
 {
-    struct obj *otmp = (struct obj *) 0;
-    int real = 0, fake = 0;
-
-    /* select the artifact to steal */
-    if (u.uhave.amulet) {
-        real = AMULET_OF_YENDOR;
-        fake = FAKE_AMULET_OF_YENDOR;
-    } else if (u.uhave.questart) {
+    char buf[BUFSZ];
+    struct obj *otmp = 0, *obj = 0;
+    int real = 0, fake = 0, n;
+
+    /* target every quest artifact, not just current role's;
+       if hero has more than one, choose randomly so that player
+       can't use inventory ordering to influence the theft */
+    for (n = 0, obj = invent; obj; obj = obj->nobj)
+        if (any_quest_artifact(obj))
+            ++n, otmp = obj;
+    if (n > 1) {
+        n = rnd(n);
         for (otmp = invent; otmp; otmp = otmp->nobj)
-            if (is_quest_artifact(otmp))
+            if (any_quest_artifact(otmp) && !--n)
                 break;
-        if (!otmp)
-            return; /* should we panic instead? */
-    } else if (u.uhave.bell) {
-        real = BELL_OF_OPENING;
-        fake = BELL;
-    } else if (u.uhave.book) {
-        real = SPE_BOOK_OF_THE_DEAD;
-    } else if (u.uhave.menorah) {
-        real = CANDELABRUM_OF_INVOCATION;
-    } else
-        return; /* you have nothing of special interest */
+    }
 
     if (!otmp) {
+        /* if we didn't find any quest arifact, find another valuable item */
+        if (u.uhave.amulet) {
+            real = AMULET_OF_YENDOR;
+            fake = FAKE_AMULET_OF_YENDOR;
+        } else if (u.uhave.bell) {
+            real = BELL_OF_OPENING;
+            fake = BELL;
+        } else if (u.uhave.book) {
+            real = SPE_BOOK_OF_THE_DEAD;
+        } else if (u.uhave.menorah) {
+            real = CANDELABRUM_OF_INVOCATION;
+        } else
+            return; /* you have nothing of special interest */
+
         /* If we get here, real and fake have been set up. */
-        for (otmp = invent; otmp; otmp = otmp->nobj)
-            if (otmp->otyp == real || (otmp->otyp == fake && !mtmp->iswiz))
-                break;
+        for (n = 0, obj = invent; obj; obj = obj->nobj)
+            if (obj->otyp == real || (obj->otyp == fake && !mtmp->iswiz))
+                ++n, otmp = obj;
+        if (n > 1) {
+            n = rnd(n);
+            for (otmp = invent; otmp; otmp = otmp->nobj)
+                if ((otmp->otyp == real
+                     || (otmp->otyp == fake && !mtmp->iswiz)) && !--n)
+                    break;
+        }
     }
 
     if (otmp) { /* we have something to snatch */
+        /* take off outer gear if we're targetting [hypothetical]
+           quest artifact suit, shirt, gloves, or rings */
+        if ((otmp == uarm || otmp == uarmu) && uarmc)
+            remove_worn_item(uarmc, FALSE);
+        if (otmp == uarmu && uarm)
+            remove_worn_item(uarm, FALSE);
+        if ((otmp == uarmg || ((otmp == uright || otmp == uleft) && uarmg))
+            && uwep) {
+            /* gloves are about to be unworn; unwield weapon(s) first */
+            if (u.twoweap)    /* remove_worn_item(uswapwep) indirectly */
+                remove_worn_item(uswapwep, FALSE); /* clears u.twoweap */
+            remove_worn_item(uwep, FALSE);
+        }
+        if ((otmp == uright || otmp == uleft) && uarmg)
+            /* calls Gloves_off() to handle wielded cockatrice corpse */
+            remove_worn_item(uarmg, FALSE);
+
+        /* finally, steal the target item */
         if (otmp->owornmask)
             remove_worn_item(otmp, TRUE);
         if (otmp->unpaid)
             subfrombill(otmp, shop_keeper(*u.ushops));
         freeinv(otmp);
-        /* mpickobj wont merge otmp because none of the above things
-           to steal are mergable */
-        (void) mpickobj(mtmp, otmp); /* may merge and free otmp */
+        Strcpy(buf, doname(otmp));
+        (void) mpickobj(mtmp, otmp); /* could merge and free otmp but won't */
 /*JP
-        pline("%s stole %s!", Monnam(mtmp), doname(otmp));
+        pline("%s steals %s!", Monnam(mtmp), buf);
 */
-        pline("%s\82Í%s\82ð\93\90\82ñ\82¾\81I", Monnam(mtmp), doname(otmp));
+        pline("%s\82Í%s\82ð\93\90\82ñ\82¾\81I", Monnam(mtmp), buf);
         if (can_teleport(mtmp->data) && !tele_restrict(mtmp))
             (void) rloc(mtmp, TRUE);
     }
@@ -705,10 +739,11 @@ boolean verbosely;
         if (mon->mhp > 0) {
             mon->misc_worn_check &= ~obj->owornmask;
             update_mon = TRUE;
-            /* don't charge for an owned saddle on dead steed (provided
-               that the hero is within the same shop at the time) */
-        } else if (mon->mtame && (obj->owornmask & W_SADDLE) && !obj->unpaid
-                   && costly_spot(omx, omy)
+
+        /* don't charge for an owned saddle on dead steed (provided
+           that the hero is within the same shop at the time) */
+        } else if (mon->mtame && (obj->owornmask & W_SADDLE) != 0L
+                   && !obj->unpaid && costly_spot(omx, omy)
                    /* being at costly_spot guarantees lev->roomno is not 0 */
                    && index(in_rooms(u.ux, u.uy, SHOPBASE),
                             levl[omx][omy].roomno)) {
@@ -740,7 +775,7 @@ boolean verbosely;
 
 /* some monsters bypass the normal rules for moving between levels or
    even leaving the game entirely; when that happens, prevent them from
-   taking the Amulet or invocation tools with them */
+   taking the Amulet, invocation items, or quest artifact with them */
 void
 mdrop_special_objs(mon)
 struct monst *mon;
@@ -750,8 +785,10 @@ struct monst *mon;
     for (obj = mon->minvent; obj; obj = otmp) {
         otmp = obj->nobj;
         /* the Amulet, invocation tools, and Rider corpses resist even when
-           artifacts and ordinary objects are given 0% resistance chance */
-        if (obj_resists(obj, 0, 0)) {
+           artifacts and ordinary objects are given 0% resistance chance;
+           current role's quest artifact is rescued too--quest artifacts
+           for the other roles are not */
+        if (obj_resists(obj, 0, 0) || is_quest_artifact(obj)) {
             obj_extract_self(obj);
             mdrop_obj(mon, obj, FALSE);
         }
index d724d0f..97c5071 100644 (file)
@@ -175,13 +175,7 @@ struct obj *otmp;
         if (otmp->owornmask)
             remove_worn_item(otmp, FALSE);
         freeinv(otmp);
-        /* mpickobj may free otmp it if merges, but we have already
-           checked for a saddle above, so no merger should happen */
-        (void) mpickobj(mtmp, otmp);
-        mtmp->misc_worn_check |= W_SADDLE;
-        otmp->owornmask = W_SADDLE;
-        otmp->leashmon = mtmp->m_id;
-        update_mon_intrinsics(mtmp, otmp, TRUE, FALSE);
+        put_saddle_on_mon(otmp, mtmp);
     } else
 /*JP
         pline("%s resists!", Monnam(mtmp));
@@ -190,6 +184,21 @@ struct obj *otmp;
     return 1;
 }
 
+void
+put_saddle_on_mon(saddle, mtmp)
+struct obj *saddle;
+struct monst *mtmp;
+{
+    if (!can_saddle(mtmp) || which_armor(mtmp, W_SADDLE))
+        return;
+    if (mpickobj(mtmp, saddle))
+        panic("merged saddle?");
+    mtmp->misc_worn_check |= W_SADDLE;
+    saddle->owornmask = W_SADDLE;
+    saddle->leashmon = mtmp->m_id;
+    update_mon_intrinsics(mtmp, saddle, TRUE, FALSE);
+}
+
 /*** Riding the monster ***/
 
 /* Can we ride this monster?  Caller should also check can_saddle() */
@@ -374,10 +383,12 @@ boolean force;      /* Quietly force this animal */
         return (FALSE);
     }
     if (!force && Underwater && !is_swimmer(ptr)) {
-/*JP
-        You_cant("ride that creature while under water.");
-*/
+#if 0 /*JP*/
+        You_cant("ride that creature while under %s.",
+                 hliquid("water"));
+#else /*\82Æ\82è\82 \82¦\82¸\90\85\82¾\82¯*/
         You("\90\85\92\86\82Å\8fæ\82é\82±\82Æ\82Í\82Å\82«\82È\82¢\81D");
+#endif
         return (FALSE);
     }
     if (!can_saddle(mtmp) || !can_ride(mtmp)) {
@@ -385,7 +396,7 @@ boolean force;      /* Quietly force this animal */
         You_cant("ride such a creature.");
 */
         You("\82»\82Ì\90\82«\95¨\82É\8fæ\82é\82±\82Æ\82Í\82Å\82«\82È\82¢\81D");
-        return (0);
+        return FALSE;
     }
 
     /* Is the player impaired? */
@@ -459,7 +470,8 @@ boolean force;      /* Quietly force this animal */
     u.usteed = mtmp;
     remove_monster(mtmp->mx, mtmp->my);
     teleds(mtmp->mx, mtmp->my, TRUE);
-    return (TRUE);
+    context.botl = TRUE;
+    return TRUE;
 }
 
 /* You and your steed have moved */
@@ -627,6 +639,7 @@ int reason; /* Player was thrown off etc. */
         verb = "are thrown";
 */
         verb = "\82Ó\82è\97\8e\82³\82ê\82½";
+        /*FALLTHRU*/
     case DISMOUNT_FELL:
 /*JP
         You("%s off of %s!", verb, mon_nam(mtmp));
@@ -737,10 +750,13 @@ int reason; /* Player was thrown off etc. */
                         adjalign(-1);
                     }
                 } else if (is_lava(u.ux, u.uy)) {
-/*JP
-                    pline("%s is pulled into the lava!", Monnam(mtmp));
-*/
-                    pline("%s\82Í\97n\8aâ\82Ì\92\86\82É\82Ð\82Á\82Ï\82ç\82ê\82½\81I", Monnam(mtmp));
+#if 0 /*JP*/
+                    pline("%s is pulled into the %s!", Monnam(mtmp),
+                          hliquid("lava"));
+#else
+                    pline("%s\82Í%s\82Ì\92\86\82É\82Ð\82Á\82Ï\82ç\82ê\82½\81I", Monnam(mtmp),
+                          hliquid("\97n\8aâ"));
+#endif
                     if (!likes_lava(mdat)) {
                         killed(mtmp);
                         adjalign(-1);
@@ -795,11 +811,11 @@ int reason; /* Player was thrown off etc. */
         in_steed_dismounting = TRUE;
         (void) float_down(0L, W_SADDLE);
         in_steed_dismounting = FALSE;
-        context.botl = 1;
+        context.botl = TRUE;
         (void) encumber_msg();
         vision_full_recalc = 1;
     } else
-        context.botl = 1;
+        context.botl = TRUE;
     /* polearms behave differently when not mounted */
     if (uwep && is_pole(uwep))
         unweapon = TRUE;
index 96c080e..6adc8f7 100644 (file)
--- a/src/sys.c
+++ b/src/sys.c
@@ -32,10 +32,15 @@ sys_early_init()
 #else
     sysopt.debugfiles = dupstr(DEBUGFILES);
 #endif
+#ifdef DUMPLOG
+    sysopt.dumplogfile = (char *) 0;
+#endif
     sysopt.env_dbgfl = 0; /* haven't checked getenv("DEBUGFILES") yet */
     sysopt.shellers = (char *) 0;
     sysopt.explorers = (char *) 0;
+    sysopt.genericusers = (char *) 0;
     sysopt.maxplayers = 0; /* XXX eventually replace MAX_NR_OF_PLAYERS */
+    sysopt.bones_pools = 0;
 
     /* record file */
     sysopt.persmax = PERSMAX;
@@ -72,6 +77,7 @@ sys_early_init()
 #endif
 
     sysopt.check_save_uid = 1;
+    sysopt.check_plname = 0;
     sysopt.seduce = 1; /* if it's compiled in, default to on */
     sysopt_seduce_set(sysopt.seduce);
     return;
@@ -93,6 +99,13 @@ sysopt_release()
     if (sysopt.debugfiles)
         free((genericptr_t) sysopt.debugfiles),
         sysopt.debugfiles = (char *) 0;
+#ifdef DUMPLOG
+    if (sysopt.dumplogfile)
+        free((genericptr_t)sysopt.dumplogfile), sysopt.dumplogfile=(char *)0;
+#endif
+    if (sysopt.genericusers)
+        free((genericptr_t) sysopt.genericusers),
+        sysopt.genericusers = (char *) 0;
 #ifdef PANICTRACE
     if (sysopt.gdbpath)
         free((genericptr_t) sysopt.gdbpath), sysopt.gdbpath = (char *) 0;
index 13d8b04..f17de84 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 teleport.c      $NHDT-Date: 1446887535 2015/11/07 09:12:15 $  $NHDT-Branch: master $:$NHDT-Revision: 1.62 $ */
+/* NetHack 3.6 teleport.c      $NHDT-Date: 1523306912 2018/04/09 20:48:32 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.73 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -133,7 +134,9 @@ unsigned entflags;
         /* default to player's original monster type */
         mdat = &mons[u.umonster];
     }
-    fakemon.data = mdat; /* set up for goodpos */
+    fakemon = zeromonst;
+    set_mon_data(&fakemon, mdat, -1); /* set up for goodpos */
+
     good_ptr = good;
     range = 1;
     /*
@@ -201,6 +204,8 @@ STATIC_OVL boolean
 tele_jump_ok(x1, y1, x2, y2)
 int x1, y1, x2, y2;
 {
+    if (!isok(x2, y2))
+        return FALSE;
     if (dndest.nlx > 0) {
         /* if inside a restricted region, can't teleport outside */
         if (within_bounded_area(x1, y1, dndest.nlx, dndest.nly, dndest.nhx,
@@ -257,7 +262,7 @@ boolean allow_drag;
         /* unearth it */
         buried_ball_to_punishment();
     }
-    ball_active = (Punished && uball->where != OBJ_FREE),
+    ball_active = (Punished && uball->where != OBJ_FREE);
     ball_still_in_range = FALSE;
 
     /* If they have to move the ball, then drag if allow_drag is true;
@@ -670,15 +675,28 @@ level_tele()
 */
         Strcpy(qbuf, "\89½\8aK\82É\88Ú\93®\82µ\82Ü\82·\82©\81H");
         do {
+            if (iflags.menu_requested) {
+                /* wizard mode 'm ^V' skips prompting on first pass
+                   (note: level Tport via menu won't have any second pass) */
+                iflags.menu_requested = FALSE;
+                if (wizard)
+                    goto levTport_menu;
+            }
             if (++trycnt == 2) {
                 if (wizard)
-                    Strcat(qbuf, " [type a number or ? for a menu]");
+/*JP
+                    Strcat(qbuf, " [type a number, name, or ? for a menu]");
+*/
+                    Strcat(qbuf, " [\90\94\8e\9a\82©\96¼\91O\82ð\82¢\82ê\82Ä\82Ë\81D?\82Å\83\81\83j\83\85\81[]");
                 else
 /*JP
-                    Strcat(qbuf, " [type a number]");
+                    Strcat(qbuf, " [type a number or name]");
 */
-                    Strcat(qbuf, " [\90\94\8e\9a\82ð\82¢\82ê\82Ä\82Ë]");
+                    Strcat(qbuf, " [\90\94\8e\9a\82©\96¼\91O\82ð\82¢\82ê\82Ä\82Ë]");
             }
+            *buf = '\0'; /* EDIT_GETLIN: if we're on second or later pass,
+                            the previous input was invalid so don't use it
+                            as getlin()'s preloaded default answer */
             getlin(qbuf, buf);
             if (!strcmp(buf, "\033")) { /* cancelled */
                 if (Confusion && rnl(5)) {
@@ -699,9 +717,12 @@ level_tele()
                 goto random_levtport;
             }
             if (wizard && !strcmp(buf, "?")) {
-                schar destlev = 0;
-                xchar destdnum = 0;
+                schar destlev;
+                xchar destdnum;
 
+            levTport_menu:
+                destlev = 0;
+                destdnum = 0;
                 newlev = (int) print_dungeon(TRUE, &destlev, &destdnum);
                 if (!newlev)
                     return;
@@ -1028,18 +1049,30 @@ struct trap *trap;
 }
 
 void
-level_tele_trap(trap)
+level_tele_trap(trap, trflags)
 struct trap *trap;
+unsigned trflags;
 {
+    char verbbuf[BUFSZ];
+
 #if 0 /*JP*/
-    You("%s onto a level teleport trap!",
-        Levitation ? (const char *) "float"
-                   : locomotion(youmonst.data, "step"));
+    if ((trflags & VIASITTING) != 0)
+        Strcpy(verbbuf, "trigger"); /* follows "You sit down." */
+    else
+        Sprintf(verbbuf, "%s onto",
+                Levitation ? (const char *) "float"
+                           : locomotion(youmonst.data, "step"));
+    You("%s a level teleport trap!", verbbuf);
 #else
-    You("\95Ê\82Ì\8aK\82Ö\82Ì\8fu\8aÔ\88Ú\93®\82Ìã©\82ð%s\81I",
-        Levitation ? (const char *) "\8c©\89º\82ë\82µ\82½"
-                   : jpast(locomotion(youmonst.data, "\93¥\82Þ")));
+    if ((trflags & VIASITTING) != 0) {
+        pline("\95Ê\82Ì\8aK\82Ö\82Ì\8fu\8aÔ\88Ú\93®\82Ìã©\82ª\94­\93®\82µ\82½\81I");
+    } else {
+        You("\95Ê\82Ì\8aK\82Ö\82Ì\8fu\8aÔ\88Ú\93®\82Ìã©\82ð%s\81I",
+            Levitation ? (const char *) "\8c©\89º\82ë\82µ\82½"
+                       : jpast(locomotion(youmonst.data, "\93¥\82Þ")));
+    }
 #endif
+
     if (Antimagic) {
         shieldeff(u.ux, u.uy);
     }
@@ -1127,11 +1160,9 @@ struct monst *mtmp;
  *
  * Pulls a monster from its current position and places a monster at
  * a new x and y.  If oldx is 0, then the monster was not in the
- * levels.monsters
- * array.  However, if oldx is 0, oldy may still have a value because mtmp is
- * a
- * migrating_mon.  Worm tails are always placed randomly around the head of
- * the worm.
+ * levels.monsters array.  However, if oldx is 0, oldy may still have
+ * a value because mtmp is a migrating_mon.  Worm tails are always
+ * placed randomly around the head of the worm.
  */
 void
 rloc_to(mtmp, x, y)
@@ -1145,14 +1176,15 @@ register int x, y;
         return;
 
     if (oldx) { /* "pick up" monster */
-        if (mtmp->wormno)
+        if (mtmp->wormno) {
             remove_worm(mtmp);
-        else {
+        else {
             remove_monster(oldx, oldy);
             newsym(oldx, oldy); /* update old location */
         }
     }
 
+    memset(mtmp->mtrack, 0, sizeof mtmp->mtrack);
     place_monster(mtmp, x, y); /* put monster down */
     update_monster_region(mtmp);
 
@@ -1310,8 +1342,7 @@ struct trap *trap;
 boolean force_it;
 int in_sight;
 {
-    int tt = trap->ttyp;
-    struct permonst *mptr = mtmp->data;
+    int tt = (trap ? trap->ttyp : NO_TRAP);
 
     if (mtmp == u.ustuck) /* probably a vortex */
         return 0;         /* temporary? kludge */
@@ -1337,8 +1368,8 @@ int in_sight;
             }
         } else if (tt == MAGIC_PORTAL) {
             if (In_endgame(&u.uz)
-                && (mon_has_amulet(mtmp) || is_home_elemental(mptr))) {
-                if (in_sight && mptr->mlet != S_ELEMENTAL) {
+                && (mon_has_amulet(mtmp) || is_home_elemental(mtmp->data))) {
+                if (in_sight && mtmp->data->mlet != S_ELEMENTAL) {
 /*JP
                     pline("%s seems to shimmer for a moment.", Monnam(mtmp));
 */
@@ -1350,10 +1381,15 @@ int in_sight;
                 assign_level(&tolevel, &trap->dst);
                 migrate_typ = MIGR_PORTAL;
             }
-        } else { /* (tt == LEVEL_TELEP) */
+        } else if (tt == LEVEL_TELEP || tt == NO_TRAP) {
             int nlev;
 
-            if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
+            if (mon_has_amulet(mtmp) || In_endgame(&u.uz)
+                /* NO_TRAP is used when forcing a monster off the level;
+                   onscary(0,0,) is true for the Wizard, Riders, lawful
+                   minions, Angels of any alignment, shopkeeper or priest
+                   currently inside his or her own special room */
+                || (tt == NO_TRAP && onscary(0, 0, mtmp))) {
                 if (in_sight)
 /*JP
                     pline("%s seems very disoriented for a moment.",
@@ -1362,16 +1398,27 @@ int in_sight;
                           Monnam(mtmp));
                 return 0;
             }
-            nlev = random_teleport_level();
-            if (nlev == depth(&u.uz)) {
-                if (in_sight)
+            if (tt == NO_TRAP) {
+                /* creature is being forced off the level to make room;
+                   it will try to return to this level (at a random spot
+                   rather than its current one) if the level is left by
+                   the hero and then revisited */
+                assign_level(&tolevel, &u.uz);
+            } else {
+                nlev = random_teleport_level();
+                if (nlev == depth(&u.uz)) {
+                    if (in_sight)
 /*JP
                     pline("%s shudders for a moment.", Monnam(mtmp));
 */
                     pline("%s\82Í\88ê\8fu\90k\82¦\82½\81D", Monnam(mtmp));
-                return 0;
+                    return 0;
+                }
+                get_level(&tolevel, nlev);
             }
-            get_level(&tolevel, nlev);
+        } else {
+            impossible("mlevel_tele_trap: unexpected trap type (%d)", tt);
+            return 0;
         }
 
         if (in_sight) {
@@ -1379,7 +1426,8 @@ int in_sight;
             pline("Suddenly, %s disappears out of sight.", mon_nam(mtmp));
 */
             pline("\93Ë\91R%s\82ª\8e\8b\8aE\82©\82ç\8fÁ\82¦\82½\81D", mon_nam(mtmp));
-            seetrap(trap);
+            if (trap)
+                seetrap(trap);
         }
         migrate_to_level(mtmp, ledger_no(&tolevel), migrate_typ, (coord *) 0);
         return 3; /* no longer on this level */
index 9246fd9..76ed222 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 timeout.c       $NHDT-Date: 1446861771 2015/11/07 02:02:51 $  $NHDT-Branch: master $:$NHDT-Revision: 1.63 $ */
+/* NetHack 3.6 timeout.c       $NHDT-Date: 1505214876 2017/09/12 11:14:36 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.75 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 STATIC_DCL void NDECL(stoned_dialogue);
 STATIC_DCL void NDECL(vomiting_dialogue);
 STATIC_DCL void NDECL(choke_dialogue);
+STATIC_DCL void NDECL(levitation_dialogue);
 STATIC_DCL void NDECL(slime_dialogue);
 STATIC_DCL void NDECL(slip_or_trip);
 STATIC_DCL void FDECL(see_lamp_flicker, (struct obj *, const char *));
 STATIC_DCL void FDECL(lantern_message, (struct obj *));
 STATIC_DCL void FDECL(cleanup_burn, (ANY_P *, long));
 
+/* used by wizard mode #timeout and #wizintrinsic; order by 'interest'
+   for timeout countdown, where most won't occur in normal play */
+const struct propname {
+    int prop_num;
+    const char *prop_name;
+} propertynames[] = {
+    { INVULNERABLE, "invulnerable" },
+    { STONED, "petrifying" },
+    { SLIMED, "becoming slime" },
+    { STRANGLED, "strangling" },
+    { SICK, "fatally sick" },
+    { STUNNED, "stunned" },
+    { CONFUSION, "confused" },
+    { HALLUC, "hallucinating" },
+    { BLINDED, "blinded" },
+    { DEAF, "deafness" },
+    { VOMITING, "vomiting" },
+    { GLIB, "slippery fingers" },
+    { WOUNDED_LEGS, "wounded legs" },
+    { SLEEPY, "sleepy" },
+    { TELEPORT, "teleporting" },
+    { POLYMORPH, "polymorphing" },
+    { LEVITATION, "levitating" },
+    { FAST, "very fast" }, /* timed 'FAST' is very fast */
+    { CLAIRVOYANT, "clairvoyant" },
+    { DETECT_MONSTERS, "monster detection" },
+    { SEE_INVIS, "see invisible" },
+    { INVIS, "invisible" },
+    /* properties beyond here don't have timed values during normal play,
+       so there's no much point in trying to order them sensibly;
+       they're either on or off based on equipment, role, actions, &c */
+    { FIRE_RES, "fire resistance" },
+    { COLD_RES, "cold resistance" },
+    { SLEEP_RES, "sleep resistance" },
+    { DISINT_RES, "disintegration resistance" },
+    { SHOCK_RES, "shock resistance" },
+    { POISON_RES, "poison resistance" },
+    { ACID_RES, "acid resistance" },
+    { STONE_RES, "stoning resistance" },
+    { DRAIN_RES, "drain resistance" },
+    { SICK_RES, "sickness resistance" },
+    { ANTIMAGIC, "magic resistance" },
+    { HALLUC_RES, "hallucination resistance" },
+    { FUMBLING, "fumbling" },
+    { HUNGER, "voracious hunger" },
+    { TELEPAT, "telepathic" },
+    { WARNING, "warning" },
+    { WARN_OF_MON, "warn: monster type or class" },
+    { WARN_UNDEAD, "warn: undead" },
+    { SEARCHING, "searching" },
+    { INFRAVISION, "infravision" },
+    { ADORNED, "adorned (+/- Cha)" },
+    { DISPLACED, "displaced" },
+    { STEALTH, "stealthy" },
+    { AGGRAVATE_MONSTER, "monster aggravation" },
+    { CONFLICT, "conflict" },
+    { JUMPING, "jumping" },
+    { TELEPORT_CONTROL, "teleport control" },
+    { FLYING, "flying" },
+    { WWALKING, "water walking" },
+    { SWIMMING, "swimming" },
+    { MAGICAL_BREATHING, "magical breathing" },
+    { PASSES_WALLS, "pass thru walls" },
+    { SLOW_DIGESTION, "slow digestion" },
+    { HALF_SPDAM, "half spell damage" },
+    { HALF_PHDAM, "half physical damage" },
+    { REGENERATION, "HP regeneration" },
+    { ENERGY_REGENERATION, "energy regeneration" },
+    { PROTECTION, "extra protection" },
+    { PROT_FROM_SHAPE_CHANGERS, "protection from shape changers" },
+    { POLYMORPH_CONTROL, "polymorph control" },
+    { UNCHANGING, "unchanging" },
+    { REFLECTING, "reflecting" },
+    { FREE_ACTION, "free action" },
+    { FIXED_ABIL, "fixed abilites" },
+    { LIFESAVED, "life will be saved" },
+    {  0, 0 },
+};
+
 /* He is being petrified - dialogue by inmet!tower */
 static NEARDATA const char *const stoned_texts[] = {
 #if 0 /*JP*/
@@ -77,26 +158,29 @@ stoned_dialogue()
         multi_reason = "\90Î\89»\82µ\82Â\82Â\82 \82é\8e\9e\82É";
         nomovemsg = You_can_move_again; /* not unconscious */
         break;
+    case 2:
+        if ((HDeaf & TIMEOUT) > 0L && (HDeaf & TIMEOUT) < 5L)
+            set_itimeout(&HDeaf, 5L); /* avoid Hear_again at tail end */
     default:
         break;
     }
     exercise(A_DEX, FALSE);
 }
 
-/* He is getting sicker and sicker prior to vomiting */
+/* hero is getting sicker and sicker prior to vomiting */
 static NEARDATA const char *const vomiting_texts[] = {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
     "are feeling mildly nauseated.", /* 14 */
     "feel slightly confused.",       /* 11 */
     "can't seem to think straight.", /* 8 */
     "feel incredibly sick.",         /* 5 */
-    "suddenly vomit!"                /* 2 */
+    "are about to vomit."            /* 2 */
 #else
     "\82¿\82å\82Á\82Æ\93f\82«\8bC\82ª\82µ\82½\81D",        /* 14 */
     "\8f­\82µ\8d¬\97\90\82µ\82½\81D",                /* 11 */
     "\82Ü\82Æ\82à\82É\8ev\8dl\82Å\82«\82È\82­\82È\82Á\82½\81D",  /* 8 */
     "\82Æ\82Ä\82à\8bC\95ª\82ª\88«\82­\82È\82Á\82½\81D",      /* 5 */
-    "\93Ë\91R\9aq\93f\82µ\82½\81I"                 /* 2 */
+    "\93Ë\91R\9aq\93f\82µ\82½\81D"                 /* 2 */
 #endif
 };
 
@@ -135,14 +219,29 @@ vomiting_dialogue()
         txt = vomiting_texts[4];
         if (cantvomit(youmonst.data))
 /*JP
-            txt = "gag uncontrolably.";
+            txt = "gag uncontrollably.";
 */
             txt = "\8bC\95ª\82Ì\88«\82³\82ª\97}\82¦\82ç\82ê\82È\82­\82È\82Á\82½\81D";
+        else if (Hallucination)
+            /* "hurl" is short for "hurl chunks" which is slang for
+               relatively violent vomiting... */
+            txt = "are about to hurl!";
         break;
     case 0:
         stop_occupation();
-        if (!cantvomit(youmonst.data))
+        if (!cantvomit(youmonst.data)) {
             morehungry(20);
+            /* case 2 used to be "You suddenly vomit!" but it wasn't sudden
+               since you've just been through the earlier messages of the
+               countdown, and it was still possible to move around between
+               that message and "You can move again." (from vomit()'s
+               nomul(-2)) with no intervening message; give one here to
+               have more specific point at which hero became unable to move
+               [vomit() issues its own message for the cantvomit() case
+               and for the FAINTING-or-worse case where stomach is empty] */
+            if (u.uhs < FAINTING)
+                You("%s!", !Hallucination ? "vomit" : "hurl chunks");
+        }
         vomit();
         break;
     default:
@@ -154,9 +253,12 @@ vomiting_dialogue()
 }
 
 static NEARDATA const char *const choke_texts[] = {
-#if 0 /*JP*/
-    "You find it hard to breathe.", "You're gasping for air.",
-    "You can no longer breathe.", "You're turning %s.", "You suffocate."
+#if 0 /*JP:T*/
+    "You find it hard to breathe.",
+    "You're gasping for air.",
+    "You can no longer breathe.",
+    "You're turning %s.",
+    "You suffocate."
 #else
     "\82 \82È\82½\82Í\8cÄ\8bz\82ª\8d¢\93ï\82É\82È\82Á\82½\81D",
     "\82 \82È\82½\82Í\8bê\82µ\82­\82Ä\82 \82¦\82¢\82¾\81D",
@@ -170,7 +272,8 @@ static NEARDATA const char *const choke_texts2[] = {
 #if 0 /*JP*/
     "Your %s is becoming constricted.",
     "Your blood is having trouble reaching your brain.",
-    "The pressure on your %s increases.", "Your consciousness is fading.",
+    "The pressure on your %s increases.",
+    "Your consciousness is fading.",
     "You suffocate."
 #else
     "\82 \82È\82½\82Ì%s\82Í\8di\82ß\82Â\82¯\82ç\82ê\82½\81D",
@@ -204,6 +307,38 @@ choke_dialogue()
     exercise(A_STR, FALSE);
 }
 
+static NEARDATA const char *const levi_texts[] = {
+    "You float slightly lower.",
+    "You wobble unsteadily %s the %s."
+};
+
+STATIC_OVL void
+levitation_dialogue()
+{
+    /* -1 because the last message comes via float_down() */
+    long i = (((HLevitation & TIMEOUT) - 1L) / 2L);
+
+    if (ELevitation)
+        return;
+
+    if (!ACCESSIBLE(levl[u.ux][u.uy].typ)
+        && !is_pool_or_lava(u.ux,u.uy))
+        return;
+
+    if (((HLevitation & TIMEOUT) % 2L) && i > 0L && i <= SIZE(levi_texts)) {
+        const char *s = levi_texts[SIZE(levi_texts) - i];
+
+        if (index(s, '%')) {
+            boolean danger = (is_pool_or_lava(u.ux, u.uy)
+                              && !Is_waterlevel(&u.uz));
+
+            pline(s, danger ? "over" : "in",
+                  danger ? surface(u.ux, u.uy) : "air");
+        } else
+            pline1(s);
+    }
+}
+
 static NEARDATA const char *const slime_texts[] = {
 #if 0 /*JP*/
     "You are turning a little %s.",   /* 5 */
@@ -260,6 +395,8 @@ slime_dialogue()
         if (multi > 0)
             nomul(0);
     }
+    if (i == 2L && (HDeaf & TIMEOUT) > 0L && (HDeaf & TIMEOUT) < 5L)
+        set_itimeout(&HDeaf, 5L); /* avoid Hear_again at tail end */
     exercise(A_DEX, FALSE);
 }
 
@@ -274,6 +411,30 @@ burn_away_slime()
     }
 }
 
+/* Intrinsic Passes_walls is temporary when your god is trying to fix
+   all troubles and then TROUBLE_STUCK_IN_WALL calls safe_teleds() but
+   it can't find anywhere to place you.  If that happens you get a small
+   value for (HPasses_walls & TIMEOUT) to move somewhere yourself.
+   Message given is "you feel much slimmer" as a joke hint that you can
+   move between things which are closely packed--like the substance of
+   solid rock! */
+static NEARDATA const char *const phaze_texts[] = {
+    "You start to feel bloated.",
+    "You are feeling rather flabby.",
+};
+
+STATIC_OVL void
+phaze_dialogue()
+{
+    long i = ((HPasses_walls & TIMEOUT) / 2L);
+
+    if (EPasses_walls || (HPasses_walls & ~TIMEOUT))
+        return;
+
+    if (((HPasses_walls & TIMEOUT) % 2L) && i > 0L && i <= SIZE(phaze_texts))
+        pline1(phaze_texts[SIZE(phaze_texts) - i]);
+}
+
 void
 nh_timeout()
 {
@@ -287,7 +448,7 @@ nh_timeout()
         baseluck -= 1;
 
     if (u.uluck != baseluck
-        && moves % (u.uhave.amulet || u.ugangr ? 300 : 600) == 0) {
+        && moves % ((u.uhave.amulet || u.ugangr) ? 300 : 600) == 0) {
         /* Cursed luckstones stop bad luck from timing out; blessed luckstones
          * stop good luck from timing out; normal luckstones stop both;
          * neither is stopped if you don't have a luckstone.
@@ -311,9 +472,15 @@ nh_timeout()
         vomiting_dialogue();
     if (Strangled)
         choke_dialogue();
+    if (HLevitation & TIMEOUT)
+        levitation_dialogue();
+    if (HPasses_walls & TIMEOUT)
+        phaze_dialogue();
     if (u.mtimedone && !--u.mtimedone) {
         if (Unchanging)
             u.mtimedone = rnd(100 * youmonst.data->mlevel + 1);
+        else if (is_were(youmonst.data))
+            you_unwere(FALSE); /* if polycontrl, asks whether to rehumanize */
         else
             rehumanize();
     }
@@ -446,6 +613,7 @@ nh_timeout()
             case DEAF:
                 set_itimeout(&HDeaf, 1L);
                 make_deaf(0L, TRUE);
+                context.botl = TRUE;
                 if (!Deaf)
                     stop_occupation();
                 break;
@@ -503,6 +671,15 @@ nh_timeout()
             case LEVITATION:
                 (void) float_down(I_SPECIAL | TIMEOUT, 0L);
                 break;
+            case PASSES_WALLS:
+                if (!Passes_walls) {
+                    if (stuck_in_wall())
+                        You_feel("hemmed in again.");
+                    else
+                        pline("You're back to your %s self again.",
+                              !Upolyd ? "normal" : "unusual");
+                }
+                break;
             case STRANGLED:
                 killer.format = KILLED_BY;
 #if 0 /*JP*/
@@ -577,6 +754,7 @@ boolean wakeup_msg;
         /* caller can follow with a direct call to Hear_again() if
            there's a need to override this when wakeup_msg is true */
         incr_itimeout(&HDeaf, how_long);
+        context.botl = TRUE;
         afternmv = Hear_again; /* this won't give any messages */
     }
     /* early wakeup from combat won't be possible until next monster turn */
@@ -711,6 +889,8 @@ long timeout;
         boolean siblings = (hatchcount > 1), redraw = FALSE;
 
         if (cansee_hatchspot) {
+            /* [bug?  m_monnam() yields accurate monster type
+               regardless of hallucination] */
 #if 0 /*JP*/
             Sprintf(monnambuf, "%s%s", siblings ? "some " : "",
                     siblings ? makeplural(m_monnam(mon)) : an(m_monnam(mon)));
@@ -776,24 +956,29 @@ long timeout;
         case OBJ_MINVENT:
             if (cansee_hatchspot) {
                 /* egg carrying monster might be invisible */
-                if (canseemon(egg->ocarry)) {
-/*JP
+                mon2 = egg->ocarry;
+                if (canseemon(mon2)
+                    && (!mon2->wormno || cansee(mon2->mx, mon2->my))) {
+#if 0 /*JP:T*/
                     Sprintf(carriedby, "%s pack",
-*/
+                            s_suffix(a_monnam(mon2)));
+#else
                     Sprintf(carriedby, "%s\82Ì\94w\95\89\82¢\91Ü\82©\82ç",
-                            s_suffix(a_monnam(egg->ocarry)));
+                            a_monnam(mon2));
+#endif
                     knows_egg = TRUE;
-                } else if (is_pool(mon->mx, mon->my))
+                } else if (is_pool(mon->mx, mon->my)) {
 /*JP
                     Strcpy(carriedby, "empty water");
 */
                     Strcpy(carriedby, "\89½\82à\82È\82¢\90\85\92\86\82©\82ç");
-                else
+                } else {
 /*JP
                     Strcpy(carriedby, "thin air");
 */
                     Strcpy(carriedby, "\89½\82à\82È\82¢\8bó\8aÔ\82©\82ç");
-#if 0 /*JP*/
+                }
+#if 0 /*JP:T*/
                 You_see("%s %s out of %s!", monnambuf,
                         locomotion(mon->data, "drop"), carriedby);
 #else
@@ -1078,7 +1263,7 @@ anything *arg;
 long timeout;
 {
     struct obj *obj = arg->a_obj;
-    boolean canseeit, many, menorah, need_newsym;
+    boolean canseeit, many, menorah, need_newsym, need_invupdate;
     xchar x, y;
     char whose[BUFSZ];
 
@@ -1095,6 +1280,7 @@ long timeout;
 
             if (menorah) {
                 obj->spe = 0; /* no more candles */
+                obj->owt = weight(obj);
             } else if (Is_candle(obj) || obj->otyp == POT_OIL) {
                 /* get rid of candles and burning oil potions;
                    we know this object isn't carried by hero,
@@ -1119,7 +1305,7 @@ long timeout;
     } else {
         canseeit = FALSE;
     }
-    need_newsym = FALSE;
+    need_newsym = need_invupdate = FALSE;
 
     /* obj->age is the age remaining at this point.  */
     switch (obj->otyp) {
@@ -1128,6 +1314,8 @@ long timeout;
         if (canseeit) {
             switch (obj->where) {
             case OBJ_INVENT:
+                need_invupdate = TRUE;
+                /*FALLTHRU*/
             case OBJ_MINVENT:
 /*JP
                 pline("%spotion of oil has burnt away.", whose);
@@ -1204,6 +1392,8 @@ long timeout;
             if (canseeit || obj->where == OBJ_INVENT) {
                 switch (obj->where) {
                 case OBJ_INVENT:
+                    need_invupdate = TRUE;
+                    /*FALLTHRU*/
                 case OBJ_MINVENT:
                     if (obj->otyp == BRASS_LANTERN)
 /*JP
@@ -1313,8 +1503,10 @@ long timeout;
                 if (menorah) {
                     switch (obj->where) {
                     case OBJ_INVENT:
+                        need_invupdate = TRUE;
+                        /*FALLTHRU*/
                     case OBJ_MINVENT:
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                         pline("%scandelabrum's flame%s.", whose,
                               many ? "s die" : " dies");
 #else
@@ -1333,6 +1525,9 @@ long timeout;
                 } else {
                     switch (obj->where) {
                     case OBJ_INVENT:
+                        /* no need_invupdate for update_inventory() necessary;
+                           useupall() -> freeinv() handles it */
+                        /*FALLTHRU*/
                     case OBJ_MINVENT:
 #if 0 /*JP*/
                         pline("%s %s consumed!", Yname2(obj),
@@ -1343,9 +1538,9 @@ long timeout;
                         break;
                     case OBJ_FLOOR:
                         /*
-                        You see some wax candles consumed!
-                        You see a wax candle consumed!
-                        */
+                          You see some wax candles consumed!
+                          You see a wax candle consumed!
+                         */
 #if 0 /*JP*/
                         You_see("%s%s consumed!", many ? "some " : "",
                                 many ? xname(obj) : an(xname(obj)));
@@ -1363,9 +1558,9 @@ long timeout;
                               : Blind ? "" : (many ? "Their flames die."
                                                    : "Its flame dies."));
 #else
-                    pline(Hallucination ? "\82»\82ê\82Í\90k\82¦\82½\81D"
-                          : Blind ? "" 
-                          : "\89\8a\82Í\8fÁ\82¦\82½\81D");
+                    pline(Hallucination ? "\82»\82ê\82Í\8bà\90Ø\82è\90º\82ð\82 \82°\82½\81I"
+                              : Blind ? "" 
+                              : "\89\8a\82Í\8fÁ\82¦\82½\81D");
 #endif
                 }
             }
@@ -1373,6 +1568,7 @@ long timeout;
 
             if (menorah) {
                 obj->spe = 0;
+                obj->owt = weight(obj);
             } else {
                 if (carried(obj)) {
                     useupall(obj);
@@ -1386,7 +1582,7 @@ long timeout;
                 }
                 obj = (struct obj *) 0;
             }
-            break;
+            break; /* case [age ==] 0 */
 
         default:
             /*
@@ -1399,8 +1595,7 @@ long timeout;
 
         if (obj && obj->age)
             begin_burn(obj, TRUE);
-
-        break;
+        break; /* case [otyp ==] candelabrum|tallow_candle|wax_candle */
 
     default:
         impossible("burn_object: unexpeced obj %s", xname(obj));
@@ -1408,6 +1603,8 @@ long timeout;
     }
     if (need_newsym)
         newsym(x, y);
+    if (need_invupdate)
+        update_inventory();
 }
 
 /*
@@ -1616,6 +1813,7 @@ do_storms()
 */
         pline("\83s\83J\83b\81I\81I\83S\83\8d\83S\83\8d\83S\83\8d\83S\83\8d\81I\81I\83h\81[\83\93\81I");
         incr_itimeout(&HDeaf, rn1(20, 30));
+        context.botl = TRUE;
         if (!u.uinvulnerable) {
             stop_occupation();
             nomul(-3);
@@ -1762,7 +1960,7 @@ timer_element *base;
     char buf[BUFSZ];
 
     if (!base) {
-        putstr(win, 0, "<empty>");
+        putstr(win, 0, " <empty>");
     } else {
         putstr(win, 0, "timeout  id   kind   call");
         for (curr = base; curr; curr = curr->next) {
@@ -1786,6 +1984,9 @@ wiz_timeout_queue()
 {
     winid win;
     char buf[BUFSZ];
+    const char *propname;
+    long intrinsic;
+    int i, p, count, longestlen, ln, specindx = 0;
 
     win = create_nhwindow(NHW_MENU); /* corner text window */
     if (win == WIN_ERR)
@@ -1798,6 +1999,46 @@ wiz_timeout_queue()
     putstr(win, 0, "");
     print_queue(win, timer_base);
 
+    /* Timed properies:
+     * check every one; the majority can't obtain temporary timeouts in
+     * normal play but those can be forced via the #wizintrinsic command.
+     */
+    count = longestlen = 0;
+    for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) {
+        p = propertynames[i].prop_num;
+        intrinsic = u.uprops[p].intrinsic;
+        if (intrinsic & TIMEOUT) {
+            ++count;
+            if ((ln = (int) strlen(propname)) > longestlen)
+                longestlen = ln;
+        }
+        if (specindx == 0 && p == FIRE_RES)
+            specindx = i;
+    }
+    putstr(win, 0, "");
+    if (!count) {
+        putstr(win, 0, "No timed properties.");
+    } else {
+        putstr(win, 0, "Timed properties:");
+        putstr(win, 0, "");
+        for (i = 0; (propname = propertynames[i].prop_name) != 0; ++i) {
+            p = propertynames[i].prop_num;
+            intrinsic = u.uprops[p].intrinsic;
+            if (intrinsic & TIMEOUT) {
+                if (specindx > 0 && i >= specindx) {
+                    putstr(win, 0, " -- settable via #wizinstrinc only --");
+                    specindx = 0;
+                }
+                /* timeout value can be up to 16777215 (0x00ffffff) but
+                   width of 4 digits should result in values lining up
+                   almost all the time (if/when they don't, it won't
+                   look nice but the information will still be accurate) */
+                Sprintf(buf, " %*s %4ld", -longestlen, propname,
+                        (intrinsic & TIMEOUT));
+                putstr(win, 0, buf);
+            }
+        }
+    }
     display_nhwindow(win, FALSE);
     destroy_nhwindow(win);
 
@@ -1813,6 +2054,7 @@ timer_sanity_check()
     for (curr = timer_base; curr; curr = curr->next)
         if (curr->kind == TIMER_OBJECT) {
             struct obj *obj = curr->arg.a_obj;
+
             if (obj->timed == 0) {
                 pline("timer sanity: untimed obj %s, timer %ld",
                       fmt_ptr((genericptr_t) obj), curr->tid);
@@ -1861,6 +2103,7 @@ anything *arg;
         panic("start_timer");
 
     gnu = (timer_element *) alloc(sizeof(timer_element));
+    (void) memset((genericptr_t)gnu, 0, sizeof(timer_element));
     gnu->next = 0;
     gnu->tid = timer_id++;
     gnu->timeout = monstermoves + when;
@@ -2326,6 +2569,23 @@ long adjust;     /* how much to adjust timeout */
     }
 }
 
+/* to support '#stats' wizard-mode command */
+void
+timer_stats(hdrfmt, hdrbuf, count, size)
+const char *hdrfmt;
+char *hdrbuf;
+long *count, *size;
+{
+    timer_element *te;
+
+    Sprintf(hdrbuf, hdrfmt, (long) sizeof (timer_element));
+    *count = *size = 0L;
+    for (te = timer_base; te; te = te->next) {
+        ++*count;
+        *size += (long) sizeof *te;
+    }
+}
+
 /* reset all timers that are marked for reseting */
 void
 relink_timers(ghostly)
index 807ca03..c4ec287 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 topten.c        $NHDT-Date: 1448117546 2015/11/21 14:52:26 $  $NHDT-Branch: master $:$NHDT-Revision: 1.40 $ */
+/* NetHack 3.6 topten.c        $NHDT-Date: 1450451497 2015/12/18 15:11:37 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.44 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -35,7 +36,10 @@ static long final_fpos;
 
 #define newttentry() (struct toptenentry *) alloc(sizeof (struct toptenentry))
 #define dealloc_ttentry(ttent) free((genericptr_t) (ttent))
+#ifndef NAMSZ
+/* Changing NAMSZ can break your existing record/logfile */
 #define NAMSZ 10
+#endif
 #define DTHSZ 100
 #define ROLESZ 3
 
@@ -69,10 +73,12 @@ STATIC_DCL void FDECL(outentry, (int, struct toptenentry *, BOOLEAN_P));
 STATIC_DCL void FDECL(discardexcess, (FILE *));
 STATIC_DCL void FDECL(readentry, (FILE *, struct toptenentry *));
 STATIC_DCL void FDECL(writeentry, (FILE *, struct toptenentry *));
-STATIC_DCL void FDECL(writexlentry, (FILE *, struct toptenentry *));
+#ifdef XLOGFILE
+STATIC_DCL void FDECL(writexlentry, (FILE *, struct toptenentry *, int));
 STATIC_DCL long NDECL(encodexlogflags);
 STATIC_DCL long NDECL(encodeconduct);
 STATIC_DCL long NDECL(encodeachieve);
+#endif
 STATIC_DCL void FDECL(free_ttlist, (struct toptenentry *));
 STATIC_DCL int FDECL(classmon, (char *, BOOLEAN_P));
 STATIC_DCL int FDECL(score_wanted, (BOOLEAN_P, int, struct toptenentry *, int,
@@ -86,10 +92,11 @@ static winid toptenwin = WIN_ERR;
 
 /* "killed by",&c ["an"] 'killer.name' */
 void
-formatkiller(buf, siz, how)
+formatkiller(buf, siz, how, incl_helpless)
 char *buf;
 unsigned siz;
 int how;
+boolean incl_helpless;
 {
     static NEARDATA const char *const killed_by_prefix[] = {
         /* DIED, CHOKING, POISONING, STARVING, */
@@ -113,9 +120,9 @@ int how;
 #if 0 /*JP*/
     unsigned l;
 #endif
-    char *kname = killer.name;
+    char c, *kname = killer.name;
 
-    buf[0] = '\0'; /* so strncat() can find the end */
+    buf[0] = '\0'; /* lint suppression */
 #if 1 /*JP*//*\90æ\82É\91Î\8fÛ\82ð\83R\83s\81[*/
     strncat(buf, kname, siz - 1);
     siz -= strlen(buf);
@@ -145,10 +152,41 @@ int how;
         (void) strncat(buf, "\82É\8eE\82³\82ê\82½", siz - 1);
 #endif
     }
-#if 0 /*JP*//*\8aù\82É\83R\83s\81[\8dÏ\82Ý*/
-    /* we're writing into buf[0] (after possibly advancing buf) rather than
-       appending, but strncat() appends a terminator and strncpy() doesn't */
-    (void) strncat(buf, kname, siz - 1);
+#if 0 /*JP*//*\8aù\82É\83R\83s\81[\8dÏ\82Ý*//*JP:TODO:\83T\83j\83^\83C\83Y\82ª\95K\97v*/
+    /* Copy kname into buf[].
+     * Object names and named fruit have already been sanitized, but
+     * monsters can have "called 'arbitrary text'" attached to them,
+     * so make sure that that text can't confuse field splitting when
+     * record, logfile, or xlogfile is re-read at some later point.
+     */
+    while (--siz > 0) {
+        c = *kname++;
+        if (c == ',')
+            c = ';';
+        /* 'xlogfile' doesn't really need protection for '=', but
+           fixrecord.awk for corrupted 3.6.0 'record' does (only
+           if using xlogfile rather than logfile to repair record) */
+        else if (c == '=')
+            c = '_';
+        /* tab is not possible due to use of mungspaces() when naming;
+           it would disrupt xlogfile parsing if it were present */
+        else if (c == '\t')
+            c = ' ';
+        *buf++ = c;
+    }
+    *buf = '\0';
+#endif
+
+#if 0 /*JP*//*JP:TODO:\8e\80\88ö\82Ì\91O\82É\8e\9d\82Á\82Ä\8ds\82©\82È\82¯\82ê\82Î\82È\82ç\82È\82¢*/
+    if (incl_helpless && multi) {
+        /* X <= siz: 'sizeof "string"' includes 1 for '\0' terminator */
+        if (multi_reason && strlen(multi_reason) + sizeof ", while " <= siz)
+            Sprintf(buf, ", while %s", multi_reason);
+        /* either multi_reason wasn't specified or wouldn't fit */
+        else if (sizeof ", while helpless" <= siz)
+            Strcpy(buf, ", while helpless");
+        /* else extra death info won't fit, so leave it out */
+    }
 #endif
 }
 
@@ -301,10 +339,10 @@ struct toptenentry *tt;
     static const char fmt33[] = "%s %s %s %s "; /* role,race,gndr,algn */
 #ifndef NO_SCAN_BRACK
     static const char fmt0[] = "%d.%d.%d %ld %d %d %d %d %d %d %ld %ld %d ";
-    static const char fmtX[] = "%s,%s%s%s\n";
+    static const char fmtX[] = "%s,%s\n";
 #else /* NO_SCAN_BRACK */
     static const char fmt0[] = "%d %d %d %ld %d %d %d %d %d %d %ld %ld %d ";
-    static const char fmtX[] = "%s %s%s%s\n";
+    static const char fmtX[] = "%s %s\n";
 
     nsb_mung_line(tt->name);
     nsb_mung_line(tt->death);
@@ -319,17 +357,8 @@ struct toptenentry *tt;
     else
         (void) fprintf(rfile, fmt33, tt->plrole, tt->plrace, tt->plgend,
                        tt->plalign);
-#if 0 /*JP*/
-    (void) fprintf(rfile, fmtX, onlyspace(tt->name) ? "_" : tt->name,
-                   tt->death,
-                   (multi ? ", while " : ""),
-                   (multi ? (multi_reason ? multi_reason : "helpless") : ""));
-#else
     (void) fprintf(rfile, fmtX, onlyspace(tt->name) ? "_" : tt->name,
-                   (multi ? (multi_reason ? multi_reason : "\96³\97Í\82È\8aÔ\82É") : ""),
-                   tt->death,
-                   "");
-#endif
+                   tt->death);
 
 #ifdef NO_SCAN_BRACK
     nsb_unmung_line(tt->name);
@@ -337,15 +366,18 @@ struct toptenentry *tt;
 #endif
 }
 
+#ifdef XLOGFILE
+
 /* as tab is never used in eg. plname or death, no need to mangle those. */
 STATIC_OVL void
-writexlentry(rfile, tt)
+writexlentry(rfile, tt, how)
 FILE *rfile;
 struct toptenentry *tt;
+int how;
 {
 #define Fprintf (void) fprintf
 #define XLOG_SEP '\t' /* xlogfile field separator. */
-    char buf[BUFSZ];
+    char buf[BUFSZ], tmpbuf[DTHSZ + 1];
 
     Sprintf(buf, "version=%d.%d.%d", tt->ver_major, tt->ver_minor,
             tt->patchlevel);
@@ -360,11 +392,13 @@ struct toptenentry *tt;
     Sprintf(buf, "%crole=%s%crace=%s%cgender=%s%calign=%s", XLOG_SEP,
             tt->plrole, XLOG_SEP, tt->plrace, XLOG_SEP, tt->plgend, XLOG_SEP,
             tt->plalign);
+    /* make a copy of death reason that doesn't include ", while helpless" */
+    formatkiller(tmpbuf, sizeof tmpbuf, how, FALSE);
     Fprintf(rfile, "%s%cname=%s%cdeath=%s",
             buf, /* (already includes separator) */
-            XLOG_SEP, plname, XLOG_SEP, tt->death);
+            XLOG_SEP, plname, XLOG_SEP, tmpbuf);
     if (multi)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         Fprintf(rfile, "%cwhile=%s", XLOG_SEP,
                 multi_reason ? multi_reason : "helpless");
 #else
@@ -374,13 +408,8 @@ struct toptenentry *tt;
     Fprintf(rfile, "%cconduct=0x%lx%cturns=%ld%cachieve=0x%lx", XLOG_SEP,
             encodeconduct(), XLOG_SEP, moves, XLOG_SEP, encodeachieve());
     Fprintf(rfile, "%crealtime=%ld%cstarttime=%ld%cendtime=%ld", XLOG_SEP,
-#if 0 /*C360-19*/
-            (long) urealtime.realtime, XLOG_SEP, (long) ubirthday, XLOG_SEP,
-            (long) urealtime.endtime);
-#else
             (long) urealtime.realtime, XLOG_SEP,
             (long) ubirthday, XLOG_SEP, (long) urealtime.finish_time);
-#endif
     Fprintf(rfile, "%cgender0=%s%calign0=%s", XLOG_SEP,
             genders[flags.initgend].filecode, XLOG_SEP,
             aligns[1 - u.ualignbase[A_ORIGINAL]].filecode);
@@ -474,6 +503,8 @@ encodeachieve()
     return r;
 }
 
+#endif /* XLOGFILE */
+
 STATIC_OVL void
 free_ttlist(tt)
 struct toptenentry *tt;
@@ -561,13 +592,10 @@ time_t when;
     copynchars(t0->plgend, genders[flags.female].filecode, ROLESZ);
     copynchars(t0->plalign, aligns[1 - u.ualign.type].filecode, ROLESZ);
     copynchars(t0->name, plname, NAMSZ);
-    formatkiller(t0->death, sizeof t0->death, how);
+    formatkiller(t0->death, sizeof t0->death, how, TRUE);
     t0->birthdate = yyyymmdd(ubirthday);
     t0->deathdate = yyyymmdd(when);
     t0->tt_next = 0;
-#if 0 /*C360-19*/
-    urealtime.endtime = when;
-#endif
 #ifdef UPDATE_RECORD_IN_PLACE
     t0->fpos = -1L;
 #endif
@@ -588,7 +616,7 @@ time_t when;
         if (!(xlfile = fopen_datafile(XLOGFILE, "a", SCOREPREFIX))) {
             HUP raw_print("Cannot open extended log file!");
         } else {
-            writexlentry(xlfile, t0);
+            writexlentry(xlfile, t0, how);
             (void) fclose(xlfile);
         }
         unlock_file(XLOGFILE);
@@ -599,6 +627,7 @@ time_t when;
         if (how != PANICKED)
             HUP {
                 char pbuf[BUFSZ];
+
                 topten_print("");
                 Sprintf(pbuf,
 #if 0 /*JP*/
@@ -1342,25 +1371,19 @@ boolean fem;
 
 /*
  * Get a random player name and class from the high score list,
- * and attach them to an object (for statues or morgue corpses).
  */
-struct obj *
-tt_oname(otmp)
-struct obj *otmp;
+struct toptenentry *
+get_rnd_toptenentry()
 {
-    int rank;
-    register int i;
-    register struct toptenentry *tt;
+    int rank, i;
     FILE *rfile;
-    struct toptenentry tt_buf;
-
-    if (!otmp)
-        return (struct obj *) 0;
+    register struct toptenentry *tt;
+    static struct toptenentry tt_buf;
 
     rfile = fopen_datafile(RECORD, "r", SCOREPREFIX);
     if (!rfile) {
         impossible("Cannot open record file!");
-        return (struct obj *) 0;
+        return NULL;
     }
 
     tt = &tt_buf;
@@ -1378,13 +1401,34 @@ pickentry:
             rewind(rfile);
             goto pickentry;
         }
-        otmp = (struct obj *) 0;
-    } else {
-        set_corpsenm(otmp, classmon(tt->plrole, (tt->plgend[0] == 'F')));
-        otmp = oname(otmp, tt->name);
+        tt = NULL;
     }
 
     (void) fclose(rfile);
+    return tt;
+}
+
+
+/*
+ * Attach random player name and class from high score list
+ * to an object (for statues or morgue corpses).
+ */
+struct obj *
+tt_oname(otmp)
+struct obj *otmp;
+{
+    struct toptenentry *tt;
+    if (!otmp)
+        return (struct obj *) 0;
+
+    tt = get_rnd_toptenentry();
+
+    if (!tt)
+        return (struct obj *) 0;
+
+    set_corpsenm(otmp, classmon(tt->plrole, (tt->plgend[0] == 'F')));
+    otmp = oname(otmp, tt->name);
+
     return otmp;
 }
 
index 0ba1430..67b4646 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 track.c $NHDT-Date: 1432512769 2015/05/25 00:12:49 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 /* track.c - version 1.0.2 */
 
index fa1298f..438e50f 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 trap.c  $NHDT-Date: 1448492213 2015/11/25 22:56:53 $  $NHDT-Branch: master $:$NHDT-Revision: 1.249 $ */
+/* NetHack 3.6 trap.c  $NHDT-Date: 1524312044 2018/04/21 12:00:44 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.290 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -36,6 +37,8 @@ STATIC_DCL char *FDECL(trapnote, (struct trap *, BOOLEAN_P));
 STATIC_DCL void FDECL(join_adjacent_pits, (struct trap *));
 #endif
 STATIC_DCL void FDECL(clear_conjoined_pits, (struct trap *));
+STATIC_DCL boolean FDECL(adj_nonconjoined_pit, (struct trap *));
+
 STATIC_DCL int FDECL(steedintrap, (struct trap *, struct obj *));
 STATIC_DCL boolean FDECL(keep_saddle_with_steedcorpse, (unsigned,
                                                         struct obj *,
@@ -181,34 +184,28 @@ const char *ostr;
 int type;
 int ef_flags;
 {
-#if 0 /*JP*/
-    static NEARDATA const char *const action[] = { "smoulder", "rust", "rot",
-                                                   "corrode" };
-#else
-    static NEARDATA const char * const action[] = {
-        "\82­\82·\82Ô\82Á\82½", "\8eK\82Ñ\82½", "\95\85\82Á\82½", "\95\85\90H\82µ\82½" };
-#endif
-#if 0 /*JP*/
-    static NEARDATA const char *const msg[] = { "burnt", "rusted", "rotten",
-                                                "corroded" };
-#else
-    static NEARDATA const char * const msg[] =  {
-        "\8fÅ\82°\82½", "\8eK\82Ñ\82½", "\95\85\82Á\82½", "\95\85\90H\82µ\82½" };
-#endif
-    boolean vulnerable = FALSE;
-    boolean is_primary = TRUE;
-    boolean check_grease = ef_flags & EF_GREASE;
-    boolean print = ef_flags & EF_VERBOSE;
-    int erosion;
+    static NEARDATA const char
+/*JP
+        *const action[] = { "smoulder", "rust", "rot", "corrode" },
+*/
+        *const action[] = { "\82­\82·\82Ô\82Á\82½", "\8eK\82Ñ\82½", "\95\85\82Á\82½", "\95\85\90H\82µ\82½" },
+/*JP
+        *const msg[] = { "burnt", "rusted", "rotten", "corroded" },
+*/
+        *const msg[] =  { "\8fÅ\82°\82½", "\8eK\82Ñ\82½", "\95\85\82Á\82½", "\95\85\90H\82µ\82½" },
+        *const bythe[] = { "heat", "oxidation", "decay", "corrosion" };
+    boolean vulnerable = FALSE, is_primary = TRUE,
+            check_grease = (ef_flags & EF_GREASE) ? TRUE : FALSE,
+            print = (ef_flags & EF_VERBOSE) ? TRUE : FALSE,
+            uvictim, vismon, visobj;
+    int erosion, cost_type;
     struct monst *victim;
-    boolean vismon;
-    boolean visobj;
-    int cost_type;
 
     if (!otmp)
         return ER_NOTHING;
 
     victim = carried(otmp) ? &youmonst : mcarried(otmp) ? otmp->ocarry : NULL;
+    uvictim = (victim == &youmonst);
     vismon = victim && (victim != &youmonst) && canseemon(victim);
     /* Is bhitpos correct here? Ugh. */
     visobj = !victim && cansee(bhitpos.x, bhitpos.y);
@@ -242,56 +239,48 @@ int ef_flags;
 
     if (!ostr)
         ostr = cxname(otmp);
+    /* 'visobj' messages insert "the"; probably ought to switch to the() */
+    if (visobj && !(uvictim || vismon) && !strncmpi(ostr, "the ", 4))
+        ostr += 4;
 
     if (check_grease && otmp->greased) {
         grease_protect(otmp, ostr, victim);
         return ER_GREASED;
+    } else if (!erosion_matters(otmp)) {
+        return ER_NOTHING;
     } else if (!vulnerable || (otmp->oerodeproof && otmp->rknown)) {
-        if (print && flags.verbose) {
-            if (victim == &youmonst)
-/*JP
-                Your("%s %s not affected.", ostr, vtense(ostr, "are"));
-*/
-                Your("%s\82Í\89e\8b¿\82ð\8eó\82¯\82È\82©\82Á\82½\81D", ostr);
-            else if (vismon)
+        if (flags.verbose && print && (uvictim || vismon))
 #if 0 /*JP*/
-                pline("%s %s %s not affected.", s_suffix(Monnam(victim)),
-                      ostr, vtense(ostr, "are"));
+            pline("%s %s %s not affected by %s.",
+                  uvictim ? "Your" : s_suffix(Monnam(victim)),
+                  ostr, vtense(ostr, "are"), bythe[type]);
 #else
-                pline("%s\82Ì%s\82Í\89e\8b¿\82ð\8eó\82¯\82È\82©\82Á\82½\81D", Monnam(victim),
-                      ostr);
+            pline("%s%s\82Í%s\82Ì\89e\8b¿\82ð\8eó\82¯\82È\82©\82Á\82½\81D",
+                  uvictim ? "\82 \82È\82½\82Ì" : s_suffix(Monnam(victim)),
+                  ostr, bythe[type]);
 #endif
-        }
         return ER_NOTHING;
     } else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) {
-        if (flags.verbose && (print || otmp->oerodeproof)) {
-            if (victim == &youmonst)
-#if 0 /*JP*/
-                pline("Somehow, your %s %s not affected.", ostr,
-                      vtense(ostr, "are"));
-#else
-                pline("\82È\82º\82©\81C%s\82Í\89e\8b¿\82ð\8eó\82¯\82È\82©\82Á\82½\81D",ostr);
-#endif
-            else if (vismon)
-#if 0 /*JP*/
-                pline("Somehow, %s %s %s not affected.",
-                      s_suffix(mon_nam(victim)), ostr, vtense(ostr, "are"));
-#else
-                pline("\82È\82º\82©\81C%s\82Ì%s\82Í\89e\8b¿\82ð\8eó\82¯\82È\82©\82Á\82½\81D",
-                      mon_nam(victim), ostr);
-#endif
-            else if (visobj)
+        if (flags.verbose && (print || otmp->oerodeproof)
+            && (uvictim || vismon || visobj))
 #if 0 /*JP*/
-                pline("Somehow, the %s %s not affected.", ostr,
-                      vtense(ostr, "are"));
+            pline("Somehow, %s %s %s not affected by the %s.",
+                  uvictim ? "your"
+                          : !vismon ? "the" /* visobj */
+                                    : s_suffix(mon_nam(victim)),
+                  ostr, vtense(ostr, "are"), bythe[type]);
 #else
-                pline("\82È\82º\82©\81C%s\82Í\89e\8b¿\82ð\8eó\82¯\82È\82©\82Á\82½\81D", ostr);
+            pline("\82È\82º\82©\81C%s%s\82Í%s\82Ì\89e\8b¿\82ð\8eó\82¯\82È\82©\82Á\82½\81D",
+                  uvictim ? "\82 \82È\82½\82Ì"
+                          : !vismon ? "the" /* visobj */
+                                    : s_suffix(mon_nam(victim)),
+                  vtense(ostr, "are"), bythe[type]);
 #endif
-        }
         /* We assume here that if the object is protected because it
          * is blessed, it still shows some minor signs of wear, and
          * the hero can distinguish this from an object that is
-         * actually proof against damage. */
+         * actually proof against damage.
+         */
         if (otmp->oerodeproof) {
             otmp->rknown = TRUE;
             if (victim == &youmonst)
@@ -300,7 +289,7 @@ int ef_flags;
 
         return ER_NOTHING;
     } else if (erosion < MAX_ERODE) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         const char *adverb = (erosion + 1 == MAX_ERODE)
                                  ? " completely"
                                  : erosion ? " further" : "";
@@ -310,24 +299,20 @@ int ef_flags;
                                  : erosion ? "\82³\82ç\82É" : "";
 #endif
 
-        if (victim == &youmonst)
-/*JP
-            Your("%s %s%s!", ostr, vtense(ostr, action[type]), adverb);
-*/
-            pline("%s\82Í%s%s\81I", ostr, adverb, action[type]);
-        else if (vismon)
+        if (uvictim || vismon || visobj)
 #if 0 /*JP*/
-            pline("%s %s %s%s!", s_suffix(Monnam(victim)), ostr,
-                  vtense(ostr, action[type]), adverb);
+            pline("%s %s %s%s!",
+                  uvictim ? "Your"
+                          : !vismon ? "The" /* visobj */
+                                    : s_suffix(Monnam(victim)),
+                  ostr, vtense(ostr, action[type]), adverb);
 #else
-            pline("%s\82Ì%s\82Í%s%s\81I", Monnam(victim), ostr,
-                  adverb, action[type]);
+            pline("%s%s\82Í%s%s!",
+                  uvictim ? "\82 \82È\82½\82Ì"
+                          : !vismon ? "" /* visobj */
+                                    : s_suffix(Monnam(victim)),
+                  ostr, adverb, action[type]);
 #endif
-        else if (visobj)
-/*JP
-            pline("The %s %s%s!", ostr, vtense(ostr, action[type]), adverb);
-*/
-            pline("%s\82Í%s%s\81I", ostr, adverb, action[type]);
 
         if (ef_flags & EF_PAY)
             costly_alteration(otmp, cost_type);
@@ -342,24 +327,20 @@ int ef_flags;
 
         return ER_DAMAGED;
     } else if (ef_flags & EF_DESTROY) {
-        if (victim == &youmonst)
-/*JP
-            Your("%s %s away!", ostr, vtense(ostr, action[type]));
-*/
-            Your("%s\82Í\8a®\91S\82É%s\81I", ostr, action[type]);
-        else if (vismon)
+        if (uvictim || vismon || visobj)
 #if 0 /*JP*/
-            pline("%s %s %s away!", s_suffix(Monnam(victim)), ostr,
-                  vtense(ostr, action[type]));
+            pline("%s %s %s away!",
+                  uvictim ? "Your"
+                          : !vismon ? "The" /* visobj */
+                                    : s_suffix(Monnam(victim)),
+                  ostr, vtense(ostr, action[type]));
 #else
-            pline("%s\82Ì%s\82Í\8a®\91S\82É%s\81I", Monnam(victim), ostr,
-                  action[type]);
+            pline("%s%s\82Í\8a®\91S\82É%s\81I",
+                  uvictim ? "\82 \82È\82½\82Ì"
+                          : !vismon ? "" /* visobj */
+                                    : s_suffix(Monnam(victim)),
+                  ostr, action[type]);
 #endif
-        else if (visobj)
-/*JP
-            pline("The %s %s away!", ostr, vtense(ostr, action[type]));
-*/
-            pline("%s\82Í\8a®\91S\82É%s\81I", ostr, action[type]);
 
         if (ef_flags & EF_PAY)
             costly_alteration(otmp, cost_type);
@@ -369,29 +350,24 @@ int ef_flags;
         return ER_DESTROYED;
     } else {
         if (flags.verbose && print) {
-            if (victim == &youmonst)
+            if (uvictim)
 #if 0 /*JP*/
-                Your("%s %s completely %s.", ostr,
-                     vtense(ostr, Blind ? "feel" : "look"), msg[type]);
+                Your("%s %s completely %s.",
+                     ostr, vtense(ostr, Blind ? "feel" : "look"), msg[type]);
 #else
-                Your("%s\82Í\8a®\91S\82É%s%s\81D", ostr,
-                     msg[type], Blind ? "\82æ\82¤\82¾" : "");
+                Your("%s\82Í\8a®\91S\82É%s%s\81D",
+                     ostr, msg[type], Blind ? "\82æ\82¤\82¾" : "");
 #endif
-            else if (vismon)
+            else if (vismon || visobj)
 #if 0 /*JP*/
-                pline("%s %s %s completely %s.", s_suffix(Monnam(victim)),
+                pline("%s %s %s completely %s.",
+                      !vismon ? "The" : s_suffix(Monnam(victim)),
                       ostr, vtense(ostr, "look"), msg[type]);
 #else
-                pline("%s\82Ì%s\82Í\8a®\91S\82É%s\81D", Monnam(victim),
+                pline("%s%s\82Í\8a®\91S\82É%s\82æ\82¤\82¾\81D",
+                      !vismon ? "" : s_suffix(Monnam(victim)),
                       ostr, msg[type]);
 #endif
-            else if (visobj)
-#if 0 /*JP*/
-                pline("The %s %s completely %s.", ostr, vtense(ostr, "look"),
-                      msg[type]);
-#else
-                pline("%s\82Í\8a®\91S\82É%s\81D", ostr, msg[type]);
-#endif
         }
         return ER_NOTHING;
     }
@@ -447,12 +423,12 @@ struct monst *victim;
 
 struct trap *
 maketrap(x, y, typ)
-register int x, y, typ;
+int x, y, typ;
 {
     static union vlaunchinfo zero_vl;
-    register struct trap *ttmp;
-    register struct rm *lev;
     boolean oldplace;
+    struct trap *ttmp;
+    struct rm *lev = &levl[x][y];
 
     if ((ttmp = t_at(x, y)) != 0) {
         if (ttmp->ttyp == MAGIC_PORTAL || ttmp->ttyp == VIBRATING_SQUARE)
@@ -465,13 +441,15 @@ register int x, y, typ;
                     && typ != SPIKED_PIT)))
             u.utrap = 0;
         /* old <tx,ty> remain valid */
-    } else if (IS_FURNITURE(levl[x][y].typ)) {
+    } else if (IS_FURNITURE(lev->typ)
+               && (!IS_GRAVE(lev->typ) || (typ != PIT && typ != HOLE))) {
         /* no trap on top of furniture (caller usually screens the
            location to inhibit this, but wizard mode wishing doesn't) */
         return (struct trap *) 0;
     } else {
         oldplace = FALSE;
         ttmp = newtrap();
+        (void) memset((genericptr_t)ttmp, 0, sizeof(struct trap));
         ttmp->ntrap = 0;
         ttmp->tx = x;
         ttmp->ty = y;
@@ -537,14 +515,13 @@ register int x, y, typ;
         /*FALLTHRU*/
     case HOLE:
     case TRAPDOOR:
-        lev = &levl[x][y];
         if (*in_rooms(x, y, SHOPBASE)
             && (typ == HOLE || typ == TRAPDOOR
                 || IS_DOOR(lev->typ) || IS_WALL(lev->typ)))
             add_damage(x, y, /* schedule repair */
                        ((IS_DOOR(lev->typ) || IS_WALL(lev->typ))
                         && !context.mon_moving)
-                           ? 200L
+                           ? SHOP_HOLE_COST
                            : 0L);
         lev->doormask = 0;     /* subsumes altarmask, icedpool... */
         if (IS_ROOM(lev->typ)) /* && !IS_AIR(lev->typ) */
@@ -800,7 +777,7 @@ int *fail_reason;
     else if (statue->spe & STATUE_FEMALE)
         mon->female = TRUE;
     /* if statue has been named, give same name to the monster */
-    if (has_oname(statue))
+    if (has_oname(statue) && !unique_corpstat(mon->data))
         mon = christen_monst(mon, ONAME(statue));
     /* mimic statue becomes seen mimic; other hiders won't be hidden */
     if (mon->m_ap_type)
@@ -896,6 +873,7 @@ int *fail_reason;
            which refers to "it" so needs to follow a message describing
            the object ("the statue comes to life" one above) */
         if (cause != ANIMATE_NORMAL && costly_spot(x, y)
+            && (carried(statue) ? statue->unpaid : !statue->no_charge)
             && (shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) != 0
             /* avoid charging for Manlobbi's statue of Manlobbi
                if stone-to-flesh is used on petrified shopkeep */
@@ -1006,19 +984,84 @@ struct obj *objchn, *saddle;
     return FALSE;
 }
 
+/* monster or you go through and possibly destroy a web.
+   return TRUE if could go through. */
+boolean
+mu_maybe_destroy_web(mtmp, domsg, trap)
+struct monst *mtmp;
+boolean domsg;
+struct trap *trap;
+{
+    boolean isyou = (mtmp == &youmonst);
+    struct permonst *mptr = mtmp->data;
+    if (amorphous(mptr) || is_whirly(mptr) || flaming(mptr)
+        || unsolid(mptr) || mptr == &mons[PM_GELATINOUS_CUBE]) {
+        xchar x = trap->tx;
+        xchar y = trap->ty;
+        if (flaming(mptr) || acidic(mptr)) {
+            if (domsg) {
+                if (isyou)
+#if 0 /*JP*/
+                    You("%s %s spider web!",
+                        (flaming(mptr)) ? "burn" : "dissolve",
+                        a_your[trap->madeby_u]);
+#else
+                    You("%s\82­\82à\82Ì\91\83\82ð%s\81I",
+                        web_you[trap->madeby_u],
+                        (flaming(mptr)) ? "\8fÄ\82¢\82½" : "\82±\82È\82²\82È\82É\82µ\82½");
+#endif
+                else
+#if 0 /*JP*/
+                    pline("%s %s %s spider web!", Monnam(mtmp),
+                          (flaming(mptr)) ? "burns" : "dissolves",
+                          a_your[trap->madeby_u]);
+#else
+                    pline("%s%s\82­\82à\82Ì\91\83\82ð%s\81I", Monnam(mtmp),
+                        web_you[trap->madeby_u],
+                        (flaming(mptr)) ? "\8fÄ\82¢\82½" : "\82±\82È\82²\82È\82É\82µ\82½");
+#endif
+            }
+            deltrap(trap);
+            newsym(x, y);
+            return TRUE;
+        }
+        if (domsg) {
+            if (isyou)
+/*JP
+                You("flow through %s spider web.", a_your[trap->madeby_u]);
+*/
+                You("%s\82­\82à\82Ì\91\83\82ð\82·\82é\82è\82Æ\92Ê\82è\94²\82¯\82½\81D", web_you[trap->madeby_u]);
+            else {
+#if 0 /*JP*/
+                pline("%s flows through %s spider web.", Monnam(mtmp),
+                      a_your[trap->madeby_u]);
+#else
+                pline("%s\82Í%s\82­\82à\82Ì\91\83\82ð\82·\82é\82è\82Æ\92Ê\82è\94²\82¯\82½\81D", Monnam(mtmp),
+                      web_you[trap->madeby_u]);
+#endif
+                seetrap(trap);
+            }
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
 void
 dotrap(trap, trflags)
 register struct trap *trap;
 unsigned trflags;
 {
     register int ttype = trap->ttyp;
-    register struct obj *otmp;
+    struct obj *otmp;
     boolean already_seen = trap->tseen,
             forcetrap = (trflags & FORCETRAP) != 0,
             webmsgok = (trflags & NOWEBMSG) == 0,
             forcebungle = (trflags & FORCEBUNGLE) != 0,
             plunged = (trflags & TOOKPLUNGE) != 0,
-            adj_pit = conjoined_pits(trap, t_at(u.ux0, u.uy0), TRUE);
+            viasitting = (trflags & VIASITTING) != 0,
+            conj_pit = conjoined_pits(trap, t_at(u.ux0, u.uy0), TRUE),
+            adj_pit = adj_nonconjoined_pit(trap);
     int oldumort;
     int steed_article = ARTICLE_THE;
 
@@ -1058,18 +1101,19 @@ unsigned trflags;
             return;
         }
         if (!Fumbling && ttype != MAGIC_PORTAL && ttype != VIBRATING_SQUARE
-            && ttype != ANTI_MAGIC && !forcebungle && !plunged && !adj_pit
+            && ttype != ANTI_MAGIC && !forcebungle && !plunged
+            && !conj_pit && !adj_pit
             && (!rn2(5) || ((ttype == PIT || ttype == SPIKED_PIT)
                             && is_clinger(youmonst.data)))) {
-#if 0 /*JP:T*/
-            You("escape %s %s.", (ttype == ARROW_TRAP && !trap->madeby_u)
+#if 0 /*JP*/
+                You("escape %s %s.", (ttype == ARROW_TRAP && !trap->madeby_u)
                                      ? "an"
                                      : a_your[trap->madeby_u],
                 defsyms[trap_to_defsym(ttype)].explanation);
 #else
-            You("%s%s\82ð\82·\82é\82è\82Æ\94ð\82¯\82½\81D",
-                set_you[trap->madeby_u],
-                defsyms[trap_to_defsym(ttype)].explanation);
+                You("%s%s\82ð\82·\82é\82è\82Æ\94ð\82¯\82½\81D",
+                    set_you[trap->madeby_u],
+                    defsyms[trap_to_defsym(ttype)].explanation);
 #endif
             return;
         }
@@ -1106,11 +1150,13 @@ unsigned trflags;
         otmp->opoisoned = 0;
         if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) { /* nothing */
             ;
-/*JP
-        } else if (thitu(8, dmgval(otmp, &youmonst), otmp, "arrow")) {
-*/
-        } else if (thitu(8, dmgval(otmp, &youmonst), otmp, "\96î")) {
-            obfree(otmp, (struct obj *) 0);
+#if 0 /*JP*/
+        } else if (thitu(8, dmgval(otmp, &youmonst), &otmp, "arrow")) {
+#else
+        } else if (thitu(8, dmgval(otmp, &youmonst), &otmp, "\96î")) {
+#endif
+            if (otmp)
+                obfree(otmp, (struct obj *) 0);
         } else {
             place_object(otmp, u.ux, u.uy);
             if (!Blind)
@@ -1144,23 +1190,26 @@ unsigned trflags;
         oldumort = u.umortality;
         if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) { /* nothing */
             ;
-/*JP
-        } else if (thitu(7, dmgval(otmp, &youmonst), otmp, "little dart")) {
-*/
-        } else if (thitu(7, dmgval(otmp, &youmonst), otmp, "\93\8a\82°\96î")) {
-            if (otmp->opoisoned)
 #if 0 /*JP*/
-                poisoned("dart", A_CON, "little dart",
-                         /* if damage triggered life-saving,
-                            poison is limited to attrib loss */
-                         (u.umortality > oldumort) ? 0 : 10, TRUE);
+        } else if (thitu(7, dmgval(otmp, &youmonst), &otmp, "little dart")) {
 #else
-                poisoned("\93\8a\82°\96î", A_CON, "\8f¬\82³\82È\93\8a\82°\96î",
-                         /* if damage triggered life-saving,
-                            poison is limited to attrib loss */
-                         (u.umortality > oldumort) ? 0 : 10, TRUE);
+        } else if (thitu(7, dmgval(otmp, &youmonst), &otmp, "\93\8a\82°\96î")) {
+#endif
+            if (otmp) {
+                if (otmp->opoisoned)
+#if 0 /*JP:T*/
+                    poisoned("dart", A_CON, "little dart",
+                             /* if damage triggered life-saving,
+                                poison is limited to attrib loss */
+                             (u.umortality > oldumort) ? 0 : 10, TRUE);
+#else
+                    poisoned("\93\8a\82°\96î", A_CON, "\8f¬\82³\82È\93\8a\82°\96î",
+                             /* if damage triggered life-saving,
+                                poison is limited to attrib loss */
+                             (u.umortality > oldumort) ? 0 : 10, TRUE);
 #endif
-            obfree(otmp, (struct obj *) 0);
+                obfree(otmp, (struct obj *) 0);
+            }
         } else {
             place_object(otmp, u.ux, u.uy);
             if (!Blind)
@@ -1391,10 +1440,7 @@ unsigned trflags;
             if (uarmc)
                 (void) water_damage(uarmc, cloak_simple_name(uarmc), TRUE);
             else if (uarm)
-/*JP
-                (void) water_damage(uarm, "armor", TRUE);
-*/
-                (void) water_damage(uarm, "\8aZ", TRUE);
+                (void) water_damage(uarm, suit_simple_name(uarm), TRUE);
             else if (uarmu)
 /*JP
                 (void) water_damage(uarmu, "shirt", TRUE);
@@ -1407,10 +1453,6 @@ unsigned trflags;
             int dam = u.mhmax;
 
 /*JP
-            pline("%s you!", A_gush_of_water_hits);
-*/
-            pline("\90\85\82ª\95¬\8fo\82µ\82Ä\82 \82È\82½\82É\96½\92\86\82µ\82½\81I");
-/*JP
             You("are covered with rust!");
 */
             You("\8eK\82É\95¢\82í\82ê\82½\81I");
@@ -1419,10 +1461,6 @@ unsigned trflags;
 */
             losehp(Maybe_Half_Phys(dam), "\8a®\91S\82É\8eK\82Ñ\82Ä", KILLED_BY);
         } else if (u.umonnum == PM_GREMLIN && rn2(3)) {
-/*JP
-            pline("%s you!", A_gush_of_water_hits);
-*/
-            pline("\90\85\82ª\95¬\8fo\82µ\82Ä\82 \82È\82½\82É\96½\92\86\82µ\82½\81I");
             (void) split_mon(&youmonst, (struct monst *) 0);
         }
 
@@ -1480,15 +1518,18 @@ unsigned trflags;
                             x_monnam(u.usteed, steed_article, "poor",
                                      SUPPRESS_SADDLE, FALSE));
 #else
-                    Sprintf(verbbuf,"\82Æ%s",
+                    Sprintf(verbbuf, "\82Æ%s",
                             x_monnam(u.usteed, steed_article, "\82©\82í\82¢\82»\82¤\82È",
                                      SUPPRESS_SADDLE, FALSE));
 #endif
-            } else if (adj_pit) {
+            } else if (conj_pit) {
 /*JP
                 You("move into an adjacent pit.");
 */
                 You("\97×\82Ì\97\8e\82µ\8c\8a\82É\88Ú\93®\82µ\82½\81D");
+            } else if (adj_pit) {
+                You("stumble over debris%s.",
+                    !rn2(5) ? " between the pits" : "");
             } else {
 #if 0 /*JP*/
                 Strcpy(verbbuf,
@@ -1524,55 +1565,56 @@ unsigned trflags;
             const char *predicament = "\89s\82¢\93S\82Ì\83g\83Q\83g\83Q\82Ì\8fã\82É";
 
             if (u.usteed) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 pline("%s %s %s!",
                       upstart(x_monnam(u.usteed, steed_article, "poor",
                                        SUPPRESS_SADDLE, FALSE)),
-                      adj_pit ? "steps" : "lands", predicament);
+                      conj_pit ? "steps" : "lands", predicament);
 #else
                 pline("%s\82Í%s%s\81I",
                       upstart(x_monnam(u.usteed, steed_article, "\82©\82í\82¢\82»\82¤\82È",
                                        SUPPRESS_SADDLE, FALSE)),
-                      predicament, adj_pit ? "\97\8e\82¿\82½" : "\8d~\82è\82½");
+                      predicament, conj_pit ? "\97\8e\82¿\82½" : "\8d~\82è\82½");
 #endif
             } else
-#if 0 /*JP*/
-                You("%s %s!", adj_pit ? "step" : "land", predicament);
-#else
-                You("%s%s\81I", predicament, adj_pit ? "\97\8e\82¿\82½" : "\8d~\82è\82½");
-#endif
+/*JP
+                You("%s %s!", conj_pit ? "step" : "land", predicament);
+*/
+                You("%s%s\81I", predicament, conj_pit ? "\97\8e\82¿\82½" : "\8d~\82è\82½");
         }
         u.utrap = rn1(6, 2);
         u.utraptype = TT_PIT;
         if (!steedintrap(trap, (struct obj *) 0)) {
             if (ttype == SPIKED_PIT) {
                 oldumort = u.umortality;
-#if 0 /*JP*/
-                losehp(Maybe_Half_Phys(rnd(adj_pit ? 6 : 10)),
+#if 0 /*JP:T*/
+                losehp(Maybe_Half_Phys(rnd(conj_pit ? 4 : adj_pit ? 6 : 10)),
                        plunged
                            ? "deliberately plunged into a pit of iron spikes"
-                           : adj_pit ? "stepped into a pit of iron spikes"
+                           : conj_pit ? "stepped into a pit of iron spikes"
+                           : adj_pit ? "stumbled into a pit of iron spikes"
                                      : "fell into a pit of iron spikes",
                        NO_KILLER_PREFIX);
 #else
-                losehp(Maybe_Half_Phys(rnd(adj_pit ? 6 : 10)),
+                losehp(Maybe_Half_Phys(rnd(conj_pit ? 4 : adj_pit ? 6 : 10)),
                        plunged
                            ? "\82í\82´\82í\82´\83g\83Q\82¾\82ç\82¯\82Ì\97\8e\82µ\8c\8a\82É\93Ë\93ü\82µ\82Ä"
-                           : adj_pit ? "\83g\83Q\82¾\82ç\82¯\82Ì\97\8e\82µ\8c\8a\82É\93¥\82Ý\8d\9e\82ñ\82Å"
+                           : conj_pit ? "\83g\83Q\82¾\82ç\82¯\82Ì\97\8e\82µ\8c\8a\82É\93¥\82Ý\8d\9e\82ñ\82Å"
+                           : adj_pit ? "\83g\83Q\82¾\82ç\82¯\82Ì\97\8e\82µ\8c\8a\82É\82æ\82ë\82ß\82«\97\8e\82¿\82Ä"
                                      : "\83g\83Q\82¾\82ç\82¯\82Ì\97\8e\82µ\8c\8a\82É\97\8e\82¿\82Ä",
                        KILLED_BY);
 #endif
                 if (!rn2(6))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                     poisoned("spikes", A_STR,
-                             adj_pit ? "stepping on poison spikes"
+                             (conj_pit || adj_pit) ? "stepping on poison spikes"
                                      : "fall onto poison spikes",
                              /* if damage triggered life-saving,
                                 poison is limited to attrib loss */
                              (u.umortality > oldumort) ? 0 : 8, FALSE);
 #else
                     poisoned("\83g\83Q", A_STR,
-                             adj_pit ? "\93Å\82Ì\93h\82ç\82ê\82½\83g\83Q\82ð\93¥\82ñ\82Å"
+                             (conj_pit || adj_pit) ? "\93Å\82Ì\93h\82ç\82ê\82½\83g\83Q\82ð\93¥\82ñ\82Å"
                                      : "\93Å\82Ì\93h\82ç\82ê\82½\83g\83Q\82Ì\8fã\82É\97\8e\82¿\82Ä",
                              /* if damage triggered life-saving,
                                 poison is limited to attrib loss */
@@ -1580,15 +1622,15 @@ unsigned trflags;
 #endif
             } else {
                 /* plunging flyers take spike damage but not pit damage */
-                if (!adj_pit
+                if (!conj_pit
                     && !(plunged && (Flying || is_clinger(youmonst.data))))
-#if 0 /*JP*/
-                    losehp(Maybe_Half_Phys(rnd(6)),
+#if 0 /*JP:T*/
+                    losehp(Maybe_Half_Phys(rnd(adj_pit ? 3 : 6)),
                            plunged ? "deliberately plunged into a pit"
                                    : "fell into a pit",
                            NO_KILLER_PREFIX);
 #else
-                    losehp(Maybe_Half_Phys(rnd(6)),
+                    losehp(Maybe_Half_Phys(rnd(adj_pit ? 3 : 6)),
                            plunged ? "\82í\82´\82í\82´\97\8e\82µ\8c\8a\82É\93Ë\93ü\82µ\82Ä"
                                    : "\97\8e\82µ\8c\8a\82É\97\8e\82¿\82Ä",
                            KILLED_BY);
@@ -1599,7 +1641,7 @@ unsigned trflags;
                 ballfall();
                 placebc();
             }
-            if (!adj_pit)
+            if (!conj_pit)
 /*JP
                 selftouch("Falling, you");
 */
@@ -1628,38 +1670,13 @@ unsigned trflags;
 
     case LEVEL_TELEP:
         seetrap(trap);
-        level_tele_trap(trap);
+        level_tele_trap(trap, trflags);
         break;
 
     case WEB: /* Our luckless player has stumbled into a web. */
         feeltrap(trap);
-        if (amorphous(youmonst.data) || is_whirly(youmonst.data)
-            || unsolid(youmonst.data)) {
-            if (acidic(youmonst.data) || u.umonnum == PM_GELATINOUS_CUBE
-                || u.umonnum == PM_FIRE_ELEMENTAL) {
-                if (webmsgok)
-#if 0 /*JP*/
-                    You("%s %s spider web!",
-                        (u.umonnum == PM_FIRE_ELEMENTAL) ? "burn"
-                                                         : "dissolve",
-                        a_your[trap->madeby_u]);
-#else
-                    You("%s\82­\82à\82Ì\91\83\82ð%s\81I",
-                        web_you[trap->madeby_u],
-                        (u.umonnum == PM_FIRE_ELEMENTAL) ? "\8fÄ\82¢\82½"
-                                                         : "\82±\82È\82²\82È\82É\82µ\82½");
-#endif
-                deltrap(trap);
-                newsym(u.ux, u.uy);
-                break;
-            }
-            if (webmsgok)
-/*JP
-                You("flow through %s spider web.", a_your[trap->madeby_u]);
-*/
-                You("%s\82­\82à\82Ì\91\83\82ð\82·\82é\82è\82Æ\92Ê\82è\94²\82¯\82½\81D", web_you[trap->madeby_u]);
+        if (mu_maybe_destroy_web(&youmonst, webmsgok, trap))
             break;
-        }
         if (webmaker(youmonst.data)) {
             if (webmsgok)
 #if 0 /*JP*/
@@ -1675,7 +1692,7 @@ unsigned trflags;
             char verbbuf[BUFSZ];
 
 #if 0 /*JP*/
-            if (forcetrap) {
+            if (forcetrap || viasitting) {
                 Strcpy(verbbuf, "are caught by");
             } else if (u.usteed) {
                 Sprintf(verbbuf, "lead %s into",
@@ -1839,25 +1856,30 @@ unsigned trflags;
         char verbbuf[BUFSZ];
 
         seetrap(trap);
-        if (u.usteed)
-/*JP
-            Sprintf(verbbuf, "lead %s",
-*/
+        if (viasitting)
+            Strcpy(verbbuf, "trigger"); /* follows "You sit down." */
+        else if (u.usteed)
+#if 0 /*JP*/
+            Sprintf(verbbuf, "lead %s onto",
+                    x_monnam(u.usteed, steed_article, (char *) 0,
+                             SUPPRESS_SADDLE, FALSE));
+#else
             Sprintf(verbbuf, "%s\82Æ\82Æ\82à\82É\94ò\82Ñ\8d\9e\82ñ\82¾",
                     x_monnam(u.usteed, steed_article, (char *) 0,
                              SUPPRESS_SADDLE, FALSE));
+#endif
         else
 #if 0 /*JP*/
-            Sprintf(verbbuf, "%s", Levitation
-                                       ? (const char *) "float"
-                                       : locomotion(youmonst.data, "step"));
+            Sprintf(verbbuf, "%s onto",
+                    Levitation ? (const char *) "float"
+                               : locomotion(youmonst.data, "step"));
 #else
             Sprintf(verbbuf,"%s",
                     jpast(Levitation ? (const char *)"\95\82\82«\82È\82ª\82ç\94ò\82Ñ\82±\82Þ"
                           : locomotion(youmonst.data, "\93¥\82Ý\8d\9e\82Þ")));
 #endif
 /*JP
-        You("%s onto a polymorph trap!", verbbuf);
+        You("%s a polymorph trap!", verbbuf);
 */
         You("\95Ï\89»\82Ìã©\82É%s\81I", verbbuf);
         if (Antimagic || Unchanging) {
@@ -2307,6 +2329,7 @@ int style;
         if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
             if (otyp == BOULDER && throws_rocks(mtmp->data)) {
                 if (rn2(3)) {
+                    if (cansee(bhitpos.x, bhitpos.y))
 /*JP
                     pline("%s snatches the boulder.", Monnam(mtmp));
 */
@@ -2328,7 +2351,7 @@ int style;
             if (multi)
                 nomul(0);
             if (thitu(9 + singleobj->spe, dmgval(singleobj, &youmonst),
-                      singleobj, (char *) 0))
+                      &singleobj, (char *) 0))
                 stop_occupation();
         }
         if (style == ROLL) {
@@ -2474,7 +2497,9 @@ int style;
         if (dist > 0 && isok(bhitpos.x + dx, bhitpos.y + dy)
             && levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS) {
             x2 = bhitpos.x, y2 = bhitpos.y; /* object stops here */
-            if (hits_bars(&singleobj, x2, y2, !rn2(20), 0)) {
+            if (hits_bars(&singleobj,
+                          x2, y2, x2+dx, y2+dy,
+                          !rn2(20), 0)) {
                 if (!singleobj) {
                     used_up = TRUE;
                     launch_drop_spot((struct obj *) 0, 0, 0);
@@ -2687,7 +2712,7 @@ register struct monst *mtmp;
            Recognizing who made the trap isn't completely
            unreasonable; everybody has their own style. */
         if (trap->madeby_u && rnl(5))
-            setmangry(mtmp);
+            setmangry(mtmp, TRUE);
 
         in_sight = canseemon(mtmp);
         see_it = cansee(mtmp->mx, mtmp->my);
@@ -2787,11 +2812,22 @@ register struct monst *mtmp;
                     pline("%s\82Í\88ê\8fu\8e~\82Ü\82Á\82Ä\90g\82ð\82·\82­\82ß\82½\82æ\82¤\82¾\81D",
                           Monnam(mtmp));
                 }
-            } else
-/*JP
-                You_hear("a distant %s squeak.", trapnote(trap, 1));
-*/
-                You_hear("\89\93\82­\82Å%s\82Å\82«\82µ\82Þ\89¹\82ð\95·\82¢\82½\81D", trapnote(trap, 1));
+            } else {
+                /* same near/far threshold as mzapmsg() */
+                int range = couldsee(mtmp->mx, mtmp->my) /* 9 or 5 */
+                               ? (BOLT_LIM + 1) : (BOLT_LIM - 3);
+
+#if 0 /*JP*/
+                You_hear("a %s squeak %s.", trapnote(trap, 1),
+                         (distu(mtmp->mx, mtmp->my) <= range * range)
+                            ? "nearby" : "in the distance");
+#else
+                You_hear("%s\82­\82Å%s\82ª\82«\82µ\82Þ\89¹\82ð\95·\82¢\82½\81D",
+                         (distu(mtmp->mx, mtmp->my) <= range * range)
+                            ? "\8bß" : "\89\93",
+                         trapnote(trap, 1));
+#endif
+            }
             /* wake up nearby monsters */
             wake_nearto(mtmp->mx, mtmp->my, 40);
             break;
@@ -2911,10 +2947,8 @@ register struct monst *mtmp;
                     (void) water_damage(target, cloak_simple_name(target),
                                         TRUE);
                 else if ((target = which_armor(mtmp, W_ARM)) != 0)
-/*JP
-                    (void) water_damage(target, "armor", TRUE);
-*/
-                    (void) water_damage(target, "\8aZ", TRUE);
+                    (void) water_damage(target, suit_simple_name(target),
+                                        TRUE);
                 else if ((target = which_armor(mtmp, W_ARMU)) != 0)
 /*JP
                     (void) water_damage(target, "shirt", TRUE);
@@ -3132,39 +3166,8 @@ register struct monst *mtmp;
             /* Monster in a web. */
             if (webmaker(mptr))
                 break;
-            if (amorphous(mptr) || is_whirly(mptr) || unsolid(mptr)) {
-                if (acidic(mptr) || mptr == &mons[PM_GELATINOUS_CUBE]
-                    || mptr == &mons[PM_FIRE_ELEMENTAL]) {
-                    if (in_sight)
-#if 0 /*JP*/
-                        pline("%s %s %s spider web!", Monnam(mtmp),
-                              (mptr == &mons[PM_FIRE_ELEMENTAL])
-                                  ? "burns"
-                                  : "dissolves",
-                              a_your[trap->madeby_u]);
-#else
-                        pline("%s%s\82­\82à\82Ì\91\83\82ð%s\81I",
-                              Monnam(mtmp),
-                              web_you[trap->madeby_u],
-                              (mptr == &mons[PM_FIRE_ELEMENTAL]) ?
-                              "\8fÄ\82¢\82½" : "\82±\82È\82²\82È\82É\82µ\82½");
-#endif
-                    deltrap(trap);
-                    newsym(mtmp->mx, mtmp->my);
-                    break;
-                }
-                if (in_sight) {
-#if 0 /*JP*/
-                    pline("%s flows through %s spider web.", Monnam(mtmp),
-                          a_your[trap->madeby_u]);
-#else
-                    pline("%s\82Í%s\82­\82à\82Ì\91\83\82ð\82·\82é\82è\82Æ\92Ê\82è\94²\82¯\82½\81D", Monnam(mtmp),
-                          web_you[trap->madeby_u]);
-#endif
-                    seetrap(trap);
-                }
+            if (mu_maybe_destroy_web(mtmp, in_sight, trap))
                 break;
-            }
             tear_web = FALSE;
             switch (monsndx(mptr)) {
             case PM_OWLBEAR: /* Eric Backus */
@@ -3177,7 +3180,7 @@ register struct monst *mtmp;
                     mtmp->mtrapped = 1;
                     break;
                 }
-            /* fall though */
+                /*FALLTHRU*/
             default:
                 if (mptr->mlet == S_GIANT
                     /* exclude baby dragons and relatively short worms */
@@ -3275,7 +3278,8 @@ register struct monst *mtmp;
 
                 if (in_sight)
                     seetrap(trap);
-                if ((mtmp->mhp -= dmgval2) <= 0)
+                mtmp->mhp -= dmgval2;
+                if (mtmp->mhp <= 0)
                     monkilled(mtmp,
                               in_sight
 /*JP
@@ -3318,14 +3322,16 @@ register struct monst *mtmp;
             } else if (in_sight) {
                 newsym(mtmp->mx, mtmp->my);
 #if 0 /*JP*/
-                pline("KAABLAMM!!!  %s triggers %s land mine!", Monnam(mtmp),
+                pline("%s%s triggers %s land mine!",
+                      !Deaf ? "KAABLAMM!!!  " : "", Monnam(mtmp),
                       a_your[trap->madeby_u]);
 #else
-                pline("\82¿\82ã\82Ç\81[\82ñ\81I\81I%s\82Í%s\92n\97\8b\82Ì\8bN\94\9a\83X\83C\83b\83`\82ð\93¥\82ñ\82¾\81I", Monnam(mtmp),
+                pline("%s%s\82Í%s\92n\97\8b\82Ì\8bN\94\9a\83X\83C\83b\83`\82ð\93¥\82ñ\82¾\81I",
+                      !Deaf ? "\82¿\82ã\82Ç\81[\82ñ\81I\81I" : "", Monnam(mtmp),
                       set_you[trap->madeby_u]);
 #endif
             }
-            if (!in_sight)
+            if (!in_sight && !Deaf)
 /*JP
                 pline("Kaablamm!  You hear an explosion in the distance!");
 */
@@ -3334,9 +3340,9 @@ register struct monst *mtmp;
             /* explosion might have destroyed a drawbridge; don't
                dish out more damage if monster is already dead */
             if (mtmp->mhp <= 0
-                || thitm(0, mtmp, (struct obj *) 0, rnd(16), FALSE))
+                || thitm(0, mtmp, (struct obj *) 0, rnd(16), FALSE)) {
                 trapkilled = TRUE;
-            else {
+            else {
                 /* monsters recursively fall into new pit */
                 if (mintrap(mtmp) == 2)
                     trapkilled = TRUE;
@@ -3448,6 +3454,8 @@ boolean byplayer;
         mon_to_stone(mon);
         return;
     }
+    if (!vamp_stone(mon))
+        return;
 
     /* give a "<mon> is slowing down" message and also remove
        intrinsic speed (comparable to similar effect on the hero) */
@@ -3460,7 +3468,7 @@ boolean byplayer;
         pline("%s\82Í\90Î\82É\82È\82Á\82½\81D", Monnam(mon));
     if (byplayer) {
         stoned = TRUE;
-        xkilled(mon, 0);
+        xkilled(mon, XKILL_NOMSG);
     } else
         monstone(mon);
 }
@@ -3537,6 +3545,7 @@ boolean byplayer;
 void
 float_up()
 {
+    context.botl = TRUE;
     if (u.utrap) {
         if (u.utraptype == TT_PIT) {
             u.utrap = 0;
@@ -3616,6 +3625,9 @@ float_up()
 */
         You("\8bó\92\86\82Å\82¤\82Ü\82­\93®\82¯\82È\82­\82È\82Á\82½\81D");
     BFlying |= I_SPECIAL;
+    /* levitation gives maximum carrying capacity, so encumbrance
+       state might be reduced */
+    (void) encumber_msg();
     return;
 }
 
@@ -3655,6 +3667,7 @@ long hmask, emask; /* might cancel timeout */
         float_vs_flight(); /* before nomul() rather than after */
         return 0;
     }
+    context.botl = TRUE;
     nomul(0); /* stop running or resting */
     if (BFlying) {
         /* controlled flight no longer overridden by levitation */
@@ -3664,6 +3677,7 @@ long hmask, emask; /* might cancel timeout */
             You("have stopped levitating and are now flying.");
 */
             You("\8bó\92\86\95\82\97V\82ð\8e~\82ß\82Ä\8bó\82ð\94ò\82Ñ\82Í\82\82ß\82½\81D");
+            (void) encumber_msg(); /* carrying capacity might have changed */
             return 1;
         }
     }
@@ -3674,6 +3688,7 @@ long hmask, emask; /* might cancel timeout */
 #else
         You("\92\85\92n\82µ\82½\82ª\81C\82Ü\82¾\88ù\82Ý\8d\9e\82Ü\82ê\82½\82Ü\82Ü\82¾\81D");
 #endif
+        (void) encumber_msg();
         return 1;
     }
 
@@ -3796,6 +3811,11 @@ long hmask, emask; /* might cancel timeout */
         }
     }
 
+    /* levitation gives maximum carrying capacity, so having it end
+       potentially triggers greater encumbrance; do this after
+       'come down' messages, before trap activation or autopickup */
+    (void) encumber_msg();
+
     /* can't rely on u.uz0 for detecting trap door-induced level change;
        it gets changed to reflect the new level before we can check it */
     assign_level(&current_dungeon_level, &u.uz);
@@ -3995,6 +4015,7 @@ domagictrap()
         /* Most of the time, it creates some monsters. */
         register int cnt = rnd(4);
 
+        /* blindness effects */
         if (!resists_blnd(&youmonst)) {
 /*JP
             You("are momentarily blinded by a flash of light!");
@@ -4008,12 +4029,22 @@ domagictrap()
             You_see("a flash of light!");
 */
             You("\82Ü\82Î\82ä\82¢\8cõ\82ð\97\81\82Ñ\82½\81I");
-        } else
+        }
+
+        /* deafness effects */
+        if (!Deaf) {
 /*JP
             You_hear("a deafening roar!");
 */
             You_hear("\8e¨\82ð\82Â\82ñ\82´\82­\82æ\82¤\82È\99ô\9aK\82ð\95·\82¢\82½\81I");
-        incr_itimeout(&HDeaf, rn1(20, 30));
+            incr_itimeout(&HDeaf, rn1(20, 30));
+            context.botl = TRUE;
+        } else {
+            /* magic vibrations still hit you */
+            You_feel("rankled.");
+            incr_itimeout(&HDeaf, rn1(5, 15));
+            context.botl = TRUE;
+        }
         while (cnt--)
             (void) makemon((struct permonst *) 0, u.ux, u.uy, NO_MM_FLAGS);
     } else
@@ -4249,6 +4280,7 @@ xchar x, y;
 {
     struct obj *obj, *nobj;
     int num = 0;
+
     for (obj = chain; obj; obj = nobj) {
         nobj = here ? obj->nexthere : obj->nobj;
         if (fire_damage(obj, force, x, y))
@@ -4263,6 +4295,51 @@ xchar x, y;
     return num;
 }
 
+/* obj has been thrown or dropped into lava; damage is worse than mere fire */
+boolean
+lava_damage(obj, x, y)
+struct obj *obj;
+xchar x, y;
+{
+    int otyp = obj->otyp, ocls = obj->oclass;
+
+    /* the Amulet, invocation items, and Rider corpses are never destroyed
+       (let Book of the Dead fall through to fire_damage() to get feedback) */
+    if (obj_resists(obj, 0, 0) && otyp != SPE_BOOK_OF_THE_DEAD)
+        return FALSE;
+    /* destroy liquid (venom), wax, veggy, flesh, paper (except for scrolls
+       and books--let fire damage deal with them), cloth, leather, wood, bone
+       unless it's inherently or explicitly fireproof or contains something;
+       note: potions are glass so fall through to fire_damage() and boil */
+    if (objects[otyp].oc_material < DRAGON_HIDE
+        && ocls != SCROLL_CLASS && ocls != SPBOOK_CLASS
+        && objects[otyp].oc_oprop != FIRE_RES
+        && otyp != WAN_FIRE && otyp != FIRE_HORN
+        /* assumes oerodeproof isn't overloaded for some other purpose on
+           non-eroding items */
+        && !obj->oerodeproof
+        /* fire_damage() knows how to deal with containers and contents */
+        && !Has_contents(obj)) {
+        if (cansee(x, y)) {
+            /* this feedback is pretty clunky and can become very verbose
+               when former contents of a burned container get here via
+               flooreffects() */
+            if (obj == thrownobj || obj == kickedobj)
+                pline("%s %s up!", is_plural(obj) ? "They" : "It",
+                      otense(obj, "burn"));
+            else
+                You_see("%s hit lava and burn up!", doname(obj));
+        }
+        if (carried(obj)) { /* shouldn't happen */
+            remove_worn_item(obj, TRUE);
+            useupall(obj);
+        } else
+            delobj(obj);
+        return TRUE;
+    }
+    return fire_damage(obj, TRUE, x, y);
+}
+
 void
 acid_damage(obj)
 struct obj *obj;
@@ -4357,7 +4434,16 @@ boolean force;
             pline("\90\85\82ª%s\82Ì\92\86\82É\93ü\82Á\82½\81I", ostr);
 
         water_damage_chain(obj->cobj, FALSE);
-        return ER_NOTHING;
+        return ER_DAMAGED; /* contents were damaged */
+    } else if (obj->otyp == OILSKIN_SACK) {
+        if (carried(obj))
+            pline("Some water slides right off your %s.", ostr);
+        makeknown(OILSKIN_SACK);
+        /* not actually damaged, but because we /didn't/ get the "water
+           gets into!" message, the player now has more information and
+           thus we need to waste any potion they may have used (also,
+           flavourwise the water is now on the floor) */
+        return ER_DAMAGED;
     } else if (!force && (Luck + 5) > rn2(20)) {
         /*  chance per item of sustaining damage:
             *   max luck:               10%
@@ -4366,10 +4452,11 @@ boolean force;
             */
         return ER_NOTHING;
     } else if (obj->oclass == SCROLL_CLASS) {
+        if (obj->otyp == SCR_BLANK_PAPER
 #ifdef MAIL
-        if (obj->otyp == SCR_MAIL)
-            return 0;
+            || obj->otyp == SCR_MAIL
 #endif
+           ) return 0;
         if (carried(obj))
 /*JP
             pline("Your %s %s.", ostr, vtense(ostr, "fade"));
@@ -4389,8 +4476,9 @@ boolean force;
 */
             pline("\8fö\8bC\82ª%s\82©\82ç\97§\82¿\82Ì\82Ú\82Á\82½\81D", xname(obj));
             return 0;
+        } else if (obj->otyp == SPE_BLANK_PAPER) {
+            return 0;
         }
-
         if (carried(obj))
 /*JP
             pline("Your %s %s.", ostr, vtense(ostr, "fade"));
@@ -4573,11 +4661,13 @@ drown()
     }
 
     if (!u.uinwater) {
-#if 0 /*JP*/
-        You("%s into the water%c", Is_waterlevel(&u.uz) ? "plunge" : "fall",
+#if 0 /*JP:T*/
+        You("%s into the %s%c", Is_waterlevel(&u.uz) ? "plunge" : "fall",
+            hliquid("water"),
             Amphibious || Swimming ? '.' : '!');
 #else
-        You("\90\85\82Ì\92\86\82É%s%s", Is_waterlevel(&u.uz) ? "\94ò\82Ñ\82±\82ñ\82¾" : "\97\8e\82¿\82½",
+        You("%s\82Ì\92\86\82É%s%s", hliquid("\90\85"),
+            Is_waterlevel(&u.uz) ? "\94ò\82Ñ\82±\82ñ\82¾" : "\97\8e\82¿\82½",
             Amphibious || Swimming ? "\81D" : "\81I");
 #endif
         if (!Swimming && !Is_waterlevel(&u.uz))
@@ -4708,9 +4798,9 @@ crawl:
         boolean succ = Is_waterlevel(&u.uz) ? TRUE : emergency_disrobe(&lost);
 
 /*JP
-        You("try to crawl out of the water.");
+        You("try to crawl out of the %s.", hliquid("water"));
 */
-        You("\90\85\82©\82ç\82Í\82¢\82 \82ª\82ë\82¤\82Æ\82µ\82½\81D");
+        You("%s\82©\82ç\82Í\82¢\82 \82ª\82ë\82¤\82Æ\82µ\82½\81D", hliquid("\90\85"));
         if (lost)
 /*JP
             You("dump some of your gear to lose weight...");
@@ -5000,7 +5090,8 @@ boolean force_failure;
                 if (ttype == BEAR_TRAP) {
                     if (mtmp->mtame)
                         abuse_dog(mtmp);
-                    if ((mtmp->mhp -= rnd(4)) <= 0)
+                    mtmp->mhp -= rnd(4);
+                    if (mtmp->mhp <= 0)
                         killed(mtmp);
                 } else if (ttype == WEB) {
                     if (!webmaker(youmonst.data)) {
@@ -5369,8 +5460,9 @@ boolean force;
     struct trap *ttmp;
     struct monst *mtmp;
     const char *trapdescr;
-    boolean here, useplural, confused = (Confusion || Hallucination),
-                             trap_skipped = FALSE, deal_with_floor_trap;
+    boolean here, useplural, deal_with_floor_trap,
+            confused = (Confusion || Hallucination),
+            trap_skipped = FALSE;
     int boxcnt = 0;
     char the_trap[BUFSZ], qbuf[QBUFSZ];
 
@@ -5385,6 +5477,11 @@ boolean force;
         pline_The("\82»\82±\82É\82 \82é\8aë\8c¯\82Í\82 \82È\82½\82Ì\8eè\82É\95\89\82¦\82È\82¢\81D");
         return 0;
     }
+    /* 'force' is true for #invoke; make it be true for #untrap if
+       carrying MKoT */
+    if (!force && has_magic_key(&youmonst))
+        force = TRUE;
+
     ttmp = t_at(x, y);
     if (ttmp && !ttmp->tseen)
         ttmp = 0;
@@ -5641,7 +5738,7 @@ boolean force;
         return 0;
     }
 
-    if ((levl[x][y].doormask & D_TRAPPED
+    if (((levl[x][y].doormask & D_TRAPPED) != 0
          && (force || (!confused && rn2(MAXULEV - u.ulevel + 11) < 10)))
         || (!force && confused && !rn2(3))) {
 /*JP
@@ -5707,6 +5804,8 @@ boolean *noticed; /* set to true iff hero notices the effect; */
     const char *trapdescr, *which;
     boolean ishero = (mon == &youmonst);
 
+    if (!mon)
+        return FALSE;
     if (mon == u.usteed)
         ishero = TRUE;
     t = t_at(ishero ? u.ux : mon->mx, ishero ? u.uy : mon->my);
@@ -5791,6 +5890,8 @@ boolean *noticed; /* set to true iff hero notices the effect; */
     unsigned dotrapflags;
     boolean ishero = (mon == &youmonst), result;
 
+    if (!mon)
+        return FALSE;
     if (mon == u.usteed)
         ishero = TRUE;
     t = t_at(ishero ? u.ux : mon->mx, ishero ? u.uy : mon->my);
@@ -5834,6 +5935,8 @@ boolean *noticed; /* set to true iff hero notices the effect; */
     struct trap *t;
     boolean ishero = (mon == &youmonst), result;
 
+    if (!mon)
+        return FALSE;
     if (mon == u.usteed)
         ishero = TRUE;
     t = t_at(ishero ? u.ux : mon->mx, ishero ? u.uy : mon->my);
@@ -5857,13 +5960,13 @@ boolean *noticed; /* set to true iff hero notices the effect; */
            or if you sense the monster who becomes trapped */
         *noticed = cansee(t->tx, t->ty) || canspotmon(mon);
         /* monster will be angered; mintrap doesn't handle that */
-        wakeup(mon);
+        wakeup(mon, TRUE);
         ++force_mintrap;
         result = (mintrap(mon) != 0);
         --force_mintrap;
         /* mon might now be on the migrating monsters list */
     }
-    return TRUE;
+    return result;
 }
 
 /* only called when the player is doing something to the chest directly */
@@ -5971,16 +6074,11 @@ boolean disarm;
                 loss += stolen_value(obj, ox, oy, (boolean) shkp->mpeaceful,
                                      TRUE);
             delete_contents(obj);
-            /* we're about to delete all things at this location,
-             * which could include the ball & chain.
-             * If we attempt to call unpunish() in the
-             * for-loop below we can end up with otmp2
-             * being invalid once the chain is gone.
-             * Deal with ball & chain right now instead.
-             */
-            if (Punished && !carried(uball)
-                && ((uchain->ox == u.ux && uchain->oy == u.uy)
-                    || (uball->ox == u.ux && uball->oy == u.uy)))
+            /* unpunish() in advance if either ball or chain (or both)
+               is going to be destroyed */
+            if (Punished && ((uchain->ox == u.ux && uchain->oy == u.uy)
+                             || (uball->where == OBJ_FLOOR
+                                 && uball->ox == u.ux && uball->oy == u.uy)))
                 unpunish();
 
             for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
@@ -6231,6 +6329,24 @@ struct trap *trap;
     }
 }
 
+boolean
+adj_nonconjoined_pit(adjtrap)
+struct trap *adjtrap;
+{
+    struct trap *trap_with_u = t_at(u.ux0, u.uy0);
+
+    if (trap_with_u && adjtrap && u.utrap && u.utraptype == TT_PIT &&
+        (trap_with_u->ttyp == PIT || trap_with_u->ttyp == SPIKED_PIT) &&
+        (adjtrap->ttyp == PIT || adjtrap->ttyp == SPIKED_PIT)) {
+        int idx;
+        for (idx = 0; idx < 8; idx++) {
+            if (xdir[idx] == u.dx && ydir[idx] == u.dy)
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
 #if 0
 /*
  * Mark all neighboring pits as conjoined pits.
@@ -6369,9 +6485,9 @@ boolean nocorpse;
             if (dam < 1)
                 dam = 1;
         }
-        if ((mon->mhp -= dam) <= 0) {
-            int xx = mon->mx;
-            int yy = mon->my;
+        mon->mhp -= dam;
+        if (mon->mhp <= 0) {
+            int xx = mon->mx, yy = mon->my;
 
             monkilled(mon, "", nocorpse ? -AD_RBRE : AD_PHYS);
             if (mon->mhp <= 0) {
@@ -6449,13 +6565,13 @@ lava_effects()
                 && objects[obj->otyp].oc_oprop != FIRE_RES
                 && obj->otyp != SCR_FIRE && obj->otyp != SPE_FIREBALL
                 && !obj_resists(obj, 0, 0)) /* for invocation items */
-                obj->in_use = TRUE;
+                obj->in_use = 1;
 
     /* Check whether we should burn away boots *first* so we know whether to
      * make the player sink into the lava. Assumption: water walking only
      * comes from boots.
      */
-    if (Wwalking && uarmf && is_organic(uarmf) && !uarmf->oerodeproof) {
+    if (uarmf && is_organic(uarmf) && !uarmf->oerodeproof) {
         obj = uarmf;
 /*JP
         pline("%s into flame!", Yobjnam2(obj, "burst"));
@@ -6470,18 +6586,18 @@ lava_effects()
     if (!Fire_resistance) {
         if (Wwalking) {
 /*JP
-            pline_The("lava here burns you!");
+            pline_The("%s here burns you!", hliquid("lava"));
 */
-            pline("\97n\8aâ\82ª\82 \82È\82½\82ð\8fÄ\82«\82Â\82­\82µ\82½\81I");
+            pline("%s\82ª\82 \82È\82½\82ð\8fÄ\82«\82Â\82­\82µ\82½\81I", hliquid("\97n\8aâ"));
             if (usurvive) {
                 losehp(dmg, lava_killer, KILLED_BY); /* lava damage */
                 goto burn_stuff;
             }
         } else
 /*JP
-            You("fall into the lava!");
+            You("fall into the %s!", hliquid("lava"));
 */
-            You("\97n\8aâ\82É\97\8e\82¿\82½\81I");
+            You("%s\82É\97\8e\82¿\82½\81I", hliquid("\97n\8aâ"));
 
         usurvive = Lifesaved || discover;
         if (wizard)
@@ -6556,13 +6672,15 @@ lava_effects()
         u.utrap = rn1(4, 4) + ((boil_away ? 2 : rn1(4, 12)) << 8);
         u.utraptype = TT_LAVA;
 #if 0 /*JP*/
-        You("sink into the lava%s!", !boil_away
-                                         ? ", but it only burns slightly"
-                                         : " and are about to be immolated");
+        You("sink into the %s%s!", hliquid("lava"),
+            !boil_away
+            ? ", but it only burns slightly"
+            : " and are about to be immolated");
 #else
-        You("\97n\8aâ\82É\92¾\82ñ%s\82¾\81I", !boil_away
-                                         ? "\82¾\82ª\81C\82¿\82å\82Á\82Æ\8fÅ\82°\82½\82¾\82¯"
-                                         : "\82Å\8fÄ\82«\8eE\82³\82ê\82»\82¤");
+        You("%s\82É\92¾\82ñ%s\82¾\81I", hliquid("\97n\8aâ"),
+            !boil_away
+            ? "\82¾\82ª\81C\82¿\82å\82Á\82Æ\8fÅ\82°\82½\82¾\82¯"
+            : "\82Å\8fÄ\82«\8eE\82³\82ê\82»\82¤");
 #endif
         if (u.uhp > 1)
             losehp(!boil_away ? 1 : (u.uhp / 2), lava_killer,
@@ -6610,6 +6728,9 @@ sink_into_lava()
             You("\8a®\91S\82É\97n\8aâ\82Ì\92\86\82É\92¾\82ñ\82Å\81A\8e\80\82É\82Ü\82µ\82½\81D\81D\81D");
             burn_away_slime(); /* add insult to injury? */
             done(DISSOLVED);
+            /* can only get here via life-saving; try to get away from lava */
+            u.utrap = 0;
+            (void) safe_teleds(TRUE);
         } else if (!u.umoved) {
             /* can't fully turn into slime while in lava, but might not
                have it be burned away until you've come awfully close */
index f0c1e37..3087f70 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 u_init.c        $NHDT-Date: 1446861772 2015/11/07 02:02:52 $  $NHDT-Branch: master $:$NHDT-Revision: 1.35 $ */
+/* NetHack 3.6 u_init.c        $NHDT-Date: 1503960969 2017/08/28 22:56:09 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.40 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2017. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
@@ -124,7 +125,7 @@ static struct trobj Rogue[] = {
     { DAGGER, 0, WEAPON_CLASS, 10, 0 }, /* quan is variable */
     { LEATHER_ARMOR, 1, ARMOR_CLASS, 1, UNDEF_BLESS },
     { POT_SICKNESS, 0, POTION_CLASS, 1, 0 },
-    { LOCK_PICK, 9, TOOL_CLASS, 1, 0 },
+    { LOCK_PICK, 0, TOOL_CLASS, 1, 0 },
     { SACK, 0, TOOL_CLASS, 1, 0 },
     { 0, 0, 0, 0, 0 }
 };
@@ -270,7 +271,8 @@ static const struct def_skill Skill_B[] = {
     { P_SPEAR, P_SKILLED },
     { P_TRIDENT, P_SKILLED },
     { P_BOW, P_BASIC },
-    { P_ATTACK_SPELL, P_SKILLED },
+    { P_ATTACK_SPELL, P_BASIC },
+    { P_ESCAPE_SPELL, P_BASIC }, /* special spell is haste self */
     { P_RIDING, P_BASIC },
     { P_TWO_WEAPON_COMBAT, P_BASIC },
     { P_BARE_HANDED_COMBAT, P_MASTER },
@@ -458,7 +460,8 @@ static const struct def_skill Skill_S[] = {
     { P_LANCE, P_SKILLED },
     { P_BOW, P_EXPERT },
     { P_SHURIKEN, P_EXPERT },
-    { P_ATTACK_SPELL, P_SKILLED },
+    { P_ATTACK_SPELL, P_BASIC },
+    { P_DIVINATION_SPELL, P_BASIC }, /* special spell is clairvoyance */
     { P_CLERIC_SPELL, P_SKILLED },
     { P_RIDING, P_SKILLED },
     { P_TWO_WEAPON_COMBAT, P_EXPERT },
@@ -699,31 +702,25 @@ u_init()
         ini_inv(Knight);
         knows_class(WEAPON_CLASS);
         knows_class(ARMOR_CLASS);
-        /* give knights chess-like mobility
-         * -- idea from wooledge@skybridge.scl.cwru.edu */
+        /* give knights chess-like mobility--idea from wooledge@..cwru.edu */
         HJumping |= FROMOUTSIDE;
         skill_init(Skill_K);
         break;
-    case PM_MONK:
-        switch (rn2(90) / 30) {
-        case 0:
-            Monk[M_BOOK].trotyp = SPE_HEALING;
-            break;
-        case 1:
-            Monk[M_BOOK].trotyp = SPE_PROTECTION;
-            break;
-        case 2:
-            Monk[M_BOOK].trotyp = SPE_SLEEP;
-            break;
-        }
+    case PM_MONK: {
+        static short M_spell[] = { SPE_HEALING, SPE_PROTECTION, SPE_SLEEP };
+
+        Monk[M_BOOK].trotyp = M_spell[rn2(90) / 30]; /* [0..2] */
         ini_inv(Monk);
         if (!rn2(5))
             ini_inv(Magicmarker);
         else if (!rn2(10))
             ini_inv(Lamp);
         knows_class(ARMOR_CLASS);
+        /* sufficiently martial-arts oriented item to ignore language issue */
+        knows_object(SHURIKEN);
         skill_init(Skill_Mon);
         break;
+    }
     case PM_PRIEST:
         ini_inv(Priest);
         if (!rn2(10))
@@ -1017,6 +1014,8 @@ register struct trobj *trop;
                    || otyp == RIN_AGGRAVATE_MONSTER
                    || otyp == RIN_HUNGER
                    || otyp == WAN_NOTHING
+                   /* orcs start with poison resistance */
+                   || (otyp == RIN_POISON_RESISTANCE && Race_if(PM_ORC))
                    /* Monks don't use weapons */
                    || (otyp == SCR_ENCHANT_WEAPON && Role_if(PM_MONK))
                    /* wizard patch -- they already have one */
index 7a7f471..5435828 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 uhitm.c $NHDT-Date: 1446887537 2015/11/07 09:12:17 $  $NHDT-Branch: master $:$NHDT-Revision: 1.151 $ */
+/* NetHack 3.6 uhitm.c $NHDT-Date: 1521684760 2018/03/22 02:12:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.176 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 #include "hack.h"
 
 STATIC_DCL boolean FDECL(known_hitum, (struct monst *, struct obj *, int *,
-                                       int, int, struct attack *));
+                                       int, int, struct attack *, int));
 STATIC_DCL boolean FDECL(theft_petrifies, (struct obj *));
 STATIC_DCL void FDECL(steal_it, (struct monst *, struct attack *));
+STATIC_DCL boolean FDECL(hitum_cleave, (struct monst *, struct attack *));
 STATIC_DCL boolean FDECL(hitum, (struct monst *, struct attack *));
-STATIC_DCL boolean FDECL(hmon_hitmon, (struct monst *, struct obj *, int));
+STATIC_DCL boolean FDECL(hmon_hitmon, (struct monst *, struct obj *, int,
+                                       int));
 STATIC_DCL int FDECL(joust, (struct monst *, struct obj *));
 STATIC_DCL void NDECL(demonpet);
-STATIC_DCL boolean FDECL(m_slips_free, (struct monst * mtmp,
-                                        struct attack *mattk));
+STATIC_DCL boolean FDECL(m_slips_free, (struct monst *, struct attack *));
 STATIC_DCL int FDECL(explum, (struct monst *, struct attack *));
 STATIC_DCL void FDECL(start_engulf, (struct monst *));
 STATIC_DCL void NDECL(end_engulf);
@@ -28,8 +30,7 @@ STATIC_DCL void FDECL(nohandglow, (struct monst *));
 STATIC_DCL boolean FDECL(shade_aware, (struct obj *));
 
 extern boolean notonhead; /* for long worms */
-/* The below might become a parameter instead if we use it a lot */
-static int dieroll;
+
 /* Used to flag attacks caused by Stormbringer's maliciousness. */
 static boolean override_confirmation = FALSE;
 
@@ -153,7 +154,7 @@ struct obj *wep; /* uwep for attack(), null for kick_monster() */
             if (!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data, AD_STCK))
                 u.ustuck = mtmp;
         }
-        wakeup(mtmp); /* always necessary; also un-mimics mimics */
+        wakeup(mtmp, TRUE); /* always necessary; also un-mimics mimics */
         return TRUE;
     }
 
@@ -206,7 +207,7 @@ struct obj *wep; /* uwep for attack(), null for kick_monster() */
      */
     if ((mtmp->mundetected || mtmp->m_ap_type) && sensemon(mtmp)) {
         mtmp->mundetected = 0;
-        wakeup(mtmp);
+        wakeup(mtmp, TRUE);
     }
 
     if (flags.confirm && mtmp->mpeaceful && !Confusion && !Hallucination
@@ -378,6 +379,7 @@ register struct monst *mtmp;
                 You("stop.  %s is in the way!", buf);
 */
                 You("\8e~\82Ü\82Á\82½\81D%s\82ª\93¹\82É\82¢\82é\81I", buf);
+                context.travel = context.travel1 = context.mv = context.run = 0;
                 return TRUE;
             } else if ((mtmp->mfrozen || (!mtmp->mcanmove)
                         || (mtmp->data->mmove == 0)) && rn2(6)) {
@@ -385,6 +387,7 @@ register struct monst *mtmp;
                 pline("%s doesn't seem to move!", Monnam(mtmp));
 */
                 pline("%s\82Í\93®\82¯\82È\82¢\82æ\82¤\82¾\81I", Monnam(mtmp));
+                context.travel = context.travel1 = context.mv = context.run = 0;
                 return TRUE;
             } else
                 return FALSE;
@@ -427,14 +430,13 @@ register struct monst *mtmp;
         if (flags.verbose) {
             if (uwep)
 /*JP
-                You("begin bashing monsters with %s.",
+                You("begin bashing monsters with %s.", yname(uwep));
 */
-                You("%s\82Å\89ö\95¨\82ð\82È\82®\82è\82Â\82¯\82½\81D",
-                    yobjnam(uwep, (char *) 0));
+                You("%s\82Å\89ö\95¨\82ð\82È\82®\82è\82Â\82¯\82½\81D", yname(uwep));
             else if (!cantwield(youmonst.data))
 #if 0 /*JP*/
-                You("begin %sing monsters with your %s %s.",
-                    Role_if(PM_MONK) ? "strik" : "bash",
+                You("begin %s monsters with your %s %s.",
+                    ing_suffix(Role_if(PM_MONK) ? "strike" : "bash"),
                     uarmg ? "gloved" : "bare", /* Del Lamb */
                     makeplural(body_part(HAND)));
 #else
@@ -479,12 +481,13 @@ atk_done:
 
 /* really hit target monster; returns TRUE if it still lives */
 STATIC_OVL boolean
-known_hitum(mon, weapon, mhit, rollneeded, armorpenalty, uattk)
+known_hitum(mon, weapon, mhit, rollneeded, armorpenalty, uattk, dieroll)
 register struct monst *mon;
 struct obj *weapon;
 int *mhit;
 int rollneeded, armorpenalty; /* for monks */
 struct attack *uattk;
+int dieroll;
 {
     register boolean malive = TRUE;
 
@@ -511,7 +514,7 @@ struct attack *uattk;
         /* we hit the monster; be careful: it might die or
            be knocked into a different location */
         notonhead = (mon->mx != x || mon->my != y);
-        malive = hmon(mon, weapon, HMON_MELEE);
+        malive = hmon(mon, weapon, HMON_MELEE, dieroll);
         if (malive) {
             /* monster still alive */
             if (!rn2(25) && mon->mhp < mon->mhpmax / 2
@@ -536,6 +539,83 @@ struct attack *uattk;
     return malive;
 }
 
+/* hit the monster next to you and the monsters to the left and right of it;
+   return False if the primary target is killed, True otherwise */
+STATIC_OVL boolean
+hitum_cleave(target, uattk)
+struct monst *target; /* non-Null; forcefight at nothing doesn't cleave... */
+struct attack *uattk; /* ... but we don't enforce that here; Null works ok */
+{
+    /* swings will be delivered in alternate directions; with consecutive
+       attacks it will simulate normal swing and backswing; when swings
+       are non-consecutive, hero will sometimes start a series of attacks
+       with a backswing--that doesn't impact actual play, just spoils the
+       simulation attempt a bit */
+    static boolean clockwise = FALSE;
+    unsigned i;
+    int count, umort, x = u.ux, y = u.uy;
+
+    /* find the direction toward primary target */
+    for (i = 0; i < 8; ++i)
+        if (xdir[i] == u.dx && ydir[i] == u.dy)
+            break;
+    if (i == 8) {
+        impossible("hitum_cleave: unknown target direction [%d,%d,%d]?",
+                   u.dx, u.dy, u.dz);
+        return TRUE; /* target hasn't been killed */
+    }
+    /* adjust direction by two so that loop's increment (for clockwise)
+       or decrement (for counter-clockwise) will point at the spot next
+       to primary target */
+    i = (i + (clockwise ? 6 : 2)) % 8;
+    umort = u.umortality; /* used to detect life-saving */
+
+    /*
+     * Three attacks:  adjacent to primary, primary, adjacent on other
+     * side.  Primary target must be present or we wouldn't have gotten
+     * here (forcefight at thin air won't 'cleave').  However, the
+     * first attack might kill it (gas spore explosion, weak long worm
+     * occupying both spots) so we don't assume that it's still present
+     * on the second attack.
+     */
+    for (count = 3; count > 0; --count) {
+        struct monst *mtmp;
+        int tx, ty, tmp, dieroll, mhit, attknum, armorpenalty;
+
+        /* ++i, wrap 8 to i=0 /or/ --i, wrap -1 to i=7 */
+        i = (i + (clockwise ? 1 : 7)) % 8;
+
+        tx = x + xdir[i], ty = y + ydir[i]; /* current target location */
+        if (!isok(tx, ty))
+            continue;
+        mtmp = m_at(tx, ty);
+        if (!mtmp) {
+            if (glyph_is_invisible(levl[tx][ty].glyph))
+                (void) unmap_invisible(tx, ty);
+            continue;
+        }
+
+        tmp = find_roll_to_hit(mtmp, uattk->aatyp, uwep,
+                               &attknum, &armorpenalty);
+        dieroll = rnd(20);
+        mhit = (tmp > dieroll);
+        (void) known_hitum(mtmp, uwep, &mhit, tmp, armorpenalty,
+                           uattk, dieroll);
+        (void) passive(mtmp, uwep, mhit, !DEADMONSTER(mtmp), AT_WEAP, !uwep);
+
+        /* stop attacking if weapon is gone or hero got killed and
+           life-saved after passive counter-attack */
+        if (!uwep || u.umortality > umort)
+            break;
+    }
+    /* set up for next time */
+    clockwise = !clockwise; /* alternate */
+
+    /* return False if primary target died, True otherwise; note: if 'target'
+       was nonNull upon entry then it's still nonNull even if *target died */
+    return (target && DEADMONSTER(target)) ? FALSE : TRUE;
+}
+
 /* hit target monster; returns TRUE if it still lives */
 STATIC_OVL boolean
 hitum(mon, uattk)
@@ -547,38 +627,53 @@ struct attack *uattk;
     int armorpenalty, attknum = 0, x = u.ux + u.dx, y = u.uy + u.dy,
                       tmp = find_roll_to_hit(mon, uattk->aatyp, uwep,
                                              &attknum, &armorpenalty);
-    int mhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
+    int dieroll = rnd(20);
+    int mhit = (tmp > dieroll || u.uswallow);
+
+    /* Cleaver attacks three spots, 'mon' and one on either side of 'mon';
+       it can't be part of dual-wielding but we guard against that anyway;
+       cleave return value reflects status of primary target ('mon') */
+    if (uwep && uwep->oartifact == ART_CLEAVER && !u.twoweap
+        && !u.uswallow && !u.ustuck && !NODIAG(u.umonnum))
+        return hitum_cleave(mon, uattk);
 
     if (tmp > dieroll)
         exercise(A_DEX, TRUE);
-    malive = known_hitum(mon, uwep, &mhit, tmp, armorpenalty, uattk);
+    malive = known_hitum(mon, uwep, &mhit, tmp, armorpenalty, uattk, dieroll);
+    if (wepbefore && !uwep)
+        wep_was_destroyed = TRUE;
+    (void) passive(mon, uwep, mhit, malive, AT_WEAP, wep_was_destroyed);
+
     /* second attack for two-weapon combat; won't occur if Stormbringer
        overrode confirmation (assumes Stormbringer is primary weapon)
        or if the monster was killed or knocked to different location */
     if (u.twoweap && !override_confirmation && malive && m_at(x, y) == mon) {
         tmp = find_roll_to_hit(mon, uattk->aatyp, uswapwep, &attknum,
                                &armorpenalty);
-        mhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
-        malive = known_hitum(mon, uswapwep, &mhit, tmp, armorpenalty, uattk);
+        dieroll = rnd(20);
+        mhit = (tmp > dieroll || u.uswallow);
+        malive = known_hitum(mon, uswapwep, &mhit, tmp, armorpenalty, uattk,
+                             dieroll);
+        /* second passive counter-attack only occurs if second attack hits */
+        if (mhit)
+            (void) passive(mon, uswapwep, mhit, malive, AT_WEAP, !uswapwep);
     }
-    if (wepbefore && !uwep)
-        wep_was_destroyed = TRUE;
-    (void) passive(mon, mhit, malive, AT_WEAP, wep_was_destroyed);
     return malive;
 }
 
 /* general "damage monster" routine; return True if mon still alive */
 boolean
-hmon(mon, obj, thrown)
+hmon(mon, obj, thrown, dieroll)
 struct monst *mon;
 struct obj *obj;
 int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
+int dieroll;
 {
     boolean result, anger_guards;
 
     anger_guards = (mon->mpeaceful
                     && (mon->ispriest || mon->isshk || is_watch(mon->data)));
-    result = hmon_hitmon(mon, obj, thrown);
+    result = hmon_hitmon(mon, obj, thrown, dieroll);
     if (mon->ispriest && !rn2(2))
         ghod_hitsu(mon);
     if (anger_guards)
@@ -588,10 +683,11 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
 
 /* guts of hmon() */
 STATIC_OVL boolean
-hmon_hitmon(mon, obj, thrown)
+hmon_hitmon(mon, obj, thrown, dieroll)
 struct monst *mon;
 struct obj *obj;
 int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
+int dieroll;
 {
     int tmp;
     struct permonst *mdat = mon->data;
@@ -621,7 +717,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
     unconventional[0] = '\0';
     saved_oname[0] = '\0';
 
-    wakeup(mon);
+    wakeup(mon, TRUE);
     if (!obj) { /* attack with bare hands */
         if (mdat == &mons[PM_SHADE])
             tmp = 0;
@@ -699,7 +795,10 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
                 tmp = dmgval(obj, mon);
                 /* a minimal hit doesn't exercise proficiency */
                 valid_weapon_attack = (tmp > 1);
-                if (!valid_weapon_attack || mon == u.ustuck || u.twoweap) {
+                if (!valid_weapon_attack || mon == u.ustuck || u.twoweap
+                    /* Cleaver can hit up to three targets at once so don't
+                       let it also hit from behind or shatter foes' weapons */
+                    || (hand_to_hand && obj->oartifact == ART_CLEAVER)) {
                     ; /* no special bonuses */
                 } else if (mon->mflee && Role_if(PM_ROGUE) && !Upolyd
                            /* multi-shot throwing is too powerful here */
@@ -719,15 +818,19 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
                                && P_SKILL(wtype) >= P_SKILLED)
                            && ((monwep = MON_WEP(mon)) != 0
                                && !is_flimsy(monwep)
-                               && !obj_resists(
-                                      monwep, 50 + 15 * greatest_erosion(obj),
-                                      100))) {
+                               && !obj_resists(monwep,
+                                       50 + 15 * (greatest_erosion(obj)
+                                                  - greatest_erosion(monwep)),
+                                               100))) {
                     /*
                      * 2.5% chance of shattering defender's weapon when
                      * using a two-handed weapon; less if uwep is rusted.
                      * [dieroll == 2 is most successful non-beheading or
                      * -bisecting hit, in case of special artifact damage;
                      * the percentage chance is (1/20)*(50/100).]
+                     * If attacker's weapon is rustier than defender's,
+                     * the obj_resists chance is increased so the shatter
+                     * chance is decreased; if less rusty, then vice versa.
                      */
                     setmnotwielded(mon, monwep);
                     mon->weapon_check = NEED_WEAPON;
@@ -789,7 +892,8 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
             else
                 setuwep((struct obj *) 0);
             freeinv(obj);
-            potionhit(mon, obj, TRUE);
+            potionhit(mon, obj,
+                      hand_to_hand ? POTHIT_HERO_BASH : POTHIT_HERO_THROW);
             if (mon->mhp <= 0)
                 return FALSE; /* killed */
             hittxt = TRUE;
@@ -999,7 +1103,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
                                 whom = strcat(strcat(s_suffix(whom), " "),
                                               mbodypart(mon, FACE));
 #else
-                                whom = strcat(strcat(s_suffix(whom), "\82Ì"),
+                                whom = strcat(s_suffix(whom),
                                               mbodypart(mon, FACE));
 #endif
 #if 0 /*JP*/
@@ -1010,7 +1114,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
                                   what, whom);
 #endif
                         }
-                        setmangry(mon);
+                        setmangry(mon, TRUE);
                         mon->mcansee = 0;
                         tmp = rn1(25, 21);
                         if (((int) mon->mblinded + tmp) > 127)
@@ -1022,7 +1126,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
                         pline(obj->otyp == CREAM_PIE ? "Splat!" : "Splash!");
 */
                         pline(obj->otyp==CREAM_PIE ? "\83r\83V\83\83\83b\81I" : "\83s\83`\83\83\83b\81I");
-                        setmangry(mon);
+                        setmangry(mon, TRUE);
                     }
                     if (thrown)
                         obfree(obj, (struct obj *) 0);
@@ -1232,14 +1336,28 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
     if ((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
         /* pudding is alive and healthy enough to split */
         && mon->mhp > 1 && !mon->mcan
-        /* iron weapon using melee or polearm hit */
-        && obj && obj == uwep && objects[obj->otyp].oc_material == IRON
+        /* iron weapon using melee or polearm hit [3.6.1: metal weapon too;
+           also allow either or both weapons to cause split when twoweap] */
+        && obj && (obj == uwep || (u.twoweap && obj == uswapwep))
+        && ((objects[obj->otyp].oc_material == IRON
+             /* allow scalpel and tsurugi to split puddings */
+             || objects[obj->otyp].oc_material == METAL)
+            /* but not bashing with darts, arrows or ya */
+            && !(is_ammo(obj) || is_missile(obj)))
         && hand_to_hand) {
         if (clone_mon(mon, 0, 0)) {
-/*JP
-            pline("%s divides as you hit it!", Monnam(mon));
-*/
-            pline("\82 \82È\82½\82Ì\8dU\8c\82\82Å%s\82Í\95ª\97ô\82µ\82½\81I", Monnam(mon));
+            char withwhat[BUFSZ];
+
+            withwhat[0] = '\0';
+#if 0 /*JP*/
+            if (u.twoweap && flags.verbose)
+                Sprintf(withwhat, " with %s", yname(obj));
+            pline("%s divides as you hit it%s!", Monnam(mon), withwhat);
+#else
+            if (u.twoweap && flags.verbose)
+                Sprintf(withwhat, "%s\82Å\82Ì", yname(obj));
+            pline("\82 \82È\82½\82Ì%s\8dU\8c\82\82Å%s\82Í\95ª\97ô\82µ\82½\81I", withwhat, Monnam(mon));
+#endif
             hittxt = TRUE;
         }
     }
@@ -1281,8 +1399,10 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
 */
                 fmt = "%s\82Í\8bâ\82Ì\8ew\97Ö\82Å\8fÄ\82©\82ê\82½\81I";
             else if (silverobj && saved_oname[0]) {
+                /* guard constructed format string against '%' in
+                   saved_oname[] from xname(via cxname()) */
 #if 0 /*JP*/
-                Sprintf(silverobjbuf, "Your %s%s %s %%s!",
+                Sprintf(silverobjbuf, "Your %s%s %s",
                         strstri(saved_oname, "silver") ? "" : "silver ",
                         saved_oname, vtense(saved_oname, "sear"));
 #else
@@ -1291,6 +1411,8 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
                         "" : "\8bâ\82Ì",
                         saved_oname);
 #endif
+                (void) strNsubst(silverobjbuf, "%", "%%", 0);
+                Strcat(silverobjbuf, " %s!");
                 fmt = silverobjbuf;
             } else
 /*JP
@@ -1309,7 +1431,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
 /*JP
             whom = strcat(s_suffix(whom), " flesh");
 */
-            whom = strcat(s_suffix(whom), "\82Ì\93÷");
+            whom = strcat(s_suffix(whom), "\93÷");
         pline(fmt, whom);
     }
     /* if a "no longer poisoned" message is coming, it will be last;
@@ -1332,7 +1454,7 @@ int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
 */
         pline("\93Å\82Í\92v\8e\80\97Ê\82¾\82Á\82½\81D\81D\81D");
         if (!already_killed)
-            xkilled(mon, 0);
+            xkilled(mon, XKILL_NOMSG);
         destroyed = TRUE; /* return FALSE; */
     } else if (destroyed) {
         if (!already_killed)
@@ -1699,13 +1821,17 @@ register struct attack *mattk;
             pline("%s is %s!", Monnam(mdef), on_fire(pd, mattk));
 */
             pline("%s\82Í%s\81I", Monnam(mdef), on_fire(mdef->data, mattk));
-        if (pd == &mons[PM_STRAW_GOLEM] || pd == &mons[PM_PAPER_GOLEM]) {
+        if (completelyburns(pd)) { /* paper golem or straw golem */
             if (!Blind)
 /*JP
                 pline("%s burns completely!", Monnam(mdef));
 */
                 pline("%s\82Í\8a®\91S\82É\94R\82¦\90s\82«\82½\81I", Monnam(mdef));
-            xkilled(mdef, 2);
+            else
+                You("smell burning%s.",
+                    (pd == &mons[PM_PAPER_GOLEM]) ? " paper"
+                      : (pd == &mons[PM_STRAW_GOLEM]) ? " straw" : "");
+            xkilled(mdef, XKILL_NOMSG | XKILL_NOCORPSE);
             tmp = 0;
             break;
             /* Don't return yet; keep hp<1 and tmp=0 for pet msg */
@@ -1848,12 +1974,14 @@ register struct attack *mattk;
         if (night() && !rn2(10) && !mdef->mcan) {
             if (pd == &mons[PM_CLAY_GOLEM]) {
                 if (!Blind)
-/*JP
+#if 0 /*JP*/
                     pline("Some writing vanishes from %s head!",
-*/
-                    pline("%s\82Ì\93ª\82É\8f\91\82¢\82Ä\82 \82é\95\8e\9a\82Ì\82¢\82­\82Â\82©\82ª\8fÁ\82¦\82½\81I",
                           s_suffix(mon_nam(mdef)));
-                xkilled(mdef, 0);
+#else
+                    pline("%s\82Ì\93ª\82É\8f\91\82¢\82Ä\82 \82é\95\8e\9a\82Ì\82¢\82­\82Â\82©\82ª\8fÁ\82¦\82½\81I",
+                          mon_nam(mdef));
+#endif
+                xkilled(mdef, XKILL_NOMSG);
                 /* Don't return yet; keep hp<1 and tmp=0 for pet msg */
             } else {
                 mdef->mcan = 1;
@@ -1868,17 +1996,21 @@ register struct attack *mattk;
     case AD_DRLI:
         if (!negated && !rn2(3) && !resists_drli(mdef)) {
             int xtmp = d(2, 6);
+
 /*JP
             pline("%s suddenly seems weaker!", Monnam(mdef));
 */
             pline("%s\82Í\93Ë\91R\8eã\82­\82È\82Á\82½\82æ\82¤\82É\8c©\82¦\82½\81I", Monnam(mdef));
             mdef->mhpmax -= xtmp;
-            if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev) {
+            mdef->mhp -= xtmp;
+            /* !m_lev: level 0 monster is killed regardless of hit points
+               rather than drop to level -1 */
+            if (mdef->mhp <= 0 || !mdef->m_lev) {
 /*JP
                 pline("%s dies!", Monnam(mdef));
 */
                 pline("%s\82Í\8e\80\82ñ\82¾\81I", Monnam(mdef));
-                xkilled(mdef, 0);
+                xkilled(mdef, XKILL_NOMSG);
             } else
                 mdef->m_lev--;
             tmp = 0;
@@ -1890,7 +2022,7 @@ register struct attack *mattk;
             pline("%s falls to pieces!", Monnam(mdef));
 */
             pline("%s\82Í\83o\83\89\83o\83\89\82É\82È\82Á\82½\81I", Monnam(mdef));
-            xkilled(mdef, 0);
+            xkilled(mdef, XKILL_NOMSG);
         }
         erode_armor(mdef, ERODE_RUST);
         tmp = 0;
@@ -1905,7 +2037,7 @@ register struct attack *mattk;
             pline("%s falls to pieces!", Monnam(mdef));
 */
             pline("%s\82Í\83o\83\89\83o\83\89\82É\82È\82Á\82½\81I", Monnam(mdef));
-            xkilled(mdef, 0);
+            xkilled(mdef, XKILL_NOMSG);
         }
         erode_armor(mdef, ERODE_ROT);
         tmp = 0;
@@ -2094,21 +2226,22 @@ register struct attack *mattk;
     }
 
     mdef->mstrategy &= ~STRAT_WAITFORU; /* in case player is very fast */
-    if ((mdef->mhp -= tmp) < 1) {
+    mdef->mhp -= tmp;
+    if (mdef->mhp < 1) {
         if (mdef->mtame && !cansee(mdef->mx, mdef->my)) {
 /*JP
             You_feel("embarrassed for a moment.");
 */
             You("\82µ\82Î\82ç\82­\8d¢\98f\82µ\82½\81D");
             if (tmp)
-                xkilled(mdef, 0); /* !tmp but hp<1: already killed */
+                xkilled(mdef, XKILL_NOMSG); /* !tmp but hp<1: already killed */
         } else if (!flags.verbose) {
 /*JP
             You("destroy it!");
 */
             You("\93|\82µ\82½\81I");
             if (tmp)
-                xkilled(mdef, 0);
+                xkilled(mdef, XKILL_NOMSG);
         } else if (tmp)
             killed(mdef);
         return 2;
@@ -2242,6 +2375,18 @@ register struct attack *mattk;
         for (otmp = mdef->minvent; otmp; otmp = otmp->nobj)
             (void) snuff_lit(otmp);
 
+        /* force vampire in bat, cloud, or wolf form to revert back to
+           vampire form now instead of dealing with that when it dies */
+        if (is_vampshifter(mdef)
+            && newcham(mdef, &mons[mdef->cham], FALSE, FALSE)) {
+            You("engulf it, then expel it.");
+            if (canspotmon(mdef))
+                pline("It turns into %s.", a_monnam(mdef));
+            else
+                map_invisible(mdef->mx, mdef->my);
+            return 1;
+        }
+
         /* engulfing a cockatrice or digesting a Rider or Medusa */
         fatal_gulp = (touch_petrifies(pd) && !Stone_resistance)
                      || (mattk->adtyp == AD_DGST
@@ -2300,7 +2445,13 @@ register struct attack *mattk;
                     m_useup(mdef, otmp);
 
                 newuhs(FALSE);
-                xkilled(mdef, 2);
+                /* start_engulf() issues "you engulf <mdef>" above; this
+                   used to specify XKILL_NOMSG but we need "you kill <mdef>"
+                   in case we're also going to get "welcome to level N+1";
+                   "you totally digest <mdef>" will be coming soon (after
+                   several turns) but the level-gain message seems out of
+                   order if the kill message is left implicit */
+                xkilled(mdef, XKILL_GIVEMSG | XKILL_NOCORPSE);
                 if (mdef->mhp > 0) { /* monster lifesaved */
 /*JP
                     You("hurriedly regurgitate the sizzling in your %s.",
@@ -2460,7 +2611,8 @@ register struct attack *mattk;
                 break;
             }
             end_engulf();
-            if ((mdef->mhp -= dam) <= 0) {
+            mdef->mhp -= dam;
+            if (mdef->mhp <= 0) {
                 killed(mdef);
                 if (mdef->mhp <= 0) /* not lifesaved */
                     return 2;
@@ -2473,11 +2625,13 @@ register struct attack *mattk;
                 is_animal(youmonst.data) ? "\93f\82«\96ß" : "\94r\8fo");
 #endif
             if (Slow_digestion || is_animal(youmonst.data)) {
-/*JP
+#if 0 /*JP*/
                 pline("Obviously, you didn't like %s taste.",
-*/
-                pline("\82Ç\82¤\82à%s\82Ì\96¡\82Í\8dD\82«\82É\82È\82ê\82È\82¢\81D",
                       s_suffix(mon_nam(mdef)));
+#else
+                pline("\82Ç\82¤\82à%s\82Ì\96¡\82Í\8dD\82«\82É\82È\82ê\82È\82¢\81D",
+                      mon_nam(mdef));
+#endif
             }
         }
     }
@@ -2512,7 +2666,7 @@ boolean wouldhavehit;
 */
         Your("\89½\8eÒ\82©\82Ö\82Ì\8dU\8c\82\82Í\8aO\82ê\82½\81D");
     if (!mdef->msleeping && mdef->mcanmove)
-        wakeup(mdef);
+        wakeup(mdef, TRUE);
 }
 
 /* attack monster as a monster. */
@@ -2521,13 +2675,15 @@ hmonas(mon)
 register struct monst *mon;
 {
     struct attack *mattk, alt_attk;
-    struct obj *weapon;
+    struct obj *weapon, **originalweapon;
     boolean altwep = FALSE, weapon_used = FALSE;
     int i, tmp, armorpenalty, sum[NATTK], nsum = 0, dhit = 0, attknum = 0;
+    int dieroll;
 
     for (i = 0; i < NATTK; i++) {
         sum[i] = 0;
-        mattk = getmattk(youmonst.data, i, sum, &alt_attk);
+        mattk = getmattk(&youmonst, mon, i, sum, &alt_attk);
+        weapon = 0;
         switch (mattk->aatyp) {
         case AT_WEAP:
         use_weapon:
@@ -2542,18 +2698,36 @@ register struct monst *mon;
              * we currently allow the player to get each of these as a weapon
              * attack.  Is this really desirable?
              */
-            /* approximate two-weapon mode */
-            weapon = (altwep && uswapwep) ? uswapwep : uwep;
-            altwep = !altwep; /* toggle for next attack */
+            /* approximate two-weapon mode; known_hitum() -> hmon() -> &c
+               might destroy the weapon argument, but it might also already
+               be Null, and we want to track that for passive() */
+            originalweapon = (altwep && uswapwep) ? &uswapwep : &uwep;
+            if (uswapwep /* set up 'altwep' flag for next iteration */
+                /* only switch to uswapwep if it's a weapon */
+                && (uswapwep->oclass == WEAPON_CLASS || is_weptool(uswapwep))
+                /* only switch if uswapwep is not bow, arrows, or darts */
+                && !(is_launcher(uswapwep) || is_ammo(uswapwep)
+                     || is_missile(uswapwep))) /* dart, shuriken, boomerang */
+                altwep = !altwep; /* toggle for next attack */
+            weapon = *originalweapon;
+            if (!weapon) /* no need to go beyond no-gloves to rings; not ...*/
+                originalweapon = &uarmg; /*... subject to erosion damage */
+
             tmp = find_roll_to_hit(mon, AT_WEAP, weapon, &attknum,
                                    &armorpenalty);
-            dhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
+            dieroll = rnd(20);
+            dhit = (tmp > dieroll || u.uswallow);
             /* Enemy dead, before any special abilities used */
-            if (!known_hitum(mon, weapon, &dhit, tmp, armorpenalty, mattk)) {
+            if (!known_hitum(mon, weapon, &dhit, tmp,
+                             armorpenalty, mattk, dieroll)) {
                 sum[i] = 2;
                 break;
             } else
                 sum[i] = dhit;
+            /* originalweapon points to an equipment slot which might
+               now be empty if the weapon was destroyed during the hit;
+               passive(,weapon,...) won't call passive_obj() in that case */
+            weapon = *originalweapon; /* might receive passive erosion */
             /* might be a worm that gets cut in half */
             if (m_at(u.ux + u.dx, u.uy + u.dy) != mon)
                 return (boolean) (nsum != 0);
@@ -2578,7 +2752,8 @@ register struct monst *mon;
         case AT_TENT:
             tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0,
                                    &attknum, &armorpenalty);
-            dhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
+            dieroll = rnd(20);
+            dhit = (tmp > dieroll || u.uswallow);
             if (dhit) {
                 int compat;
 
@@ -2601,7 +2776,7 @@ register struct monst *mon;
                     sum[i] = damageum(mon, mattk);
                     break;
                 }
-                wakeup(mon);
+                wakeup(mon, TRUE);
                 /* maybe this check should be in damageum()? */
                 if (mon->data == &mons[PM_SHADE]
                     && !(mattk->aatyp == AT_KICK && uarmf
@@ -2659,7 +2834,7 @@ register struct monst *mon;
              * already grabbed in a previous attack
              */
             dhit = 1;
-            wakeup(mon);
+            wakeup(mon, TRUE);
             if (mon->data == &mons[PM_SHADE])
 /*JP
                 Your("hug passes harmlessly through %s.", mon_nam(mon));
@@ -2689,7 +2864,7 @@ register struct monst *mon;
 
         case AT_EXPL: /* automatic hit if next to */
             dhit = -1;
-            wakeup(mon);
+            wakeup(mon, TRUE);
             sum[i] = explum(mon, mattk);
             break;
 
@@ -2697,7 +2872,7 @@ register struct monst *mon;
             tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0,
                                    &attknum, &armorpenalty);
             if ((dhit = (tmp > rnd(20 + i)))) {
-                wakeup(mon);
+                wakeup(mon, TRUE);
                 if (mon->data == &mons[PM_SHADE])
 /*JP
                     Your("attempt to surround %s is harmless.", mon_nam(mon));
@@ -2728,6 +2903,7 @@ register struct monst *mon;
                  || youmonst.data->mlet == S_ORC
                  || youmonst.data->mlet == S_GNOME) && !weapon_used)
                 goto use_weapon;
+            /*FALLTHRU*/
 
         case AT_NONE:
         case AT_BOOM:
@@ -2747,11 +2923,11 @@ register struct monst *mon;
             u.mh = -1; /* dead in the current form */
             rehumanize();
         }
-        if (sum[i] == 2)
-            return (boolean) passive(mon, 1, 0, mattk->aatyp, FALSE);
-        /* defender dead */
-        else {
-            (void) passive(mon, sum[i], 1, mattk->aatyp, FALSE);
+        if (sum[i] == 2) {
+            /* defender dead */
+            return (boolean) passive(mon, weapon, 1, 0, mattk->aatyp, FALSE);
+        else {
+            (void) passive(mon, weapon, sum[i], 1, mattk->aatyp, FALSE);
             nsum |= sum[i];
         }
         if (!Upolyd)
@@ -2765,10 +2941,11 @@ register struct monst *mon;
 /*      Special (passive) attacks on you by monsters done here.
  */
 int
-passive(mon, mhit, malive, aatyp, wep_was_destroyed)
-register struct monst *mon;
-register boolean mhit;
-register int malive;
+passive(mon, weapon, mhit, malive, aatyp, wep_was_destroyed)
+struct monst *mon;
+struct obj *weapon; /* uwep or uswapwep or uarmg or uarmf or Null */
+boolean mhit;
+int malive;
 uchar aatyp;
 boolean wep_was_destroyed;
 {
@@ -2793,14 +2970,14 @@ boolean wep_was_destroyed;
      */
     switch (ptr->mattk[i].adtyp) {
     case AD_FIRE:
-        if (mhit && !mon->mcan) {
+        if (mhit && !mon->mcan && weapon) {
             if (aatyp == AT_KICK) {
                 if (uarmf && !rn2(6))
                     (void) erode_obj(uarmf, xname(uarmf), ERODE_BURN,
                                      EF_GREASE | EF_VERBOSE);
             } else if (aatyp == AT_WEAP || aatyp == AT_CLAW
                        || aatyp == AT_MAGC || aatyp == AT_TUCH)
-                passive_obj(mon, (struct obj *) 0, &(ptr->mattk[i]));
+                passive_obj(mon, weapon, &(ptr->mattk[i]));
         }
         break;
     case AD_ACID:
@@ -2811,24 +2988,27 @@ boolean wep_was_destroyed;
 */
                 You("\89½\82©\82ð\97\81\82Ñ\82¹\82ç\82ê\82½\81I");
             else
-/*JP
-                You("are splashed by %s acid!", s_suffix(mon_nam(mon)));
-*/
-                You("%s\82Ì\8e_\82ð\97\81\82Ñ\82¹\82ç\82ê\82½\81I", s_suffix(mon_nam(mon)));
+#if 0 /*JP:T*/
+                You("are splashed by %s %s!", s_suffix(mon_nam(mon)),
+                    hliquid("acid"));
+#else
+                You("%s\82Ì%s\82ð\97\81\82Ñ\82¹\82ç\82ê\82½\81I", mon_nam(mon),
+                    hliquid("\8e_"));
+#endif
 
             if (!Acid_resistance)
                 mdamageu(mon, tmp);
             if (!rn2(30))
                 erode_armor(&youmonst, ERODE_CORRODE);
         }
-        if (mhit) {
+        if (mhit && weapon) {
             if (aatyp == AT_KICK) {
                 if (uarmf && !rn2(6))
                     (void) erode_obj(uarmf, xname(uarmf), ERODE_CORRODE,
                                      EF_GREASE | EF_VERBOSE);
             } else if (aatyp == AT_WEAP || aatyp == AT_CLAW
                        || aatyp == AT_MAGC || aatyp == AT_TUCH)
-                passive_obj(mon, (struct obj *) 0, &(ptr->mattk[i]));
+                passive_obj(mon, weapon, &(ptr->mattk[i]));
         }
         exercise(A_STR, FALSE);
         break;
@@ -2857,25 +3037,25 @@ boolean wep_was_destroyed;
         }
         break;
     case AD_RUST:
-        if (mhit && !mon->mcan) {
+        if (mhit && !mon->mcan && weapon) {
             if (aatyp == AT_KICK) {
                 if (uarmf)
                     (void) erode_obj(uarmf, xname(uarmf), ERODE_RUST,
                                      EF_GREASE | EF_VERBOSE);
             } else if (aatyp == AT_WEAP || aatyp == AT_CLAW
                        || aatyp == AT_MAGC || aatyp == AT_TUCH)
-                passive_obj(mon, (struct obj *) 0, &(ptr->mattk[i]));
+                passive_obj(mon, weapon, &(ptr->mattk[i]));
         }
         break;
     case AD_CORR:
-        if (mhit && !mon->mcan) {
+        if (mhit && !mon->mcan && weapon) {
             if (aatyp == AT_KICK) {
                 if (uarmf)
                     (void) erode_obj(uarmf, xname(uarmf), ERODE_CORRODE,
                                      EF_GREASE | EF_VERBOSE);
             } else if (aatyp == AT_WEAP || aatyp == AT_CLAW
                        || aatyp == AT_MAGC || aatyp == AT_TUCH)
-                passive_obj(mon, (struct obj *) 0, &(ptr->mattk[i]));
+                passive_obj(mon, weapon, &(ptr->mattk[i]));
         }
         break;
     case AD_MAGM:
@@ -2896,17 +3076,14 @@ boolean wep_was_destroyed;
         break;
     case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
         if (mhit) {
-            struct obj *obj = (struct obj *) 0;
-
             if (aatyp == AT_KICK) {
-                obj = uarmf;
-                if (!obj)
+                if (!weapon)
                     break;
             } else if (aatyp == AT_BITE || aatyp == AT_BUTT
                        || (aatyp >= AT_STNG && aatyp < AT_WEAP)) {
                 break; /* no object involved */
             }
-            passive_obj(mon, obj, &(ptr->mattk[i]));
+            passive_obj(mon, weapon, &(ptr->mattk[i]));
         }
         break;
     default:
@@ -2923,18 +3100,22 @@ boolean wep_was_destroyed;
                     break;
                 }
                 if (mon->mcansee) {
-/*JP
+#if 0 /*JP*/
                     if (ureflects("%s gaze is reflected by your %s.",
-*/
-                    if (ureflects("%s\82Ì\82É\82ç\82Ý\82Í%s\82É\82æ\82Á\82Ä\94½\8eË\82³\82ê\82½\81D",
                                   s_suffix(Monnam(mon)))) {
+#else
+                    if (ureflects("%s\82Ì\82É\82ç\82Ý\82Í%s\82É\82æ\82Á\82Ä\94½\8eË\82³\82ê\82½\81D",
+                                  Monnam(mon))) {
+#endif
                         ;
                     } else if (Free_action) {
-/*JP
+#if 0 /*JP*/
                         You("momentarily stiffen under %s gaze!",
-*/
-                        You("%s\82Ì\82É\82ç\82Ý\82Å\88ê\8fu\8dd\92¼\82µ\82½\81I",
                             s_suffix(mon_nam(mon)));
+#else
+                        You("%s\82Ì\82É\82ç\82Ý\82Å\88ê\8fu\8dd\92¼\82µ\82½\81I",
+                            mon_nam(mon));
+#endif
                     } else if (Hallucination && rn2(4)) {
 #if 0 /*JP*/
                         pline("%s looks %s%s.", Monnam(mon),
@@ -3062,13 +3243,14 @@ boolean wep_was_destroyed;
  */
 void
 passive_obj(mon, obj, mattk)
-register struct monst *mon;
-register struct obj *obj; /* null means pick uwep, uswapwep or uarmg */
+struct monst *mon;
+struct obj *obj;          /* null means pick uwep, uswapwep or uarmg */
 struct attack *mattk;     /* null means we find one internally */
 {
     struct permonst *ptr = mon->data;
-    register int i;
+    int i;
 
+    /* [this first bit is obsolete; we're not called with Null anymore] */
     /* if caller hasn't specified an object, use uwep, uswapwep or uarmg */
     if (!obj) {
         obj = (u.twoweap && uswapwep && !rn2(2)) ? uswapwep : uwep;
@@ -3091,28 +3273,30 @@ struct attack *mattk;     /* null means we find one internally */
 
     switch (mattk->adtyp) {
     case AD_FIRE:
-        if (!rn2(6) && !mon->mcan) {
+        if (!rn2(6) && !mon->mcan
+            /* steam vortex: fire resist applies, fire damage doesn't */
+            && mon->data != &mons[PM_STEAM_VORTEX]) {
             (void) erode_obj(obj, NULL, ERODE_BURN, EF_NONE);
         }
         break;
     case AD_ACID:
         if (!rn2(6)) {
-            (void) erode_obj(obj, NULL, ERODE_CORRODE, EF_NONE);
+            (void) erode_obj(obj, NULL, ERODE_CORRODE, EF_GREASE);
         }
         break;
     case AD_RUST:
         if (!mon->mcan) {
-            (void) erode_obj(obj, NULL, ERODE_RUST, EF_NONE);
+            (void) erode_obj(obj, (char *) 0, ERODE_RUST, EF_GREASE);
         }
         break;
     case AD_CORR:
         if (!mon->mcan) {
-            (void) erode_obj(obj, NULL, ERODE_CORRODE, EF_NONE);
+            (void) erode_obj(obj, (char *) 0, ERODE_CORRODE, EF_GREASE);
         }
         break;
     case AD_ENCH:
         if (!mon->mcan) {
-            if (drain_item(obj) && carried(obj)
+            if (drain_item(obj, TRUE) && carried(obj)
                 && (obj->known || obj->oclass == ARMOR_CLASS)) {
 /*JP
                 pline("%s less effective.", Yobjnam2(obj, "seem"));
@@ -3172,7 +3356,7 @@ struct monst *mtmp;
     if (what)
         pline(fmt, what);
 
-    wakeup(mtmp); /* clears mimicking */
+    wakeup(mtmp, FALSE); /* clears mimicking */
     /* if hero is blind, wakeup() won't display the monster even though
        it's no longer concealed */
     if (!canspotmon(mtmp)
@@ -3248,7 +3432,7 @@ struct obj *otmp; /* source of flash */
             }
             if (mtmp->mhp > 0) {
                 if (!context.mon_moving)
-                    setmangry(mtmp);
+                    setmangry(mtmp, TRUE);
                 if (tmp < 9 && !mtmp->isshk && rn2(4))
                     monflee(mtmp, rn2(4) ? rnd(100) : 0, FALSE, TRUE);
                 mtmp->mcansee = 0;
@@ -3271,7 +3455,9 @@ int dmg;
     pline("%s\82Í%s\81I", Monnam(mon),
           (dmg > mon->mhp / 2) ? "\8bê\92É\82Ì\90º\82ð\82 \82°\82½" : "\8c\83\92É\82Å\8b©\82ñ\82¾");
 #endif
-    if ((mon->mhp -= dmg) <= 0) {
+    mon->mhp -= dmg;
+    wake_nearto(mon->mx, mon->my, 30);
+    if (mon->mhp <= 0) {
         if (context.mon_moving)
             monkilled(mon, (char *) 0, AD_BLND);
         else
index 89b34a9..509b8da 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 vault.c $NHDT-Date: 1446078792 2015/10/29 00:33:12 $  $NHDT-Branch: master $:$NHDT-Revision: 1.39 $ */
+/* NetHack 3.6 vault.c $NHDT-Date: 1452132199 2016/01/07 02:03:19 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.42 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -202,6 +203,13 @@ findgd()
     return (struct monst *) 0;
 }
 
+void
+vault_summon_gd()
+{
+    if (vault_occupied(u.urooms) && !findgd())
+        u.uinvault = (VAULT_GUARD_TIME - 1);
+}
+
 char
 vault_occupied(array)
 char *array;
@@ -232,8 +240,9 @@ invault()
     vaultroom -= ROOMOFFSET;
 
     guard = findgd();
-    if (++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */
-        char buf[BUFSZ];
+    if (++u.uinvault % VAULT_GUARD_TIME == 0 && !guard) {
+        /* if time ok and no guard now. */
+        char buf[BUFSZ] = DUMMY;
         register int x, y, dd, gx, gy;
         int lx = 0, ly = 0;
         long umoney;
@@ -361,9 +370,9 @@ invault()
         if (u.uswallow) {
             /* can't interrogate hero, don't interrogate engulfer */
 /*JP
-            verbalize("What's going on here?");
+            if (!Deaf) verbalize("What's going on here?");
 */
-            verbalize("\82±\82±\82Å\89½\82ð\82µ\82Ä\82¢\82é\82ñ\82¾\81H");
+            if (!Deaf) verbalize("\82±\82±\82Å\89½\82ð\82µ\82Ä\82¢\82é\82ñ\82¾\81H");
             if (gsensed)
 /*JP
                 pline_The("other presence vanishes.");
@@ -375,11 +384,13 @@ invault()
         if (youmonst.m_ap_type == M_AP_OBJECT || u.uundetected) {
             if (youmonst.m_ap_type == M_AP_OBJECT
                 && youmonst.mappearance != GOLD_PIECE)
-/*JP
-                verbalize("Hey! Who left that %s in here?",
-*/
-                verbalize("\82¨\82¢\81I\82¾\82ê\82ª\82±\82Ì%s\82ð\82±\82±\82É\92u\82¢\82Ä\8ds\82Á\82½\82ñ\82¾\81H",
-                          mimic_obj_name(&youmonst));
+#if 0 /*JP*/
+                if (!Deaf) verbalize("Hey! Who left that %s in here?",
+                                    mimic_obj_name(&youmonst));
+#else
+                if (!Deaf) verbalize("\82¨\82¢\81I\82¾\82ê\82ª\82±\82Ì%s\82ð\82±\82±\82É\92u\82¢\82Ä\8ds\82Á\82½\82ñ\82¾\81H",
+                                    mimic_obj_name(&youmonst));
+#endif
             /* You're mimicking some object or you're hidden. */
 /*JP
             pline("Puzzled, %s turns around and leaves.", mhe(guard));
@@ -392,6 +403,9 @@ invault()
             /* [we ought to record whether this this message has already
                been given in order to vary it upon repeat visits, but
                discarding the monster and its egd data renders that hard] */
+            if (Deaf)
+                pline("%s huffs and turns to leave.", noit_Monnam(guard));
+            else
 /*JP
             verbalize("I'll be back when you're ready to speak to me!");
 */
@@ -407,15 +421,18 @@ invault()
         }
         trycount = 5;
         do {
-/*JP
-            getlin("\"Hello stranger, who are you?\" -", buf);
-*/
-            getlin("\81u\8c©\82È\82¢\8aç\82¾\82È\81C\82¨\82Ü\82¦\82Í\92N\82¾\81H\81v-", buf);
+#if 0 /*JP*/
+            getlin(Deaf ? "You are required to supply your name. -"
+                        : "\"Hello stranger, who are you?\" -", buf);
+#else
+            getlin(Deaf ? "\96¼\91O\82ð\8c¾\82¤\82æ\82¤\82É\8b\81\82ß\82ç\82ê\82½\81D-"
+                        : "\81u\8c©\82È\82¢\8aç\82¾\82È\81C\82¨\82Ü\82¦\82Í\92N\82¾\81H\81v-", buf);
+#endif
             (void) mungspaces(buf);
 #if 0 /*JP*/
-        } while (!letter(buf[0]) && --trycount > 0);
+        } while (!buf[0] && --trycount > 0);
 #else
-        } while (!letter(buf[0]) && !is_kanji(buf[0]) && --trycount > 0);
+        } while (!buf[0] && !is_kanji(buf[0]) && --trycount > 0);
 #endif
 
         if (u.ualign.type == A_LAWFUL
@@ -433,18 +450,32 @@ invault()
         || !strcmp(buf, "\83N\83\8d\83C\83\\83X") || !strcmp(buf, "\83N\83\8c\83I\83\\81[\83g")) {
 #endif
             if (!mvitals[PM_CROESUS].died) {
-                verbalize(
+                if (Deaf) {
+                    if (!Blind)
+                        pline("%s waves goodbye.", noit_Monnam(guard));
+                } else {
+                    verbalize(
 /*JP
                     "Oh, yes, of course.  Sorry to have disturbed you.");
 */
                     "\82¢\82â\81C\82±\82è\82á\81C\82¦\81[\82Æ\81C\82¨\91\9b\82ª\82¹\82µ\82Ü\82µ\82½\81D");
+                }
                 mongone(guard);
             } else {
-                setmangry(guard);
-/*JP
-                verbalize("Back from the dead, are you?  I'll remedy that!");
-*/
-                verbalize("\82Ù\82¤\81I\8e\80\82Ì\90¢\8aE\82©\82ç\96ß\82Á\82Ä\82«\82½\82Ì\82©\81H\82¤\82»\82È\82ç\8fã\8eè\82É\82Â\82¯\81I");
+                setmangry(guard, FALSE);
+                if (Deaf) {
+                   if (!Blind)
+                        pline("%s mouths something and looks very angry!",
+                              noit_Monnam(guard));
+                } else {
+#if 0 /*JP:T*/
+                   verbalize(
+                           "Back from the dead, are you?  I'll remedy that!");
+#else
+                   verbalize(
+                           "\82Ù\82¤\81I\8e\80\82Ì\90¢\8aE\82©\82ç\96ß\82Á\82Ä\82«\82½\82Ì\82©\81H\82¤\82»\82È\82ç\8fã\8eè\82É\82Â\82¯\81I");
+#endif
+                }
                 /* don't want guard to waste next turn wielding a weapon */
                 if (!MON_WEP(guard)) {
                     guard->weapon_check = NEED_HTH_WEAPON;
@@ -453,25 +484,44 @@ invault()
             }
             return;
         }
+        if (Deaf)
+            pline("%s doesn't %srecognize you.", noit_Monnam(guard),
+                    (Blind) ? "" : "appear to ");
+        else
 /*JP
         verbalize("I don't know you.");
 */
         verbalize("\92m\82ç\82ñ\82È\81D");
         umoney = money_cnt(invent);
-        if (Deaf) {
-            ;
-        } else if (!umoney && !hidden_gold()) {
+        if (!umoney && !hidden_gold()) {
+            if (Deaf)
+                pline("%s stomps%s.", noit_Monnam(guard),
+                      (Blind) ? "" : " and beckons");
+            else
 /*JP
             verbalize("Please follow me.");
 */
             verbalize("\8e\84\82Ì\8cã\82É\82Â\82¢\82Ä\82«\82È\82³\82¢\81D");
         } else {
-            if (!umoney)
+            if (!umoney) {
+                if (Deaf) {
+                    if (!Blind)
+                        pline("%s glares at you%s.", noit_Monnam(guard),
+                              invent ? "r stuff" : "");
+                } else {
 /*JP
                 verbalize("You have hidden gold.");
 */
                 verbalize("\82Ü\82¾\8bà\89Ý\82ð\89B\82µ\82Ä\82é\82È\81D");
-            verbalize(
+                }
+            }
+            if (Deaf) {
+                if (!Blind)
+                    pline(
+                       "%s holds out %s palm and beckons with %s other hand.",
+                          noit_Monnam(guard), mhis(guard), mhis(guard));
+            } else {
+                verbalize(
 /*JP
                 "Most likely all your gold was stolen from this vault.");
 */
@@ -480,6 +530,7 @@ invault()
             verbalize("Please drop that gold and follow me.");
 */
             verbalize("\82»\82ê\82ð\82»\82Á\82­\82è\96ß\82µ\82Ä\82©\82ç\81C\8e\84\82Ì\8cã\82É\82Â\82¢\82Ä\82«\82È\82³\82¢\81D");
+            }
         }
         EGD(guard)->gdx = gx;
         EGD(guard)->gdy = gy;
@@ -657,12 +708,13 @@ register struct monst *grd;
         return -1; /* teleported guard - treat as monster */
 
     if (egrd->witness) {
+        if (!Deaf)
 #if 0 /*JP*/
-        verbalize("How dare you %s that gold, scoundrel!",
-                  (egrd->witness & GD_EATGOLD) ? "consume" : "destroy");
+            verbalize("How dare you %s that gold, scoundrel!",
+                      (egrd->witness & GD_EATGOLD) ? "consume" : "destroy");
 #else
-        verbalize("\82æ\82­\82à\82Ü\82 \8bà\82ð%s\82à\82Ì\82¾\81C\88«\93}\82ß\81I",
-                  (egrd->witness & GD_EATGOLD) ? "\8eg\82Á\82½" : "\89ó\82µ\82½");
+            verbalize("\82æ\82­\82à\82Ü\82 \8bà\82ð%s\82à\82Ì\82¾\81C\88«\93}\82ß\81I",
+                      (egrd->witness & GD_EATGOLD) ? "\8eg\82Á\82½" : "\89ó\82µ\82½");
 #endif
         egrd->witness = 0;
         grd->mpeaceful = 0;
@@ -766,18 +818,28 @@ register struct monst *grd;
             }
             if (egrd->warncnt < 6) {
                 egrd->warncnt = 6;
-                if (!Deaf)
+                if (Deaf) {
+                    if (!Blind)
+                        pline("%s holds out %s palm demandingly!",
+                              noit_Monnam(grd), mhis(grd));
+                } else {
 /*JP
                     verbalize("Drop all your gold, scoundrel!");
 */
                     verbalize("\8bà\82ð\91S\95\94\92u\82¢\82Ä\82ä\82¯\81C\82È\82ç\82¸\82à\82Ì\81I");
+                }
                 return 0;
             } else {
-                if (!Deaf)
+                if (Deaf) {
+                    if (!Blind)
+                        pline("%s rubs %s hands with enraged delight!",
+                              noit_Monnam(grd), mhis(grd));
+                } else {
 /*JP
                     verbalize("So be it, rogue!");
 */
                     verbalize("\93\90\90l\82ß\81I");
+                }
                 grd->mpeaceful = 0;
                 return -1;
             }
@@ -895,7 +957,7 @@ nextpos:
     else
         ny += dy;
 
-    while ((typ = (crm = &levl[nx][ny])->typ) != 0) {
+    while ((typ = (crm = &levl[nx][ny])->typ) != STONE) {
         /* in view of the above we must have IS_WALL(typ) or typ == POOL */
         /* must be a wall here */
         if (isok(nx + nx - x, ny + ny - y) && !IS_POOL(typ)
index 1e19e98..2d18ac2 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 version.c       $NHDT-Date: 1449328116 2015/12/05 15:08:36 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.41 $ */
+/* NetHack 3.6 version.c       $NHDT-Date: 1524693365 2018/04/25 21:56:05 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 #include "../japanese/jpatchlevel.h"
 #endif
 
-#define BETA_INFO ""
+#if defined(NETHACK_GIT_SHA)
+const char * NetHack_git_sha = NETHACK_GIT_SHA;
+#endif
+#if defined(NETHACK_GIT_BRANCH)
+const char * NetHack_git_branch = NETHACK_GIT_BRANCH;
+#endif
 
-STATIC_DCL void FDECL(insert_rtoptions, (winid,char *,const char *));
+STATIC_DCL void FDECL(insert_rtoption, (char *));
 
 /* fill buffer with short version (so caller can avoid including date.h) */
 char *
@@ -39,13 +45,41 @@ char *
 getversionstring(buf)
 char *buf;
 {
+    boolean details = FALSE;
+
     Strcpy(buf, VERSION_ID);
-#if defined(BETA) && defined(BETA_INFO)
-    Sprintf(eos(buf), " %s", BETA_INFO);
+#if defined(RUNTIME_PORT_ID) || \
+    defined(NETHACK_GIT_SHA) || defined(NETHACK_GIT_BRANCH)
+    details = TRUE;
+#endif
+
+    if (details) {
+#if defined(RUNTIME_PORT_ID) || defined(NETHACK_GIT_SHA) || defined(NETHACK_GIT_BRANCH)
+        int c = 0;
+#endif
+#if defined(RUNTIME_PORT_ID)
+        char tmpbuf[BUFSZ];
+        char *tmp = (char *)0;
 #endif
+
+        Sprintf(eos(buf), " (");
 #if defined(RUNTIME_PORT_ID)
-    append_port_id(buf);
+        tmp = get_port_id(tmpbuf);        
+        if (tmp)
+            Sprintf(eos(buf), "%s%s", c++ ? "," : "", tmp);
 #endif
+#if defined(NETHACK_GIT_SHA)
+        if (NetHack_git_sha)
+            Sprintf(eos(buf), "%s%s", c++ ? "," : "", NetHack_git_sha);
+#endif
+#if defined(NETHACK_GIT_BRANCH)
+#if defined(BETA)
+        if (NetHack_git_branch)
+            Sprintf(eos(buf), "%sbranch:%s", c++ ? "," : "", NetHack_git_branch);
+#endif
+#endif
+        Sprintf(eos(buf), ")");
+    }
     return buf;
 }
 
@@ -67,9 +101,8 @@ int
 doextversion()
 {
     dlb *f;
-    char *cr, *pd, buf[BUFSZ];
+    char buf[BUFSZ];
     winid win = create_nhwindow(NHW_TEXT);
-    boolean rtadded = FALSE;
 
     /* instead of using ``display_file(OPTIONS_USED,TRUE)'' we handle
        the file manually so we can include dynamic version info */
@@ -84,8 +117,7 @@ doextversion()
         /*
          * already inserted above:
          * + outdented program name and version plus build date and time
-         * dat/options; display the contents with lines prefixed by '-'
-         * deleted:
+         * dat/options; display contents with lines prefixed by '-' deleted:
          * - blank-line
          * -     indented program name and version
          *   blank-line
@@ -104,10 +136,7 @@ doextversion()
         boolean prolog = TRUE; /* to skip indented program name */
 
         while (dlb_fgets(buf, BUFSZ, f)) {
-            if ((cr = index(buf, '\n')) != 0)
-                *cr = 0;
-            if ((cr = index(buf, '\r')) != 0)
-                *cr = 0;
+            (void) strip_newline(buf);
             if (index(buf, '\t') != 0)
                 (void) tabexpand(buf);
 
@@ -121,16 +150,9 @@ doextversion()
             if (prolog || !*buf)
                 continue;
 
-            if (!rtadded) {
-                const char *catchphrase = ", and basic NetHack features.";
+            if (index(buf, ':'))
+                insert_rtoption(buf);
 
-                pd = strstri(buf, catchphrase);
-                if (pd) {
-                    *pd = '\0';
-                    insert_rtoptions(win, buf, &catchphrase[2]);
-                    rtadded = TRUE; /* only do it once */
-               }
-            }
             if (*buf)
                 putstr(win, 0, buf);
         }
@@ -141,12 +163,52 @@ doextversion()
     return 0;
 }
 
+void early_version_info(pastebuf)
+boolean pastebuf;
+{
+    char buf[BUFSZ], buf2[BUFSZ];
+    char *tmp = getversionstring(buf);
+
+    /* this is early enough that we have to do
+       our own line-splitting */
+    if (tmp) {
+        tmp = strstri(buf," (");
+        if (tmp) *tmp++ = '\0';
+    }
+
+    Sprintf(buf2, "%s\n", buf);
+    if (tmp) Sprintf(eos(buf2), "%s\n", tmp);
+    raw_printf("%s", buf2);
+
+    if (pastebuf) {
+#ifdef RUNTIME_PASTEBUF_SUPPORT
+        /*
+         * Call a platform/port-specific routine to insert the
+         * version information into a paste buffer. Useful for
+         * easy inclusion in bug reports.
+         */
+        port_insert_pastebuf(buf2);
+#else
+        raw_printf("%s", "Paste buffer copy is not available.\n");
+#endif
+    }
+}
+
 extern const char regex_id[];
 
-static const char *rt_opts[] = {
-    "pattern matching via", regex_id,
+/*
+ * makedefs should put the first token into dat/options; we'll substitute
+ * the second value for it.  The token must contain at least one colon
+ * so that we can spot it, and should not contain spaces so that makedefs
+ * won't split it across lines.  Ideally the length should be close to
+ * that of the substituted value since we don't do phrase-splitting/line-
+ * wrapping when displaying it.
+ */
+static struct rt_opt {
+    const char *token, *value;
+} rt_opts[] = {
+    { ":PATMATCH:", regex_id },
 };
-static const char indent[] = "    ";
 
 /*
  * 3.6.0
@@ -155,57 +217,17 @@ static const char indent[] = "    ";
  * game image, so we insert those options here.
  */
 STATIC_OVL void
-insert_rtoptions(win, buf, finalphrase)
-winid win;
+insert_rtoption(buf)
 char *buf;
-const char *finalphrase;
 {
-    char rtbuf[BUFSZ];
-    int l, i;
-    const char *s1 = 0, *s2 = 0, *s3 = 0, *s4 = 0;
-
-    if ((int) strlen(buf) >= (BUFSZ - 1))
-        return;
-
-    strcpy(rtbuf, buf);
-    for (i = 0; i < (SIZE(rt_opts) + 1); i += 2) {
-        if (i < SIZE(rt_opts)) {
-            s1 = ", ";
-            s2 = rt_opts[i];
-            s3 = " ";
-            s4 = rt_opts[i+1];
-        } else {
-            s1 = " ";
-            s2 = finalphrase;
-            s3 = "";
-            s4 = "";
-        }
-        l = (int) strlen(rtbuf) + (int) strlen(s1) + (int) strlen(s2)
-            + (int) strlen(s3) + (int) strlen(s4) + 1;
-        if (l <= (COLNO - 5) && l < (BUFSZ - 1)) {
-            Strcat(rtbuf, s1);
-            Strcat(rtbuf, s2);
-            Strcat(rtbuf, s3);
-            Strcat(rtbuf, s4);
-        } else {
-            putstr(win, 0, rtbuf);
-            if (i >= SIZE(rt_opts))
-                s1 = "";
-            l = (int) strlen(indent) + (int) strlen(s1) + (int) strlen(s2)
-                + (int) strlen(s3) + (int) strlen(s4) + 1;
-            if (l <= (COLNO - 5) && l < (BUFSZ - 1)) {
-                Strcpy(rtbuf, indent);
-                Strcat(rtbuf, s1);
-                Strcat(rtbuf, s2);
-                Strcat(rtbuf, s3);
-                Strcat(rtbuf, s4);
-            }
-        }
-    }
+    int i;
 
-    if (l)
-        putstr(win, 0, rtbuf);
-    *buf = '\0';
+    for (i = 0; i < SIZE(rt_opts); ++i) {
+        if (strstri(buf, rt_opts[i].token))
+            (void) strsubst(buf, rt_opts[i].token, rt_opts[i].value);
+        /* we don't break out of the loop after a match; there might be
+           other matches on the same line */
+    }
 }
 
 #ifdef MICRO
@@ -213,7 +235,9 @@ boolean
 comp_times(filetime)
 long filetime;
 {
-    return (boolean) (filetime < BUILD_TIME);
+    /* BUILD_TIME is constant but might have L suffix rather than UL;
+       'filetime' is historically signed but ought to have been unsigned */
+    return (boolean) ((unsigned long) filetime < (unsigned long) BUILD_TIME);
 }
 #endif
 
index 77475af..2dcc85b 100644 (file)
@@ -175,9 +175,9 @@ register struct rm *lev;
         if (obj->otyp == BOULDER)
             return 1;
 
-    /* Mimics mimicing a door or boulder block light. */
+    /* Mimics mimicing a door or boulder or ... block light. */
     if ((mon = m_at(x, y)) && (!mon->minvis || See_invisible)
-        && (is_door_mappear(mon) || is_obj_mappear(mon,BOULDER)))
+        && is_lightblocker_mappear(mon))
         return 1;
 
     return 0;
index d2ce35f..9ef7c3f 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 weapon.c        $NHDT-Date: 1446078767 2015/10/29 00:32:47 $  $NHDT-Branch: master $:$NHDT-Revision: 1.55 $ */
+/* NetHack 3.6 weapon.c        $NHDT-Date: 1454660575 2016/02/05 08:22:55 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.57 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -337,12 +338,12 @@ struct monst *mon;
     if (ptr == &mons[PM_SHADE] && !shade_glare(otmp))
         tmp = 0;
 
-    /* "very heavy iron ball"; weight increase is in increments of 160 */
+    /* "very heavy iron ball"; weight increase is in increments */
     if (otyp == HEAVY_IRON_BALL && tmp > 0) {
         int wt = (int) objects[HEAVY_IRON_BALL].oc_weight;
 
         if ((int) otmp->owt > wt) {
-            wt = ((int) otmp->owt - wt) / 160;
+            wt = ((int) otmp->owt - wt) / IRON_BALL_W_INCR;
             tmp += rnd(4 * wt);
             if (tmp > 25)
                 tmp = 25; /* objects[].oc_wldam */
@@ -914,7 +915,7 @@ boolean verbose;
                 pline("%s %s gets %s.", s_suffix(Monnam(obj->ocarry)),
                       xname(obj), wetness);
 #else
-                pline("%s%s\82Í%s\81D", s_suffix(Monnam(obj->ocarry)),
+                pline("%s\82Ì%s\82Í%s\81D", Monnam(obj->ocarry),
                       xname(obj), wetness);
 #endif
         }
@@ -952,7 +953,7 @@ boolean verbose;
                 pline("%s %s drie%s.", s_suffix(Monnam(obj->ocarry)),
                       xname(obj), !newspe ? " out" : "");
 #else
-                pline("%s%s\82Í%s\81D", s_suffix(Monnam(obj->ocarry)),
+                pline("%s\82Ì%s\82Í%s\81D", Monnam(obj->ocarry),
                       xname(obj), !newspe ? "\8a£\82«\82«\82Á\82½" : "\8a£\82¢\82½");
 #endif
         }
@@ -1302,7 +1303,7 @@ enhance_weapon_skill()
 
 /*
  * Change from restricted to unrestricted, allowing P_BASIC as max.  This
- * function may be called with with P_NONE.  Used in pray.c.
+ * function may be called with with P_NONE.  Used in pray.c as well as below.
  */
 void
 unrestrict_weapon_skill(skill)
@@ -1656,6 +1657,10 @@ const struct def_skill *class_skill;
             P_ADVANCE(skill) = practice_needed_to_advance(P_SKILL(skill) - 1);
         }
     }
+
+    /* each role has a special spell; allow at least basic for its type
+       (despite the function name, this works for spell skills too) */
+    unrestrict_weapon_skill(spell_skilltype(urole.spelspec));
 }
 
 void
index 26bcff4..9e36189 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 were.c  $NHDT-Date: 1432512763 2015/05/25 00:12:43 $  $NHDT-Branch: master $:$NHDT-Revision: 1.18 $ */
+/* NetHack 3.6 were.c  $NHDT-Date: 1505214877 2017/09/12 11:14:37 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -66,6 +67,8 @@ register struct monst *mon;
     } else if (!rn2(30) || Protection_from_shape_changers) {
         new_were(mon); /* change back into human form */
     }
+    /* update innate intrinsics (mainly Drain_resistance) */
+    set_uasmon(); /* new_were() doesn't do this */
 }
 
 int
@@ -74,17 +77,17 @@ int pm;
 {
     switch (pm) {
     case PM_WEREWOLF:
-        return (PM_HUMAN_WEREWOLF);
+        return PM_HUMAN_WEREWOLF;
     case PM_HUMAN_WEREWOLF:
-        return (PM_WEREWOLF);
+        return PM_WEREWOLF;
     case PM_WEREJACKAL:
-        return (PM_HUMAN_WEREJACKAL);
+        return PM_HUMAN_WEREJACKAL;
     case PM_HUMAN_WEREJACKAL:
-        return (PM_WEREJACKAL);
+        return PM_WEREJACKAL;
     case PM_WERERAT:
-        return (PM_HUMAN_WERERAT);
+        return PM_HUMAN_WERERAT;
     case PM_HUMAN_WERERAT:
-        return (PM_WERERAT);
+        return PM_WERERAT;
     default:
         return NON_PM;
     }
@@ -152,15 +155,16 @@ register struct monst *mon;
     possibly_unwield(mon, FALSE);
 }
 
-int were_summon(ptr, yours, visible,
-                genbuf) /* were-creature (even you) summons a horde */
-register struct permonst *ptr;
-register boolean yours;
+/* were-creature (even you) summons a horde */
+int
+were_summon(ptr, yours, visible, genbuf)
+struct permonst *ptr;
+boolean yours;
 int *visible; /* number of visible helpers created */
 char *genbuf;
 {
-    register int i, typ, pm = monsndx(ptr);
-    register struct monst *mtmp;
+    int i, typ, pm = monsndx(ptr);
+    struct monst *mtmp;
     int total = 0;
 
     *visible = 0;
@@ -170,8 +174,8 @@ char *genbuf;
         switch (pm) {
         case PM_WERERAT:
         case PM_HUMAN_WERERAT:
-            typ =
-                rn2(3) ? PM_SEWER_RAT : rn2(3) ? PM_GIANT_RAT : PM_RABID_RAT;
+            typ = rn2(3) ? PM_SEWER_RAT
+                         : rn2(3) ? PM_GIANT_RAT : PM_RABID_RAT;
             if (genbuf)
 /*JP
                 Strcpy(genbuf, "rat");
@@ -180,7 +184,7 @@ char *genbuf;
             break;
         case PM_WEREJACKAL:
         case PM_HUMAN_WEREJACKAL:
-            typ = PM_JACKAL;
+            typ = rn2(7) ? PM_JACKAL : rn2(3) ? PM_COYOTE : PM_FOX;
             if (genbuf)
 /*JP
                 Strcpy(genbuf, "jackal");
@@ -189,7 +193,7 @@ char *genbuf;
             break;
         case PM_WEREWOLF:
         case PM_HUMAN_WEREWOLF:
-            typ = rn2(5) ? PM_WOLF : PM_WINTER_WOLF;
+            typ = rn2(5) ? PM_WOLF : rn2(2) ? PM_WARG : PM_WINTER_WOLF;
             if (genbuf)
 /*JP
                 Strcpy(genbuf, "wolf");
@@ -217,18 +221,18 @@ you_were()
     char qbuf[QBUFSZ];
     boolean controllable_poly = Polymorph_control && !(Stunned || Unaware);
 
-    if (Unchanging || (u.umonnum == u.ulycn))
+    if (Unchanging || u.umonnum == u.ulycn)
         return;
     if (controllable_poly) {
 #if 0 /*JP*/
         /* `+4' => skip "were" prefix to get name of beast */
         Sprintf(qbuf, "Do you want to change into %s?",
                 an(mons[u.ulycn].mname + 4));
-#else
+#else /* \93ú\96{\8cê\82Å\82Í\90ê\97p\8aÖ\90\94\82ð\8eg\82¤ */
         Sprintf(qbuf, "%s\82É\95Ï\89»\82µ\82Ü\82·\82©\81H",
                 beastname(mons[u.ulycn].mname));
 #endif
-        if (yn(qbuf) == 'n')
+        if (!paranoid_query(ParanoidWerechange, qbuf))
             return;
     }
     (void) polymon(u.ulycn);
@@ -245,14 +249,27 @@ boolean purify;
         You_feel("purified.");
 */
         You("\8fò\82ß\82ç\82ê\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81D");
-        u.ulycn = NON_PM; /* cure lycanthropy */
+        set_ulycn(NON_PM); /* cure lycanthropy */
     }
     if (!Unchanging && is_were(youmonst.data)
+        && (!controllable_poly
 /*JP
-        && (!controllable_poly || yn("Remain in beast form?") == 'n'))
+            || !paranoid_query(ParanoidWerechange, "Remain in beast form?")))
 */
-        && (!controllable_poly || yn("\8fb\82Ì\8ep\82Ì\82Ü\82Ü\82Å\82¢\82é\81H") == 'n'))
+            || !paranoid_query(ParanoidWerechange, "\8fb\82Ì\8ep\82Ì\82Ü\82Ü\82Å\82¢\82é\81H")))
         rehumanize();
+    else if (is_were(youmonst.data) && !u.mtimedone)
+        u.mtimedone = rn1(200, 200); /* 40% of initial were change */
+}
+
+/* lycanthropy is being caught or cured, but no shape change is involved */
+void
+set_ulycn(which)
+int which;
+{
+    u.ulycn = which;
+    /* add or remove lycanthrope's innate intrinsics (Drain_resistance) */
+    set_uasmon();
 }
 
 /*were.c*/
index 420bbf6..864234d 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 wield.c $NHDT-Date: 1446887539 2015/11/07 09:12:19 $  $NHDT-Branch: master $:$NHDT-Revision: 1.47 $ */
+/* NetHack 3.6 wield.c $NHDT-Date: 1496959480 2017/06/08 22:04:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.54 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2009. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -104,6 +105,10 @@ register struct obj *obj;
 */
             pline("%s\82Í\8bP\82«\82ð\8e~\82ß\82½\81D", xname(olduwep));
     }
+    if (uwep == obj
+        && ((uwep && uwep->oartifact == ART_OGRESMASHER)
+            || (olduwep && olduwep->oartifact == ART_OGRESMASHER)))
+        context.botl = 1;
     /* Note: Explicitly wielding a pick-axe will not give a "bashing"
      * message.  Wielding one via 'a'pplying it will.
      * 3.2.2:  Wielding arbitrary objects will give bashing message too.
@@ -210,6 +215,10 @@ struct obj *wep;
              * and the message must be before the death message and
              * Lifesaved rewielding.  Yet we want the message to
              * say "weapon in hand", thus this kludge.
+             * [That comment is obsolete.  It dates from the days (3.0)
+             * when unwielding Firebrand could cause hero to be burned
+             * to death in Hell due to loss of fire resistance.
+             * "Lifesaved re-wielding or re-wearing" is ancient history.]
              */
             long dummy = wep->owornmask;
 
@@ -281,12 +290,16 @@ register struct obj *obj;
 
 /*** Commands to change particular slot(s) ***/
 
-static NEARDATA const char wield_objs[] = { ALL_CLASSES, ALLOW_NONE,
-                                            WEAPON_CLASS, TOOL_CLASS, 0 };
-static NEARDATA const char ready_objs[] = { COIN_CLASS, ALL_CLASSES,
-                                            ALLOW_NONE, WEAPON_CLASS, 0 };
-static NEARDATA const char bullets[] = /* (note: different from dothrow.c) */
-    { COIN_CLASS, ALL_CLASSES, ALLOW_NONE, GEM_CLASS, WEAPON_CLASS, 0 };
+static NEARDATA const char wield_objs[] = {
+    ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, TOOL_CLASS, 0
+};
+static NEARDATA const char ready_objs[] = {
+    ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, 0
+};
+static NEARDATA const char bullets[] = { /* (note: different from dothrow.c) */
+    ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, ALLOW_NONE,
+    GEM_CLASS, WEAPON_CLASS, 0
+};
 
 int
 dowield()
@@ -377,10 +390,10 @@ doswapweapon()
     result = ready_weapon(oldswap);
 
     /* Set your new secondary weapon */
-    if (uwep == oldwep)
+    if (uwep == oldwep) {
         /* Wield failed for some reason */
         setuswapwep(oldswap);
-    else {
+    else {
         setuswapwep(oldwep);
         if (uswapwep)
             prinv((char *) 0, uswapwep, 0L);
@@ -400,80 +413,179 @@ doswapweapon()
 int
 dowieldquiver()
 {
-    register struct obj *newquiver;
-    const char *quivee_types =
-        (uslinging()
-         || (uswapwep && objects[uswapwep->otyp].oc_skill == P_SLING))
-            ? bullets
-            : ready_objs;
+    char qbuf[QBUFSZ];
+    struct obj *newquiver;
+    const char *quivee_types;
+    int res;
+    boolean finish_splitting = FALSE,
+            was_uwep = FALSE, was_twoweap = u.twoweap;
 
     /* Since the quiver isn't in your hands, don't check cantwield(), */
     /* will_weld(), touch_petrifies(), etc. */
     multi = 0;
-
-    /* Prompt for a new quiver */
-    if (!(newquiver = getobj(quivee_types, "ready")))
+    /* forget last splitobj() before calling getobj() with ALLOW_COUNT */
+    context.objsplit.child_oid = context.objsplit.parent_oid = 0;
+
+    /* Prompt for a new quiver: "What do you want to ready?"
+       (Include gems/stones as likely candidates if either primary
+       or secondary weapon is a sling.) */
+    quivee_types = (uslinging()
+                    || (uswapwep
+                        && objects[uswapwep->otyp].oc_skill == P_SLING))
+                   ? bullets
+                   : ready_objs;
+    newquiver = getobj(quivee_types, "ready");
+
+    if (!newquiver) {
         /* Cancelled */
         return 0;
-
-    /* Handle no object, or object in other slot */
-    /* Any type is okay, since we give no intrinsics anyways */
-    if (newquiver == &zeroobj) {
+    } else if (newquiver == &zeroobj) { /* no object */
         /* Explicitly nothing */
         if (uquiver) {
 /*JP
             You("now have no ammunition readied.");
 */
             pline("\91\95\93U\82·\82é\82½\82ß\82Ì\96î\92e\82ª\82È\82­\82È\82Á\82½\81D");
-            setuqwep(newquiver = (struct obj *) 0);
+            /* skip 'quivering: prinv()' */
+            setuqwep((struct obj *) 0);
         } else {
 /*JP
             You("already have no ammunition readied!");
 */
             pline("\91\95\93U\82·\82é\82½\82ß\82Ì\96î\92e\82ª\82È\82¢\81D");
-            return 0;
         }
+        return 0;
+    } else if (newquiver->o_id == context.objsplit.child_oid) {
+        /* if newquiver is the result of supplying a count to getobj()
+           we don't want to split something already in the quiver;
+           for any other item, we need to give it its own inventory slot */
+        if (uquiver && uquiver->o_id == context.objsplit.parent_oid) {
+            unsplitobj(newquiver);
+            goto already_quivered;
+        }
+        finish_splitting = TRUE;
     } else if (newquiver == uquiver) {
+    already_quivered:
 /*JP
         pline("That ammunition is already readied!");
 */
         pline("\82à\82¤\91\95\93U\82³\82ê\82Ä\82¢\82é\81I");
         return 0;
-    } else if (newquiver == uwep) {
-        /* Prevent accidentally readying the main weapon */
-#if 0 /*JP*/
-        pline("%s already being used as a weapon!",
-              !is_plural(uwep) ? "That is" : "They are");
-#else
-        pline("\82à\82¤\95\90\8aí\82Æ\82µ\82Ä\8eg\82í\82ê\82Ä\82¢\82é\81I");
-#endif
-        return 0;
     } else if (newquiver->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE)) {
 /*JP
         You("cannot ready that!");
 */
         You("\82»\82ê\82Í\8eg\82¦\82È\82¢\81I");
         return 0;
-    } else {
-        long dummy;
+    } else if (newquiver == uwep) {
+        int weld_res = !uwep->bknown;
 
-        /* Check if it's the secondary weapon */
-        if (newquiver == uswapwep) {
-            setuswapwep((struct obj *) 0);
-            untwoweapon();
+        if (welded(uwep)) {
+            weldmsg(uwep);
+            reset_remarm(); /* same as dowield() */
+            return weld_res;
         }
+        /* offer to split stack if wielding more than 1 */
+        if (uwep->quan > 1L && inv_cnt(FALSE) < 52 && splittable(uwep)) {
+            Sprintf(qbuf, "You are wielding %ld %s.  Ready %ld of them?",
+                    uwep->quan, simpleonames(uwep), uwep->quan - 1L);
+            switch (ynq(qbuf)) {
+            case 'q':
+                return 0;
+            case 'y':
+                /* leave 1 wielded, split rest off and put into quiver */
+                newquiver = splitobj(uwep, uwep->quan - 1L);
+                finish_splitting = TRUE;
+                goto quivering;
+            default:
+                break;
+            }
+            Strcpy(qbuf, "Ready all of them instead?");
+        } else {
+            boolean use_plural = (is_plural(uwep) || pair_of(uwep));
 
-        /* Okay to put in quiver; print it */
-        dummy = newquiver->owornmask;
-        newquiver->owornmask |= W_QUIVER;
-        prinv((char *) 0, newquiver, 0L);
-        newquiver->owornmask = dummy;
+            Sprintf(qbuf, "You are wielding %s.  Ready %s instead?",
+                    !use_plural ? "that" : "those",
+                    !use_plural ? "it" : "them");
+        }
+        /* require confirmation to ready the main weapon */
+        if (ynq(qbuf) != 'y') {
+            (void) Shk_Your(qbuf, uwep); /* replace qbuf[] contents */
+            pline("%s%s %s wielded.", qbuf,
+                  simpleonames(uwep), otense(uwep, "remain"));
+            return 0;
+        }
+        /* quivering main weapon, so no longer wielding it */
+        setuwep((struct obj *) 0);
+        untwoweapon();
+        was_uwep = TRUE;
+    } else if (newquiver == uswapwep) {
+        if (uswapwep->quan > 1L && inv_cnt(FALSE) < 52
+            && splittable(uswapwep)) {
+            Sprintf(qbuf, "%s %ld %s.  Ready %ld of them?",
+                    u.twoweap ? "You are dual wielding"
+                              : "Your alternate weapon is",
+                    uswapwep->quan, simpleonames(uswapwep),
+                    uswapwep->quan - 1L);
+            switch (ynq(qbuf)) {
+            case 'q':
+                return 0;
+            case 'y':
+                /* leave 1 alt-wielded, split rest off and put into quiver */
+                newquiver = splitobj(uswapwep, uswapwep->quan - 1L);
+                finish_splitting = TRUE;
+                goto quivering;
+            default:
+                break;
+            }
+            Strcpy(qbuf, "Ready all of them instead?");
+        } else {
+            boolean use_plural = (is_plural(uswapwep) || pair_of(uswapwep));
+
+            Sprintf(qbuf, "%s your %s weapon.  Ready %s instead?",
+                    !use_plural ? "That is" : "Those are",
+                    u.twoweap ? "second" : "alternate",
+                    !use_plural ? "it" : "them");
+        }
+        /* require confirmation to ready the alternate weapon */
+        if (ynq(qbuf) != 'y') {
+            (void) Shk_Your(qbuf, uswapwep); /* replace qbuf[] contents */
+            pline("%s%s %s %s.", qbuf,
+                  simpleonames(uswapwep), otense(uswapwep, "remain"),
+                  u.twoweap ? "wielded" : "as secondary weapon");
+            return 0;
+        }
+        /* quivering alternate weapon, so no more uswapwep */
+        setuswapwep((struct obj *) 0);
+        untwoweapon();
     }
 
-    /* Finally, place it in the quiver */
+ quivering:
+    if (finish_splitting) {
+        freeinv(newquiver);
+        newquiver->nomerge = 1;
+        addinv(newquiver);
+        newquiver->nomerge = 0;
+    }
+    /* place item in quiver before printing so that inventory feedback
+       includes "(at the ready)" */
     setuqwep(newquiver);
-    /* Take no time since this is a convenience slot */
-    return 0;
+    prinv((char *) 0, newquiver, 0L);
+
+    /* quiver is a convenience slot and manipulating it ordinarily
+       consumes no time, but unwielding primary or secondary weapon
+       should take time (perhaps we're adjacent to a rust monster
+       or disenchanter and want to hit it immediately, but not with
+       something we're wielding that's vulnerable to its damage) */
+    res = 0;
+    if (was_uwep) {
+        You("are now empty %s.", body_part(HANDED));
+        res = 1;
+    } else if (was_twoweap && !u.twoweap) {
+        You("are no longer wielding two weapons at once.");
+        res = 1;
+    }
+    return res;
 }
 
 /* used for #rub and for applying pick-axe, whip, grappling hook or polearm */
@@ -757,14 +869,27 @@ register int amount;
     if (!uwep || (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep))) {
         char buf[BUFSZ];
 
+        if (amount >= 0 && uwep && will_weld(uwep)) { /* cursed tin opener */
+            if (!Blind) {
+                Sprintf(buf, "%s with %s aura.",
+                        Yobjnam2(uwep, "glow"), an(hcolor(NH_AMBER)));
+                uwep->bknown = !Hallucination;
+            } else {
+                /* cursed tin opener is wielded in right hand */
+                Sprintf(buf, "Your right %s tingles.", body_part(HAND));
+            }
+            uncurse(uwep);
+            update_inventory();
+        } else {
 #if 0 /*JP*/
-        Sprintf(buf, "Your %s %s.", makeplural(body_part(HAND)),
-                (amount >= 0) ? "twitch" : "itch");
+            Sprintf(buf, "Your %s %s.", makeplural(body_part(HAND)),
+                    (amount >= 0) ? "twitch" : "itch");
 #else
-        Sprintf(buf, "\82 \82È\82½\82Ì%s\82Í%s\81D", makeplural(body_part(HAND)),
-                (amount >= 0) ? "\82Ð\82«\82Â\82Á\82½" : "\83\80\83Y\83\80\83Y\82µ\82½");
+            Sprintf(buf, "\82 \82È\82½\82Ì%s\82Í%s\81D", makeplural(body_part(HAND)),
+                    (amount >= 0) ? "\82Ð\82«\82Â\82Á\82½" : "\83\80\83Y\83\80\83Y\82µ\82½");
 #endif
-        strange_feeling(otmp, buf);
+        }
+        strange_feeling(otmp, buf); /* pline()+docall()+useup() */
         exercise(A_DEX, (boolean) (amount >= 0));
         return 0;
     }
index 1423f8c..7a62582 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 windows.c       $NHDT-Date: 1448013599 2015/11/20 09:59:59 $  $NHDT-Branch: master $:$NHDT-Revision: 1.35 $ */
+/* NetHack 3.6 windows.c       $NHDT-Date: 1495232365 2017/05/19 22:19:25 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.41 $ */
 /* Copyright (c) D. Cohrs, 1993. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -57,6 +57,18 @@ extern void *FDECL(trace_procs_chain, (int, int, void *, void *, void *));
 
 STATIC_DCL void FDECL(def_raw_print, (const char *s));
 
+#ifdef DUMPLOG
+STATIC_DCL winid FDECL(dump_create_nhwindow, (int));
+STATIC_DCL void FDECL(dump_clear_nhwindow, (winid));
+STATIC_DCL void FDECL(dump_display_nhwindow, (winid, BOOLEAN_P));
+STATIC_DCL void FDECL(dump_destroy_nhwindow, (winid));
+STATIC_DCL void FDECL(dump_start_menu, (winid));
+STATIC_DCL void FDECL(dump_add_menu, (winid, int, const ANY_P *, CHAR_P, CHAR_P, int, const char *, BOOLEAN_P));
+STATIC_DCL void FDECL(dump_end_menu, (winid, const char *));
+STATIC_DCL int FDECL(dump_select_menu, (winid, int, MENU_ITEM_P **));
+STATIC_DCL void FDECL(dump_putstr, (winid, int, const char *));
+#endif /* DUMPLOG */
+
 #ifdef HANGUPHANDLING
 volatile
 #endif
@@ -226,22 +238,25 @@ const char *s;
         exit(EXIT_FAILURE);
     }
     if (!winchoices[1].procs) {
-        raw_printf("Window type %s not recognized.  The only choice is: %s.",
+        config_error_add("Window type %s not recognized.  The only choice is: %s",
                    s, winchoices[0].procs->name);
     } else {
-        raw_printf("Window type %s not recognized.  Choices are:", s);
+        char buf[BUFSZ];
+        boolean first = TRUE;
+        buf[0] = '\0';
         for (i = 0; winchoices[i].procs; i++) {
             if ('+' == winchoices[i].procs->name[0])
                 continue;
             if ('-' == winchoices[i].procs->name[0])
                 continue;
-            raw_printf("        %s", winchoices[i].procs->name);
+            Sprintf(eos(buf), "%s%s", first ? "" : ",", winchoices[i].procs->name);
+            first = FALSE;
         }
+        config_error_add("Window type %s not recognized.  Choices are: %s", s, buf);
     }
 
     if (windowprocs.win_raw_print == def_raw_print)
-        terminate(EXIT_SUCCESS);
-    wait_synch();
+        nh_terminate(EXIT_SUCCESS);
 }
 
 #ifdef WINCHAIN
@@ -459,9 +474,7 @@ static short FDECL(hup_set_font_name, (winid, char *));
 #endif
 static char *NDECL(hup_get_color_string);
 #endif /* CHANGE_COLOR */
-#ifdef STATUS_VIA_WINDOWPORT
-static void FDECL(hup_status_update, (int, genericptr_t, int, int));
-#endif
+static void FDECL(hup_status_update, (int, genericptr_t, int, int, int, unsigned long *));
 
 static int NDECL(hup_int_ndecl);
 static void NDECL(hup_void_ndecl);
@@ -511,14 +524,9 @@ static struct window_procs hup_procs = {
     hup_void_ndecl,                                   /* end_screen */
     hup_outrip, genl_preference_update, genl_getmsghistory,
     genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     hup_void_ndecl,                                   /* status_init */
     hup_void_ndecl,                                   /* status_finish */
     genl_status_enablefield, hup_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif /* STATUS_VIA_WINDOWPORT */
     genl_can_suspend_no,
 };
 
@@ -747,16 +755,17 @@ hup_get_color_string(VOID_ARGS)
 }
 #endif /* CHANGE_COLOR */
 
-#ifdef STATUS_VIA_WINDOWPORT
 /*ARGSUSED*/
 static void
-hup_status_update(idx, ptr, chg, percent)
-int idx UNUSED, chg UNUSED, percent UNUSED;
+hup_status_update(idx, ptr, chg, pc, color, colormasks)
+int idx UNUSED;
 genericptr_t ptr UNUSED;
+int chg UNUSED, pc UNUSED, color UNUSED;
+unsigned long *colormasks UNUSED;
+
 {
     return;
 }
-#endif /* STATUS_VIA_WINDOWPORT */
 
 /*
  * Non-specific stubs.
@@ -800,7 +809,6 @@ const char *string UNUSED;
 
 #endif /* HANGUPHANDLING */
 
-#ifdef STATUS_VIA_WINDOWPORT
 
 /****************************************************************************/
 /* genl backward compat stuff                                               */
@@ -816,6 +824,7 @@ void
 genl_status_init()
 {
     int i;
+
     for (i = 0; i < MAXBLSTATS; ++i) {
         status_vals[i] = (char *) alloc(MAXCO);
         *status_vals[i] = '\0';
@@ -836,8 +845,7 @@ genl_status_finish()
     /* free alloc'd memory here */
     for (i = 0; i < MAXBLSTATS; ++i) {
         if (status_vals[i])
-            free((genericptr_t) status_vals[i]);
-        status_vals[i] = (char *) 0;
+            free((genericptr_t) status_vals[i]), status_vals[i] = (char *) 0;
     }
 }
 
@@ -853,83 +861,434 @@ boolean enable;
     status_activefields[fieldidx] = enable;
 }
 
+/* call once for each field, then call with BL_FLUSH to output the result */
 void
-genl_status_update(idx, ptr, chg, percent)
-int idx, chg, percent;
+genl_status_update(idx, ptr, chg, percent, color, colormasks)
+int idx;
 genericptr_t ptr;
+int chg UNUSED, percent UNUSED, color UNUSED;
+unsigned long *colormasks UNUSED;
 {
     char newbot1[MAXCO], newbot2[MAXCO];
     long cond, *condptr = (long *) ptr;
     register int i;
-    char *text = (char *) ptr;
+    unsigned pass, lndelta;
+    enum statusfields idx1, idx2, *fieldlist;
+    char *nb, *text = (char *) ptr;
 
-    enum statusfields fieldorder[2][15] = {
+    static enum statusfields fieldorder[][15] = {
+        /* line one */
         { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
           BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH,
           BL_FLUSH },
-        { BL_LEVELDESC, BL_GOLD, BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX,
-          BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER,
-          BL_CAP, BL_CONDITION, BL_FLUSH }
+        /* line two, default order */
+        { BL_LEVELDESC, BL_GOLD,
+          BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
+          BL_XP, BL_EXP, BL_HD,
+          BL_TIME,
+          BL_HUNGER, BL_CAP, BL_CONDITION,
+          BL_FLUSH },
+        /* move time to the end */
+        { BL_LEVELDESC, BL_GOLD,
+          BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
+          BL_XP, BL_EXP, BL_HD,
+          BL_HUNGER, BL_CAP, BL_CONDITION,
+          BL_TIME, BL_FLUSH },
+        /* move experience and time to the end */
+        { BL_LEVELDESC, BL_GOLD,
+          BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
+          BL_HUNGER, BL_CAP, BL_CONDITION,
+          BL_XP, BL_EXP, BL_HD, BL_TIME, BL_FLUSH },
+        /* move level description plus gold and experience and time to end */
+        { BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX, BL_AC,
+          BL_HUNGER, BL_CAP, BL_CONDITION,
+          BL_LEVELDESC, BL_GOLD, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_FLUSH },
     };
 
+    /* in case interface is using genl_status_update() but has not
+       specified WC2_FLUSH_STATUS (status_update() for field values
+       is buffered so final BL_FLUSH is needed to produce output) */
+    windowprocs.wincap2 |= WC2_FLUSH_STATUS;
+
     if (idx != BL_FLUSH) {
         if (!status_activefields[idx])
             return;
         switch (idx) {
         case BL_CONDITION:
-            cond = *condptr;
-            *status_vals[idx] = '\0';
+            cond = condptr ? *condptr : 0L;
+            nb = status_vals[idx];
+            *nb = '\0';
+            if (cond & BL_MASK_STONE)
+                Strcpy(nb = eos(nb), " Stone");
+            if (cond & BL_MASK_SLIME)
+                Strcpy(nb = eos(nb), " Slime");
+            if (cond & BL_MASK_STRNGL)
+                Strcpy(nb = eos(nb), " Strngl");
+            if (cond & BL_MASK_FOODPOIS)
+                Strcpy(nb = eos(nb), " FoodPois");
+            if (cond & BL_MASK_TERMILL)
+                Strcpy(nb = eos(nb), " TermIll");
             if (cond & BL_MASK_BLIND)
-                Strcat(status_vals[idx], " Blind");
+                Strcpy(nb = eos(nb), " Blind");
+            if (cond & BL_MASK_DEAF)
+                Strcpy(nb = eos(nb), " Deaf");
+            if (cond & BL_MASK_STUN)
+                Strcpy(nb = eos(nb), " Stun");
             if (cond & BL_MASK_CONF)
-                Strcat(status_vals[idx], " Conf");
-            if (cond & BL_MASK_FOODPOIS)
-                Strcat(status_vals[idx], " FoodPois");
-            if (cond & BL_MASK_ILL)
-                Strcat(status_vals[idx], " Ill");
-            if (cond & BL_MASK_STUNNED)
-                Strcat(status_vals[idx], " Stun");
+                Strcpy(nb = eos(nb), " Conf");
             if (cond & BL_MASK_HALLU)
-                Strcat(status_vals[idx], " Hallu");
-            if (cond & BL_MASK_SLIMED)
-                Strcat(status_vals[idx], " Slime");
+                Strcpy(nb = eos(nb), " Hallu");
+            if (cond & BL_MASK_LEV)
+                Strcpy(nb = eos(nb), " Lev");
+            if (cond & BL_MASK_FLY)
+                Strcpy(nb = eos(nb), " Fly");
+            if (cond & BL_MASK_RIDE)
+                Strcpy(nb = eos(nb), " Ride");
             break;
         default:
             Sprintf(status_vals[idx],
-                    status_fieldfmt[idx] ? status_fieldfmt[idx] : "%s", text);
+                    status_fieldfmt[idx] ? status_fieldfmt[idx] : "%s",
+                    text ? text : "");
             break;
         }
-    }
+        return; /* processed one field other than BL_FLUSH */
+    } /* (idx != BL_FLUSH) */
 
-    /* This genl version updates everything on the display, everytime */
-    newbot1[0] = '\0';
-    for (i = 0; fieldorder[0][i] != BL_FLUSH; ++i) {
-        int idx1 = fieldorder[0][i];
+    /* We've received BL_FLUSH; time to output the gathered data */
+    nb = newbot1;
+    *nb = '\0';
+    for (i = 0; (idx1 = fieldorder[0][i]) != BL_FLUSH; ++i) {
         if (status_activefields[idx1])
-            Strcat(newbot1, status_vals[idx1]);
-    }
-    newbot2[0] = '\0';
-    for (i = 0; fieldorder[1][i] != BL_FLUSH; ++i) {
-        int idx2 = fieldorder[1][i];
-        if (status_activefields[idx2])
-            Strcat(newbot2, status_vals[idx2]);
+            Strcpy(nb = eos(nb), status_vals[idx1]);
     }
+    /* if '$' is encoded, buffer length of \GXXXXNNNN is 9 greater than
+       single char; we want to subtract that 9 when checking display length */
+    lndelta = (status_activefields[BL_GOLD]
+               && strstr(status_vals[BL_GOLD], "\\G")) ? 9 : 0;
+    /* basic bot2 formats groups of second line fields into five buffers,
+       then decides how to order those buffers based on comparing lengths
+       of [sub]sets of them to the width of the map; we have more control
+       here but currently emulate that behavior */
+    for (pass = 1; pass <= 4; pass++) {
+        fieldlist = fieldorder[pass];
+        nb = newbot2;
+        *nb = '\0';
+        for (i = 0; (idx2 = fieldlist[i]) != BL_FLUSH; ++i) {
+            if (status_activefields[idx2]) {
+                const char *val = status_vals[idx2];
+
+                switch (idx2) {
+                case BL_HP: /* for pass 4, Hp comes first; mungspaces()
+                               will strip the unwanted leading spaces */
+                case BL_XP: case BL_HD:
+                case BL_TIME:
+                    Strcpy(nb = eos(nb), " ");
+                    break;
+                case BL_LEVELDESC:
+                    /* leveldesc has no leading space, so if we've moved
+                       it past the first position, provide one */
+                    if (i != 0)
+                        Strcpy(nb = eos(nb), " ");
+                    break;
+                /*
+                 * We want "  hunger encumbrance conditions"
+                 *   or    "  encumbrance conditions"
+                 *   or    "  hunger conditions"
+                 *   or    "  conditions"
+                 * 'hunger'      is either " " or " hunger_text";
+                 * 'encumbrance' is either " " or " encumbrance_text";
+                 * 'conditions'  is either ""  or " cond1 cond2...".
+                 */
+                case BL_HUNGER:
+                    /* hunger==" " - keep it, end up with " ";
+                       hunger!=" " - insert space and get "  hunger" */
+                    if (strcmp(val, " "))
+                        Strcpy(nb = eos(nb), " ");
+                    break;
+                case BL_CAP:
+                    /* cap==" " - suppress it, retain "  hunger" or " ";
+                       cap!=" " - use it, get "  hunger cap" or "  cap" */
+                    if (!strcmp(val, " "))
+                        ++val;
+                    break;
+                default:
+                    break;
+                }
+                Strcpy(nb = eos(nb), val); /* status_vals[idx2] */
+            } /* status_activefields[idx2] */
+
+            if (idx2 == BL_CONDITION && pass < 4
+                && strlen(newbot2) - lndelta > COLNO)
+                break; /* switch to next order */
+        } /* i */
+
+        if (idx2 == BL_FLUSH) { /* made it past BL_CONDITION */
+            if (pass > 1)
+                mungspaces(newbot2);
+            break;
+        }
+    } /* pass */
     curs(WIN_STATUS, 1, 0);
     putstr(WIN_STATUS, 0, newbot1);
     curs(WIN_STATUS, 1, 1);
     putmixed(WIN_STATUS, 0, newbot2); /* putmixed() due to GOLD glyph */
 }
 
-#ifdef STATUS_HILITES
+STATIC_VAR struct window_procs dumplog_windowprocs_backup;
+STATIC_VAR FILE *dumplog_file;
+
+#ifdef DUMPLOG
+STATIC_VAR time_t dumplog_now;
+
+STATIC_DCL char *FDECL(dump_fmtstr, (const char *, char *));
+
+STATIC_OVL char *
+dump_fmtstr(fmt, buf)
+const char *fmt;
+char *buf;
+{
+    const char *fp = fmt;
+    char *bp = buf;
+    int slen, len = 0;
+    char tmpbuf[BUFSZ];
+    char verbuf[BUFSZ];
+    long uid;
+    time_t now;
+
+    now = dumplog_now;
+    uid = (long) getuid();
+
+    /*
+     * Note: %t and %T assume that time_t is a 'long int' number of
+     * seconds since some epoch value.  That's quite iffy....  The
+     * unit of time might be different and the datum size might be
+     * some variant of 'long long int'.  [Their main purpose is to
+     * construct a unique file name rather than record the date and
+     * time; violating the 'long seconds since base-date' assumption
+     * may or may not interfere with that usage.]
+     */
+
+    while (fp && *fp && len < BUFSZ-1) {
+        if (*fp == '%') {
+            fp++;
+            switch (*fp) {
+            default:
+                goto finish;
+            case '\0': /* fallthrough */
+            case '%':  /* literal % */
+                Sprintf(tmpbuf, "%%");
+                break;
+            case 't': /* game start, timestamp */
+                Sprintf(tmpbuf, "%lu", (unsigned long) ubirthday);
+                break;
+            case 'T': /* current time, timestamp */
+                Sprintf(tmpbuf, "%lu", (unsigned long) now);
+                break;
+            case 'd': /* game start, YYYYMMDDhhmmss */
+                Sprintf(tmpbuf, "%08ld%06ld",
+                        yyyymmdd(ubirthday), hhmmss(ubirthday));
+                break;
+            case 'D': /* current time, YYYYMMDDhhmmss */
+                Sprintf(tmpbuf, "%08ld%06ld", yyyymmdd(now), hhmmss(now));
+                break;
+            case 'v': /* version, eg. "3.6.1-0" */
+                Sprintf(tmpbuf, "%s", version_string(verbuf));
+                break;
+            case 'u': /* UID */
+                Sprintf(tmpbuf, "%ld", uid);
+                break;
+            case 'n': /* player name */
+                Sprintf(tmpbuf, "%s", *plname ? plname : "unknown");
+                break;
+            case 'N': /* first character of player name */
+                Sprintf(tmpbuf, "%c", *plname ? *plname : 'u');
+                break;
+            }
+
+            slen = strlen(tmpbuf);
+            if (len + slen < BUFSZ-1) {
+                len += slen;
+                Sprintf(bp, "%s", tmpbuf);
+                bp += slen;
+                if (*fp) fp++;
+            } else
+                break;
+        } else {
+            *bp = *fp;
+            bp++;
+            fp++;
+            len++;
+        }
+    }
+ finish:
+    *bp = '\0';
+    return buf;
+}
+#endif /* DUMPLOG */
+
+void
+dump_open_log(now)
+time_t now;
+{
+#ifdef DUMPLOG
+    char buf[BUFSZ];
+    char *fname;
+
+    dumplog_now = now;
+#ifdef SYSCF
+    if (!sysopt.dumplogfile)
+        return;
+    fname = dump_fmtstr(sysopt.dumplogfile, buf);
+#else
+    fname = dump_fmtstr(DUMPLOG_FILE, buf);
+#endif
+    dumplog_file = fopen(fname, "w");
+    dumplog_windowprocs_backup = windowprocs;
+
+#else /*!DUMPLOG*/
+    nhUse(now);
+#endif /*?DUMPLOG*/
+}
+
 void
-genl_status_threshold(fldidx, thresholdtype, threshold, behavior, under, over)
-int fldidx, thresholdtype;
-int behavior, under, over;
-anything threshold;
+dump_close_log()
+{
+    if (dumplog_file) {
+        (void) fclose(dumplog_file);
+        dumplog_file = (FILE *) 0;
+    }
+}
+
+void
+dump_forward_putstr(win, attr, str, no_forward)
+winid win;
+int attr;
+const char *str;
+int no_forward;
+{
+    if (dumplog_file)
+        fprintf(dumplog_file, "%s\n", str);
+    if (!no_forward)
+        putstr(win, attr, str);
+}
+
+/*ARGSUSED*/
+STATIC_OVL void
+dump_putstr(win, attr, str)
+winid win UNUSED;
+int attr UNUSED;
+const char *str;
+{
+    if (dumplog_file)
+        fprintf(dumplog_file, "%s\n", str);
+}
+
+STATIC_OVL winid
+dump_create_nhwindow(dummy)
+int dummy;
+{
+    return dummy;
+}
+
+/*ARGUSED*/
+STATIC_OVL void
+dump_clear_nhwindow(win)
+winid win UNUSED;
+{
+    return;
+}
+
+/*ARGSUSED*/
+STATIC_OVL void
+dump_display_nhwindow(win, p)
+winid win UNUSED;
+boolean p UNUSED;
 {
     return;
 }
-#endif /* STATUS_HILITES */
-#endif /* STATUS_VIA_WINDOWPORT */
+
+/*ARGUSED*/
+STATIC_OVL void
+dump_destroy_nhwindow(win)
+winid win UNUSED;
+{
+    return;
+}
+
+/*ARGUSED*/
+STATIC_OVL void
+dump_start_menu(win)
+winid win UNUSED;
+{
+    return;
+}
+
+/*ARGSUSED*/
+STATIC_OVL void
+dump_add_menu(win, glyph, identifier, ch, gch, attr, str, preselected)
+winid win UNUSED;
+int glyph UNUSED;
+const anything *identifier UNUSED;
+char ch;
+char gch UNUSED;
+int attr UNUSED;
+const char *str;
+boolean preselected UNUSED;
+{
+    if (dumplog_file) {
+        if (glyph == NO_GLYPH)
+            fprintf(dumplog_file, " %s\n", str);
+        else
+            fprintf(dumplog_file, "  %c - %s\n", ch, str);
+    }
+}
+
+/*ARGSUSED*/
+STATIC_OVL void
+dump_end_menu(win, str)
+winid win UNUSED;
+const char *str;
+{
+    if (dumplog_file) {
+        if (str)
+            fprintf(dumplog_file, "%s\n", str);
+        else
+            fputs("\n", dumplog_file);
+    }
+}
+
+STATIC_OVL int
+dump_select_menu(win, how, item)
+winid win UNUSED;
+int how UNUSED;
+menu_item **item;
+{
+    *item = (menu_item *) 0;
+    return 0;
+}
+
+void
+dump_redirect(onoff_flag)
+boolean onoff_flag;
+{
+    if (dumplog_file) {
+        if (onoff_flag) {
+            windowprocs.win_create_nhwindow = dump_create_nhwindow;
+            windowprocs.win_clear_nhwindow = dump_clear_nhwindow;
+            windowprocs.win_display_nhwindow = dump_display_nhwindow;
+            windowprocs.win_destroy_nhwindow = dump_destroy_nhwindow;
+            windowprocs.win_start_menu = dump_start_menu;
+            windowprocs.win_add_menu = dump_add_menu;
+            windowprocs.win_end_menu = dump_end_menu;
+            windowprocs.win_select_menu = dump_select_menu;
+            windowprocs.win_putstr = dump_putstr;
+        } else {
+            windowprocs = dumplog_windowprocs_backup;
+        }
+        iflags.in_dumplog = onoff_flag;
+    } else {
+        iflags.in_dumplog = FALSE;
+    }
+}
 
 /*windows.c*/
index 4bbb509..8419361 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 wizard.c        $NHDT-Date: 1446078768 2015/10/29 00:32:48 $  $NHDT-Branch: master $:$NHDT-Revision: 1.42 $ */
+/* NetHack 3.6 wizard.c        $NHDT-Date: 1456618999 2016/02/28 00:23:19 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2016. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -25,21 +26,37 @@ STATIC_DCL boolean FDECL(you_have, (int));
 STATIC_DCL unsigned long FDECL(target_on, (int, struct monst *));
 STATIC_DCL unsigned long FDECL(strategy, (struct monst *));
 
+/* adding more neutral creatures will tend to reduce the number of monsters
+   summoned by nasty(); adding more lawful creatures will reduce the number
+   of monsters summoned by lawfuls; adding more chaotic creatures will reduce
+   the number of monsters summoned by chaotics; prior to 3.6.1, there were
+   only four lawful candidates, so lawful summoners tended to summon more
+   (trying to get lawful or neutral but obtaining chaotic instead) than
+   their chaotic counterparts */
 static NEARDATA const int nasties[] = {
-    PM_COCKATRICE, PM_ETTIN, PM_STALKER, PM_MINOTAUR, PM_RED_DRAGON,
-    PM_BLACK_DRAGON, PM_GREEN_DRAGON, PM_OWLBEAR, PM_PURPLE_WORM,
-    PM_ROCK_TROLL, PM_XAN, PM_GREMLIN, PM_UMBER_HULK, PM_VAMPIRE_LORD,
-    PM_XORN, PM_ZRUTY, PM_ELF_LORD, PM_ELVENKING, PM_YELLOW_DRAGON,
-    PM_LEOCROTTA, PM_BALUCHITHERIUM, PM_CARNIVOROUS_APE, PM_FIRE_GIANT,
-    PM_COUATL, PM_CAPTAIN, PM_WINGED_GARGOYLE, PM_MASTER_MIND_FLAYER,
-    PM_FIRE_ELEMENTAL, PM_JABBERWOCK, PM_ARCH_LICH, PM_OGRE_KING, PM_OLOG_HAI,
-    PM_IRON_GOLEM, PM_OCHRE_JELLY, PM_GREEN_SLIME, PM_DISENCHANTER
+    /* neutral */
+    PM_COCKATRICE, PM_ETTIN, PM_STALKER, PM_MINOTAUR,
+    PM_OWLBEAR, PM_PURPLE_WORM, PM_XAN, PM_UMBER_HULK,
+    PM_XORN, PM_ZRUTY, PM_LEOCROTTA, PM_BALUCHITHERIUM,
+    PM_CARNIVOROUS_APE, PM_FIRE_ELEMENTAL, PM_JABBERWOCK,
+    PM_IRON_GOLEM, PM_OCHRE_JELLY, PM_GREEN_SLIME,
+    /* chaotic */
+    PM_BLACK_DRAGON, PM_RED_DRAGON, PM_ARCH_LICH, PM_VAMPIRE_LORD,
+    PM_MASTER_MIND_FLAYER, PM_DISENCHANTER, PM_WINGED_GARGOYLE,
+    PM_STORM_GIANT, PM_OLOG_HAI, PM_ELF_LORD, PM_ELVENKING,
+    PM_OGRE_KING, PM_CAPTAIN, PM_GREMLIN,
+    /* lawful */
+    PM_SILVER_DRAGON, PM_ORANGE_DRAGON, PM_GREEN_DRAGON,
+    PM_YELLOW_DRAGON, PM_GUARDIAN_NAGA, PM_FIRE_GIANT,
+    PM_ALEAX, PM_COUATL, PM_HORNED_DEVIL, PM_BARBED_DEVIL,
+    /* (titans, ki-rin, and golden nagas are suitably nasty, but
+       they're summoners so would aggravate excessive summoning) */
 };
 
 static NEARDATA const unsigned wizapp[] = {
     PM_HUMAN,      PM_WATER_DEMON,  PM_VAMPIRE,       PM_RED_DRAGON,
     PM_TROLL,      PM_UMBER_HULK,   PM_XORN,          PM_XAN,
-    PM_COCKATRICE, PM_FLOATING_EYE, PM_GUARDIAN_NAGA, PM_TRAPPER
+    PM_COCKATRICE, PM_FLOATING_EYE, PM_GUARDIAN_NAGA, PM_TRAPPER,
 };
 
 /* If you've found the Amulet, make the Wizard appear after some time */
@@ -120,7 +137,8 @@ register struct monst *mtmp;
     register struct obj *otmp;
 
     for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
-        if (otmp->otyp == AMULET_OF_YENDOR || is_quest_artifact(otmp)
+        if (otmp->otyp == AMULET_OF_YENDOR
+            || any_quest_artifact(otmp)
             || otmp->otyp == BELL_OF_OPENING
             || otmp->otyp == CANDELABRUM_OF_INVOCATION
             || otmp->otyp == SPE_BOOK_OF_THE_DEAD)
@@ -176,7 +194,7 @@ register short otyp;
         if (otyp) {
             if (otmp->otyp == otyp)
                 return 1;
-        } else if (is_quest_artifact(otmp))
+        } else if (any_quest_artifact(otmp))
             return 1;
     }
     return 0;
@@ -208,7 +226,7 @@ register short otyp;
         if (otyp) {
             if (otmp->otyp == otyp)
                 return otmp;
-        } else if (is_quest_artifact(otmp))
+        } else if (any_quest_artifact(otmp))
             return otmp;
     return (struct obj *) 0;
 }
@@ -323,11 +341,49 @@ register struct monst *mtmp;
     return dstrat;
 }
 
+void
+choose_stairs(sx, sy)
+xchar *sx;
+xchar *sy;
+{
+    xchar x = 0, y = 0;
+
+    if (builds_up(&u.uz)) {
+        if (xdnstair) {
+            x = xdnstair;
+            y = ydnstair;
+        } else if (xdnladder) {
+            x = xdnladder;
+            y = ydnladder;
+        }
+    } else {
+        if (xupstair) {
+            x = xupstair;
+            y = yupstair;
+        } else if (xupladder) {
+            x = xupladder;
+            y = yupladder;
+        }
+    }
+
+    if (!x && sstairs.sx) {
+        x = sstairs.sx;
+        y = sstairs.sy;
+    }
+
+    if (x && y) {
+        *sx = x;
+        *sy = y;
+    }
+
+}
+
 int
 tactics(mtmp)
 register struct monst *mtmp;
 {
     unsigned long strat = strategy(mtmp);
+    xchar sx = 0, sy = 0;
 
     mtmp->mstrategy =
         (mtmp->mstrategy & (STRAT_WAITMASK | STRAT_APPEARMSG)) | strat;
@@ -335,15 +391,17 @@ register struct monst *mtmp;
     switch (strat) {
     case STRAT_HEAL: /* hide and recover */
         /* if wounded, hole up on or near the stairs (to block them) */
-        /* unless, of course, there are no stairs (e.g. endlevel) */
+        choose_stairs(&sx, &sy);
         mtmp->mavenge = 1; /* covetous monsters attack while fleeing */
         if (In_W_tower(mtmp->mx, mtmp->my, &u.uz)
-            || (mtmp->iswiz && !xupstair && !mon_has_amulet(mtmp))) {
+            || (mtmp->iswiz && !sx && !mon_has_amulet(mtmp))) {
             if (!rn2(3 + mtmp->mhp / 10))
                 (void) rloc(mtmp, TRUE);
-        } else if (xupstair
-                   && (mtmp->mx != xupstair || mtmp->my != yupstair)) {
-            (void) mnearto(mtmp, xupstair, yupstair, TRUE);
+        } else if (sx && (mtmp->mx != sx || mtmp->my != sy)) {
+            if (!mnearto(mtmp, sx, sy, TRUE)) {
+                m_into_limbo(mtmp);
+                return 0;
+            }
         }
         /* if you're not around, cast healing spells */
         if (distu(mtmp->mx, mtmp->my) > (BOLT_LIM * BOLT_LIM))
@@ -351,7 +409,7 @@ register struct monst *mtmp;
                 mtmp->mhp += rnd(8);
                 return 1;
             }
-    /* fall through :-) */
+        /*FALLTHRU*/
 
     case STRAT_NONE: /* harass */
         if (!rn2(!mtmp->mflee ? 5 : 33))
@@ -403,7 +461,8 @@ register struct monst *mtmp;
                 return 0;
             }
         } else { /* a monster has it - 'port beside it. */
-            (void) mnearto(mtmp, tx, ty, FALSE);
+            if (!mnearto(mtmp, tx, ty, FALSE))
+                m_into_limbo(mtmp);
             return 0;
         }
     }
@@ -412,14 +471,40 @@ register struct monst *mtmp;
     return 0;
 }
 
+/* are there any monsters mon could aggravate? */
+boolean
+has_aggravatables(mon)
+struct monst *mon;
+{
+    struct monst *mtmp;
+    boolean in_w_tower = In_W_tower(mon->mx, mon->my, &u.uz);
+
+    if (in_w_tower != In_W_tower(u.ux, u.uy, &u.uz))
+        return FALSE;
+
+    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+        if (DEADMONSTER(mtmp))
+            continue;
+        if (in_w_tower != In_W_tower(mtmp->mx, mtmp->my, &u.uz))
+            continue;
+        if ((mtmp->mstrategy & STRAT_WAITFORU) != 0
+            || mtmp->msleeping || !mtmp->mcanmove)
+            return TRUE;
+    }
+    return FALSE;
+}
+
 void
 aggravate()
 {
     register struct monst *mtmp;
+    boolean in_w_tower = In_W_tower(u.ux, u.uy, &u.uz);
 
     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
         if (DEADMONSTER(mtmp))
             continue;
+        if (in_w_tower != In_W_tower(mtmp->mx, mtmp->my, &u.uz))
+            continue;
         mtmp->mstrategy &= ~(STRAT_WAITFORU | STRAT_APPEARMSG);
         mtmp->msleeping = 0;
         if (!mtmp->mcanmove && !rn2(5)) {
@@ -466,57 +551,88 @@ pick_nasty()
     return res;
 }
 
-/* create some nasty monsters, aligned or neutral with the caster */
-/* a null caster defaults to a chaotic caster (e.g. the wizard) */
+/* create some nasty monsters, aligned with the caster or neutral; chaotic
+   and unaligned are treated as equivalent; if summoner is Null, this is
+   for late-game harassment (after the Wizard has been killed at least once
+   or the invocation ritual has been performed), in which case we treat
+   'summoner' as neutral, since that will produce the greatest number of
+   creatures on average (in 3.6.0 and earlier, Null was treated as chaotic);
+   returns the number of monsters created */
 int
-nasty(mcast)
-struct monst *mcast;
+nasty(summoner)
+struct monst *summoner;
 {
     register struct monst *mtmp;
-    register int i, j, tmp;
-    int castalign = (mcast ? sgn(mcast->data->maligntyp) : -1);
+    register int i, j;
+    int castalign = (summoner ? sgn(summoner->data->maligntyp) : 0);
     coord bypos;
-    int count, census;
+    int count, census, tmp, makeindex, s_cls, m_cls;
+
+#define MAXNASTIES 10 /* more than this can be created */
 
     /* some candidates may be created in groups, so simple count
        of non-null makemon() return is inadequate */
     census = monster_census(FALSE);
 
     if (!rn2(10) && Inhell) {
+        /* this might summon a demon prince or lord */
         count = msummon((struct monst *) 0); /* summons like WoY */
     } else {
         count = 0;
-        tmp = (u.ulevel > 3) ? u.ulevel / 3 : 1; /* just in case -- rph */
-        /* if we don't have a casting monster, the nasties appear around you
-         */
+        s_cls = summoner ? summoner->data->mlet : 0;
+        tmp = (u.ulevel > 3) ? u.ulevel / 3 : 1;
+        /* if we don't have a casting monster, nasties appear around hero,
+           otherwise they'll appear around spot summoner thinks she's at */
         bypos.x = u.ux;
         bypos.y = u.uy;
-        for (i = rnd(tmp); i > 0; --i)
+        for (i = rnd(tmp); i > 0 && count < MAXNASTIES; --i)
+            /* Of the 42 nasties[], 10 are lawful, 14 are chaotic,
+             * and 18 are neutral.
+             *
+             * Neutral caster, used for late-game harrassment,
+             * has 18/42 chance to stop the inner loop on each
+             * critter, 24/42 chance for another iteration.
+             * Lawful caster has 28/42 chance to stop unless the
+             * summoner is an angel or demon, in which case the
+             * chance is 26/42.
+             * Chaotic or unaligned caster has 32/42 chance to
+             * stop, so will summon fewer creatures on average.
+             *
+             * The outer loop potentially gives chaotic/unaligned
+             * a chance to even things up since others will hit
+             * MAXNASTIES sooner, but its number of iterations is
+             * randomized so it won't always do so.
+             */
             for (j = 0; j < 20; j++) {
-                int makeindex;
-
                 /* Don't create more spellcasters of the monsters' level or
                  * higher--avoids chain summoners filling up the level.
                  */
                 do {
                     makeindex = pick_nasty();
-                } while (mcast && attacktype(&mons[makeindex], AT_MAGC)
-                         && monstr[makeindex] >= monstr[mcast->mnum]);
+                    m_cls = mons[makeindex].mlet;
+                } while (summoner
+                         && ((attacktype(&mons[makeindex], AT_MAGC)
+                              && monstr[makeindex] >= monstr[summoner->mnum])
+                             || (s_cls == S_DEMON && m_cls == S_ANGEL)
+                             || (s_cls == S_ANGEL && m_cls == S_DEMON)));
                 /* do this after picking the monster to place */
-                if (mcast
-                    && !enexto(&bypos, mcast->mux, mcast->muy,
-                               &mons[makeindex]))
+                if (summoner && !enexto(&bypos, summoner->mux, summoner->muy,
+                                        &mons[makeindex]))
                     continue;
+                /* this honors genocide but overrides extinction; it ignores
+                   inside-hell-only (G_HELL) & outside-hell-only (G_NOHELL) */
                 if ((mtmp = makemon(&mons[makeindex], bypos.x, bypos.y,
                                     NO_MM_FLAGS)) != 0) {
                     mtmp->msleeping = mtmp->mpeaceful = mtmp->mtame = 0;
                     set_malign(mtmp);
-                } else /* GENOD? */
+                } else /* random monster to substitute for geno'd selection */
                     mtmp = makemon((struct permonst *) 0, bypos.x, bypos.y,
                                    NO_MM_FLAGS);
                 if (mtmp) {
-                    count++;
-                    if (mtmp->data->maligntyp == 0
+                    /* delay first use of spell or breath attack */
+                    mtmp->mspec_used = rnd(4);
+                    if (++count >= MAXNASTIES
+                        || mtmp->data->maligntyp == 0
                         || sgn(mtmp->data->maligntyp) == castalign)
                         break;
                 }
@@ -728,11 +844,12 @@ register struct monst *mtmp;
                       random_malediction[rn2(SIZE(random_malediction))],
                       random_insult[rn2(SIZE(random_insult))]);
 #endif
-    } else if (is_lminion(mtmp)) {
+    } else if (is_lminion(mtmp)
+               && !(mtmp->isminion && EMIN(mtmp)->renegade)) {
         com_pager(rn2(QTN_ANGELIC - 1 + (Hallucination ? 1 : 0))
                   + QT_ANGELIC);
     } else {
-        if (!rn2(5))
+        if (!rn2(is_minion(mtmp->data) ? 100 : 5))
 /*JP
             pline("%s casts aspersions on your ancestry.", Monnam(mtmp));
 */
index aed90fb..f39a0a7 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 worm.c  $NHDT-Date: 1446887540 2015/11/07 09:12:20 $  $NHDT-Branch: master $:$NHDT-Revision: 1.19 $ */
+/* NetHack 3.6 worm.c  $NHDT-Date: 1456528599 2016/02/26 23:16:39 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2009. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -94,11 +95,9 @@ get_wormno()
 
     while (new_wormno < MAX_NUM_WORMS) {
         if (!wheads[new_wormno])
-            return new_wormno; /* found an empty wtails[] slot at new_wormno
-                                  */
+            return new_wormno; /* found empty wtails[] slot at new_wormno */
         new_wormno++;
     }
-
     return 0; /* level infested with worms */
 }
 
@@ -301,11 +300,9 @@ register struct monst *worm;
     /*  if (!wnum) return;  bullet proofing */
 
     /*  This does not work right now because mattacku() thinks that the head
-     * is
-     *  out of range of the player.  We might try to kludge, and bring the
-     * head
-     *  within range for a tiny moment, but this needs a bit more looking at
-     *  before we decide to do this.
+     *  is out of range of the player.  We might try to kludge, and bring
+     *  the head within range for a tiny moment, but this needs a bit more
+     *  looking at before we decide to do this.
      */
     for (seg = wtails[wnum]; seg; seg = seg->nseg)
         if (distu(seg->wx, seg->wy) < 3)
@@ -378,7 +375,6 @@ struct obj *weap;
      *  it's head at "curr" and its tail at "new_tail".  The old worm
      *  must be at least level 3 in order to produce a new worm.
      */
-
     new_worm = 0;
     new_wnum = (worm->m_lev >= 3 && !rn2(3)) ? get_wormno() : 0;
     if (new_wnum) {
@@ -593,6 +589,28 @@ struct monst *worm;
     }
 }
 
+void
+sanity_check_worm(worm)
+struct monst *worm;
+{
+    struct wseg *curr;
+
+    if (!worm)
+        panic("no worm!");
+    if (!worm->wormno)
+        panic("not a worm?!");
+
+    curr = wtails[worm->wormno];
+
+    while (curr != wheads[worm->wormno]) {
+        if (!isok(curr->wx, curr->wy))
+            panic("worm seg not isok");
+        if (level.monsters[curr->wx][curr->wy] != worm)
+            panic("worm not at seg location");
+        curr = curr->nseg;
+    }
+}
+
 /*
  *  remove_worm()
  *
@@ -701,23 +719,28 @@ register xchar *nx, *ny;
               : (y > 1 ? (y < ROWNO ? (rn2(3) - 1) : -rn2(2)) : rn2(2)));
 }
 
+/* for size_monst(cmd.c) to support #stats */
+int
+size_wseg(worm)
+struct monst *worm;
+{
+    return (int) (count_wsegs(worm) * sizeof (struct wseg));
+}
+
 /*  count_wsegs()
- *  returns the number of visible segments that a worm has.
+ *  returns the number of segments that a worm has.
  */
 int
 count_wsegs(mtmp)
 struct monst *mtmp;
 {
     register int i = 0;
-    register struct wseg *curr = (wtails[mtmp->wormno])->nseg;
+    register struct wseg *curr;
 
-    /*  if (!mtmp->wormno) return 0;  bullet proofing */
-
-    while (curr) {
-        i++;
-        curr = curr->nseg;
+    if (mtmp->wormno) {
+        for (curr = wtails[mtmp->wormno]->nseg; curr; curr = curr->nseg)
+            i++;
     }
-
     return i;
 }
 
@@ -821,4 +844,29 @@ int x1, y1, x2, y2;
     return FALSE;
 }
 
+/* construct an index number for a worm tail segment */
+int
+wseg_at(worm, x, y)
+struct monst *worm;
+int x, y;
+{
+    int res = 0;
+
+    if (worm && worm->wormno && m_at(x, y) == worm) {
+        struct wseg *curr;
+        int i, n;
+        xchar wx = (xchar) x, wy = (xchar) y;
+
+        for (i = 0, curr = wtails[worm->wormno]; curr; curr = curr->nseg) {
+            if (curr->wx == wx && curr->wy == wy)
+                break;
+            ++i;
+        }
+        for (n = i; curr; curr = curr->nseg)
+            ++n;
+        res = n - i;
+    }
+    return res;
+}
+
 /*worm.c*/
index dca7db1..92b33fe 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 worn.c  $NHDT-Date: 1446887541 2015/11/07 09:12:21 $  $NHDT-Branch: master $:$NHDT-Revision: 1.47 $ */
+/* NetHack 3.6 worn.c  $NHDT-Date: 1496959481 2017/06/08 22:04:41 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -36,11 +37,11 @@ const struct worn {
              { 0, 0 } };
 
 /* This only allows for one blocking item per property */
-#define w_blocks(o, m)                                                     \
-    ((o->otyp == MUMMY_WRAPPING && ((m) &W_ARMC))                          \
-         ? INVIS                                                           \
-         : (o->otyp == CORNUTHAUM && ((m) &W_ARMH) && !Role_if(PM_WIZARD)) \
-               ? CLAIRVOYANT                                               \
+#define w_blocks(o, m) \
+    ((o->otyp == MUMMY_WRAPPING && ((m) & W_ARMC))                          \
+         ? INVIS                                                            \
+         : (o->otyp == CORNUTHAUM && ((m) & W_ARMH) && !Role_if(PM_WIZARD)) \
+               ? CLAIRVOYANT                                                \
                : 0)
 /* note: monsters don't have clairvoyance, so your role
    has no significant effect on their use of w_blocks() */
@@ -82,6 +83,9 @@ long mask;
                         if (oobj->oartifact)
                             set_artifact_intrinsic(oobj, 0, mask);
                     }
+                    /* in case wearing or removal is in progress or removal
+                       is pending (via 'A' command for multiple items) */
+                    cancel_doff(oobj, wp->w_mask);
                 }
                 *(wp->w_obj) = obj;
                 if (obj) {
@@ -124,6 +128,10 @@ register struct obj *obj;
         u.twoweap = 0;
     for (wp = worn; wp->w_mask; wp++)
         if (obj == *(wp->w_obj)) {
+            /* in case wearing or removal is in progress or removal
+               is pending (via 'A' command for multiple items) */
+            cancel_doff(obj, wp->w_mask);
+
             *(wp->w_obj) = 0;
             p = objects[obj->otyp].oc_oprop;
             u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask;
@@ -632,7 +640,7 @@ outer_break:
                       simpleonames(best), otense(best, "glow"),
                       hcolor(NH_BLACK));
 #else
-                pline("%s%s\82Í\82µ\82Î\82ç\82­%s\8bP\82¢\82½\81D", s_suffix(Monnam(mon)),
+                pline("%s\82Ì%s\82Í\82µ\82Î\82ç\82­%s\8bP\82¢\82½\81D", Monnam(mon),
                       simpleonames(best),
                       jconj_adj(hcolor(NH_BLACK)));
 #endif
index 2e82397..8e93f20 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 write.c $NHDT-Date: 1446078770 2015/10/29 00:32:50 $  $NHDT-Branch: master $:$NHDT-Revision: 1.16 $ */
+/* NetHack 3.6 write.c $NHDT-Date: 1450261366 2015/12/16 10:22:46 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.17 $ */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -63,7 +63,7 @@ register struct obj *otmp;
 }
 
 /* decide whether the hero knowns a particular scroll's label;
-   unfortunately, we can't track things are haven't been added to
+   unfortunately, we can't track things that haven't been added to
    the discoveries list and aren't present in current inventory,
    so some scrolls with ought to yield True will end up False */
 STATIC_OVL boolean
@@ -101,9 +101,9 @@ register struct obj *pen;
 {
     register struct obj *paper;
 #if 0 /*JP*/
-    char namebuf[BUFSZ], *nm, *bp;
+    char namebuf[BUFSZ] = DUMMY, *nm, *bp;
 #else
-    char namebuf[BUFSZ], *nm;
+    char namebuf[BUFSZ] = DUMMY, *nm;
 #endif
     register struct obj *new_obj;
     int basecost, actualcost;
@@ -156,7 +156,7 @@ register struct obj *pen;
             You("don't know if that %s is blank or not.", typeword);
 */
             You("%s\82ª\94\92\8e\86\82©\82Ç\82¤\82©\82í\82©\82ç\82È\82¢\81I", typeword);
-            return 1;
+            return 0;
         } else if (paper->oclass == SPBOOK_CLASS) {
             /* can't write a magic book while blind */
 /*JP
@@ -164,7 +164,7 @@ register struct obj *pen;
 */
             pline("%s\82Å\82Í\93_\8e\9a\82ð\8dì\82ê\82È\82¢\81D",
                   upstart(ysimple_name(pen)));
-            return 1;
+            return 0;
         }
     }
     paper->dknown = 1;
@@ -421,17 +421,26 @@ found:
     new_obj->cursed = (curseval < 0);
 #ifdef MAIL
     if (new_obj->otyp == SCR_MAIL)
-        new_obj->spe = 1;
+        /* 0: delivered in-game via external event (or randomly for fake mail);
+           1: from bones or wishing; 2: written with marker */
+        new_obj->spe = 2;
 #endif
+    /* unlike alchemy, for example, a successful result yields the
+       specifically chosen item so hero recognizes it even if blind;
+       the exception is for being lucky writing an undiscovered scroll,
+       where the label associated with the type-name isn't known yet */
+    new_obj->dknown = label_known(new_obj->otyp, invent) ? 1 : 0;
+
 #if 0 /*JP*/
-    new_obj =
-        hold_another_object(new_obj, "Oops!  %s out of your grasp!",
-                            The(aobjnam(new_obj, "slip")), (const char *) 0);
+    new_obj = hold_another_object(new_obj, "Oops!  %s out of your grasp!",
+                                  The(aobjnam(new_obj, "slip")),
+                                  (const char *) 0);
 #else
     new_obj =
         hold_another_object(new_obj, "\82¨\82Á\82Æ\81I%s\82Í\82 \82È\82½\82Ì\8eè\82©\82ç\8a\8a\82è\97\8e\82¿\82½\81I",
                             xname(new_obj), (const char *) 0);
 #endif
+    nhUse(new_obj); /* try to avoid complaint about dead assignment */
     return 1;
 }
 
index 514f14d..02772f9 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -1,5 +1,6 @@
-/* NetHack 3.6 zap.c   $NHDT-Date: 1447987787 2015/11/20 02:49:47 $  $NHDT-Branch: master $:$NHDT-Revision: 1.236 $ */
+/* NetHack 3.6 zap.c   $NHDT-Date: 1524470244 2018/04/23 07:57:24 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.275 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -63,12 +64,12 @@ STATIC_VAR const char are_blinded_by_the_flash[] =
 */
     "\82Ü\82Î\82ä\82¢\8cõ\82Å\96Ú\82ª\8c©\82¦\82È\82­\82È\82Á\82½\81I";
 
-const char *const flash_types[] =
-    {                  /* also used in buzzmu(mcastu.c) */
+const char *const flash_types[] =       /* also used in buzzmu(mcastu.c) */
+    {
 #if 0 /*JP*/
-      "magic missile", /* Wands must be 0-9 */
-      "bolt of fire", "bolt of cold", "sleep ray", "death ray",
-      "bolt of lightning", "", "", "", "",
+        "magic missile", /* Wands must be 0-9 */
+        "bolt of fire", "bolt of cold", "sleep ray", "death ray",
+        "bolt of lightning", "", "", "", "",
 #else
         "\96\82\96@\82Ì\96î", /* Wands must be 0-9 */
         "\89Î\82Ì\91M\8cõ",
@@ -83,10 +84,10 @@ const char *const flash_types[] =
 #endif
 
 #if 0 /*JP*/
-      "magic missile", /* Spell equivalents must be 10-19 */
-      "fireball", "cone of cold", "sleep ray", "finger of death",
-      "bolt of lightning", /* There is no spell, used for retribution */
-      "", "", "", "",
+        "magic missile", /* Spell equivalents must be 10-19 */
+        "fireball", "cone of cold", "sleep ray", "finger of death",
+        "bolt of lightning", /* there is no spell, used for retribution */
+        "", "", "", "",
 #else
         "\96\82\96@\82Ì\96î", /* Spell equivalents must be 10-19 */
         "\89Î\82Ì\8bÊ",
@@ -101,10 +102,10 @@ const char *const flash_types[] =
 #endif
 
 #if 0 /*JP*/
-      "blast of missiles", /* Dragon breath equivalents 20-29*/
-      "blast of fire", "blast of frost", "blast of sleep gas",
-      "blast of disintegration", "blast of lightning", "blast of poison gas",
-      "blast of acid", "", ""
+        "blast of missiles", /* Dragon breath equivalents 20-29*/
+        "blast of fire", "blast of frost", "blast of sleep gas",
+        "blast of disintegration", "blast of lightning",
+        "blast of poison gas", "blast of acid", "", ""
 #else
         "\96\82\96@\82Ì\96î\82Ì\91§", /* Dragon breath equivalents 20-29*/
         "\89Î\82Ì\91§",
@@ -184,18 +185,20 @@ struct obj *otmp;
     boolean wake = TRUE; /* Most 'zaps' should wake monster */
     boolean reveal_invis = FALSE, learn_it = FALSE;
     boolean dbldam = Role_if(PM_KNIGHT) && u.uhave.questart;
+    boolean helpful_gesture = FALSE;
     int dmg, otyp = otmp->otyp;
 /*JP
     const char *zap_type_text = "spell";
 */
     const char *zap_type_text = "\96\82\96@";
     struct obj *obj;
-    boolean disguised_mimic =
-        (mtmp->data->mlet == S_MIMIC && mtmp->m_ap_type != M_AP_NOTHING);
+    boolean disguised_mimic = (mtmp->data->mlet == S_MIMIC
+                               && mtmp->m_ap_type != M_AP_NOTHING);
 
     if (u.uswallow && mtmp == u.ustuck)
         reveal_invis = FALSE;
 
+    notonhead = (mtmp->mx != bhitpos.x || mtmp->my != bhitpos.y);
     switch (otyp) {
     case WAN_STRIKING:
 /*JP
@@ -205,6 +208,8 @@ struct obj *otmp;
     /* fall through */
     case SPE_FORCE_BOLT:
         reveal_invis = TRUE;
+        if (disguised_mimic)
+            seemimic(mtmp);
         if (resists_magm(mtmp)) { /* match effect on player */
             shieldeff(mtmp->mx, mtmp->my);
 /*JP
@@ -227,6 +232,8 @@ struct obj *otmp;
     case WAN_SLOW_MONSTER:
     case SPE_SLOW_MONSTER:
         if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
+            if (disguised_mimic)
+                seemimic(mtmp);
             mon_adjust_speed(mtmp, -1, otmp);
             m_dowear(mtmp, FALSE); /* might want speed boots */
             if (u.uswallow && (mtmp == u.ustuck) && is_whirly(mtmp->data)) {
@@ -244,9 +251,13 @@ struct obj *otmp;
         break;
     case WAN_SPEED_MONSTER:
         if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
+            if (disguised_mimic)
+                seemimic(mtmp);
             mon_adjust_speed(mtmp, 1, otmp);
             m_dowear(mtmp, FALSE); /* might want speed boots */
         }
+        if (mtmp->mtame)
+            helpful_gesture = TRUE;
         break;
     case WAN_UNDEAD_TURNING:
     case SPE_TURN_UNDEAD:
@@ -276,11 +287,17 @@ struct obj *otmp;
                it guard against involuntary polymorph attacks too... */
             shieldeff(mtmp->mx, mtmp->my);
         } else if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
+            boolean polyspot = (otyp != POT_POLYMORPH),
+                    give_msg = (!Hallucination
+                                && (canseemon(mtmp)
+                                    || (u.uswallow && mtmp == u.ustuck)));
+
             /* dropped inventory (due to death by system shock,
                or loss of wielded weapon and/or worn armor due to
                limitations of new shape) won't be hit by this zap */
-            for (obj = mtmp->minvent; obj; obj = obj->nobj)
-                bypass_obj(obj);
+            if (polyspot)
+                for (obj = mtmp->minvent; obj; obj = obj->nobj)
+                    bypass_obj(obj);
             /* natural shapechangers aren't affected by system shock
                (unless protection from shapechangers is interfering
                with their metabolism...) */
@@ -294,26 +311,39 @@ struct obj *otmp;
                 }
                 /* context.bypasses = TRUE; ## for make_corpse() */
                 /* no corpse after system shock */
-                xkilled(mtmp, 3);
+                xkilled(mtmp, XKILL_GIVEMSG | XKILL_NOCORPSE);
             } else if (newcham(mtmp, (struct permonst *) 0,
-                               (otyp != POT_POLYMORPH), FALSE)) {
-                if (!Hallucination && canspotmon(mtmp))
+                               polyspot, give_msg) != 0
+                       /* if shapechange failed because there aren't
+                          enough eligible candidates (most likely for
+                          vampshifter), try reverting to original form */
+                       || (mtmp->cham >= LOW_PM
+                           && newcham(mtmp, &mons[mtmp->cham],
+                                      polyspot, give_msg) != 0)) {
+                if (give_msg && (canspotmon(mtmp)
+                                 || (u.uswallow && mtmp == u.ustuck)))
                     learn_it = TRUE;
             }
         }
         break;
     case WAN_CANCELLATION:
     case SPE_CANCELLATION:
+        if (disguised_mimic)
+            seemimic(mtmp);
         (void) cancel_monst(mtmp, otmp, TRUE, TRUE, FALSE);
         break;
     case WAN_TELEPORTATION:
     case SPE_TELEPORT_AWAY:
+        if (disguised_mimic)
+            seemimic(mtmp);
         reveal_invis = !u_teleport_mon(mtmp, TRUE);
         break;
     case WAN_MAKE_INVISIBLE: {
         int oldinvis = mtmp->minvis;
         char nambuf[BUFSZ];
 
+        if (disguised_mimic)
+            seemimic(mtmp);
         /* format monster's name before altering its visibility */
         Strcpy(nambuf, Monnam(mtmp));
         mon_set_minvis(mtmp);
@@ -322,6 +352,7 @@ struct obj *otmp;
             pline("%s turns transparent!", nambuf);
 */
             pline("%s\82Í\93§\96¾\82É\82È\82Á\82½\81I", nambuf);
+            reveal_invis = TRUE;
             learn_it = TRUE;
         }
         break;
@@ -368,7 +399,7 @@ struct obj *otmp;
             Sprintf(buf, "%s %s", s_suffix(Monnam(mtmp)),
                     distant_name(obj, xname));
 #else
-            Sprintf(buf, "%s\82Ì%s", s_suffix(Monnam(mtmp)),
+            Sprintf(buf, "%s\82Ì%s", Monnam(mtmp),
                     distant_name(obj, xname));
 #endif
             if (cansee(mtmp->mx, mtmp->my)) {
@@ -466,19 +497,22 @@ struct obj *otmp;
             wake = FALSE;
         break;
     case SPE_DRAIN_LIFE:
+        if (disguised_mimic)
+            seemimic(mtmp);
         dmg = monhp_per_lvl(mtmp);
         if (dbldam)
             dmg *= 2;
         if (otyp == SPE_DRAIN_LIFE)
             dmg = spell_damage_bonus(dmg);
-        if (resists_drli(mtmp))
+        if (resists_drli(mtmp)) {
             shieldeff(mtmp->mx, mtmp->my);
-        else if (!resist(mtmp, otmp->oclass, dmg, NOTELL) && mtmp->mhp > 0) {
+        else if (!resist(mtmp, otmp->oclass, dmg, NOTELL) && mtmp->mhp > 0) {
             mtmp->mhp -= dmg;
             mtmp->mhpmax -= dmg;
-            if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1)
-                xkilled(mtmp, 1);
-            else {
+            /* die if already level 0, regardless of hit points */
+            if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1) {
+                killed(mtmp);
+            } else {
                 mtmp->m_lev--;
                 if (canseemon(mtmp))
 /*JP
@@ -497,7 +531,7 @@ struct obj *otmp;
     }
     if (wake) {
         if (mtmp->mhp > 0) {
-            wakeup(mtmp);
+            wakeup(mtmp, helpful_gesture ? FALSE : TRUE);
             m_respond(mtmp);
             if (mtmp->isshk && !*u.ushops)
                 hot_pursuit(mtmp);
@@ -539,7 +573,8 @@ struct monst *mtmp;
                     otmp->cknown = 1;
             }
         }
-        (void) display_minventory(mtmp, MINV_ALL | MINV_NOLET, (char *) 0);
+        (void) display_minventory(mtmp, MINV_ALL | MINV_NOLET | PICK_NONE,
+                                  (char *) 0);
     } else {
 #if 0 /*JP*/
         pline("%s is not carrying anything%s.", noit_Monnam(mtmp),
@@ -653,9 +688,9 @@ coord *cc;
         if (mtmp->m_id) {
             mtmp2->m_id = mtmp->m_id;
             /* might be bringing quest leader back to life */
-            if (quest_status.leader_is_dead &&
+            if (quest_status.leader_is_dead
                 /* leader_is_dead implies leader_m_id is valid */
-                mtmp2->m_id == quest_status.leader_m_id)
+                && mtmp2->m_id == quest_status.leader_m_id)
                 quest_status.leader_is_dead = FALSE;
         }
         mtmp2->mx = mtmp->mx;
@@ -691,6 +726,16 @@ coord *cc;
         mtmp2->mblinded = 0;
         mtmp2->mstun = 0;
         mtmp2->mconf = 0;
+        /* when traits are for a shopeekper, dummy monster 'mtmp' won't
+           have necessary eshk data for replmon() -> replshk() */
+        if (mtmp2->isshk) {
+            neweshk(mtmp);
+            *ESHK(mtmp) = *ESHK(mtmp2);
+            if (ESHK(mtmp2)->bill_p != 0
+                && ESHK(mtmp2)->bill_p != (struct bill_x *) -1000)
+                ESHK(mtmp)->bill_p = &(ESHK(mtmp)->bill[0]);
+            mtmp->isshk = 1;
+        }
         replmon(mtmp, mtmp2);
         newsym(mtmp2->mx, mtmp2->my); /* Might now be invisible */
 
@@ -739,6 +784,8 @@ int *container_nesting;
 /*
  * Attempt to revive the given corpse, return the revived monster if
  * successful.  Note: this does NOT use up the corpse if it fails.
+ * If corpse->quan is more than 1, only one corpse will be affected
+ * and only one monster will be resurrected.
  */
 struct monst *
 revive(corpse, by_hero)
@@ -750,6 +797,7 @@ boolean by_hero;
     struct obj *container;
     coord xy;
     xchar x, y;
+    boolean one_of;
     int montype, container_nesting = 0;
 
     if (corpse->otyp != CORPSE) {
@@ -784,16 +832,16 @@ boolean by_hero;
             break; /* x,y are 0 */
         }
     }
-    if (!x || !y ||
+    if (!x || !y
         /* Rules for revival from containers:
-           - the container cannot be locked
-           - the container cannot be heavily nested (>2 is arbitrary)
-           - the container cannot be a statue or bag of holding
-           (except in very rare cases for the latter)
-        */
-        (container && (container->olocked || container_nesting > 2
-                       || container->otyp == STATUE
-                       || (container->otyp == BAG_OF_HOLDING && rn2(40)))))
+         *  - the container cannot be locked
+         *  - the container cannot be heavily nested (>2 is arbitrary)
+         *  - the container cannot be a statue or bag of holding
+         *    (except in very rare cases for the latter)
+         */
+        || (container && (container->olocked || container_nesting > 2
+                          || container->otyp == STATUE
+                          || (container->otyp == BAG_OF_HOLDING && rn2(40)))))
         return (struct monst *) 0;
 
     /* record the object's location now that we're sure where it is */
@@ -810,7 +858,9 @@ boolean by_hero;
             x = xy.x, y = xy.y;
     }
 
-    if (mons[montype].mlet == S_EEL && !IS_POOL(levl[x][y].typ)) {
+    if ((mons[montype].mlet == S_EEL && !IS_POOL(levl[x][y].typ))
+        || (mons[montype].mlet == S_TROLL
+            && uwep && uwep->oartifact == ART_TROLLSBANE)) {
         if (by_hero && cansee(x,y))
 /*JP
             pline("%s twitches feebly.",
@@ -859,32 +909,45 @@ boolean by_hero;
     if (mtmp->m_ap_type)
         seemimic(mtmp);
 
+    one_of = (corpse->quan > 1L);
+    if (one_of)
+        corpse = splitobj(corpse, 1L);
+
     /* if this is caused by the hero there might be a shop charge */
     if (by_hero) {
         struct monst *shkp = 0;
 
         x = corpse->ox, y = corpse->oy;
-        if (costly_spot(x, y))
+        if (costly_spot(x, y)
+            && (carried(corpse) ? corpse->unpaid : !corpse->no_charge))
             shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
 
-        if (cansee(x, y))
-#if 0 /*JP*/
-            pline(
-                "%s glows iridescently.",
-                upstart(corpse_xname(corpse, (const char *) 0, CXN_PFX_THE)));
-#else
-            pline(
-                "%s\82Í\93ø\90F\82É\8bP\82¢\82½\81D",
-                upstart(corpse_xname(corpse, (const char *) 0, CXN_PFX_THE)));
-#endif
-        else if (shkp)
+        if (cansee(x, y)) {
+            char buf[BUFSZ];
+            unsigned pfx = CXN_PFX_THE;
+
+            Strcpy(buf, one_of ? "one of " : "");
+            if (carried(corpse) && !corpse->unpaid) {
+                Strcat(buf, "your ");
+                pfx = CXN_NO_PFX;
+            }
+            if (one_of)
+                corpse->quan++; /* force plural */
+            Strcat(buf, corpse_xname(corpse, (const char *) 0, pfx));
+            if (one_of) /* could be simplified to ''corpse->quan = 1L;'' */
+                corpse->quan--;
+/*JP
+            pline("%s glows iridescently.", upstart(buf));
+*/
+            pline("%s\82Í\93ø\90F\82É\8bP\82¢\82½\81D", upstart(buf));
+        } else if (shkp) {
             /* need some prior description of the corpse since
                stolen_value() will refer to the object as "it" */
 /*JP
             pline("A corpse is resuscitated.");
 */
             pline("\8e\80\91Ì\82ª\91h\90\82µ\82½\81D");
-
+        }
         /* don't charge for shopkeeper's own corpse if we just revived him */
         if (shkp && mtmp != shkp)
             (void) stolen_value(corpse, x, y, (boolean) shkp->mpeaceful,
@@ -932,7 +995,7 @@ boolean by_hero;
     }
 
     /* monster retains its name */
-    if (has_oname(corpse))
+    if (has_oname(corpse) && !unique_corpstat(mtmp->data))
         mtmp = christen_monst(mtmp, ONAME(corpse));
     /* partially eaten corpse yields wounded monster */
     if (corpse->oeaten)
@@ -990,10 +1053,11 @@ struct monst *mon;
     struct monst *mtmp2;
     char owner[BUFSZ], corpse[BUFSZ];
     boolean youseeit;
-    int once = 0, res = 0;
+    int res = 0;
 
     youseeit = (mon == &youmonst) ? TRUE : canseemon(mon);
     otmp2 = (mon == &youmonst) ? invent : mon->minvent;
+    owner[0] = corpse[0] = '\0'; /* lint suppression */
 
     while ((otmp = otmp2) != 0) {
         otmp2 = otmp->nobj;
@@ -1002,25 +1066,21 @@ struct monst *mon;
         if (otmp->otyp != CORPSE)
             continue;
         /* save the name; the object is liable to go away */
-        if (youseeit)
+        if (youseeit) {
             Strcpy(corpse,
                    corpse_xname(otmp, (const char *) 0, CXN_SINGULAR));
+            Shk_Your(owner, otmp); /* includes a trailing space */
+        }
 
-        /* for a merged group, only one is revived; should this be fixed? */
+        /* for a stack, only one is revived */
         if ((mtmp2 = revive(otmp, !context.mon_moving)) != 0) {
             ++res;
-            if (youseeit) {
-                if (!once++)
-/*JP
-                    Strcpy(owner, (mon == &youmonst) ? "Your"
-*/
-                    Strcpy(owner, (mon == &youmonst) ? "\82 \82È\82½"
-                                                     : s_suffix(Monnam(mon)));
+            if (youseeit)
 /*JP
-                pline("%s %s suddenly comes alive!", owner, corpse);
+                pline("%s%s suddenly comes alive!", owner, corpse);
 */
-                pline("%s\82Ì%s\82Í\93Ë\91R\90\96½\82ð\91Ñ\82Ñ\82½\81I", owner, corpse);
-            else if (canseemon(mtmp2))
+                pline("%s%s\82Í\93Ë\91R\90\96½\82ð\91Ñ\82Ñ\82½\81I", owner, corpse);
+            else if (canseemon(mtmp2))
 /*JP
                 pline("%s suddenly appears!", Amonnam(mtmp2));
 */
@@ -1133,8 +1193,9 @@ register struct obj *obj;
  * possibly carried by you or a monster
  */
 boolean
-drain_item(obj)
-register struct obj *obj;
+drain_item(obj, by_you)
+struct obj *obj;
+boolean by_you;
 {
     boolean u_ring;
 
@@ -1149,7 +1210,8 @@ register struct obj *obj;
         return FALSE;
 
     /* Charge for the cost of the object */
-    costly_alteration(obj, COST_DRAIN);
+    if (by_you)
+        costly_alteration(obj, COST_DRAIN);
 
     /* Drain the object and any implied effects */
     obj->spe--;
@@ -1181,6 +1243,10 @@ register struct obj *obj;
         if ((obj->owornmask & W_RING) && u_ring)
             u.udaminc--;
         break;
+    case RIN_PROTECTION:
+        if (u_ring)
+            context.botl = 1; /* bot() will recalc u.uac */
+        break;
     case HELM_OF_BRILLIANCE:
         if ((obj->owornmask & W_ARMH) && (obj == uarmh)) {
             ABON(A_INT)--;
@@ -1194,10 +1260,11 @@ register struct obj *obj;
             context.botl = 1;
         }
         break;
-    case RIN_PROTECTION:
-        context.botl = 1;
+    default:
         break;
     }
+    if (context.botl)
+        bot();
     if (carried(obj))
         update_inventory();
     return TRUE;
@@ -1571,14 +1638,15 @@ int id;
 
     otmp->cursed = obj->cursed;
     otmp->blessed = obj->blessed;
-    otmp->oeroded = obj->oeroded;
-    otmp->oeroded2 = obj->oeroded2;
-    if (!is_flammable(otmp) && !is_rustprone(otmp))
-        otmp->oeroded = 0;
-    if (!is_corrodeable(otmp) && !is_rottable(otmp))
-        otmp->oeroded2 = 0;
-    if (is_damageable(otmp))
-        otmp->oerodeproof = obj->oerodeproof;
+
+    if (erosion_matters(otmp)) {
+        if (is_flammable(otmp) || is_rustprone(otmp))
+            otmp->oeroded = obj->oeroded;
+        if (is_corrodeable(otmp) || is_rottable(otmp))
+            otmp->oeroded2 = obj->oeroded2;
+        if (is_damageable(otmp))
+            otmp->oerodeproof = obj->oerodeproof;
+    }
 
     /* Keep chest/box traps and poisoned ammo if we may */
     if (obj->otrapped && Is_box(otmp))
@@ -1734,9 +1802,9 @@ int id;
                 if (*u.ushops
                     && *in_rooms(u.ux, u.uy, 0)
                            == *in_rooms(shkp->mx, shkp->my, 0)
-                    && !costly_spot(u.ux, u.uy))
+                    && !costly_spot(u.ux, u.uy)) {
                     make_angry_shk(shkp, ox, oy);
-                else {
+                else {
 /*JP
                     pline("%s gets angry!", Monnam(shkp));
 */
@@ -1761,7 +1829,7 @@ struct obj *obj;
 {
     int res = 1; /* affected object by default */
     struct permonst *ptr;
-    struct monst *mon;
+    struct monst *mon, *shkp;
     struct obj *item;
     xchar oox, ooy;
     boolean smell = FALSE, golem_xform = FALSE;
@@ -1792,19 +1860,18 @@ struct obj *obj;
                 break;
             }
             if (obj->otyp == STATUE) {
-                /* animate_statue() forces all golems to become flesh golems
-                 */
+                /* animate_statue() forces all golems to become flesh golems */
                 mon = animate_statue(obj, oox, ooy, ANIMATE_SPELL, (int *) 0);
             } else { /* (obj->otyp == FIGURINE) */
                 if (golem_xform)
                     ptr = &mons[PM_FLESH_GOLEM];
                 mon = makemon(ptr, oox, ooy, NO_MINVENT);
                 if (mon) {
-                    if (costly_spot(oox, ooy) && !obj->no_charge) {
-                        if (costly_spot(u.ux, u.uy))
-                            addtobill(obj, carried(obj), FALSE, FALSE);
-                        else
-                            stolen_value(obj, oox, ooy, TRUE, FALSE);
+                    if (costly_spot(oox, ooy)
+                        && (carried(obj) ? obj->unpaid : !obj->no_charge)) {
+                        shkp = shop_keeper(*in_rooms(oox, ooy, SHOPBASE));
+                        stolen_value(obj, oox, ooy,
+                                     (shkp && shkp->mpeaceful), FALSE);
                     }
                     if (obj->timed)
                         obj_stop_timers(obj);
@@ -2059,10 +2126,14 @@ struct obj *obj, *otmp;
                         You_hear("\89½\82©\82ª\8dÓ\82¯\82é\89¹\82ð\95·\82¢\82½\81D");
                 }
             } else {
+                int oox = obj->ox;
+                int ooy = obj->oy;
                 if (context.mon_moving
                         ? !breaks(obj, obj->ox, obj->oy)
                         : !hero_breaks(obj, obj->ox, obj->oy, FALSE))
                     maybelearnit = FALSE; /* nothing broke */
+                else
+                    newsym_force(oox,ooy);
                 res = 0;
             }
             if (maybelearnit)
@@ -2076,7 +2147,7 @@ struct obj *obj, *otmp;
 #endif
             break;
         case SPE_DRAIN_LIFE:
-            (void) drain_item(obj);
+            (void) drain_item(obj, TRUE);
             break;
         case WAN_TELEPORTATION:
         case SPE_TELEPORT_AWAY:
@@ -2107,7 +2178,7 @@ struct obj *obj, *otmp;
                                                        : "health");
 #else
                         You("%s\82Ì%s\82ª\8c\80\93I\82É\95Ï\89»\82·\82é\82Ì\82ð\8c©\82½\81D",
-                            s_suffix(an(mons[corpsenm].mname)),
+                            mons[corpsenm].mname,
                             nonliving(&mons[corpsenm]) ? "\89^\93®\90«"
                                                        : "\8c\92\8dN");
 #endif
@@ -2281,6 +2352,7 @@ backfire(otmp)
 struct obj *otmp;
 {
     int dmg;
+
     otmp->in_use = TRUE; /* in case losehp() is fatal */
 /*JP
     pline("%s suddenly explodes!", The(xname(otmp)));
@@ -2330,10 +2402,12 @@ dozap()
         if ((damage = zapyourself(obj, TRUE)) != 0) {
 #if 0 /*JP*/
             char buf[BUFSZ];
+
             Sprintf(buf, "zapped %sself with a wand", uhim());
             losehp(Maybe_Half_Phys(damage), buf, NO_KILLER_PREFIX);
 #else
-            losehp(Maybe_Half_Phys(damage), "\8e©\95ª\8e©\90g\82Ì\8fñ\82Ì\97Í\82ð\97\81\82Ñ\82Ä", KILLED_BY);
+            losehp(Maybe_Half_Phys(damage),
+                "\8e©\95ª\8e©\90g\82Ì\8fñ\82Ì\97Í\82ð\97\81\82Ñ\82Ä", KILLED_BY);
 #endif
         }
     } else {
@@ -2652,6 +2726,7 @@ boolean ordinary;
     case WAN_LIGHT: /* (broken wand) */
         /* assert( !ordinary ); */
         damage = d(obj->spe, 25);
+        /*FALLTHRU*/
     case EXPENSIVE_CAMERA:
         if (!damage)
             damage = 5;
@@ -2669,7 +2744,13 @@ boolean ordinary;
         }
         if (u.utrap) { /* escape web or bear trap */
             (void) openholdingtrap(&youmonst, &learn_it);
-        } else { /* trigger previously escaped trapdoor */
+        } else {
+            struct obj *otmp;
+            /* unlock carried boxes */
+            for (otmp = invent; otmp; otmp = otmp->nobj)
+                if (Is_box(otmp))
+                    (void) boxlock(otmp, obj);
+            /* trigger previously escaped trapdoor */
             (void) openfallingtrap(&youmonst, TRUE, &learn_it);
         }
         break;
@@ -2828,6 +2909,8 @@ struct obj *obj; /* wand or spell */
 {
     int steedhit = FALSE;
 
+    bhitpos.x = u.usteed->mx, bhitpos.y = u.usteed->my;
+    notonhead = FALSE;
     switch (obj->otyp) {
     /*
      * Wands that are allowed to hit the steed
@@ -2940,7 +3023,11 @@ boolean youattack, allow_cancel_kill, self_cancel;
 
         if (mdef->data == &mons[PM_CLAY_GOLEM]) {
             if (canseemon(mdef))
+#if 0 /*JP*/
                 pline(writing_vanishes, s_suffix(mon_nam(mdef)));
+#else
+                pline(writing_vanishes, mon_nam(mdef));
+#endif
 
             if (allow_cancel_kill) {
                 if (youattack)
@@ -2999,10 +3086,10 @@ struct obj *obj; /* wand or spell */
         if (is_db_wall(x, y) && find_drawbridge(&xx, &yy)) {
             open_drawbridge(xx, yy);
             disclose = TRUE;
-        } else if (u.dz > 0 && (x == xdnstair && y == ydnstair) &&
+        } else if (u.dz > 0 && (x == xdnstair && y == ydnstair)
                    /* can't use the stairs down to quest level 2 until
                       leader "unlocks" them; give feedback if you try */
-                   on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
+                   && on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
 /*JP
             pline_The("stairs seem to ripple momentarily.");
 */
@@ -3410,6 +3497,7 @@ int range, *skipstart, *skipend;
 {
     int tr = (range / 4);
     int tmp = range - ((tr > 0) ? rnd(tr) : 0);
+
     *skipstart = tmp;
     *skipend = tmp - ((tmp / 4) * rnd(3));
     if (*skipend >= tmp)
@@ -3488,7 +3576,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
         }
 
         if (is_pick(obj) && inside_shop(x, y)
-            && (mtmp = shkcatch(obj, x, y))) {
+            && (mtmp = shkcatch(obj, x, y)) != 0) {
             tmp_at(DISP_END, 0);
             return mtmp;
         }
@@ -3497,8 +3585,9 @@ struct obj **pobj; /* object tossed/used, set to NULL
 
         /* iron bars will block anything big enough */
         if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
-            && typ == IRONBARS && hits_bars(pobj, x - ddx, y - ddy,
-                                            point_blank ? 0 : !rn2(5), 1)) {
+            && typ == IRONBARS
+            && hits_bars(pobj, x - ddx, y - ddy, bhitpos.x, bhitpos.y,
+                         point_blank ? 0 : !rn2(5), 1)) {
             /* caveat: obj might now be null... */
             obj = *pobj;
             bhitpos.x -= ddx;
@@ -3652,7 +3741,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
                     if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
                         && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
                         shopdoor = TRUE;
-                        add_damage(bhitpos.x, bhitpos.y, 400L);
+                        add_damage(bhitpos.x, bhitpos.y, SHOP_DOOR_COST);
                     }
                 }
                 break;
@@ -3686,6 +3775,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
             && obj->otyp == HEAVY_IRON_BALL) {
             struct obj *bobj;
             struct trap *t;
+
             if ((bobj = sobj_at(BOULDER, x, y)) != 0) {
                 if (cansee(x, y))
 #if 0 /*JP*/
@@ -3791,7 +3881,7 @@ int dx, dy;
         if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
             if (Fumbling || rn2(20) >= ACURR(A_DEX)) {
                 /* we hit ourselves */
-                (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), obj,
+                (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), &obj,
 /*JP
                              "boomerang");
 */
@@ -3826,7 +3916,8 @@ int dx, dy;
     return (struct monst *) 0;
 }
 
-/* used by buzz(); also used by munslime(muse.c); returns damage to mon */
+/* used by buzz(); also used by munslime(muse.c); returns damage applied
+   to mon; note: caller is responsible for killing mon if damage is fatal */
 int
 zhitm(mon, type, nd, ootmp)
 register struct monst *mon;
@@ -4135,15 +4226,15 @@ xchar sx, sy;
     case ZT_ACID:
         if (Acid_resistance) {
 /*JP
-            pline_The("acid doesn't hurt.");
+            pline_The("%s doesn't hurt.", hliquid("acid"));
 */
-            pline("\8e_\82Å\82Í\8f\9d\82Â\82©\82È\82©\82Á\82½\81D");
+            pline_The("%s\82Å\82Í\8f\9d\82Â\82©\82È\82©\82Á\82½\81D", hliquid("\8e_"));
             dam = 0;
         } else {
 /*JP
-            pline_The("acid burns!");
+            pline_The("%s burns!", hliquid("acid"));
 */
-            pline("\8e_\82Å\8fÄ\82¯\82½\81I");
+            pline_The("%s\82Å\8fÄ\82¯\82½\81I", hliquid("\8e_"));
             dam = d(nd, 6);
             exercise(A_STR, FALSE);
         }
@@ -4303,7 +4394,16 @@ const char *fltxt;
     if (type < 0)
         monkilled(mon, (char *) 0, -AD_RBRE);
     else
-        xkilled(mon, 2);
+        xkilled(mon, XKILL_NOMSG | XKILL_NOCORPSE);
+}
+
+void
+buzz(type, nd, sx, sy, dx, dy)
+int type, nd;
+xchar sx, sy;
+int dx, dy;
+{
+    dobuzz(type, nd, sx, sy, dx, dy, TRUE);
 }
 
 /*
@@ -4316,13 +4416,13 @@ const char *fltxt;
  * called with dx = dy = 0 with vertical bolts
  */
 void
-buzz(type, nd, sx, sy, dx, dy)
+dobuzz(type, nd, sx, sy, dx, dy, say)
 register int type, nd;
 register xchar sx, sy;
 register int dx, dy;
+boolean say; /* Announce out of sight hit/miss events if true */
 {
     int range, abstype = abs(type) % 10;
-    struct rm *lev;
     register xchar lsx, lsy;
     struct monst *mon;
     coord save_bhitpos;
@@ -4371,23 +4471,22 @@ register int dx, dy;
         sx += dx;
         lsy = sy;
         sy += dy;
-        if (isok(sx, sy) && (lev = &levl[sx][sy])->typ) {
-            mon = m_at(sx, sy);
-            if (cansee(sx, sy)) {
-                /* reveal/unreveal invisible monsters before tmp_at() */
-                if (mon && !canspotmon(mon))
-                    map_invisible(sx, sy);
-                else if (!mon && glyph_is_invisible(levl[sx][sy].glyph)) {
-                    unmap_object(sx, sy);
-                    newsym(sx, sy);
-                }
-                if (ZAP_POS(lev->typ) || (isok(lsx, lsy) && cansee(lsx, lsy)))
-                    tmp_at(sx, sy);
-                delay_output(); /* wait a little */
-            }
-        } else
+        if (!isok(sx, sy) || levl[sx][sy].typ == STONE)
             goto make_bounce;
 
+        mon = m_at(sx, sy);
+        if (cansee(sx, sy)) {
+            /* reveal/unreveal invisible monsters before tmp_at() */
+            if (mon && !canspotmon(mon))
+                map_invisible(sx, sy);
+            else if (!mon)
+                (void) unmap_invisible(sx, sy);
+            if (ZAP_POS(levl[sx][sy].typ)
+                || (isok(lsx, lsy) && cansee(lsx, lsy)))
+                tmp_at(sx, sy);
+            delay_output(); /* wait a little */
+        }
+
         /* hit() and miss() need bhitpos to match the target */
         bhitpos.x = sx, bhitpos.y = sy;
         /* Fireballs only damage when they explode */
@@ -4400,6 +4499,7 @@ register int dx, dy;
             if (type >= 0)
                 mon->mstrategy &= ~STRAT_WAITMASK;
         buzzmonst:
+            notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
             if (zap_hit(find_mac(mon), spell_type)) {
                 if (mon_reflects(mon, (char *) 0)) {
                     if (cansee(mon->mx, mon->my)) {
@@ -4474,23 +4574,39 @@ register int dx, dy;
                     if (tmp == MAGIC_COOKIE) { /* disintegration */
                         disintegrate_mon(mon, type, fltxt);
                     } else if (mon->mhp < 1) {
-                        if (type < 0)
+                        if (type < 0) {
+                            /* mon has just been killed by another monster */
                             monkilled(mon, fltxt, AD_RBRE);
-                        else
-                            killed(mon);
+                        } else {
+                            int xkflags = XKILL_GIVEMSG; /* killed(mon); */
+
+                            /* killed by hero; we know 'type' isn't negative;
+                               if it's fire, highly flammable monsters leave
+                               no corpse; don't bother reporting that they
+                               "burn completely" -- unnecessary verbosity */
+                            if ((type % 10 == ZT_FIRE)
+                                /* paper golem or straw golem */
+                                && completelyburns(mon->data))
+                                xkflags |= XKILL_NOCORPSE;
+                            xkilled(mon, xkflags);
+                        }
                     } else {
                         if (!otmp) {
                             /* normal non-fatal hit */
-                            hit(fltxt, mon, exclam(tmp));
+                            if (say || canseemon(mon))
+                                hit(fltxt, mon, exclam(tmp));
                         } else {
                             /* some armor was destroyed; no damage done */
                             if (canseemon(mon))
-/*JP
+#if 0 /*JP*/
                                 pline("%s %s is disintegrated!",
-*/
-                                pline("%s\82Ì%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81I",
                                       s_suffix(Monnam(mon)),
                                       distant_name(otmp, xname));
+#else
+                                pline("%s\82Ì%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81I",
+                                      Monnam(mon),
+                                      distant_name(otmp, xname));
+#endif
                             m_useup(mon, otmp);
                         }
                         if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */
@@ -4499,7 +4615,8 @@ register int dx, dy;
                 }
                 range -= 2;
             } else {
-                miss(fltxt, mon);
+                if (say || canseemon(mon))
+                    miss(fltxt, mon);
             }
         } else if (sx == u.ux && sy == u.uy && range >= 0) {
             nomul(0);
@@ -4549,33 +4666,39 @@ register int dx, dy;
             nomul(0);
         }
 
-        if (!ZAP_POS(lev->typ) || (closed_door(sx, sy) && (range >= 0))) {
-            int bounce;
+        if (!ZAP_POS(levl[sx][sy].typ)
+            || (closed_door(sx, sy) && range >= 0)) {
+            int bounce, bchance;
             uchar rmn;
+            boolean fireball;
 
         make_bounce:
-            if (type == ZT_SPELL(ZT_FIRE)) {
-                sx = lsx;
-                sy = lsy;
-                break; /* fireballs explode before the wall */
-            }
+            bchance = (levl[sx][sy].typ == STONE) ? 10
+                : (In_mines(&u.uz) && IS_WALL(levl[sx][sy].typ)) ? 20
+                : 75;
             bounce = 0;
-            range--;
-            if (range && isok(lsx, lsy) && cansee(lsx, lsy)) {
-#if 0 /*JP*/
-                    pline("%s %s!", The(fltxt),
-                          Is_airlevel(&u.uz)
-                          ? "vanishes into the aether"
-                          : "bounces");
-#else
-                    pline("%s\82Í%s\81I", The(fltxt),
-                          Is_airlevel(&u.uz)
-                          ? "\83G\81[\83e\83\8b\8bó\8aÔ\82É\8fÁ\82¦\82½"
-                          : "\94½\8eË\82µ\82½");
-#endif
-                    if (Is_airlevel(&u.uz)) goto get_out_buzz;
+            fireball = (type == ZT_SPELL(ZT_FIRE));
+            if ((--range > 0 && isok(lsx, lsy) && cansee(lsx, lsy))
+                || fireball) {
+                if (Is_airlevel(&u.uz)) { /* nothing to bounce off of */
+/*JP
+                    pline_The("%s vanishes into the aether!", fltxt);
+*/
+                    pline_The("%s\82Í\83G\81[\83e\83\8b\8bó\8aÔ\82É\8fÁ\82¦\82½\81I", fltxt);
+                    if (fireball)
+                        type = ZT_WAND(ZT_FIRE); /* skip pending fireball */
+                    break;
+                } else if (fireball) {
+                    sx = lsx;
+                    sy = lsy;
+                    break; /* fireballs explode before the obstacle */
+                } else
+/*JP
+                    pline_The("%s bounces!", fltxt);
+*/
+                    pline_The("%s\82Í\94½\8eË\82µ\82½\81I", fltxt);
             }
-            if (!dx || !dy || !rn2(20)) {
+            if (!dx || !dy || !rn2(bchance)) {
                 dx = -dx;
                 dy = -dy;
             } else {
@@ -4593,7 +4716,8 @@ register int dx, dy;
 
                 switch (bounce) {
                 case 0:
-                    dx = -dx; /* fall into... */
+                    dx = -dx;
+                    /*FALLTHRU*/
                 case 1:
                     dy = -dy;
                     break;
@@ -4608,7 +4732,6 @@ register int dx, dy;
     tmp_at(DISP_END, 0);
     if (type == ZT_SPELL(ZT_FIRE))
         explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
- get_out_buzz:
     if (shopdamage)
 #if 0 /*JP*/
         pay_for_damage(abstype == ZT_FIRE
@@ -4617,7 +4740,7 @@ register int dx, dy;
                              ? "shatter"
                              /* "damage" indicates wall rather than door */
                              : abstype == ZT_ACID
-                             ? "damage"
+                                ? "damage"
                                 : abstype == ZT_DEATH
                                    ? "disintegrate"
                                    : "destroy",
@@ -4650,7 +4773,7 @@ const char *msg;
         msg = "The ice crackles and melts.";
 */
         msg = "\95X\82Í\83s\83L\83s\83L\96Â\82è\81C\97n\82¯\82½\81D";
-    if (lev->typ == DRAWBRIDGE_UP) {
+    if (lev->typ == DRAWBRIDGE_UP || lev->typ == DRAWBRIDGE_DOWN) {
         lev->drawbridgemask &= ~DB_ICE; /* revert to DB_MOAT */
     } else { /* lev->typ == ICE */
 #ifdef STUPID
@@ -4818,16 +4941,16 @@ short exploding_wand_typ;
 
     case ZT_COLD:
         if (is_pool(x, y) || is_lava(x, y)) {
-            boolean lava = is_lava(x, y);
-            boolean moat = is_moat(x, y);
+            boolean lava = is_lava(x, y),
+                    moat = is_moat(x, y);
 
             if (lev->typ == WATER) {
                 /* For now, don't let WATER freeze. */
                 if (see_it)
 /*JP
-                    pline_The("water freezes for a moment.");
+                    pline_The("%s freezes for a moment.", hliquid("water"));
 */
-                    pline("\90\85\82Í\88ê\8fu\93\80\82Á\82½\81D");
+                    pline_The("%s\82Í\88ê\8fu\93\80\82Á\82½\81D", hliquid("\90\85"));
                 else
 /*JP
                     You_hear("a soft crackling.");
@@ -4835,34 +4958,36 @@ short exploding_wand_typ;
                     You_hear("\83s\83L\81I\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
                 rangemod -= 1000; /* stop */
             } else {
+                char buf[BUFSZ];
+
+                Strcpy(buf, waterbody_name(x, y)); /* for MOAT */
                 rangemod -= 3;
                 if (lev->typ == DRAWBRIDGE_UP) {
                     lev->drawbridgemask &= ~DB_UNDER; /* clear lava */
                     lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
                 } else {
                     if (!lava)
-                        lev->icedpool =
-                            (lev->typ == POOL ? ICED_POOL : ICED_MOAT);
-                    lev->typ = (lava ? ROOM : ICE);
+                        lev->icedpool = (lev->typ == POOL) ? ICED_POOL
+                                                           : ICED_MOAT;
+                    lev->typ = lava ? ROOM : ICE;
                 }
                 bury_objs(x, y);
                 if (see_it) {
                     if (lava)
 /*JP
-                        Norep("The lava cools and solidifies.");
+                        Norep("The %s cools and solidifies.", hliquid("lava"));
 */
-                        Norep("\97n\8aâ\82Í\97â\82¦\8cÅ\82Ü\82Á\82½\81D");
+                        Norep("%s\82Í\97â\82¦\8cÅ\82Ü\82Á\82½\81D", hliquid("lava"));
                     else if (moat)
 /*JP
-                        Norep("The %s is bridged with ice!",
+                        Norep("The %s is bridged with ice!", buf);
 */
-                        Norep("%s\82É\95X\82Ì\8b´\82ª\82©\82¯\82ç\82ê\82½\81I",
-                              waterbody_name(x, y));
+                        Norep("%s\82É\95X\82Ì\8b´\82ª\82©\82¯\82ç\82ê\82½\81I", buf);
                     else
 /*JP
-                        Norep("The water freezes.");
+                        Norep("The %s freezes.", hliquid("water"));
 */
-                        Norep("\90\85\82Í\93\80\82Á\82½\81D");
+                        Norep("%s\82Í\93\80\82Á\82½\81D", hliquid("\95X"));
                     newsym(x, y);
                 } else if (!lava)
 /*JP
@@ -4920,6 +5045,10 @@ short exploding_wand_typ;
         }
         break; /* ZT_COLD */
 
+    case ZT_POISON_GAS:
+        (void) create_gas_cloud(x, y, 1, 8);
+        break;
+
     case ZT_ACID:
         if (lev->typ == IRONBARS) {
             if ((lev->wall_info & W_NONDIGGABLE) != 0) {
@@ -4942,7 +5071,7 @@ short exploding_wand_typ;
                     lev->typ = ROOM;
                     if (see_it)
                         newsym(x, y);
-                    add_damage(x, y, (type >= 0) ? 300L : 0L);
+                    add_damage(x, y, (type >= 0) ? SHOP_BARS_COST : 0L);
                     if (type >= 0)
                         *shopdamage = TRUE;
                 } else {
@@ -5096,7 +5225,7 @@ short exploding_wand_typ;
         if (new_doormask >= 0) { /* door gets broken */
             if (*in_rooms(x, y, SHOPBASE)) {
                 if (type >= 0) {
-                    add_damage(x, y, 400L);
+                    add_damage(x, y, SHOP_DOOR_COST);
                     *shopdamage = TRUE;
                 } else /* caused by monster */
                     add_damage(x, y, 0L);
@@ -5130,12 +5259,9 @@ short exploding_wand_typ;
             pline("%s\81D", !Blind ? "\82Û\82í\82Á\82Æ\89\8c\82ª\82 \82ª\82Á\82½" : "\89\8c\82Ì\83v\83\93\82Æ\82¢\82¤\93õ\82¢\82ª\82µ\82½");
         }
     if ((mon = m_at(x, y)) != 0) {
-        /* Cannot use wakeup() which also angers the monster */
-        mon->msleeping = 0;
-        if (mon->m_ap_type)
-            seemimic(mon);
+        wakeup(mon, FALSE);
         if (type >= 0) {
-            setmangry(mon);
+            setmangry(mon, TRUE);
             if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
                 ghod_hitsu(mon);
             if (mon->isshk && !*u.ushops)
@@ -5160,7 +5286,10 @@ register struct obj *obj; /* no texts here! */
         if (billable(&shkp, obj, objroom, FALSE)) {
             /* shop message says "you owe <shk> <$> for it!" so we need
                to precede that with a message explaining what "it" is */
+/*JP
             You("fracture %s %s.", s_suffix(shkname(shkp)), xname(obj));
+*/
+            You("%s\82Ì%s\82ð\89ó\82µ\82½\81D", shkname(shkp), xname(obj));
             breakobj(obj, x, y, TRUE, FALSE); /* charges for shop goods */
         }
     }
@@ -5327,8 +5456,8 @@ register int osym, dmgtyp;
                 break;
             case FOOD_CLASS:
                 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
-                    dindx = obj->owt / 20;
-                    dmg = 1;
+                    dindx = 1; /* boil and explode */
+                    dmg = (obj->owt + 19) / 20;
                 } else {
                     skip++;
                 }
@@ -5380,13 +5509,16 @@ register int osym, dmgtyp;
             if (!cnt)
                 continue;
 #if 0 /*JP*/
-            mult = (cnt == quan)
-                       ? (quan > 1) ? "All of your " : "Your"
-                       : (cnt == 1L) ? "One of your" : "Some of your";
+            mult = (cnt == 1L)
+                   ? (quan == 1L) ? "Your"                        /* 1 of 1 */
+                                  : "One of your"                 /* 1 of N */
+                   : (cnt < quan) ? "Some of your"                /* n of N */
+                                  : (quan == 2L) ? "Both of your" /* 2 of 2 */
+                                                 : "All of your"; /* N of N */
 #else
             mult = (cnt == quan)
-                       ? ""
-                       : (cnt == 1L) ? "\82Ì\82Ð\82Æ\82Â" : "\82Ì\82¢\82­\82Â\82©";
+                   ? ""
+                   : (cnt == 1L) ? "\82Ì\82Ð\82Æ\82Â" : "\82Ì\82¢\82­\82Â\82©";
 #endif
 #if 0 /*JP*/
             pline("%s %s %s!", mult, xname(obj),
@@ -5419,6 +5551,8 @@ register int osym, dmgtyp;
                     const char *how = destroy_strings[dindx][2];
                     boolean one = (cnt == 1L);
 
+                    if (dmgtyp == AD_FIRE && osym == FOOD_CLASS)
+                        how = "exploding glob of slime";
                     if (physical_damage)
                         dmg = Maybe_Half_Phys(dmg);
                     losehp(dmg, one ? how : (const char *) makeplural(how),
@@ -5495,8 +5629,8 @@ int osym, dmgtyp;
                 break;
             case FOOD_CLASS:
                 if (obj->otyp == GLOB_OF_GREEN_SLIME) {
-                    dindx = obj->owt / 20;
-                    tmp++;
+                    dindx = 1; /* boil and explode */
+                    tmp += (obj->owt + 19) / 20;
                 } else {
                     skip++;
                 }
@@ -5688,7 +5822,8 @@ int triesleft;
 void
 makewish()
 {
-    char buf[BUFSZ], promptbuf[BUFSZ];
+    static char buf[BUFSZ] = DUMMY;
+    char promptbuf[BUFSZ];
     struct obj *otmp, nothing;
     int tries = 0;
 
index 0c5e02f..e5a93ff 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 amirip.c        $NHDT-Date: 1432512795 2015/05/25 00:13:15 $  $NHDT-Branch: master $:$NHDT-Revision: 1.13 $ */
+/* NetHack 3.6 amirip.c        $NHDT-Date: 1450453302 2015/12/18 15:41:42 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
 /* Copyright (c) Kenneth Lorber, Bethesda, Maryland 1991,1992,1993,1995,1996.
  */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -161,7 +161,7 @@ time_t when;
               0xc0, 0xff, NULL);
 
     /* Put together death description */
-    formatkiller(buf, sizeof buf, how);
+    formatkiller(buf, sizeof buf, how, FALSE);
 
     tw = TextLength(rp, buf, STONE_LINE_LEN) + 40;
 
@@ -196,7 +196,7 @@ time_t when;
     tomb_text(buf);
 
     /* Put together death description */
-    formatkiller(buf, sizeof buf, how);
+    formatkiller(buf, sizeof buf, how, FALSE);
 
     /* Put death type on stone */
     for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; line++) {
index 5f32f77..1819ccd 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 winami.c        $NHDT-Date: 1432512794 2015/05/25 00:13:14 $  $NHDT-Branch: master $:$NHDT-Revision: 1.19 $ */
+/* NetHack 3.6 winami.c        $NHDT-Date: 1501981093 2017/08/06 00:58:13 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */
 /* Copyright (c) Gregg Wonderly, Naperville, Illinois,  1991,1992,1993,1996.
  */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -51,13 +51,8 @@ struct window_procs amii_procs = {
     /* other defs that really should go away (they're tty specific) */
     amii_delay_output, amii_delay_output, amii_outrip, genl_preference_update,
     genl_getmsghistory, genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init, genl_status_finish, genl_status_enablefield,
     genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_yes,
 };
 
@@ -88,13 +83,8 @@ struct window_procs amiv_procs = {
     /* other defs that really should go away (they're tty specific) */
     amii_delay_output, amii_delay_output, amii_outrip, genl_preference_update,
     genl_getmsghistory, genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init, genl_status_finish, genl_status_enablefield,
     genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_yes,
 };
 
@@ -436,7 +426,7 @@ amii_askname()
     if (*plname == '\33') {
         clearlocks();
         exit_nhwindows(NULL);
-        terminate(0);
+        nh_terminate(0);
     }
 }
 
@@ -543,7 +533,7 @@ amii_player_selection()
                CloseShWindow( cwin );
                clearlocks();
                exit_nhwindows(NULL);
-               terminate(0);
+               nh_terminate(0);
                }
                else
                    DisplayBeep( NULL );
@@ -573,7 +563,7 @@ amii_player_selection()
                CloseShWindow( cwin );
                clearlocks();
                exit_nhwindows(NULL);
-               terminate(0);
+               nh_terminate(0);
                break;
            }
        }
@@ -807,8 +797,8 @@ amii_get_ext_cmd(void)
         }
 
         return (-1);
-    } else {
-#else
+    }
+#endif
 
     amii_clear_nhwindow(WIN_MESSAGE); /* Was NHW_MESSAGE */
     if (scrollmsg) {
@@ -932,58 +922,61 @@ amii_get_ext_cmd(void)
             DisplayBeep(NULL);
     }
     return (-1);
-#endif
-    }
+}
 
-    static int put_ext_cmd(obufp, colx, cw, bottom) char * obufp;
-    int colx, bottom;
-    struct amii_WinDesc *cw;
-    {
-        struct Window *w = cw->win;
-        char *t;
-
-        t = (char *) alloc(strlen(obufp) + 7);
-        if (t != NULL) {
-            if (scrollmsg) {
-                sprintf(t, "xxx%s", obufp);
-                t[0] = 1;
-                t[1] = 1;
-                t[2] = '#';
-                amii_curs(WIN_MESSAGE, 0, bottom);
-                SetAPen(w->RPort, C_WHITE);
-                Text(w->RPort, "># ", 3);
-                /* SetAPen( w->RPort, C_BLACK ); */ /* Black text on black
-                                                       screen doesn't look too
-                                                       well ... -jhsa */
-                Text(w->RPort, t + 3, strlen(t) - 3);
-            } else {
-                sprintf(t, "# %s", obufp);
-                amii_curs(WIN_MESSAGE, 0, bottom);
-                SetAPen(w->RPort, C_WHITE);
-                Text(w->RPort, t, strlen(t));
-            }
-            if (scrollmsg)
-                SetAPen(w->RPort, C_WHITE);
-            if (cw->data[cw->maxrow - 1])
-                free(cw->data[cw->maxrow - 1]);
-            cw->data[cw->maxrow - 1] = t;
-        } else {
+static int
+put_ext_cmd(obufp, colx, cw, bottom)
+char * obufp;
+int colx, bottom;
+struct amii_WinDesc *cw;
+{
+    struct Window *w = cw->win;
+    char *t;
+
+    t = (char *) alloc(strlen(obufp) + 7);
+    if (t != NULL) {
+        if (scrollmsg) {
+            sprintf(t, "xxx%s", obufp);
+            t[0] = 1;
+            t[1] = 1;
+            t[2] = '#';
             amii_curs(WIN_MESSAGE, 0, bottom);
             SetAPen(w->RPort, C_WHITE);
-            Text(w->RPort, "# ", 2);
-            /* SetAPen( w->RPort, C_BLACK ); */ /* Black on black ... -jhsa */
-            Text(w->RPort, obufp, strlen(obufp));
+            Text(w->RPort, "># ", 3);
+            /* SetAPen( w->RPort, C_BLACK ); */ /* Black text on black
+                                                 * screen doesn't look
+                                                 * too well ... -jhsa */
+            Text(w->RPort, t + 3, strlen(t) - 3);
+        } else {
+            sprintf(t, "# %s", obufp);
+            amii_curs(WIN_MESSAGE, 0, bottom);
             SetAPen(w->RPort, C_WHITE);
+            Text(w->RPort, t, strlen(t));
         }
-        amii_curs(WIN_MESSAGE, colx = strlen(obufp) + 3 + (scrollmsg != 0),
-                  bottom);
-        return (colx);
+        if (scrollmsg)
+            SetAPen(w->RPort, C_WHITE);
+        if (cw->data[cw->maxrow - 1])
+            free(cw->data[cw->maxrow - 1]);
+        cw->data[cw->maxrow - 1] = t;
+    } else {
+        amii_curs(WIN_MESSAGE, 0, bottom);
+        SetAPen(w->RPort, C_WHITE);
+        Text(w->RPort, "# ", 2);
+        /* SetAPen( w->RPort, C_BLACK ); */ /* Black on black ... -jhsa */
+        Text(w->RPort, obufp, strlen(obufp));
+        SetAPen(w->RPort, C_WHITE);
     }
+    amii_curs(WIN_MESSAGE, colx = strlen(obufp) + 3 + (scrollmsg != 0),
+              bottom);
+    return colx;
+}
 
-    /* Ask a question and get a response */
-
-    char amii_yn_function(query, resp, def) const char * query, *resp;
-    char def;
+/* Ask a question and get a response */
+char
+amii_yn_function(query, resp, def)
+const char * query, *resp;
+char def;
+{
     /*
      *   Generic yes/no function. 'def' is the default (returned by space or
      *   return; 'esc' returns 'q', or 'n', or the default, depending on
@@ -995,155 +988,158 @@ amii_get_ext_cmd(void)
      *   are allowed); if it includes an <esc>, anything beyond that won't
      *   be shown in the prompt to the user but will be acceptable as input.
      */
-    {
-        register char q;
-        char rtmp[40];
-        boolean digit_ok, allow_num;
-        char prompt[BUFSZ];
-        register struct amii_WinDesc *cw;
-
-        if (cw = amii_wins[WIN_MESSAGE])
-            cw->disprows = 0;
-        if (resp) {
-            char *rb, respbuf[QBUFSZ];
-
-            allow_num = (index(resp, '#') != 0);
-            Strcpy(respbuf, resp);
-            /* any acceptable responses that follow <esc> aren't displayed */
-            if ((rb = index(respbuf, '\033')) != 0)
-                *rb = '\0';
-            (void) strncpy(prompt, query, QBUFSZ - 1);
-            prompt[QBUFSZ - 1] = '\0';
-            Sprintf(eos(prompt), " [%s]", respbuf);
-            if (def)
-                Sprintf(eos(prompt), " (%c)", def);
-            Strcat(prompt, " ");
-            pline("%s", prompt);
-        } else {
-            amii_putstr(WIN_MESSAGE, 0, query);
-            cursor_on(WIN_MESSAGE);
-            q = WindowGetchar();
-            cursor_off(WIN_MESSAGE);
-            *rtmp = q;
-            rtmp[1] = 0;
-            amii_addtopl(rtmp);
-            goto clean_up;
-        }
+    register char q;
+    char rtmp[40];
+    boolean digit_ok, allow_num;
+    char prompt[BUFSZ];
+    register struct amii_WinDesc *cw;
+
+    if (cw = amii_wins[WIN_MESSAGE])
+        cw->disprows = 0;
+    if (resp) {
+        char *rb, respbuf[QBUFSZ];
+
+        allow_num = (index(resp, '#') != 0);
+        Strcpy(respbuf, resp);
+        /* any acceptable responses that follow <esc> aren't displayed */
+        if ((rb = index(respbuf, '\033')) != 0)
+            *rb = '\0';
+        (void) strncpy(prompt, query, QBUFSZ - 1);
+        prompt[QBUFSZ - 1] = '\0';
+        Sprintf(eos(prompt), " [%s]", respbuf);
+        if (def)
+            Sprintf(eos(prompt), " (%c)", def);
+        Strcat(prompt, " ");
+        pline("%s", prompt);
+    } else {
+        amii_putstr(WIN_MESSAGE, 0, query);
+        cursor_on(WIN_MESSAGE);
+        q = WindowGetchar();
+        cursor_off(WIN_MESSAGE);
+        *rtmp = q;
+        rtmp[1] = '\0';
+        amii_addtopl(rtmp);
+        goto clean_up;
+    }
 
-        do { /* loop until we get valid input */
-            cursor_on(WIN_MESSAGE);
-            q = lowc(WindowGetchar());
-            cursor_off(WIN_MESSAGE);
+    do { /* loop until we get valid input */
+        cursor_on(WIN_MESSAGE);
+        q = lowc(WindowGetchar());
+        cursor_off(WIN_MESSAGE);
 #if 0
 /* fix for PL2 */
-           if (q == '\020') { /* ctrl-P */
-               if(!doprev) (void) tty_doprev_message(); /* need two initially */
-               (void) tty_doprev_message();
-               q = (char)0;
-               doprev = 1;
-               continue;
-           } else if(doprev) {
-               tty_clear_nhwindow(WIN_MESSAGE);
-               cw->maxcol = cw->maxrow;
-               doprev = 0;
-               amii_addtopl(prompt);
-               continue;
-           }
-#endif
-            digit_ok = allow_num && isdigit(q);
-            if (q == '\033') {
-                if (index(resp, 'q'))
-                    q = 'q';
-                else if (index(resp, 'n'))
-                    q = 'n';
-                else
-                    q = def;
-                break;
-            } else if (index(quitchars, q)) {
+        if (q == '\020') { /* ctrl-P */
+            if(!doprev)
+                (void) tty_doprev_message(); /* need two initially */
+            (void) tty_doprev_message();
+            q = (char)0;
+            doprev = 1;
+            continue;
+        } else if (doprev) {
+            tty_clear_nhwindow(WIN_MESSAGE);
+            cw->maxcol = cw->maxrow;
+            doprev = 0;
+            amii_addtopl(prompt);
+            continue;
+        }
+#endif /*0*/
+        digit_ok = allow_num && isdigit(q);
+        if (q == '\033') {
+            if (index(resp, 'q'))
+                q = 'q';
+            else if (index(resp, 'n'))
+                q = 'n';
+            else
                 q = def;
-                break;
+            break;
+        } else if (index(quitchars, q)) {
+            q = def;
+            break;
+        }
+        if (!index(resp, q) && !digit_ok) {
+            amii_bell();
+            q = (char) 0;
+        } else if (q == '#' || digit_ok) {
+            char z, digit_string[2];
+            int n_len = 0;
+            long value = 0;
+
+            amii_addtopl("#"), n_len++;
+            digit_string[1] = '\0';
+            if (q != '#') {
+                digit_string[0] = q;
+                amii_addtopl(digit_string), n_len++;
+                value = q - '0';
+                q = '#';
             }
-            if (!index(resp, q) && !digit_ok) {
-                amii_bell();
-                q = (char) 0;
-            } else if (q == '#' || digit_ok) {
-                char z, digit_string[2];
-                int n_len = 0;
-                long value = 0;
-                amii_addtopl("#"), n_len++;
-                digit_string[1] = '\0';
-                if (q != '#') {
-                    digit_string[0] = q;
+            do { /* loop until we get a non-digit */
+                cursor_on(WIN_MESSAGE);
+                z = lowc(WindowGetchar());
+                cursor_off(WIN_MESSAGE);
+                if (isdigit(z)) {
+                    value = (10 * value) + (z - '0');
+                    if (value < 0)
+                        break; /* overflow: try again */
+                    digit_string[0] = z;
                     amii_addtopl(digit_string), n_len++;
-                    value = q - '0';
-                    q = '#';
-                }
-                do { /* loop until we get a non-digit */
-                    cursor_on(WIN_MESSAGE);
-                    z = lowc(WindowGetchar());
-                    cursor_off(WIN_MESSAGE);
-                    if (isdigit(z)) {
-                        value = (10 * value) + (z - '0');
-                        if (value < 0)
-                            break; /* overflow: try again */
-                        digit_string[0] = z;
-                        amii_addtopl(digit_string), n_len++;
-                    } else if (z == 'y' || index(quitchars, z)) {
-                        if (z == '\033')
-                            value = -1; /* abort */
-                        z = '\n';       /* break */
-                    } else if (z == '\b') {
-                        if (n_len <= 1) {
-                            value = -1;
-                            break;
-                        } else {
-                            value /= 10;
-                            removetopl(1), n_len--;
-                        }
-                    } else {
+                } else if (z == 'y' || index(quitchars, z)) {
+                    if (z == '\033')
                         value = -1; /* abort */
-                        amii_bell();
+                    z = '\n';       /* break */
+                } else if (z == '\b') {
+                    if (n_len <= 1) {
+                        value = -1;
                         break;
+                    } else {
+                        value /= 10;
+                        removetopl(1), n_len--;
                     }
-                } while (z != '\n');
-                if (value > 0)
-                    yn_number = value;
-                else if (value == 0)
-                    q = 'n'; /* 0 => "no" */
-                else {       /* remove number from top line, then try again */
-                    removetopl(n_len), n_len = 0;
-                    q = '\0';
+                } else {
+                    value = -1; /* abort */
+                    amii_bell();
+                    break;
                 }
+            } while (z != '\n');
+            if (value > 0)
+                yn_number = value;
+            else if (value == 0)
+                q = 'n'; /* 0 => "no" */
+            else {       /* remove number from top line, then try again */
+                removetopl(n_len), n_len = 0;
+                q = '\0';
             }
-        } while (!q);
-
-        if (q != '#' && q != '\033') {
-            Sprintf(rtmp, "%c", q);
-            amii_addtopl(rtmp);
         }
-    clean_up:
-        cursor_off(WIN_MESSAGE);
-        clear_nhwindow(WIN_MESSAGE);
-        return q;
+    } while (!q);
+
+    if (q != '#' && q != '\033') {
+        Sprintf(rtmp, "%c", q);
+        amii_addtopl(rtmp);
     }
+ clean_up:
+    cursor_off(WIN_MESSAGE);
+    clear_nhwindow(WIN_MESSAGE);
+    return q;
+}
 
-    void amii_display_file(fn, complain) const char * fn;
-    boolean complain;
-    {
-        register struct amii_WinDesc *cw;
-        register int win;
-        register dlb *fp;
-        register char *t;
-        register char buf[200];
-
-        if (fn == NULL)
-            panic("NULL file name in display_file()");
-
-        if ((fp = dlb_fopen(fn, RDTMODE)) == (dlb *) NULL) {
-            if (complain) {
-                sprintf(buf, "Can't display %s: %s", fn,
+void
+amii_display_file(fn, complain)
+const char * fn;
+boolean complain;
+{
+    register struct amii_WinDesc *cw;
+    register int win;
+    register dlb *fp;
+    register char *t;
+    register char buf[200];
+
+    if (fn == NULL)
+        panic("NULL file name in display_file()");
+
+    if ((fp = dlb_fopen(fn, RDTMODE)) == (dlb *) NULL) {
+        if (complain) {
+            sprintf(buf, "Can't display %s: %s", fn,
 #if defined(_DCC) || defined(__GNUC__)
-                        strerror(errno)
+                    strerror(errno)
 #else
 #ifdef __SASC_60
                     __sys_errlist[errno]
@@ -1151,520 +1147,510 @@ amii_get_ext_cmd(void)
                     sys_errlist[errno]
 #endif
 #endif
-                            );
-                amii_addtopl(buf);
-            }
-            return;
-        }
-        win = amii_create_nhwindow(NHW_TEXT);
-
-        /* Set window title to file name */
-        if (cw = amii_wins[win])
-            cw->morestr = (char *) fn;
-
-        while (dlb_fgets(buf, sizeof(buf), fp) != NULL) {
-            if (t = index(buf, '\n'))
-                *t = 0;
-            amii_putstr(win, 0, buf);
+                    );
+            amii_addtopl(buf);
         }
-        dlb_fclose(fp);
-
-        /* If there were lines in the file, display those lines */
+        return;
+    }
+    win = amii_create_nhwindow(NHW_TEXT);
 
-        if (amii_wins[win]->cury > 0)
-            amii_display_nhwindow(win, TRUE);
+    /* Set window title to file name */
+    if (cw = amii_wins[win])
+        cw->morestr = (char *) fn;
 
-        amii_wins[win]->morestr = NULL; /* don't free title string */
-        amii_destroy_nhwindow(win);
+    while (dlb_fgets(buf, sizeof(buf), fp) != NULL) {
+        if (t = index(buf, '\n'))
+            *t = 0;
+        amii_putstr(win, 0, buf);
     }
+    dlb_fclose(fp);
 
-    /* Put a 3-D motif border around the gadget.  String gadgets or those
-     * which do not have highlighting are rendered down.  Boolean gadgets
-     * are rendered in the up position by default.
-     */
+    /* If there were lines in the file, display those lines */
+    if (amii_wins[win]->cury > 0)
+        amii_display_nhwindow(win, TRUE);
 
-    void SetBorder(gd) register struct Gadget * gd;
-    {
-        register struct Border *bp;
-        register short *sp;
-        register int i, inc = -1, dec = -1;
-        int borders = 6;
-        int hipen = sysflags.amii_dripens[SHINEPEN],
-            shadowpen = sysflags.amii_dripens[SHADOWPEN];
+    amii_wins[win]->morestr = NULL; /* don't free title string */
+    amii_destroy_nhwindow(win);
+}
+
+/* Put a 3-D motif border around the gadget.  String gadgets or those
+ * which do not have highlighting are rendered down.  Boolean gadgets
+ * are rendered in the up position by default.
+ */
+void
+SetBorder(gd)
+register struct Gadget * gd;
+{
+    register struct Border *bp;
+    register short *sp;
+    register int i, inc = -1, dec = -1;
+    int borders = 6;
+    int hipen = sysflags.amii_dripens[SHINEPEN],
+        shadowpen = sysflags.amii_dripens[SHADOWPEN];
 #ifdef INTUI_NEW_LOOK
-        struct DrawInfo *dip;
+    struct DrawInfo *dip;
 #endif
 
 #ifdef INTUI_NEW_LOOK
-        if (IntuitionBase->LibNode.lib_Version >= 37) {
-            if (dip = GetScreenDrawInfo(HackScreen)) {
-                hipen = dip->dri_Pens[SHINEPEN];
-                shadowpen = dip->dri_Pens[SHADOWPEN];
-                FreeScreenDrawInfo(HackScreen, dip);
-            }
+    if (IntuitionBase->LibNode.lib_Version >= 37) {
+        if ((dip = GetScreenDrawInfo(HackScreen)) != 0) {
+            hipen = dip->dri_Pens[SHINEPEN];
+            shadowpen = dip->dri_Pens[SHADOWPEN];
+            FreeScreenDrawInfo(HackScreen, dip);
         }
+    }
 #endif
-        /* Allocate two border structures one for up image and one for down
-         * image, plus vector arrays for the border lines.
-         */
+    /* Allocate two border structures one for up image and one for down
+     * image, plus vector arrays for the border lines.
+     */
+    if (gd->GadgetType == STRGADGET)
+        borders = 12;
+    if ((bp = (struct Border *) alloc(((sizeof (struct Border) * 2)
+                                       + (sizeof (short) * borders)) * 2))
+        == NULL) {
+        return;
+    }
 
-        if (gd->GadgetType == STRGADGET)
-            borders = 12;
+    /* For a string gadget, we expand the border beyond the area where
+     * the text will be entered.
+     */
 
-        if ((bp = (struct Border *) alloc(((sizeof(struct Border) * 2)
-                                           + (sizeof(short) * borders)) * 2))
-            == NULL) {
-            return;
+    /* Remove any special rendering flags to avoid confusing intuition */
+    gd->Flags &= ~(GADGHIGHBITS | GADGIMAGE);
+
+    sp = (short *) (bp + 4);
+    if (gd->GadgetType == STRGADGET
+        || (gd->GadgetType == BOOLGADGET
+            && (gd->Flags & GADGHIGHBITS) == GADGHNONE)) {
+        sp[0] = -1;
+        sp[1] = gd->Height - 1;
+        sp[2] = -1;
+        sp[3] = -1;
+        sp[4] = gd->Width - 1;
+        sp[5] = -1;
+
+        sp[6] = gd->Width + 1;
+        sp[7] = -2;
+        sp[8] = gd->Width + 1;
+        sp[9] = gd->Height + 1;
+        sp[10] = -2;
+        sp[11] = gd->Height + 1;
+
+        sp[12] = -2;
+        sp[13] = gd->Height;
+        sp[14] = -2;
+        sp[15] = -2;
+        sp[16] = gd->Width;
+        sp[17] = -2;
+        sp[18] = gd->Width;
+        sp[19] = gd->Height;
+        sp[20] = -2;
+        sp[21] = gd->Height;
+
+        for (i = 0; i < 3; ++i) {
+            bp[i].LeftEdge = bp[i].TopEdge = -1;
+            bp[i].FrontPen = (i == 0 || i == 1) ? shadowpen : hipen;
+
+            /* Have to use JAM2 so that the old colors disappear. */
+            bp[i].BackPen = C_BLACK;
+            bp[i].DrawMode = JAM2;
+            bp[i].Count = (i == 0 || i == 1) ? 3 : 5;
+            bp[i].XY = &sp[i * 6];
+            bp[i].NextBorder = (i == 2) ? NULL : &bp[i + 1];
         }
 
-        /* For a string gadget, we expand the border beyond the area where
-         * the text will be entered.
-         */
+        /* bp[0] and bp[1] two pieces for the up image */
+        gd->GadgetRender = (APTR) bp;
+
+        /* No image change for select */
+        gd->SelectRender = (APTR) bp;
 
-        /* Remove any special rendering flags to avoid confusing intuition
+        gd->LeftEdge++;
+        gd->TopEdge++;
+        gd->Flags |= GADGHCOMP;
+    } else {
+        /* Create the border vector values for up and left side, and
+         * also the lower and right side.
+         */
+        sp[0] = dec;
+        sp[1] = gd->Height + inc;
+        sp[2] = dec;
+        sp[3] = dec;
+        sp[4] = gd->Width + inc;
+        sp[5] = dec;
+
+        sp[6] = gd->Width + inc;
+        sp[7] = dec;
+        sp[8] = gd->Width + inc;
+        sp[9] = gd->Height + inc;
+        sp[10] = dec;
+        sp[11] = gd->Height + inc;
+
+        /* We are creating 4 sets of borders, the two sides of the
+         * rectangle share the border vectors with the opposite image,
+         * but specify different colors.
          */
+        for (i = 0; i < 4; ++i) {
+            bp[i].TopEdge = bp[i].LeftEdge = 0;
 
-        gd->Flags &= ~(GADGHIGHBITS | GADGIMAGE);
-
-        sp = (short *) (bp + 4);
-        if (gd->GadgetType == STRGADGET
-            || (gd->GadgetType == BOOLGADGET
-                && (gd->Flags & GADGHIGHBITS) == GADGHNONE)) {
-            sp[0] = -1;
-            sp[1] = gd->Height - 1;
-            sp[2] = -1;
-            sp[3] = -1;
-            sp[4] = gd->Width - 1;
-            sp[5] = -1;
-
-            sp[6] = gd->Width + 1;
-            sp[7] = -2;
-            sp[8] = gd->Width + 1;
-            sp[9] = gd->Height + 1;
-            sp[10] = -2;
-            sp[11] = gd->Height + 1;
-
-            sp[12] = -2;
-            sp[13] = gd->Height;
-            sp[14] = -2;
-            sp[15] = -2;
-            sp[16] = gd->Width;
-            sp[17] = -2;
-            sp[18] = gd->Width;
-            sp[19] = gd->Height;
-            sp[20] = -2;
-            sp[21] = gd->Height;
-
-            for (i = 0; i < 3; ++i) {
-                bp[i].LeftEdge = bp[i].TopEdge = -1;
-                bp[i].FrontPen = (i == 0 || i == 1) ? shadowpen : hipen;
-
-                /* Have to use JAM2 so that the old colors disappear. */
-                bp[i].BackPen = C_BLACK;
-                bp[i].DrawMode = JAM2;
-                bp[i].Count = (i == 0 || i == 1) ? 3 : 5;
-                bp[i].XY = &sp[i * 6];
-                bp[i].NextBorder = (i == 2) ? NULL : &bp[i + 1];
+            /* A GADGHNONE is always down */
+            if (gd->GadgetType == BOOLGADGET
+                && (gd->Flags & GADGHIGHBITS) != GADGHNONE) {
+                bp[i].FrontPen = (i == 1 || i == 2) ? shadowpen : hipen;
+            } else {
+                bp[i].FrontPen = (i == 1 || i == 3) ? hipen : shadowpen;
             }
 
-            /* bp[0] and bp[1] two pieces for the up image */
-            gd->GadgetRender = (APTR) bp;
+            /* Have to use JAM2 so that the old colors disappear. */
+            bp[i].BackPen = C_BLACK;
+            bp[i].DrawMode = JAM2;
+            bp[i].Count = 3;
+            bp[i].XY = &sp[6 * ((i & 1) != 0)];
+            bp[i].NextBorder = (i == 1 || i == 3) ? NULL : &bp[i + 1];
+        }
 
-            /* No image change for select */
-            gd->SelectRender = (APTR) bp;
+        /* bp[0] and bp[1] two pieces for the up image */
+        gd->GadgetRender = (APTR) bp;
 
-            gd->LeftEdge++;
-            gd->TopEdge++;
-            gd->Flags |= GADGHCOMP;
-        } else {
-            /* Create the border vector values for up and left side, and
-             * also the lower and right side.
-             */
-
-            sp[0] = dec;
-            sp[1] = gd->Height + inc;
-            sp[2] = dec;
-            sp[3] = dec;
-            sp[4] = gd->Width + inc;
-            sp[5] = dec;
-
-            sp[6] = gd->Width + inc;
-            sp[7] = dec;
-            sp[8] = gd->Width + inc;
-            sp[9] = gd->Height + inc;
-            sp[10] = dec;
-            sp[11] = gd->Height + inc;
-
-            /* We are creating 4 sets of borders, the two sides of the
-             * rectangle share the border vectors with the opposite image,
-             * but specify different colors.
-             */
-
-            for (i = 0; i < 4; ++i) {
-                bp[i].TopEdge = bp[i].LeftEdge = 0;
-
-                /* A GADGHNONE is always down */
-
-                if (gd->GadgetType == BOOLGADGET
-                    && (gd->Flags & GADGHIGHBITS) != GADGHNONE) {
-                    bp[i].FrontPen = (i == 1 || i == 2) ? shadowpen : hipen;
-                } else {
-                    bp[i].FrontPen = (i == 1 || i == 3) ? hipen : shadowpen;
-                }
+        /* bp[2] and bp[3] two pieces for the down image */
+        gd->SelectRender = (APTR)(bp + 2);
+        gd->Flags |= GADGHIMAGE;
+    }
+}
 
-                /* Have to use JAM2 so that the old colors disappear. */
-                bp[i].BackPen = C_BLACK;
-                bp[i].DrawMode = JAM2;
-                bp[i].Count = 3;
-                bp[i].XY = &sp[6 * ((i & 1) != 0)];
-                bp[i].NextBorder = (i == 1 || i == 3) ? NULL : &bp[i + 1];
-            }
+/* Following function copied from wintty.c;
+   Modified slightly to fit amiga needs */
+void
+amii_player_selection()
+{
+    int i, k, n;
+    char pick4u = 'n', thisch, lastch = 0;
+    char pbuf[QBUFSZ], plbuf[QBUFSZ], rolenamebuf[QBUFSZ];
+    winid win;
+    anything any;
+    menu_item *selected = 0;
+
+    rigid_role_checks();
 
-            /* bp[0] and bp[1] two pieces for the up image */
-            gd->GadgetRender = (APTR) bp;
+    /* Should we randomly pick for the player? */
+    if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE
+        || flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) {
+        char *prompt;
 
-            /* bp[2] and bp[3] two pieces for the down image */
-            gd->SelectRender = (APTR)(bp + 2);
-            gd->Flags |= GADGHIMAGE;
+        prompt = build_plselection_prompt(pbuf, QBUFSZ,
+                                          flags.initrole, flags.initrace,
+                                          flags.initgend, flags.initalign);
+        pline("%s", prompt);
+        do { /* loop until we get valid input */
+            cursor_on(WIN_MESSAGE);
+            pick4u = lowc(WindowGetchar());
+            cursor_off(WIN_MESSAGE);
+            if (index(quitchars, pick4u))
+                pick4u = 'y';
+        } while (!index(ynqchars, pick4u));
+        pbuf[0] = pick4u;
+        pbuf[1] = 0;
+        amii_addtopl(pbuf);
+
+        if (pick4u != 'y' && pick4u != 'n') {
+        give_up: /* Quit */
+            if (selected)
+                free((genericptr_t) selected);
+            clearlocks();
+            exit_nhwindows(NULL);
+            nh_terminate(0);
+            /*NOTREACHED*/
+            return;
         }
     }
 
-    /* Following function copied from wintty.c */
-    /* Modified slightly to fit amiga needs */
-
-    void amii_player_selection()
-    {
-        int i, k, n;
-        char pick4u = 'n', thisch, lastch = 0;
-        char pbuf[QBUFSZ], plbuf[QBUFSZ], rolenamebuf[QBUFSZ];
-        winid win;
-        anything any;
-        menu_item *selected = 0;
-
-        rigid_role_checks();
-
-        /* Should we randomly pick for the player? */
-        if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE
-            || flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) {
-            char *prompt = build_plselection_prompt(
-                pbuf, QBUFSZ, flags.initrole, flags.initrace, flags.initgend,
-                flags.initalign);
-            pline("%s", prompt);
-            do { /* loop until we get valid input */
-                cursor_on(WIN_MESSAGE);
-                pick4u = lowc(WindowGetchar());
-                cursor_off(WIN_MESSAGE);
-                if (index(quitchars, pick4u))
-                    pick4u = 'y';
-            } while (!index(ynqchars, pick4u));
-            pbuf[0] = pick4u;
-            pbuf[1] = 0;
-            amii_addtopl(pbuf);
-
-            if (pick4u != 'y' && pick4u != 'n') {
-            give_up: /* Quit */
-                if (selected)
-                    free((genericptr_t) selected);
-                clearlocks();
-                exit_nhwindows(NULL);
-                terminate(0);
-                /*NOTREACHED*/
-                return;
+    (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
+                                   flags.initrole, flags.initrace,
+                                   flags.initgend, flags.initalign);
+
+    /* Select a role, if necessary */
+    /* we'll try to be compatible with pre-selected race/gender/alignment,
+     * but may not succeed */
+    if (flags.initrole < 0) {
+        /* Process the choice */
+        if (pick4u == 'y' || flags.initrole == ROLE_RANDOM
+            || flags.randomall) {
+            /* Pick a random role */
+            flags.initrole = pick_role(flags.initrace, flags.initgend,
+                                       flags.initalign, PICK_RANDOM);
+            if (flags.initrole < 0) {
+                amii_putstr(WIN_MESSAGE, 0, "Incompatible role!");
+                flags.initrole = randrole();
             }
-        }
-
-        (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
-                                       flags.initrace, flags.initgend,
-                                       flags.initalign);
+        } else {
+            /* Prompt for a role */
+            win = create_nhwindow(NHW_MENU);
+            start_menu(win);
+            any.a_void = 0; /* zero out all bits */
+            for (i = 0; roles[i].name.m; i++) {
+                if (ok_role(i, flags.initrace, flags.initgend,
+                            flags.initalign)) {
+                    any.a_int = i + 1; /* must be non-zero */
+                    thisch = lowc(roles[i].name.m[0]);
+                    if (thisch == lastch)
+                        thisch = highc(thisch);
+                    if (flags.initgend != ROLE_NONE
+                        && flags.initgend != ROLE_RANDOM) {
+                        if (flags.initgend == 1 && roles[i].name.f)
+                            Strcpy(rolenamebuf, roles[i].name.f);
+                        else
+                            Strcpy(rolenamebuf, roles[i].name.m);
+                    } else {
+                        if (roles[i].name.f) {
+                            Strcpy(rolenamebuf, roles[i].name.m);
+                            Strcat(rolenamebuf, "/");
+                            Strcat(rolenamebuf, roles[i].name.f);
+                        } else
+                            Strcpy(rolenamebuf, roles[i].name.m);
+                    }
+                    add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE,
+                             an(rolenamebuf), MENU_UNSELECTED);
+                    lastch = thisch;
+                }
+            }
+            any.a_int = pick_role(flags.initrace, flags.initgend,
+                                  flags.initalign, PICK_RANDOM) + 1;
+            if (any.a_int == 0) /* must be non-zero */
+                any.a_int = randrole() + 1;
+            add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
+                     MENU_UNSELECTED);
+            any.a_int = i + 1; /* must be non-zero */
+            add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
+                     MENU_UNSELECTED);
+            Sprintf(pbuf, "Pick a role for your %s", plbuf);
+            end_menu(win, pbuf);
+            n = select_menu(win, PICK_ONE, &selected);
+            destroy_nhwindow(win);
 
-        /* Select a role, if necessary */
-        /* we'll try to be compatible with pre-selected race/gender/alignment,
-         * but may not succeed */
-        if (flags.initrole < 0) {
             /* Process the choice */
-            if (pick4u == 'y' || flags.initrole == ROLE_RANDOM
-                || flags.randomall) {
-                /* Pick a random role */
-                flags.initrole = pick_role(flags.initrace, flags.initgend,
-                                           flags.initalign, PICK_RANDOM);
-                if (flags.initrole < 0) {
-                    amii_putstr(WIN_MESSAGE, 0, "Incompatible role!");
-                    flags.initrole = randrole();
+            if (n != 1 || selected[0].item.a_int == any.a_int)
+                goto give_up; /* Selected quit */
+
+            flags.initrole = selected[0].item.a_int - 1;
+            free((genericptr_t) selected), selected = 0;
+        }
+        (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
+                                       flags.initrole, flags.initrace,
+                                       flags.initgend, flags.initalign);
+    }
+
+    /* Select a race, if necessary */
+    /* force compatibility with role, try for compatibility with
+     * pre-selected gender/alignment */
+    if (flags.initrace < 0
+        || !validrace(flags.initrole, flags.initrace)) {
+        /* pre-selected race not valid */
+        if (pick4u == 'y' || flags.initrace == ROLE_RANDOM
+            || flags.randomall) {
+            flags.initrace = pick_race(flags.initrole, flags.initgend,
+                                       flags.initalign, PICK_RANDOM);
+            if (flags.initrace < 0) {
+                amii_putstr(WIN_MESSAGE, 0, "Incompatible race!");
+                flags.initrace = randrace(flags.initrole);
+            }
+        } else { /* pick4u == 'n' */
+            /* Count the number of valid races */
+            n = 0; /* number valid */
+            k = 0; /* valid race */
+            for (i = 0; races[i].noun; i++) {
+                if (ok_race(flags.initrole, i, flags.initgend,
+                            flags.initalign)) {
+                    n++;
+                    k = i;
                 }
-            } else {
-                /* Prompt for a role */
+            }
+            if (n == 0) {
+                for (i = 0; races[i].noun; i++) {
+                    if (validrace(flags.initrole, i)) {
+                        n++;
+                        k = i;
+                    }
+                }
+            }
+
+            /* Permit the user to pick, if there is more than one */
+            if (n > 1) {
                 win = create_nhwindow(NHW_MENU);
                 start_menu(win);
                 any.a_void = 0; /* zero out all bits */
-                for (i = 0; roles[i].name.m; i++) {
-                    if (ok_role(i, flags.initrace, flags.initgend,
+                for (i = 0; races[i].noun; i++)
+                    if (ok_race(flags.initrole, i, flags.initgend,
                                 flags.initalign)) {
                         any.a_int = i + 1; /* must be non-zero */
-                        thisch = lowc(roles[i].name.m[0]);
-                        if (thisch == lastch)
-                            thisch = highc(thisch);
-                        if (flags.initgend != ROLE_NONE
-                            && flags.initgend != ROLE_RANDOM) {
-                            if (flags.initgend == 1 && roles[i].name.f)
-                                Strcpy(rolenamebuf, roles[i].name.f);
-                            else
-                                Strcpy(rolenamebuf, roles[i].name.m);
-                        } else {
-                            if (roles[i].name.f) {
-                                Strcpy(rolenamebuf, roles[i].name.m);
-                                Strcat(rolenamebuf, "/");
-                                Strcat(rolenamebuf, roles[i].name.f);
-                            } else
-                                Strcpy(rolenamebuf, roles[i].name.m);
-                        }
-                        add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE,
-                                 an(rolenamebuf), MENU_UNSELECTED);
-                        lastch = thisch;
+                        add_menu(win, NO_GLYPH, &any, races[i].noun[0], 0,
+                                 ATR_NONE, races[i].noun,
+                                 MENU_UNSELECTED);
                     }
-                }
-                any.a_int = pick_role(flags.initrace, flags.initgend,
+                any.a_int = pick_race(flags.initrole, flags.initgend,
                                       flags.initalign, PICK_RANDOM) + 1;
                 if (any.a_int == 0) /* must be non-zero */
-                    any.a_int = randrole() + 1;
+                    any.a_int = randrace(flags.initrole) + 1;
                 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
                          MENU_UNSELECTED);
                 any.a_int = i + 1; /* must be non-zero */
                 add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
                          MENU_UNSELECTED);
-                Sprintf(pbuf, "Pick a role for your %s", plbuf);
+                Sprintf(pbuf, "Pick the race of your %s", plbuf);
                 end_menu(win, pbuf);
                 n = select_menu(win, PICK_ONE, &selected);
                 destroy_nhwindow(win);
-
-                /* Process the choice */
                 if (n != 1 || selected[0].item.a_int == any.a_int)
                     goto give_up; /* Selected quit */
 
-                flags.initrole = selected[0].item.a_int - 1;
+                k = selected[0].item.a_int - 1;
                 free((genericptr_t) selected), selected = 0;
             }
-            (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
-                                           flags.initrace, flags.initgend,
-                                           flags.initalign);
+            flags.initrace = k;
         }
+        (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
+                                       flags.initrole, flags.initrace,
+                                       flags.initgend, flags.initalign);
+    }
 
-        /* Select a race, if necessary */
-        /* force compatibility with role, try for compatibility with
-         * pre-selected gender/alignment */
-        if (flags.initrace < 0
-            || !validrace(flags.initrole, flags.initrace)) {
-            /* pre-selected race not valid */
-            if (pick4u == 'y' || flags.initrace == ROLE_RANDOM
-                || flags.randomall) {
-                flags.initrace = pick_race(flags.initrole, flags.initgend,
-                                           flags.initalign, PICK_RANDOM);
-                if (flags.initrace < 0) {
-                    amii_putstr(WIN_MESSAGE, 0, "Incompatible race!");
-                    flags.initrace = randrace(flags.initrole);
+    /* Select a gender, if necessary */
+    /* force compatibility with role/race, try for compatibility with
+     * pre-selected alignment */
+    if (flags.initgend < 0
+        || !validgend(flags.initrole, flags.initrace, flags.initgend)) {
+        /* pre-selected gender not valid */
+        if (pick4u == 'y' || flags.initgend == ROLE_RANDOM
+            || flags.randomall) {
+            flags.initgend = pick_gend(flags.initrole, flags.initrace,
+                                       flags.initalign, PICK_RANDOM);
+            if (flags.initgend < 0) {
+                amii_putstr(WIN_MESSAGE, 0, "Incompatible gender!");
+                flags.initgend = randgend(flags.initrole, flags.initrace);
+            }
+        } else { /* pick4u == 'n' */
+            /* Count the number of valid genders */
+            n = 0; /* number valid */
+            k = 0; /* valid gender */
+            for (i = 0; i < ROLE_GENDERS; i++) {
+                if (ok_gend(flags.initrole, flags.initrace, i,
+                            flags.initalign)) {
+                    n++;
+                    k = i;
                 }
-            } else { /* pick4u == 'n' */
-                /* Count the number of valid races */
-                n = 0; /* number valid */
-                k = 0; /* valid race */
-                for (i = 0; races[i].noun; i++) {
-                    if (ok_race(flags.initrole, i, flags.initgend,
-                                flags.initalign)) {
+            }
+            if (n == 0) {
+                for (i = 0; i < ROLE_GENDERS; i++) {
+                    if (validgend(flags.initrole, flags.initrace, i)) {
                         n++;
                         k = i;
                     }
                 }
-                if (n == 0) {
-                    for (i = 0; races[i].noun; i++) {
-                        if (validrace(flags.initrole, i)) {
-                            n++;
-                            k = i;
-                        }
-                    }
-                }
-
-                /* Permit the user to pick, if there is more than one */
-                if (n > 1) {
-                    win = create_nhwindow(NHW_MENU);
-                    start_menu(win);
-                    any.a_void = 0; /* zero out all bits */
-                    for (i = 0; races[i].noun; i++)
-                        if (ok_race(flags.initrole, i, flags.initgend,
-                                    flags.initalign)) {
-                            any.a_int = i + 1; /* must be non-zero */
-                            add_menu(win, NO_GLYPH, &any, races[i].noun[0], 0,
-                                     ATR_NONE, races[i].noun,
-                                     MENU_UNSELECTED);
-                        }
-                    any.a_int = pick_race(flags.initrole, flags.initgend,
-                                          flags.initalign, PICK_RANDOM) + 1;
-                    if (any.a_int == 0) /* must be non-zero */
-                        any.a_int = randrace(flags.initrole) + 1;
-                    add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
-                             MENU_UNSELECTED);
-                    any.a_int = i + 1; /* must be non-zero */
-                    add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
-                             MENU_UNSELECTED);
-                    Sprintf(pbuf, "Pick the race of your %s", plbuf);
-                    end_menu(win, pbuf);
-                    n = select_menu(win, PICK_ONE, &selected);
-                    destroy_nhwindow(win);
-                    if (n != 1 || selected[0].item.a_int == any.a_int)
-                        goto give_up; /* Selected quit */
-
-                    k = selected[0].item.a_int - 1;
-                    free((genericptr_t) selected), selected = 0;
-                }
-                flags.initrace = k;
             }
-            (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
-                                           flags.initrace, flags.initgend,
-                                           flags.initalign);
-        }
 
-        /* Select a gender, if necessary */
-        /* force compatibility with role/race, try for compatibility with
-         * pre-selected alignment */
-        if (flags.initgend < 0
-            || !validgend(flags.initrole, flags.initrace, flags.initgend)) {
-            /* pre-selected gender not valid */
-            if (pick4u == 'y' || flags.initgend == ROLE_RANDOM
-                || flags.randomall) {
-                flags.initgend = pick_gend(flags.initrole, flags.initrace,
-                                           flags.initalign, PICK_RANDOM);
-                if (flags.initgend < 0) {
-                    amii_putstr(WIN_MESSAGE, 0, "Incompatible gender!");
-                    flags.initgend = randgend(flags.initrole, flags.initrace);
-                }
-            } else { /* pick4u == 'n' */
-                /* Count the number of valid genders */
-                n = 0; /* number valid */
-                k = 0; /* valid gender */
-                for (i = 0; i < ROLE_GENDERS; i++) {
+            /* Permit the user to pick, if there is more than one */
+            if (n > 1) {
+                win = create_nhwindow(NHW_MENU);
+                start_menu(win);
+                any.a_void = 0; /* zero out all bits */
+                for (i = 0; i < ROLE_GENDERS; i++)
                     if (ok_gend(flags.initrole, flags.initrace, i,
                                 flags.initalign)) {
-                        n++;
-                        k = i;
-                    }
-                }
-                if (n == 0) {
-                    for (i = 0; i < ROLE_GENDERS; i++) {
-                        if (validgend(flags.initrole, flags.initrace, i)) {
-                            n++;
-                            k = i;
-                        }
+                        any.a_int = i + 1;
+                        add_menu(win, NO_GLYPH, &any, genders[i].adj[0], 0,
+                                 ATR_NONE, genders[i].adj, MENU_UNSELECTED);
                     }
-                }
+                any.a_int = pick_gend(flags.initrole, flags.initrace,
+                                      flags.initalign, PICK_RANDOM) + 1;
+                if (any.a_int == 0) /* must be non-zero */
+                    any.a_int = randgend(flags.initrole, flags.initrace) + 1;
+                add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
+                         MENU_UNSELECTED);
+                any.a_int = i + 1; /* must be non-zero */
+                add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
+                         MENU_UNSELECTED);
+                Sprintf(pbuf, "Pick the gender of your %s", plbuf);
+                end_menu(win, pbuf);
+                n = select_menu(win, PICK_ONE, &selected);
+                destroy_nhwindow(win);
+                if (n != 1 || selected[0].item.a_int == any.a_int)
+                    goto give_up; /* Selected quit */
 
-                /* Permit the user to pick, if there is more than one */
-                if (n > 1) {
-                    win = create_nhwindow(NHW_MENU);
-                    start_menu(win);
-                    any.a_void = 0; /* zero out all bits */
-                    for (i = 0; i < ROLE_GENDERS; i++)
-                        if (ok_gend(flags.initrole, flags.initrace, i,
-                                    flags.initalign)) {
-                            any.a_int = i + 1;
-                            add_menu(win, NO_GLYPH, &any, genders[i].adj[0],
-                                     0, ATR_NONE, genders[i].adj,
-                                     MENU_UNSELECTED);
-                        }
-                    any.a_int = pick_gend(flags.initrole, flags.initrace,
-                                          flags.initalign, PICK_RANDOM) + 1;
-                    if (any.a_int == 0) /* must be non-zero */
-                        any.a_int =
-                            randgend(flags.initrole, flags.initrace) + 1;
-                    add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
-                             MENU_UNSELECTED);
-                    any.a_int = i + 1; /* must be non-zero */
-                    add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
-                             MENU_UNSELECTED);
-                    Sprintf(pbuf, "Pick the gender of your %s", plbuf);
-                    end_menu(win, pbuf);
-                    n = select_menu(win, PICK_ONE, &selected);
-                    destroy_nhwindow(win);
-                    if (n != 1 || selected[0].item.a_int == any.a_int)
-                        goto give_up; /* Selected quit */
-
-                    k = selected[0].item.a_int - 1;
-                    free((genericptr_t) selected), selected = 0;
-                }
-                flags.initgend = k;
+                k = selected[0].item.a_int - 1;
+                free((genericptr_t) selected), selected = 0;
             }
-            (void) root_plselection_prompt(plbuf, QBUFSZ - 1, flags.initrole,
-                                           flags.initrace, flags.initgend,
-                                           flags.initalign);
+            flags.initgend = k;
         }
+        (void) root_plselection_prompt(plbuf, QBUFSZ - 1,
+                                       flags.initrole, flags.initrace,
+                                       flags.initgend, flags.initalign);
+    }
 
-        /* Select an alignment, if necessary */
-        /* force compatibility with role/race/gender */
-        if (flags.initalign < 0
-            || !validalign(flags.initrole, flags.initrace, flags.initalign)) {
-            /* pre-selected alignment not valid */
-            if (pick4u == 'y' || flags.initalign == ROLE_RANDOM
-                || flags.randomall) {
-                flags.initalign = pick_align(flags.initrole, flags.initrace,
-                                             flags.initgend, PICK_RANDOM);
-                if (flags.initalign < 0) {
-                    amii_putstr(WIN_MESSAGE, 0, "Incompatible alignment!");
-                    flags.initalign =
-                        randalign(flags.initrole, flags.initrace);
+    /* Select an alignment, if necessary */
+    /* force compatibility with role/race/gender */
+    if (flags.initalign < 0
+        || !validalign(flags.initrole, flags.initrace, flags.initalign)) {
+        /* pre-selected alignment not valid */
+        if (pick4u == 'y' || flags.initalign == ROLE_RANDOM
+            || flags.randomall) {
+            flags.initalign = pick_align(flags.initrole, flags.initrace,
+                                         flags.initgend, PICK_RANDOM);
+            if (flags.initalign < 0) {
+                amii_putstr(WIN_MESSAGE, 0, "Incompatible alignment!");
+                flags.initalign = randalign(flags.initrole, flags.initrace);
+            }
+        } else { /* pick4u == 'n' */
+            /* Count the number of valid alignments */
+            n = 0; /* number valid */
+            k = 0; /* valid alignment */
+            for (i = 0; i < ROLE_ALIGNS; i++) {
+                if (ok_align(flags.initrole, flags.initrace,
+                             flags.initgend, i)) {
+                    n++;
+                    k = i;
                 }
-            } else { /* pick4u == 'n' */
-                /* Count the number of valid alignments */
-                n = 0; /* number valid */
-                k = 0; /* valid alignment */
+            }
+            if (n == 0) {
                 for (i = 0; i < ROLE_ALIGNS; i++) {
-                    if (ok_align(flags.initrole, flags.initrace,
-                                 flags.initgend, i)) {
+                    if (validalign(flags.initrole, flags.initrace, i)) {
                         n++;
                         k = i;
                     }
                 }
-                if (n == 0) {
-                    for (i = 0; i < ROLE_ALIGNS; i++) {
-                        if (validalign(flags.initrole, flags.initrace, i)) {
-                            n++;
-                            k = i;
-                        }
+            }
+
+            /* Permit the user to pick, if there is more than one */
+            if (n > 1) {
+                win = create_nhwindow(NHW_MENU);
+                start_menu(win);
+                any.a_void = 0; /* zero out all bits */
+                for (i = 0; i < ROLE_ALIGNS; i++)
+                    if (ok_align(flags.initrole, flags.initrace,
+                                 flags.initgend, i)) {
+                        any.a_int = i + 1;
+                        add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], 0,
+                                 ATR_NONE, aligns[i].adj, MENU_UNSELECTED);
                     }
-                }
+                any.a_int = pick_align(flags.initrole, flags.initrace,
+                                       flags.initgend, PICK_RANDOM) + 1;
+                if (any.a_int == 0) /* must be non-zero */
+                    any.a_int = randalign(flags.initrole, flags.initrace) + 1;
+                add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
+                         MENU_UNSELECTED);
+                any.a_int = i + 1; /* must be non-zero */
+                add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
+                         MENU_UNSELECTED);
+                Sprintf(pbuf, "Pick the alignment of your %s", plbuf);
+                end_menu(win, pbuf);
+                n = select_menu(win, PICK_ONE, &selected);
+                destroy_nhwindow(win);
+                if (n != 1 || selected[0].item.a_int == any.a_int)
+                    goto give_up; /* Selected quit */
 
-                /* Permit the user to pick, if there is more than one */
-                if (n > 1) {
-                    win = create_nhwindow(NHW_MENU);
-                    start_menu(win);
-                    any.a_void = 0; /* zero out all bits */
-                    for (i = 0; i < ROLE_ALIGNS; i++)
-                        if (ok_align(flags.initrole, flags.initrace,
-                                     flags.initgend, i)) {
-                            any.a_int = i + 1;
-                            add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], 0,
-                                     ATR_NONE, aligns[i].adj,
-                                     MENU_UNSELECTED);
-                        }
-                    any.a_int = pick_align(flags.initrole, flags.initrace,
-                                           flags.initgend, PICK_RANDOM) + 1;
-                    if (any.a_int == 0) /* must be non-zero */
-                        any.a_int =
-                            randalign(flags.initrole, flags.initrace) + 1;
-                    add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
-                             MENU_UNSELECTED);
-                    any.a_int = i + 1; /* must be non-zero */
-                    add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
-                             MENU_UNSELECTED);
-                    Sprintf(pbuf, "Pick the alignment of your %s", plbuf);
-                    end_menu(win, pbuf);
-                    n = select_menu(win, PICK_ONE, &selected);
-                    destroy_nhwindow(win);
-                    if (n != 1 || selected[0].item.a_int == any.a_int)
-                        goto give_up; /* Selected quit */
-
-                    k = selected[0].item.a_int - 1;
-                    free((genericptr_t) selected), selected = 0;
-                }
-                flags.initalign = k;
+                k = selected[0].item.a_int - 1;
+                free((genericptr_t) selected), selected = 0;
             }
+            flags.initalign = k;
         }
-        /* Success! */
     }
+    /* Success! */
+}
 #endif /* AMIGA_INTUITION */
index a5e4b95..3d59f59 100644 (file)
@@ -55,7 +55,7 @@ void ClearCol(struct Window *w);
 void
 EditColor()
 {
-    extern const char *configfile;
+    extern char configfile[];
     int i, done = 0, okay = 0;
     long code, qual, class;
     register struct Gadget *gd, *dgad;
index eee7bd4..9bf36a8 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 tos.c   $NHDT-Date: 1432512796 2015/05/25 00:13:16 $  $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */
+/* NetHack 3.6 tos.c   $NHDT-Date: 1501979358 2017/08/06 00:29:18 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.8 $ */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -271,17 +271,20 @@ char *from, *to;
     int fromfd, tofd, r;
     char *buf;
 
-    if ((fromfd = open(from, O_RDONLY | O_BINARY, 0)) < 0)
+    fromfd = open(from, O_RDONLY | O_BINARY, 0);
+    if (fromfd < 0)
         return -1;
-    if ((tofd = open(to, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, FCMASK))
-        < 0)
+    tofd = open(to, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, FCMASK);
+    if (tofd < 0) {
+        close(fromfd);
         return -1;
-    buf = (char *) alloc((size_t) BIGBUF);
+    }
+    buf = (char *) alloc((unsigned) BIGBUF);
     while ((r = read(fromfd, buf, BIGBUF)) > 0)
         write(tofd, buf, r);
     close(fromfd);
     close(tofd);
-    free(buf);
+    free((genericptr_t) buf);
     return 0; /* successful */
 }
 
index 8d97560..6d76e8b 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 macmain.c       $NHDT-Date: 1432512796 2015/05/25 00:13:16 $  $NHDT-Branch: master $:$NHDT-Revision: 1.21 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2009. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* main.c - Mac NetHack */
index 2d43d9c..0c087fc 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 mactopl.c       $NHDT-Date: 1432512797 2015/05/25 00:13:17 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
index 17663d0..3c08bf3 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 macunix.c       $NHDT-Date: 1432512797 2015/05/25 00:13:17 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* This file collects some Unix dependencies */
index 308daa9..7b3e91b 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 mgetline.c      $NHDT-Date: 1432512797 2015/05/25 00:13:17 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
index 7258fd4..3126d76 100644 (file)
@@ -1,4 +1,4 @@
-# NetHack 3.6  Makefile.GCC    $NHDT-Date: 1432512792 2015/05/25 00:13:12 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $
+# NetHack 3.6  Makefile.GCC    $NHDT-Date: 1519600525 2018/02/25 23:15:25 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.34 $
 #      Copyright (c) NetHack PC Development Team 1996-2006.
 #      PC NetHack 3.6 Makefile for djgpp V2
 #
@@ -66,7 +66,7 @@ LIBRARIES = $(LIBS) $(TERMLIB)
 #
 # If you have yacc/lex or a work-alike set YACC_LEX to Y
 #
-YACC_LEX = Y
+YACC_LEX = N
 ifeq ($(YACC_LEX),Y)
 DO_YACC = YACC_ACT
 DO_LEX  = LEX_ACT
@@ -161,8 +161,8 @@ LFLAGS =
 else
 
 # Debugging
-#cflags = -pg -c -I../include $(DLBFLG) -DUSE_TILES
-#LFLAGS = -pg
+#cflags = -g -c -I../include $(DLBFLG) -DUSE_TILES
+#LFLAGS = -g
 
 #    Normal
 cflags = -c -O -I../include $(DLBFLG) -DUSE_TILES
@@ -173,7 +173,7 @@ endif
 #================ RULES ==================
 #==========================================
 
-.SUFFIXES: .exe .o .tib .til .uu .c .y .l
+.SUFFIXES: .exe .o .til .uu .c .y .l
 
 #==========================================
 # Rules for files in src
@@ -241,7 +241,7 @@ U  = $(UTIL)/
 #  Utility Objects.
 #==========================================
 
-VGAOBJ      = $(O)vidvga.o
+VGAOBJ      = $(O)vidvga.o $(O)vidvesa.o
 
 MAKESRC            = makedefs.c
 
@@ -267,10 +267,10 @@ RECOVOBJS   = $(O)recover.o
 
 ifeq ($(SUPPRESS_GRAPHICS),Y)
 TILOBJ       =
+TILOBJ2      =
 TEXTIO       =
 TEXTIO2      =
-PLANAR_TIB   =
-OVERVIEW_TIB =
+TILE_BMP     =
 TILEUTIL     = 
 TILEFILES    = 
 TILEFILES2   = 
@@ -281,7 +281,9 @@ PPMWRIT2     =
 
 else
 
-TILOBJ      = $(O)tile.o $(O)pctiles.o $(VGAOBJ)
+TILOBJ      = $(O)tile.o $(VGAOBJ)
+
+TILOBJ2     = $(O)tileset.o $(O)bmptiles.o $(O)giftiles.o
 
 TEXTIO      = $(O)tiletext.o $(O)tiletxt.o $(O)drawing.o $(O)decl.o $(O)monst.o \
                $(O)objects.o $(O)stubvid.o
@@ -289,11 +291,9 @@ TEXTIO      = $(O)tiletext.o $(O)tiletxt.o $(O)drawing.o $(O)decl.o $(O)monst.o
 TEXTIO2     = $(O)tiletex2.o $(O)tiletxt2.o $(O)drawing.o $(O)decl.o $(O)monst.o \
                $(O)objects.o $(O)stubvid.o
 
-PLANAR_TIB  = $(DAT)/NetHack1.tib
+TILE_BMP    = $(DAT)/nhtiles.bmp
 
-OVERVIEW_TIB = $(DAT)/NetHacko.tib
-
-TILEUTIL    = $(TILOBJ) $(U)tile2bin.exe $(U)til2bin2.exe $(PLANAR_TIB) $(OVERVIEW_TIB)
+TILEUTIL    = $(TILOBJ) $(U)tile2bin.exe $(U)til2bin2.exe $(TILE_BMP)
 
 TILEFILES   = $(WSHR)/monsters.txt $(WSHR)/objects.txt $(WSHR)/other.txt
 
@@ -308,6 +308,9 @@ PPMWRITERS  = $(O)ppmwrite.o $(O)alloc.o $(O)panic.o
 PPMWRIT2    = $(O)ppmwrit2.o $(O)alloc.o $(O)panic.o
 endif
 
+#REGEX = $(O)pmatchregex.o
+#REGEX = $(O)cppregex.o
+REGEX = $(O)posixreg.o
 
 DLBOBJ = $(O)dlb.o
 
@@ -336,7 +339,7 @@ VOBJ19 = $(O)trap.o     $(O)u_init.o  $(O)uhitm.o    $(O)vault.o    $(O)vision.o
 VOBJ20 = $(O)vis_tab.o  $(O)weapon.o  $(O)were.o     $(O)wield.o    $(O)windows.o
 VOBJ21 = $(O)wintty.o   $(O)wizard.o  $(O)worm.o     $(O)worn.o     $(O)write.o
 VOBJ22 = $(O)zap.o      $(O)light.o   $(O)dlb.o      $(O)dig.o      $(O)teleport.o
-VOBJ23 = $(O)region.o $(O)sys.o
+VOBJ23 = $(O)region.o   $(O)sys.o     $(REGEX)
 
 SOBJ   = $(O)msdos.o    $(O)sound.o   $(O)pcsys.o    $(O)tty.o     $(O)unix.o \
         $(O)video.o    $(O)vidtxt.o  $(O)pckeys.o
@@ -349,7 +352,7 @@ VOBJ  = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) \
        $(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) \
        $(VOBJ21) $(VOBJ22) $(VOBJ23)
 
-ALLOBJ = $(VOBJ) $(SOBJ) $(TILOBJ) $(VVOBJ)
+ALLOBJ = $(VOBJ) $(SOBJ) $(TILOBJ) $(TILOBJ2) $(VVOBJ)
 
 #==========================================
 # Header file macros
@@ -391,7 +394,7 @@ DLB_H      = $(INCL)/dlb.h
 ifeq ($(SUPPRESS_GRAPHICS),Y)
 TILE_H     =
 else
-TILE_H    = $(WSHR)/tile.h $(MSYS)/pctiles.h
+TILE_H    = $(WSHR)/tile.h $(INCL)/tileset.h
 endif
 
 ifeq ($(USE_DLB),Y)
@@ -448,11 +451,12 @@ endif
 ifdef TERMLIB
        @$(subst /,\,copy $(SSHR)/termcap $(GAMEDIR))
 endif
-       @$(subst /,\,if exist $(DAT)/*.tib copy $(DAT)/*.tib $(GAMEDIR))
+       @$(subst /,\,if exist $(TILE_BMP) copy $(TILE_BMP) $(GAMEDIR))
        @$(subst /,\,if exist $(DAT)/symbols copy $(DAT)/symbols $(GAMEDIR))
        @$(subst /,\,copy $(SSHR)/NetHack.cnf  $(GAMEDIR)/defaults.nh)
-       @$(subst /,\,copy $(MSYS)/NHAccess.nh  $(GAMEDIR))
+       -@$(subst /,\,touch $(GAMEDIR)/record)
        @$(subst /,\,copy $(DOC)/guidebo*.txt  $(GAMEDIR))
+       @$(subst /,\,copy ../sys/winnt/sysconf  $(GAMEDIR))
        @$(subst /,\,if exist $(DOC)/nethack.txt copy $(DOC)/nethack.txt $(GAMEDIR))
 ifdef CWSDPMI
        @$(subst /,\,if exist $(CWSDPMI) copy $(CWSDPMI) $(GAMEDIR))
@@ -466,7 +470,35 @@ endif
 #==========================================
 
 $(GAMEFILE): $(O)obj.tag $(PATCHLEV_H) $(O)utility.tag $(ALLOBJ) $(O)$(GAME).lnk
-       $(LINK) $(LFLAGS) -o$(GAME).exe @$(O)$(GAME).lnk $(LIBRARIES) $(ZLIB)
+        @if exist temp.a del temp.a
+        @ar ru temp.a $(VOBJ01)
+        @ar ru temp.a $(VOBJ02)
+        @ar ru temp.a $(VOBJ03)
+        @ar ru temp.a $(VOBJ04)
+        @ar ru temp.a $(VOBJ05)
+        @ar ru temp.a $(VOBJ06)
+        @ar ru temp.a $(VOBJ07)
+        @ar ru temp.a $(VOBJ08)
+        @ar ru temp.a $(VOBJ09)
+        @ar ru temp.a $(VOBJ10)
+        @ar ru temp.a $(VOBJ11)
+        @ar ru temp.a $(VOBJ12)
+        @ar ru temp.a $(VOBJ13)
+        @ar ru temp.a $(VOBJ14)
+        @ar ru temp.a $(VOBJ15)
+        @ar ru temp.a $(VOBJ16)
+        @ar ru temp.a $(VOBJ17)
+        @ar ru temp.a $(VOBJ18)
+        @ar ru temp.a $(VOBJ19)
+        @ar ru temp.a $(VOBJ20)
+        @ar ru temp.a $(VOBJ21)
+        @ar ru temp.a $(VOBJ22)
+        @ar ru temp.a $(VOBJ23)
+        @ar ru temp.a $(SOBJ)
+        @ar ru temp.a $(TILOBJ)
+        @ar ru temp.a $(TILOBJ2)
+        @ar ru temp.a $(VVOBJ)
+       $(LINK) $(LFLAGS) -o$(GAME).exe temp.a $(LIBRARIES) $(ZLIB)
        @$(subst /,\,stubedit $(GAME).exe minstack=2048K)
        @$(subst /,\,copy $(GAME).exe $(GAMEFILE))
        @$(subst /,\,del $(GAME).exe)
@@ -497,6 +529,7 @@ $(O)$(GAME).lnk: $(ALLOBJ)
         echo $(VOBJ23) >> $(subst /,\,$@)
         echo $(SOBJ)   >> $(subst /,\,$@)
         echo $(TILOBJ) >> $(subst /,\,$@)
+        echo $(TILOBJ2) >> $(subst /,\,$@)
         echo $(VVOBJ)  >> $(subst /,\,$@)
 
 
@@ -513,6 +546,7 @@ clean:
        $(subst /,\,if exist $(O)sp_lev.tag del $(O)sp_lev.tag)
        $(subst /,\,if exist $(O)thintile.tag del $(O)thintile.tag)
        $(subst /,\,if exist $(O)utility.tag del $(O)utility.tag)
+       $(subst /,\,if exist temp.a del temp.a)
 
 spotless: clean
 
@@ -527,6 +561,7 @@ spotless: clean
        $(subst /,\,if exist $(U)dgn_comp.exe del $(U)dgn_comp.exe)
        $(subst /,\,if exist $(U)recover.exe del $(U)recover.exe)
        $(subst /,\,if exist $(U)tilemap.exe del $(U)tilemap.exe)
+       $(subst /,\,if exist $(U)tile2bmp.exe del $(U)tile2bmp.exe)
        $(subst /,\,if exist $(U)tile2bin.exe del $(U)tile2bin.exe)
        $(subst /,\,if exist $(U)til2bin2.exe del $(U)til2bin2.exe)
        $(subst /,\,if exist $(U)thintile.exe del $(U)thintile.exe)
@@ -547,11 +582,13 @@ spotless: clean
        $(subst /,\,if exist $(DAT)/dungeon del $(DAT)/dungeon)
        $(subst /,\,if exist $(DAT)/oracles del $(DAT)/oracles)
        $(subst /,\,if exist $(DAT)/quest.dat del $(DAT)/quest.dat)
+       $(subst /,\,if exist $(DAT)/bogusmon del $(DAT)/bogusmon)
+       $(subst /,\,if exist $(DAT)/engrave del $(DAT)/engrave)
+       $(subst /,\,if exist $(DAT)/epitaph del $(DAT)/epitaph)
        $(subst /,\,if exist $(DAT)/dlb.lst del $(DAT)/dlb.lst)
        $(subst /,\,if exist $(DAT)/nhdat del $(DAT)/nhdat)
        $(subst /,\,if exist $(DAT)/*.lev del $(DAT)/*.lev)
-       $(subst /,\,if exist $(PLANAR_TIB) del $(PLANAR_TIB))
-       $(subst /,\,if exist $(OVERVIEW_TIB) del $(OVERVIEW_TIB))
+       $(subst /,\,if exist $(TILE_BMP) del $(TILE_BMP))
        $(subst /,\,if exist $(WSHR)/monthin.txt del $(WSHR)/monthin.txt)
        $(subst /,\,if exist $(WSHR)/objthin.txt del $(WSHR)/objthin.txt)
        $(subst /,\,if exist $(WSHR)/oththin.txt del $(WSHR)/oththin.txt)
@@ -614,7 +651,9 @@ $(O)makedefs.o:  $(CONFIG_H)        $(PERMONST_H)      $(INCL)/objclass.h \
 #==========================================
 
 $(U)lev_comp.exe:  $(SPLEVOBJS)
-       $(LINK) $(LFLAGS) -o$@ $(SPLEVOBJS)
+       -rm -f temp.a
+       @ar ru temp.a $(SPLEVOBJS)
+       $(LINK) $(LFLAGS) -o$@ temp.a
 
 ifeq ($(YACC_LEX),Y)
 
@@ -770,23 +809,26 @@ $(O)tilemap.o: $(WSHR)/tilemap.c $(HACK_H) $(TILE_H)
 #  Required for tile support
 #==========================================
 
-$(DAT)/NetHack1.tib: $(TILEFILES) $(U)tile2bin.exe
+$(DAT)/nhtiles.bmp: $(TILEFILES) $(U)tile2bmp.exe
        @echo Creating binary tile files (this may take some time)
        @$(subst /,\,chdir $(DAT))
-       @$(subst /,\,$(U)tile2bin.exe)
+       @$(subst /,\,$(U)tile2bmp.exe $@)
        @$(subst /,\,chdir $(SRC))
 
-$(DAT)/NetHacko.tib: $(O)thintile.tag $(TILEFILES2) $(U)til2bin2.exe
-       @echo Creating overview binary tile files (this may take some time)
-       @$(subst /,\,chdir $(DAT))
-       @$(subst /,\,$(U)til2bin2.exe)
-       @$(subst /,\,chdir $(SRC))
+$(U)tile2bmp.exe: $(O)tile2bmp.o $(TEXTIO)
+       -rm -f temp.a
+       @ar ru temp.a $(TEXTIO)
+       $(LINK) $(LFLAGS) -o$@ $(O)tile2bmp.o temp.a
 
 $(U)tile2bin.exe: $(O)tile2bin.o $(TEXTIO)
-       $(LINK) $(LFLAGS) -o$@ $(O)tile2bin.o $(TEXTIO)
+       -rm -f temp.a
+       @ar ru temp.a $(TEXTIO)
+       $(LINK) $(LFLAGS) -o$@ $(O)tile2bin.o temp.a
 
 $(U)til2bin2.exe: $(O)til2bin2.o $(TEXTIO2)
-       $(LINK) $(LFLAGS) -o$@ $(O)til2bin2.o $(TEXTIO2)
+       -rm -f temp.a
+       @ar ru temp.a $(TEXTIO2)
+       $(LINK) $(LFLAGS) -o$@ $(O)til2bin2.o temp.a
 
 $(U)thintile.exe: $(O)thintile.o 
        $(LINK) $(LFLAGS) -o$@ $(O)thintile.o
@@ -798,6 +840,9 @@ $(O)thintile.tag: $(U)thintile.exe $(TILEFILES)
        @$(subst /,\,$(U)thintile.exe)
        @$(subst /,\,echo thintiles created >$@)
 
+$(O)tile2bmp.o:  $(HACK_H) $(TILE_H) $(WSHR)/tile2bmp.c
+       $(CC) $(cflags) -I$(MSYS) -I$(WSHR) -o$@ $(WSHR)/tile2bmp.c
+
 $(O)tile2bin.o:  $(HACK_H) $(TILE_H) $(MSYS)/pctiles.h $(MSYS)/pcvideo.h $(MSYS)/tile2bin.c
        $(CC) $(cflags) -I$(MSYS) -I$(WSHR) -o$@ $(MSYS)/tile2bin.c
 
@@ -900,6 +945,15 @@ $(DAT)/quest.dat: $(O)utility.tag  $(DAT)/quest.txt
 $(DAT)/oracles:             $(O)utility.tag    $(DAT)/oracles.txt
        @$(subst /,\,$(U)makedefs.exe -h)
 
+$(DAT)/bogusmon:     $(O)utility.tag    $(DAT)/bogusmon.txt
+       @$(subst /,\,$(U)makedefs.exe -s)
+
+$(DAT)/engrave:             $(O)utility.tag    $(DAT)/engrave.txt
+       @$(subst /,\,$(U)makedefs.exe -s)
+
+$(DAT)/epitaph:             $(O)utility.tag    $(DAT)/epitaph.txt
+       @$(subst /,\,$(U)makedefs.exe -s)
+
 $(O)sp_lev.tag: $(O)utility.tag $(DAT)/bigroom.des  $(DAT)/castle.des \
        $(DAT)/endgame.des $(DAT)/gehennom.des $(DAT)/knox.des \
        $(DAT)/medusa.des  $(DAT)/oracle.des   $(DAT)/tower.des \
@@ -949,24 +1003,14 @@ $(DAT)/dungeon:    $(O)utility.tag  $(DAT)/dungeon.def
 #note that dir below assumes bin/dir.exe from djgpp distribution
 #
 $(DAT)/nhdat:  $(U)dlb_main.exe $(DAT)/data $(DAT)/rumors $(DAT)/dungeon \
-           $(DAT)/oracles $(DAT)/quest.dat $(O)sp_lev.tag
+           $(DAT)/oracles $(DAT)/quest.dat $(O)sp_lev.tag \
+           $(DAT)/bogusmon $(DAT)/engrave $(DAT)/epitaph $(DAT)/tribute
        @$(subst /,\,echo dat done >$(O)dat.tag)
        @$(subst /,\,cd $(DAT))
        @$(subst /,\,copy $(MSYS)/msdoshlp.txt .)
-       @$(subst /,\,echo data >dlb.lst)
-       @$(subst /,\,echo dungeon >>dlb.lst)
-       @$(subst /,\,echo oracles >>dlb.lst)
-       @$(subst /,\,echo options >>dlb.lst)
-       @$(subst /,\,echo quest.dat >>dlb.lst)
-       @$(subst /,\,echo rumors >>dlb.lst)
-       @$(subst /,\,echo help >>dlb.lst)
-       @$(subst /,\,echo hh >>dlb.lst)
-       @$(subst /,\,echo cmdhelp >>dlb.lst)
-       @$(subst /,\,echo history >>dlb.lst)
-       @$(subst /,\,echo opthelp >>dlb.lst)
-       @$(subst /,\,echo wizhelp >>dlb.lst)
-       @$(subst /,\,echo license >>dlb.lst)
-       @$(subst /,\,echo msdoshlp.txt >>dlb.lst)
+       @$(LS) data dungeon oracles options quest.dat rumors help hh >dlb.lst
+       @$(LS) cmdhelp history opthelp wizhelp license msdoshlp.txt >>dlb.lst
+       @$(LS) bogusmon engrave epitaph tribute >>dlb.lst
        $(LS) $(subst /,\,*.lev) >>dlb.lst
        @$(subst /,\,$(U)dlb_main cvIf dlb.lst nhdat)
        @$(subst /,\,cd $(SRC))
@@ -994,6 +1038,15 @@ $(O)unix.o:        $(HACK_H) $(SSHR)/pcunix.c
 $(O)pcsys.o : $(HACK_H) $(SSHR)/pcsys.c
        $(CC) $(cflags) -o$@ $(SSHR)/pcsys.c
 
+$(O)posixreg.o : $(HACK_H) $(SSHR)/posixreg.c
+       $(CC) $(cflags) -o$@ $(SSHR)/posixreg.c
+
+$(O)cppregex.o : $(HACK_H) $(SSHR)/cppregex.cpp
+       gpp $(cflags) -std=c++11 -o$@ $(SSHR)/cppregex.cpp
+
+$(O)pmatchre.o : $(HACK_H) $(SSHR)/pmatchre.c
+       $(CC) $(cflags) -o$@ $(SSHR)/pmatchre.c
+
 # sys/msdos
 $(O)msdos.o : $(HACK_H)  $(MSYS)/msdos.c
 #      $(CC) $(cflags) -o$@ $(MSYS)/msdos.c
@@ -1013,6 +1066,9 @@ $(O)video.o : $(HACK_H)  $(MSYS)/pcvideo.h $(MSYS)/portio.h $(MSYS)/video.c
 $(O)vidvga.o : $(HACK_H)  $(MSYS)/pcvideo.h $(MSYS)/portio.h $(TILE_H) $(MSYS)/vidvga.c
        $(CC) $(cflags) -I$(MSYS) -I$(WSHR) -o$@ $(MSYS)/vidvga.c
 
+$(O)vidvesa.o : $(HACK_H)  $(MSYS)/pcvideo.h $(MSYS)/portio.h $(TILE_H) $(MSYS)/vidvesa.c
+       $(CC) $(cflags) -I$(MSYS) -I$(WSHR) -o$@ $(MSYS)/vidvesa.c
+
 $(O)vidtxt.o : $(HACK_H)  $(MSYS)/pcvideo.h $(MSYS)/portio.h $(TILE_H) $(MSYS)/vidtxt.c
 #      $(CC) $(cflags) -o$@ -I$(MSYS) $(MSYS)/vidtxt.c
 
@@ -1040,8 +1096,6 @@ $(O)tos.o: ../sys/atari/tos.c $(HACK_H) $(INCL)/tcap.h
 $(O)pcmain.o: ../sys/share/pcmain.c $(HACK_H) $(INCL)/dlb.h \
                #$(INCL)/win32api.h
        $(CC) $(cflags) -o$@ ../sys/share/pcmain.c
-$(O)pcsys.o: ../sys/share/pcsys.c $(HACK_H)
-       $(CC) $(cflags) -o$@ ../sys/share/pcsys.c
 $(O)pctty.o: ../sys/share/pctty.c $(HACK_H)
        $(CC) $(cflags) -o$@ ../sys/share/pctty.c
 $(O)pcunix.o: ../sys/share/pcunix.c $(HACK_H)
@@ -1270,6 +1324,10 @@ $(O)worm.o: worm.c $(HACK_H) $(INCL)/lev.h
 $(O)worn.o: worn.c $(HACK_H)
 $(O)write.o: write.c $(HACK_H)
 $(O)zap.o: zap.c $(HACK_H)
+$(O)pmatchre.o: $(SSHR)/pmatchre.c $(HACK_H)
+$(O)tileset.o: $(WSHR)/tileset.c $(HACK_H)
+$(O)bmptiles.o: $(WSHR)/bmptiles.c $(INCL)/config.h $(INCL)/tileset.h $(INCL)/integer.h
+$(O)giftiles.o: $(WSHR)/giftiles.c $(INCL)/config.h $(INCL)/tileset.h $(INCL)/integer.h
 
 # end of file
 
index 567b8ee..ec59b99 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 pckeys.c        $NHDT-Date: 1432512792 2015/05/25 00:13:12 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
+/* NetHack 3.6 pckeys.c        $NHDT-Date: 1501465420 2017/07/31 01:43:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.12 $ */
 /* Copyright (c) NetHack PC Development Team 1996                 */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "pcvideo.h"
 
 boolean FDECL(pckeys, (unsigned char, unsigned char));
+static void FDECL(userpan, (BOOLEAN_P));
+static void FDECL(overview, (BOOLEAN_P));
+static void FDECL(traditional, (BOOLEAN_P));
+static void NDECL(refresh);
 
 extern struct WinDesc *wins[MAXWIN]; /* from wintty.c */
 extern boolean inmap;                /* from video.c */
@@ -35,8 +39,8 @@ unsigned char shift;
     boolean opening_dialog;
 
     opening_dialog = pl_character[0] ? FALSE : TRUE;
-#ifdef SIMULATE_CURSOR
     switch (scancode) {
+#ifdef SIMULATE_CURSOR
     case 0x3d: /* F3 = toggle cursor type */
         HideCursor();
         cursor_type += 1;
@@ -47,25 +51,24 @@ unsigned char shift;
 #endif
     case 0x74: /* Control-right_arrow = scroll horizontal to right */
         if ((shift & CTRL) && iflags.tile_view && !opening_dialog)
-            vga_userpan(1);
+            userpan(1);
         break;
-
     case 0x73: /* Control-left_arrow = scroll horizontal to left */
         if ((shift & CTRL) && iflags.tile_view && !opening_dialog)
-            vga_userpan(0);
+            userpan(0);
         break;
     case 0x3E: /* F4 = toggle overview mode */
         if (iflags.tile_view && !opening_dialog && !Is_rogue_level(&u.uz)) {
             iflags.traditional_view = FALSE;
-            vga_overview(iflags.over_view ? FALSE : TRUE);
-            vga_refresh();
+            overview(iflags.over_view ? FALSE : TRUE);
+            refresh();
         }
         break;
     case 0x3F: /* F5 = toggle traditional mode */
         if (iflags.tile_view && !opening_dialog && !Is_rogue_level(&u.uz)) {
             iflags.over_view = FALSE;
-            vga_traditional(iflags.traditional_view ? FALSE : TRUE);
-            vga_refresh();
+            traditional(iflags.traditional_view ? FALSE : TRUE);
+            refresh();
         }
         break;
     default:
@@ -73,6 +76,61 @@ unsigned char shift;
     }
     return TRUE;
 }
+
+static void
+userpan(on)
+boolean on;
+{
+#ifdef SCREEN_VGA
+    if (iflags.usevga)
+        vga_userpan(on);
+#endif
+#ifdef SCREEN_VESA
+    if (iflags.usevesa)
+        vesa_userpan(on);
+#endif
+}
+
+static void
+overview(on)
+boolean on;
+{
+#ifdef SCREEN_VGA
+    if (iflags.usevga)
+        vga_overview(on);
+#endif
+#ifdef SCREEN_VESA
+    if (iflags.usevesa)
+        vesa_overview(on);
+#endif
+}
+
+static void
+traditional(on)
+boolean on;
+{
+#ifdef SCREEN_VGA
+    if (iflags.usevga)
+        vga_traditional(on);
+#endif
+#ifdef SCREEN_VESA
+    if (iflags.usevesa)
+        vesa_traditional(on);
+#endif
+}
+
+static void
+refresh()
+{
+#ifdef SCREEN_VGA
+    if (iflags.usevga)
+        vga_refresh();
+#endif
+#ifdef SCREEN_VESA
+    if (iflags.usevesa)
+        vesa_refresh();
+#endif
+}
 #endif /* USE_TILES */
 #endif /* MSDOS */
 
index 58f29a3..e568123 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 pctiles.h       $NHDT-Date: 1432512791 2015/05/25 00:13:11 $  $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
+/* NetHack 3.6 pctiles.h       $NHDT-Date: 1457207040 2016/03/05 19:44:00 $  $NHDT-Branch: chasonr $:$NHDT-Revision: 1.9 $ */
 /*   Copyright (c) NetHack PC Development Team 1993, 1994             */
 /*   NetHack may be freely redistributed.  See license for details.   */
 /*                                                                    */
  */
 
 #ifdef USE_TILES
+#ifndef TILE_X
+#define TILE_X 16
+#endif
+
 #define NETHACK_PLANAR_TILEFILE "NetHack1.tib"   /* Planar style tiles */
 #define NETHACK_PACKED_TILEFILE "NetHack2.tib"   /* Packed style tiles */
 #define NETHACK_OVERVIEW_TILEFILE "NetHacko.tib" /* thin overview tiles */
index e62bd7b..bc2f876 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 pcvideo.h       $NHDT-Date: 1432512792 2015/05/25 00:13:12 $  $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
+/* NetHack 3.6 pcvideo.h       $NHDT-Date: 1457207040 2016/03/05 19:44:00 $  $NHDT-Branch: chasonr $:$NHDT-Revision: 1.9 $ */
 /*   Copyright (c) NetHack PC Development Team 1993, 1994           */
 /*   NetHack may be freely redistributed.  See license for details. */
 /*                                                                  */
@@ -166,7 +166,7 @@ struct overview_planar_cell_struct {
 #define M_BRIGHTCYAN 11
 
 #define M_TEXT M_GRAY
-#define BACKGROUND_COLOR 0
+#define BACKGROUND_COLOR 1
 #define ATTRIB_NORMAL M_TEXT       /* Normal attribute */
 #define ATTRIB_INTENSE M_WHITE     /* Intense White */
 #define ATTRIB_MONO_NORMAL 0x01    /* Underlined,white */
@@ -176,9 +176,9 @@ struct overview_planar_cell_struct {
 #endif                             /*SCREEN_BIOS || SCREEN_DJGPPFAST */
 
 #if defined(SCREEN_VGA) || defined(SCREEN_8514)
-#define BACKGROUND_VGA_COLOR 0
+#define BACKGROUND_VGA_COLOR 1
 #define ATTRIB_VGA_NORMAL CLR_GRAY /* Normal attribute */
-#define ATTRIB_VGA_INTENSE 13      /* Intense White 94/06/07 palette chg*/
+#define ATTRIB_VGA_INTENSE 14      /* Intense White 94/06/07 palette chg*/
 #endif                             /*SCREEN_VGA || SCREEN_8514*/
 
 #if defined(PC9800)
@@ -258,9 +258,6 @@ E int NDECL(vga_detect);
 #ifdef SIMULATE_CURSOR
 E void NDECL(vga_DrawCursor);
 #endif
-E void FDECL(vga_DisplayCell, (struct planar_cell_struct *, int, int));
-E void FDECL(vga_DisplayCell_O,
-             (struct overview_planar_cell_struct *, int, int));
 E void NDECL(vga_Finish);
 E char __far *NDECL(vga_FontPtrs);
 E void NDECL(vga_get_scr_size);
@@ -272,12 +269,8 @@ E void FDECL(vga_update_positionbar, (char *));
 E void NDECL(vga_HideCursor);
 #endif
 E void NDECL(vga_Init);
-E void FDECL(vga_SwitchMode, (unsigned int));
-E void FDECL(vga_SetPalette, (char *));
 E void NDECL(vga_tty_end_screen);
 E void FDECL(vga_tty_startup, (int *, int *));
-E void FDECL(vga_WriteChar, (int, int, int, int));
-E void FDECL(vga_WriteStr, (char *, int, int, int, int));
 E void FDECL(vga_xputs, (const char *, int, int));
 E void FDECL(vga_xputc, (CHAR_P, int));
 E void FDECL(vga_xputg, (int, int, unsigned));
@@ -286,6 +279,35 @@ E void FDECL(vga_overview, (BOOLEAN_P));
 E void FDECL(vga_traditional, (BOOLEAN_P));
 E void NDECL(vga_refresh);
 #endif /* SCREEN_VGA */
+#ifdef SCREEN_VESA
+E void NDECL(vesa_backsp);
+E void FDECL(vesa_clear_screen, (int));
+E void FDECL(vesa_cl_end, (int, int));
+E void FDECL(vesa_cl_eos, (int));
+E int NDECL(vesa_detect);
+#ifdef SIMULATE_CURSOR
+E void NDECL(vesa_DrawCursor);
+#endif
+E void NDECL(vesa_Finish);
+E void NDECL(vesa_get_scr_size);
+E void FDECL(vesa_gotoloc, (int, int));
+#ifdef POSITIONBAR
+E void FDECL(vesa_update_positionbar, (char *));
+#endif
+#ifdef SIMULATE_CURSOR
+E void NDECL(vesa_HideCursor);
+#endif
+E void NDECL(vesa_Init);
+E void NDECL(vesa_tty_end_screen);
+E void FDECL(vesa_tty_startup, (int *, int *));
+E void FDECL(vesa_xputs, (const char *, int, int));
+E void FDECL(vesa_xputc, (CHAR_P, int));
+E void FDECL(vesa_xputg, (int, int, unsigned));
+E void FDECL(vesa_userpan, (BOOLEAN_P));
+E void FDECL(vesa_overview, (BOOLEAN_P));
+E void FDECL(vesa_traditional, (BOOLEAN_P));
+E void NDECL(vesa_refresh);
+#endif /* SCREEN_VESA */
 #endif /* NO_TERMS   */
 
 #undef E
index 63e9de9..34e0f81 100644 (file)
@@ -1,10 +1,10 @@
 @echo off
 REM    NetHack 3.6 setup.bat   $NHDT-Date: 1432512792 2015/05/25 00:13:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.9 $
-REM    Copyright (c) NetHack PC Development Team 1990 - 2012
+REM    Copyright (c) NetHack PC Development Team 1990 - 2018
 REM    NetHack may be freely redistributed.  See license for details.
 
 echo.
-echo   Copyright (c) NetHack PC Development Team 1990 - 2012
+echo   Copyright (c) NetHack PC Development Team 1990 - 2018
 echo   NetHack may be freely redistributed.  See license for details.
 echo.
 REM setup batch file for msdos, see Install.dos for details.
@@ -59,6 +59,12 @@ echo "Copying ..\..\include\patchl~1.h -> ..\..\include\patchlev.h"
 copy ..\..\include\patchl~1.h ..\..\include\patchlev.h
 if exist ..\..\include\patchlev.old del /Q ..\..\include\patchlev.old
 ren ..\..\include\patchl~1.h patchlev.old
+:long2c
+echo "Copying ..\..\sys\share\pmatch~1.c -> ..\..\sys\share\pmatchre.c"
+copy ..\..\sys\share\pmatch~1.c ..\..\sys\share\pmatchre.c
+:long2d
+echo "Copying ..\..\sys\share\posixr~1.c -> ..\..\sys\share\posixreg.c"
+copy ..\..\sys\share\posixr~1.c ..\..\sys\share\posixreg.c
 :long2ok
 
 REM Missing guidebook is not fatal to the build process
index 8ecdbfe..4c7a322 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 tile2bin.c      $NHDT-Date: 1432512792 2015/05/25 00:13:12 $  $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
+/* NetHack 3.6 tile2bin.c      $NHDT-Date: 1457207041 2016/03/05 19:44:01 $  $NHDT-Branch: chasonr $:$NHDT-Revision: 1.9 $ */
 /*   Copyright (c) NetHack PC Development Team 1993, 1994, 1995     */
 /*   NetHack may be freely redistributed.  See license for details. */
 
 extern unsigned _stklen = STKSIZ;
 #endif
 
+/* Produce only a planar file if building the overview file; with packed
+   files, we can make overview-size tiles on the fly */
+#if defined(OVERVIEW_FILE) && defined(PACKED_FILE)
+#undef PACKED_FILE
+#endif
+
 extern char *FDECL(tilename, (int, int));
 
 #ifdef PLANAR_FILE
@@ -62,7 +68,8 @@ struct tibhdr_struct tibheader;
 
 static void FDECL(write_tibtile, (int));
 static void FDECL(write_tibheader, (FILE *, struct tibhdr_struct *));
-static void FDECL(build_tibtile, (pixel(*) [TILE_X]));
+static void FDECL(build_tibtile, (pixel(*) [TILE_X], BOOLEAN_P));
+static void NDECL(remap_colors);
 
 #ifndef OVERVIEW_FILE
 char *tilefiles[] = { "../win/share/monsters.txt", "../win/share/objects.txt",
@@ -85,6 +92,7 @@ char *argv[];
     struct tm *newtime;
     time_t aclock;
     char *paletteptr;
+    unsigned num_monsters = 0;
 
     if (argc != 1) {
         Fprintf(stderr, "usage: tile2bin (from the util directory)\n");
@@ -135,6 +143,7 @@ char *argv[];
         }
 
         if (!paletteflag) {
+            remap_colors();
             paletteptr = tibheader.palette;
             for (i = 0; i < num_colors; i++) {
                 *paletteptr++ = ColorMap[CM_RED][i],
@@ -145,15 +154,33 @@ char *argv[];
         }
 
         while (read_text_tile(pixels)) {
-            build_tibtile(pixels);
+            build_tibtile(pixels, FALSE);
             write_tibtile(tilecount);
             tilecount++;
         }
 
         (void) fclose_text_file();
+        if (filenum == 0) {
+            num_monsters = tilecount;
+        }
         ++filenum;
     }
 
+    /* Build the statue glyphs */
+    if (!fopen_text_file(tilefiles[0], RDTMODE)) {
+        Fprintf(stderr,
+                "usage: tile2bin (from the util or src directory)\n");
+        exit(EXIT_FAILURE);
+    }
+
+    while (read_text_tile(pixels)) {
+        build_tibtile(pixels, TRUE);
+        write_tibtile(tilecount);
+        tilecount++;
+    }
+
+    (void) fclose_text_file();
+
 #if defined(_MSC_VER)
     tibheader.compiler = MSC_COMP;
 #elif defined(__BORLANDC__)
@@ -207,18 +234,25 @@ struct tibhdr_struct *tibhdr;
 }
 
 static void
-build_tibtile(pixels)
+build_tibtile(pixels, statues)
 pixel (*pixels)[TILE_X];
+boolean statues;
 {
+    static int graymappings[] = {
+        /* .  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  */
+        0, 1, 17, 18, 19, 20, 27, 22, 23, 24, 25, 26, 21, 15, 13, 14, 14
+    };
     int i, j, k, co_off;
     unsigned char co_mask, tmp;
 
+#ifdef PLANAR_FILE
 #ifndef OVERVIEW_FILE
     memset((void *) &planetile, 0, sizeof(struct planar_cell_struct));
 #else
     memset((void *) &planetile, 0,
            sizeof(struct overview_planar_cell_struct));
 #endif
+#endif
     for (j = 0; j < TILE_Y; j++) {
         for (i = 0; i < TILE_X; i++) {
             for (k = 0; k < num_colors; k++) {
@@ -229,6 +263,15 @@ pixel (*pixels)[TILE_X];
             }
             if (k >= num_colors)
                 Fprintf(stderr, "color not in colormap!\n");
+            if (statues) {
+                k = graymappings[k];
+            } else {
+                if (k == 16) {
+                    k = 13;
+                } else if (k == 13) {
+                    k = 16;
+                }
+            }
 #ifdef PACKED_FILE
             packtile[j][i] = k;
 #endif
@@ -242,6 +285,14 @@ pixel (*pixels)[TILE_X];
                 co_mask = masktable[i];
             }
 
+            if (!statues) {
+                if (k == 28) {
+                    k = 0;
+                }
+                if (k >= 16) {
+                    fprintf(stderr, "Warning: pixel value %d in 16 color bitmap\n", k);
+                }
+            }
             tmp = planetile.plane[0].image[j][co_off];
             planetile.plane[0].image[j][co_off] =
                 (k & 0x0008) ? (tmp | co_mask) : (tmp & ~co_mask);
@@ -299,3 +350,19 @@ int recnum;
     fwrite(&packtile, sizeof(packtile), 1, tibfile2);
 #endif
 }
+
+static void
+remap_colors()
+{
+    char swap;
+
+    swap = ColorMap[CM_RED][13];
+    ColorMap[CM_RED][13] = ColorMap[CM_RED][16];
+    ColorMap[CM_RED][16] = swap;
+    swap = ColorMap[CM_GREEN][13];
+    ColorMap[CM_GREEN][13] = ColorMap[CM_GREEN][16];
+    ColorMap[CM_GREEN][16] = swap;
+    swap = ColorMap[CM_BLUE][13];
+    ColorMap[CM_BLUE][13] = ColorMap[CM_BLUE][16];
+    ColorMap[CM_BLUE][16] = swap;
+}
diff --git a/sys/msdos/vesa.h b/sys/msdos/vesa.h
new file mode 100644 (file)
index 0000000..1184a42
--- /dev/null
@@ -0,0 +1,81 @@
+/* NetHack 3.6 vesa.h  $NHDT-Date: 1507161296 2017/10/04 23:54:56 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.0 $ */
+
+/* VESA structures from the VESA BIOS Specification, retrieved 15 Jan 2016
+ * from http://flint.cs.yale.edu/cs422/readings/hardware/vbe3.pdf
+ * Part of rchason vesa port */
+
+#ifndef VESA_H
+#define VESA_H
+
+#include <stdint.h>
+
+struct VbeInfoBlock {
+    uint8_t  VbeSignature[4];   /* VBE Signature */
+    uint16_t VbeVersion;        /* VBE Version */
+    uint32_t OemStringPtr;      /* VbeFarPtr to OEM String */
+    uint32_t Capabilities;      /* Capabilities of graphics controller */
+    uint32_t VideoModePtr;      /* VbeFarPtr to VideoModeList */
+    uint16_t TotalMemory;       /* Number of 64kb memory blocks */
+    /* Added for VBE 2.0+ */
+    uint16_t OemSoftwareRev;    /* VBE implementation Software revision */
+    uint32_t OemVendorNamePtr;  /* VbeFarPtr to Vendor Name String */
+    uint32_t OemProductNamePtr; /* VbeFarPtr to Product Name String */
+    uint32_t OemProductRevPtr;  /* VbeFarPtr to Product Revision String */
+    uint8_t  Reserved[222];     /* Reserved for VBE implementation scratch area */
+    uint8_t  OemData[256];      /* Data Area for OEM Strings */
+} __attribute__((packed));
+
+struct ModeInfoBlock {
+    /* Mandatory information for all VBE revisions */
+    uint16_t ModeAttributes;        /* mode attributes */
+    uint8_t  WinAAttributes;        /* window A attributes */
+    uint8_t  WinBAttributes;        /* window B attributes */
+    uint16_t WinGranularity;        /* window granularity */
+    uint16_t WinSize;               /* window size */
+    uint16_t WinASegment;           /* window A start segment */
+    uint16_t WinBSegment;           /* window B start segment */
+    uint32_t WinFuncPtr;            /* real mode pointer to window function */
+    uint16_t BytesPerScanLine;      /* bytes per scan line */
+    /* Mandatory information for VBE 1.2 and above */
+    uint16_t XResolution;           /* horizontal resolution in pixels or characters */
+    uint16_t YResolution;           /* vertical resolution in pixels or characters */
+    uint8_t  XCharSize;             /* character cell width in pixels */
+    uint8_t  YCharSize;             /* character cell height in pixels */
+    uint8_t  NumberOfPlanes;        /* number of memory planes */
+    uint8_t  BitsPerPixel;          /* bits per pixel */
+    uint8_t  NumberOfBanks;         /* number of banks */
+    uint8_t  MemoryModel;           /* memory model type */
+    uint8_t  BankSize;              /* bank size in KB */
+    uint8_t  NumberOfImagePages;    /* number of images */
+    uint8_t  Reserved1;             /* reserved for page function */
+    /* Direct Color fields (required for direct/6 and YUV/7 memory models) */
+    uint8_t  RedMaskSize;           /* size of direct color red mask in bits */
+    uint8_t  RedFieldPosition;      /* bit position of lsb of red mask */
+    uint8_t  GreenMaskSize;         /* size of direct color green mask in bits */
+    uint8_t  GreenFieldPosition;    /* bit position of lsb of green mask */
+    uint8_t  BlueMaskSize;          /* size of direct color blue mask in bits */
+    uint8_t  BlueFieldPosition;     /* bit position of lsb of blue mask */
+    uint8_t  RsvdMaskSize;          /* size of direct color reserved mask in bits */
+    uint8_t  RsvdFieldPosition;     /* bit position of lsb of reserved mask */
+    uint8_t  DirectColorModeInfo;   /* direct color mode attributes */
+    /* Mandatory information for VBE 2.0 and above */
+    uint32_t PhysBasePtr;           /* physical address for flat memory frame buffer */
+    uint32_t Reserved2;             /* Reserved - always set to 0 */
+    uint16_t Reserved3;             /* Reserved - always set to 0 */
+    /* Mandatory information for VBE 3.0 and above */
+    uint16_t LinBytesPerScanLine;   /* bytes per scan line for linear modes */
+    uint8_t  BnkNumberOfImagePages; /* number of images for banked modes */
+    uint8_t  LinNumberOfImagePages; /* number of images for linear modes */
+    uint8_t  LinRedMaskSize;        /* size of direct color red mask (linear modes) */
+    uint8_t  LinRedFieldPosition;   /* bit position of lsb of red mask (linear modes) */
+    uint8_t  LinGreenMaskSize;      /* size of direct color green mask  (linear modes) */
+    uint8_t  LinGreenFieldPosition; /* bit position of lsb of green mask (linear modes) */
+    uint8_t  LinBlueMaskSize;       /* size of direct color blue mask  (linear modes) */
+    uint8_t  LinBlueFieldPosition;  /* bit position of lsb of blue mask (linear modes) */
+    uint8_t  LinRsvdMaskSize;       /* size of direct color reserved mask (linear modes) */
+    uint8_t  LinRsvdFieldPosition;  /* bit position of lsb of reserved mask (linear modes) */
+    uint32_t MaxPixelClock;         /* maximum pixel clock (in Hz) for graphics mode */
+    uint8_t  Reserved4[189];        /* remainder of ModeInfoBlock */
+} __attribute__((packed));
+
+#endif
index ce1de04..cfa5e97 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 video.c $NHDT-Date: 1432512791 2015/05/25 00:13:11 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
+/* NetHack 3.6 video.c $NHDT-Date: 1457207042 2016/03/05 19:44:02 $  $NHDT-Branch: chasonr $:$NHDT-Revision: 1.11 $ */
 /*   Copyright (c) NetHack PC Development Team 1993, 1994, 2001            */
 /*   NetHack may be freely redistributed.  See license for details. */
 /*                                                                 */
@@ -80,6 +80,11 @@ get_scr_size()
         vga_get_scr_size();
     } else
 #endif
+#ifdef SCREEN_VESA
+    if (iflags.usevesa) {
+        vesa_get_scr_size();
+    } else
+#endif
         txt_get_scr_size();
 }
 
@@ -142,6 +147,10 @@ backsp()
     } else if (iflags.usevga) {
         vga_backsp();
 #endif
+#ifdef SCREEN_VESA
+    } else if (iflags.usevesa) {
+        vesa_backsp();
+#endif
     }
 }
 
@@ -154,6 +163,10 @@ clear_screen()
     } else if (iflags.usevga) {
         vga_clear_screen(BACKGROUND_VGA_COLOR);
 #endif
+#ifdef SCREEN_VESA
+    } else if (iflags.usevesa) {
+        vesa_clear_screen(BACKGROUND_VGA_COLOR);
+#endif
     }
 }
 
@@ -169,6 +182,10 @@ void cl_end() /* clear to end of line */
     } else if (iflags.usevga) {
         vga_cl_end(col, row);
 #endif
+#ifdef SCREEN_VESA
+    } else if (iflags.usevesa) {
+        vesa_cl_end(col, row);
+#endif
     }
     tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
 }
@@ -183,6 +200,10 @@ void cl_eos() /* clear to end of screen */
     } else if (iflags.usevga) {
         vga_cl_eos(cy);
 #endif
+#ifdef SCREEN_VESA
+    } else if (iflags.usevesa) {
+        vesa_cl_eos(cy);
+#endif
     }
     tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
 }
@@ -199,6 +220,10 @@ register int col, row;
     } else if (iflags.usevga) {
         vga_gotoloc(col, row);
 #endif
+#ifdef SCREEN_VESA
+    } else if (iflags.usevesa) {
+        vesa_gotoloc(col, row);
+#endif
     }
 }
 
@@ -224,6 +249,10 @@ home()
     } else if (iflags.usevga) {
         vga_gotoloc(0, 0);
 #endif
+#ifdef SCREEN_VESA
+    } else if (iflags.usevesa) {
+        vesa_gotoloc(0, 0);
+#endif
     }
 }
 
@@ -237,6 +266,10 @@ int col, row;
     } else if (iflags.usevga) {
         vga_gotoloc(col, row);
 #endif
+#ifdef SCREEN_VESA
+    } else if (iflags.usevesa) {
+        vesa_gotoloc(col, row);
+#endif
     }
 }
 
@@ -361,6 +394,10 @@ tty_end_screen()
     } else if (iflags.usevga) {
         vga_tty_end_screen();
 #endif
+#ifdef SCREEN_VESA
+    } else if (iflags.usevesa) {
+        vesa_tty_end_screen();
+#endif
     }
 }
 
@@ -396,6 +433,11 @@ int *wid, *hgt;
         vga_tty_startup(wid, hgt);
     } else
 #endif
+#ifdef SCREEN_VESA
+    if (iflags.usevesa) {
+        vesa_tty_startup(wid, hgt);
+    } else
+#endif
         txt_startup(wid, hgt);
 
     *wid = CO;
@@ -430,39 +472,44 @@ tty_start_screen()
 void
 gr_init()
 {
-    if (iflags.usevga) {
 #ifdef SCREEN_VGA
+    if (iflags.usevga) {
         vga_Init();
+    } else
 #endif
 #ifdef SCREEN_VESA
-    } else if (iflags.usevesa) {
+    if (iflags.usevesa) {
         vesa_Init();
-
+    } else
 #endif
 #ifdef SCREEN_8514
-    } else if (iflags.use8514) {
+    if (iflags.use8514) {
         v8514_Init();
+    } else
 #endif
-    }
+    {}
 }
 
 void
 gr_finish()
 {
     if (iflags.grmode) {
-        if (iflags.usevga) {
 #ifdef SCREEN_VGA
+        if (iflags.usevga) {
             vga_Finish();
+        } else
 #endif
 #ifdef SCREEN_VESA
-        } else if (iflags.usevesa) {
+        if (iflags.usevesa) {
             vesa_Finish();
+        } else
 #endif
 #ifdef SCREEN_8514
-        } else if (iflags.use8514) {
+        if (iflags.use8514) {
             v8514_Finish();
+        } else
 #endif
-        }
+        {}
     }
 }
 
@@ -511,6 +558,10 @@ const char *s;
     } else if (iflags.usevga) {
         vga_xputs(s, col, row);
 #endif
+#ifdef SCREEN_VESA
+    } else if (iflags.usevesa) {
+        vesa_xputs(s, col, row);
+#endif
     }
 }
 
@@ -529,6 +580,10 @@ char ch;
     } else if (iflags.usevga) {
         vga_xputc(ch, attribute);
 #endif /*SCREEN_VGA*/
+#ifdef SCREEN_VESA
+    } else if (iflags.usevesa) {
+        vesa_xputc(ch, attribute);
+#endif /*SCREEN_VESA*/
     }
 }
 
@@ -541,9 +596,13 @@ unsigned special;
     if (!iflags.grmode || !iflags.tile_view) {
         xputc((char) ch);
 #ifdef SCREEN_VGA
-    } else {
+    } else if (iflags.grmode && iflags.usevga) {
         vga_xputg(glyphnum, ch, special);
 #endif
+#ifdef SCREEN_VESA
+    } else if (iflags.grmode && iflags.usevesa) {
+        vesa_xputg(glyphnum, ch, special);
+#endif
     }
 }
 
@@ -555,9 +614,13 @@ char *posbar;
     if (!iflags.grmode)
         return;
 #ifdef SCREEN_VGA
-    else
+    else if (iflags.usevga)
         vga_update_positionbar(posbar);
 #endif
+#ifdef SCREEN_VESA
+    else if (iflags.usevesa)
+        vesa_update_positionbar(posbar);
+#endif
 }
 #endif
 
@@ -593,7 +656,12 @@ void
 DrawCursor()
 {
 #ifdef SCREEN_VGA
-    vga_DrawCursor();
+    if (iflags.usevga)
+        vga_DrawCursor();
+#endif
+#ifdef SCREEN_VESA
+    if (iflags.usevesa)
+        vesa_DrawCursor();
 #endif
 }
 
@@ -601,7 +669,12 @@ void
 HideCursor()
 {
 #ifdef SCREEN_VGA
-    vga_HideCursor();
+    if (iflags.usevga)
+        vga_HideCursor();
+#endif
+#ifdef SCREEN_VESA
+    if (iflags.usevesa)
+        vesa_HideCursor();
 #endif
 }
 
@@ -854,7 +927,9 @@ char *sopt;
      * getch();
      */
     iflags.grmode = 0;
+    iflags.hasvesa = 0;
     iflags.hasvga = 0;
+    iflags.usevesa = 0;
     iflags.usevga = 0;
 
     if (strncmpi(sopt, "def", 3) == 0) { /* default */
@@ -892,9 +967,10 @@ char *sopt;
 #endif
         /*
          * Auto-detect Priorities (arbitrary for now):
-         *     VGA
+         *     VESA, VGA
          */
-        if (iflags.hasvga) {
+        if (iflags.hasvesa) iflags.usevesa = 1;
+        else if (iflags.hasvga) {
             iflags.usevga = 1;
             /* VGA depends on BIOS to enable function keys*/
             iflags.BIOS = 1;
@@ -911,9 +987,13 @@ tileview(enable)
 boolean enable;
 {
 #ifdef SCREEN_VGA
-    if (iflags.grmode)
+    if (iflags.grmode && iflags.usevga)
         vga_traditional(enable ? FALSE : TRUE);
 #endif
+#ifdef SCREEN_VESA
+    if (iflags.grmode && iflags.usevesa)
+        vesa_traditional(enable ? FALSE : TRUE);
+#endif
 }
 #endif /* NO_TERMS  */
 
index 82e18e8..6dd2383 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 vidtxt.c        $NHDT-Date: 1432512791 2015/05/25 00:13:11 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
+/* NetHack 3.6 vidtxt.c        $NHDT-Date: 1457207043 2016/03/05 19:44:03 $  $NHDT-Branch: chasonr $:$NHDT-Revision: 1.11 $ */
 /*   Copyright (c) NetHack PC Development Team 1993                 */
 /*   NetHack may be freely redistributed.  See license for details. */
 /*                                                                  */
@@ -235,18 +235,19 @@ void txt_cl_eos() /* clear to end of screen */
 #else
     txt_get_cursor(&col, &row);
     txt_cl_end(col, row); /* clear to end of line */
-    txt_gotoxy(0, (row < (LI - 1) ? row + 1 : (LI - 1)));
-    regs.h.dl = (char) (CO - 1); /* X  of lower right */
-    regs.h.dh = (char) (LI - 1); /* Y  of lower right */
-    regs.h.cl = 0;               /* X  of upper left */
-                                 /* Y (row)  of upper left */
-    regs.h.ch = (char) (row < (LI - 1) ? row + 1 : (LI - 1));
-    regs.x.cx = 0;
-    regs.x.ax = 0;
-    regs.x.bx = 0;
-    regs.h.bh = (char) attrib_text_normal;
-    regs.h.ah = SCROLL;
-    (void) int86(VIDEO_BIOS, &regs, &regs); /* Scroll or initialize window */
+    if (row < LI - 1) {
+        txt_gotoxy(0, (row < (LI - 1) ? row + 1 : (LI - 1)));
+        regs.h.dl = (char) (CO - 1); /* X  of lower right */
+        regs.h.dh = (char) (LI - 1); /* Y  of lower right */
+        regs.h.cl = 0;               /* X  of upper left */
+                                     /* Y (row)  of upper left */
+        regs.h.ch = (char) (row < (LI - 1) ? row + 1 : (LI - 1));
+        regs.x.ax = 0;
+        regs.x.bx = 0;
+        regs.h.bh = (char) attrib_text_normal;
+        regs.h.ah = SCROLL;
+        (void) int86(VIDEO_BIOS, &regs, &regs); /* Scroll or initialize window */
+    }
 #endif
 }
 
diff --git a/sys/msdos/vidvesa.c b/sys/msdos/vidvesa.c
new file mode 100644 (file)
index 0000000..e9b7bb1
--- /dev/null
@@ -0,0 +1,1613 @@
+/*   Copyright (c) NetHack PC Development Team 1995                 */
+/*   VESA BIOS functions copyright (c) Ray Chason 2016              */
+/*   NetHack may be freely redistributed.  See license for details. */
+/*
+ * vidvesa.c - VGA Hardware video support with VESA BIOS Extensions
+ */
+
+#include "hack.h"
+
+#ifdef SCREEN_VESA /* this file is for SCREEN_VESA only    */
+#include <dpmi.h>
+
+#include "pcvideo.h"
+#include "tile.h"
+#include "pctiles.h"
+#include "vesa.h"
+#include "wintty.h"
+#include "tileset.h"
+
+#define BACKGROUND_VESA_COLOR 1
+#define FIRST_TEXT_COLOR 240
+
+static unsigned long FDECL(vesa_SetWindow, (int window, unsigned long offset));
+static unsigned long FDECL(vesa_ReadPixel32, (unsigned x, unsigned y));
+static void FDECL(vesa_WritePixel32, (unsigned x, unsigned y,
+        unsigned long color));
+static void FDECL(vesa_WritePixel, (unsigned x, unsigned y, unsigned color));
+static unsigned long FDECL(vesa_MakeColor, (unsigned r, unsigned g, unsigned b));
+static void FDECL(vesa_GetRGB, (
+        unsigned long color,
+        unsigned char *rp, unsigned char *gp, unsigned char *bp));
+static void FDECL(vesa_FillRect, (
+        unsigned left, unsigned top,
+        unsigned width, unsigned height,
+        unsigned color));
+
+static void NDECL(vesa_redrawmap);
+static void FDECL(vesa_cliparound, (int, int));
+static void FDECL(decal_packed, (const struct TileImage *tile, unsigned special));
+static void FDECL(vesa_SwitchMode, (unsigned mode));
+static boolean FDECL(vesa_SetPalette, (const struct Pixel *));
+static boolean FDECL(vesa_SetHardPalette, (const struct Pixel *));
+static boolean FDECL(vesa_SetSoftPalette, (const struct Pixel *));
+static void FDECL(vesa_DisplayCell, (const struct TileImage *tile, int, int));
+static void FDECL(vesa_DisplayCellInMemory, (const struct TileImage *tile,
+        int, char buf[TILE_Y][640*2]));
+static unsigned FDECL(vesa_FindMode, (unsigned long mode_addr, unsigned bits));
+static void FDECL(vesa_WriteChar, (int, int, int, int, BOOLEAN_P));
+static void FDECL(vesa_WriteCharInMemory, (int, int, char buf[TILE_Y][640*2],
+        int));
+static void FDECL(vesa_WriteStr, (const char *, int, int, int, int));
+static char __far *NDECL(vesa_FontPtrs);
+
+#ifdef POSITIONBAR
+static void NDECL(positionbar);
+#endif
+
+extern int clipx, clipxmax; /* current clipping column from wintty.c */
+extern int curcol, currow;  /* current column and row        */
+extern int g_attribute;
+extern int attrib_text_normal;  /* text mode normal attribute */
+extern int attrib_gr_normal;    /* graphics mode normal attribute */
+extern int attrib_gr_intense;   /* graphics mode intense attribute */
+extern boolean inmap;           /* in the map window */
+extern boolean restoring;
+
+/*
+ * Global Variables
+ */
+
+static unsigned char __far *font;
+
+static struct map_struct {
+    int glyph;
+    int ch;
+    int attr;
+    unsigned special;
+} map[ROWNO][COLNO]; /* track the glyphs */
+
+#define vesa_clearmap()                                   \
+    {                                                     \
+        int x, y;                                         \
+        for (y = 0; y < ROWNO; ++y)                       \
+            for (x = 0; x < COLNO; ++x) {                 \
+                map[y][x].glyph = cmap_to_glyph(S_stone); \
+                map[y][x].ch = S_stone;                   \
+                map[y][x].attr = 0;                       \
+                map[y][x].special = 0;                    \
+            }                                             \
+    }
+#define TOP_MAP_ROW 1
+
+static int viewport_size = 40;
+
+static const struct Pixel defpalette[] = {    /* Colors for text and the position bar */
+       { 0x18, 0x18, 0x18, 0xff }, /* CLR_BLACK */
+       { 0xaa, 0x00, 0x00, 0xff }, /* CLR_RED */
+       { 0x00, 0xaa, 0x00, 0xff }, /* CLR_GREEN */
+       { 0x99, 0x40, 0x00, 0xff }, /* CLR_BROWN */
+       { 0x00, 0x00, 0xaa, 0xff }, /* CLR_BLUE */
+       { 0xaa, 0x00, 0xaa, 0xff }, /* CLR_MAGENTA */
+       { 0x00, 0xaa, 0xaa, 0xff }, /* CLR_CYAN */
+       { 0xaa, 0xaa, 0xaa, 0xff }, /* CLR_GRAY */
+       { 0x55, 0x55, 0x55, 0xff }, /* NO_COLOR */
+       { 0xff, 0x90, 0x00, 0xff }, /* CLR_ORANGE */
+       { 0x00, 0xff, 0x00, 0xff }, /* CLR_BRIGHT_GREEN */
+       { 0xff, 0xff, 0x00, 0xff }, /* CLR_YELLOW */
+       { 0x00, 0x00, 0xff, 0xff }, /* CLR_BRIGHT_BLUE */
+       { 0xff, 0x00, 0xff, 0xff }, /* CLR_BRIGHT_MAGENTA */
+       { 0x00, 0xff, 0xff, 0xff }, /* CLR_BRIGHT_CYAN */
+       { 0xff, 0xff, 0xff, 0xff }  /* CLR_WHITE */
+};
+
+/* Information about the selected VESA mode */
+static unsigned short vesa_mode = 0xFFFF; /* Mode number */
+static unsigned short vesa_x_res; /* X resolution */
+static unsigned short vesa_y_res; /* Y resolution */
+static unsigned short vesa_x_center; /* X centering offset */
+static unsigned short vesa_y_center; /* Y centering offset */
+static unsigned short vesa_scan_line; /* Bytes per scan line */
+static int vesa_read_win;  /* Select the read window */
+static int vesa_write_win; /* Select the write window */
+static unsigned long vesa_win_pos[2]; /* Window position */
+static unsigned long vesa_win_addr[2]; /* Window physical address */
+static unsigned long vesa_win_size; /* Window size */
+static unsigned long vesa_win_gran; /* Window granularity */
+static unsigned char vesa_pixel_size;
+static unsigned char vesa_pixel_bytes;
+static unsigned char vesa_red_pos;
+static unsigned char vesa_red_size;
+static unsigned char vesa_green_pos;
+static unsigned char vesa_green_size;
+static unsigned char vesa_blue_pos;
+static unsigned char vesa_blue_size;
+static unsigned long vesa_palette[256];
+
+struct OldModeInfo {
+    unsigned mode;
+
+    unsigned short XResolution;    /* horizontal resolution in pixels or characters */
+    unsigned short YResolution;    /* vertical resolution in pixels or characters */
+    unsigned char  BitsPerPixel;   /* bits per pixel */
+    unsigned char  MemoryModel;    /* memory model type */
+};
+
+static const struct OldModeInfo old_mode_table[] = {
+    { 0x0101,  640,  480,  8, 4 },
+    { 0x0103,  800,  600,  8, 4 },
+    { 0x0105, 1024,  768,  8, 4 },
+    { 0x0107, 1280, 1024,  8, 4 },
+    { 0x0110,  640,  480, 15, 6 },
+    { 0x0111,  640,  480, 16, 6 },
+    { 0x0112,  640,  480, 24, 6 },
+    { 0x0113,  800,  600, 15, 6 },
+    { 0x0114,  800,  600, 16, 6 },
+    { 0x0115,  800,  600, 24, 6 },
+    { 0x0116, 1024,  768, 15, 6 },
+    { 0x0117, 1024,  768, 16, 6 },
+    { 0x0118, 1024,  768, 24, 6 },
+    { 0x0119, 1280, 1024, 15, 6 },
+    { 0x011A, 1280, 1024, 16, 6 },
+    { 0x011B, 1280, 1024, 24, 6 },
+};
+
+/* Retrieve the mode info block */
+static boolean
+vesa_GetModeInfo(mode, info)
+unsigned mode;
+struct ModeInfoBlock *info;
+{
+    int mode_info_sel = -1; /* custodial */
+    int mode_info_seg;
+    __dpmi_regs regs;
+
+    mode_info_seg = __dpmi_allocate_dos_memory(
+            (sizeof(*info) + 15) / 16,
+            &mode_info_sel);
+    if (mode_info_seg < 0) goto error;
+
+    memset(info, 0, sizeof(*info));
+    dosmemput(info, sizeof(*info), mode_info_seg * 16L);
+
+    memset(&regs, 0, sizeof(regs));
+    regs.x.ax = 0x4F01;
+    regs.x.cx = mode;
+    regs.x.di = 0;
+    regs.x.es = mode_info_seg;
+    (void) __dpmi_int(VIDEO_BIOS, &regs);
+
+    if (regs.x.ax != 0x004F) goto error;
+    dosmemget(mode_info_seg * 16L, sizeof(*info), info);
+    if (!(info->ModeAttributes & 0x0001)) goto error;
+
+    if (!(info->ModeAttributes & 0x0002)) {
+        /* Older VESA BIOS that did not return certain mode properties, but
+           that has fixed mode numbers; search the table to find the right
+           mode properties */
+
+        unsigned i;
+
+        for (i = 0; i < SIZE(old_mode_table); ++i) {
+            if (mode == old_mode_table[i].mode) {
+                break;
+            }
+        }
+        if (i >= SIZE(old_mode_table)) goto error;
+
+        info->XResolution = old_mode_table[i].XResolution;
+        info->YResolution = old_mode_table[i].YResolution;
+        info->NumberOfPlanes = 1;
+        info->BitsPerPixel = old_mode_table[i].BitsPerPixel;
+        info->NumberOfBanks = 1;
+        info->MemoryModel = old_mode_table[i].MemoryModel;
+    }
+
+    __dpmi_free_dos_memory(mode_info_sel);
+    return TRUE;
+
+error:
+    if (mode_info_sel != -1) __dpmi_free_dos_memory(mode_info_sel);
+    return FALSE;
+}
+
+/* Set the memory window and return the offset */
+static unsigned long
+vesa_SetWindow(window, offset)
+int window;
+unsigned long offset;
+{
+    /* If the desired offset is already within the window, leave the window
+       as it is and return the address based on the current window position.
+       This minimizes the use of the window switch function.
+
+       On the first call to the function, vesa_win_pos[window] == 0xFFFFFFFF,
+       the offset will always be less than this, and the BIOS will always be
+       called. */
+
+    unsigned long pos = vesa_win_pos[window];
+    if (offset < pos || pos + vesa_win_size <= offset) {
+        __dpmi_regs regs;
+
+        memset(&regs, 0, sizeof(regs));
+        regs.x.ax = 0x4F05;
+        regs.h.bh = 0x00;
+        regs.h.bl = window;
+        regs.x.dx = offset / vesa_win_gran;
+        pos = regs.x.dx * vesa_win_gran;
+        (void) __dpmi_int(VIDEO_BIOS, &regs);
+        vesa_win_pos[window] = pos;
+    }
+
+    offset = offset - vesa_win_pos[window] + vesa_win_addr[window];
+    /* Keep from crashing the system if some malfunction gives us a bad
+       offset */
+    if (offset < 0xA0000 || offset > 0xBFFFF) {
+        vesa_SwitchMode(MODETEXT);
+        fprintf(stderr, "Abort: offset=%08lX\n", offset);
+        exit(1);
+    }
+    return offset;
+}
+
+static unsigned long
+vesa_ReadPixel32(x, y)
+unsigned x, y;
+{
+    unsigned long offset = y * vesa_scan_line + x * vesa_pixel_bytes;
+    unsigned long addr, color;
+    unsigned i;
+
+    switch (vesa_pixel_size) {
+    case 8:
+        addr = vesa_SetWindow(vesa_read_win, offset);
+        color = _farpeekb(_dos_ds, addr);
+        break;
+
+    case 15:
+    case 16:
+        addr = vesa_SetWindow(vesa_read_win, offset);
+        color = _farpeekw(_dos_ds, addr);
+        break;
+
+    case 24:
+        /* Pixel may cross a window boundary */
+        color = 0;
+        for (i = 0; i < 3; ++i) {
+            addr = vesa_SetWindow(vesa_read_win, offset + i);
+            color |= (unsigned long) _farpeekb(_dos_ds, addr) << (i * 8);
+        }
+        break;
+
+    case 32:
+        addr = vesa_SetWindow(vesa_read_win, offset);
+        color = _farpeekl(_dos_ds, addr);
+        break;
+    }
+    return color;
+}
+
+static void
+vesa_WritePixel32(x, y, color)
+unsigned x, y;
+unsigned long color;
+{
+    unsigned long offset = y * vesa_scan_line + x * vesa_pixel_bytes;
+    unsigned long addr;
+    unsigned i;
+
+    switch (vesa_pixel_size) {
+    case 8:
+        addr = vesa_SetWindow(vesa_write_win, offset);
+        _farpokeb(_dos_ds, addr, color);
+        break;
+
+    case 15:
+    case 16:
+        addr = vesa_SetWindow(vesa_write_win, offset);
+        _farpokew(_dos_ds, addr, color);
+        break;
+
+    case 24:
+        /* Pixel may cross a window boundary */
+        for (i = 0; i < 3; ++i) {
+            addr = vesa_SetWindow(vesa_read_win, offset + i);
+            _farpokeb(_dos_ds, addr, (unsigned char) (color >> (i * 8)));
+        }
+        break;
+
+    case 32:
+        addr = vesa_SetWindow(vesa_write_win, offset);
+        _farpokel(_dos_ds, addr, color);
+        break;
+    }
+}
+
+static void
+vesa_WritePixel(x, y, color)
+unsigned x, y;
+unsigned color;
+{
+    if (vesa_pixel_size == 8) {
+        vesa_WritePixel32(x, y, color);
+    } else {
+        vesa_WritePixel32(x, y, vesa_palette[color & 0xFF]);
+    }
+}
+
+static unsigned long
+vesa_MakeColor(r, g, b)
+unsigned r, g, b;
+{
+    r = (r & 0xFF) >> (8 - vesa_red_size);
+    g = (g & 0xFF) >> (8 - vesa_green_size);
+    b = (b & 0xFF) >> (8 - vesa_blue_size);
+    return ((unsigned long) r << vesa_red_pos)
+         | ((unsigned long) g << vesa_green_pos)
+         | ((unsigned long) b << vesa_blue_pos);
+}
+
+static void
+vesa_GetRGB(color, rp, gp, bp)
+unsigned long color;
+unsigned char *rp, *gp, *bp;
+{
+    unsigned r, g, b;
+
+    r = color >> vesa_red_pos;
+    g = color >> vesa_green_pos;
+    b = color >> vesa_blue_pos;
+    r <<= 8 - vesa_red_size;
+    g <<= 8 - vesa_green_size;
+    b <<= 8 - vesa_blue_size;
+    *rp = (unsigned char) r;
+    *gp = (unsigned char) g;
+    *bp = (unsigned char) b;
+}
+
+static void
+vesa_FillRect(left, top, width, height, color)
+unsigned left, top, width, height, color;
+{
+    unsigned x, y;
+
+    for (y = 0; y < height; ++y) {
+        for (x = 0; x < width; ++x) {
+            vesa_WritePixel(left + x, top + y, color);
+        }
+    }
+}
+
+void
+vesa_get_scr_size()
+{
+    CO = 80;
+    LI = 29;
+}
+
+void
+vesa_backsp()
+{
+    int col, row;
+
+    col = curcol; /* Character cell row and column */
+    row = currow;
+
+    if (col > 0)
+        col = col - 1;
+    vesa_gotoloc(col, row);
+}
+
+void
+vesa_clear_screen(colour)
+int colour;
+{
+    vesa_FillRect(0, 0, vesa_x_res, vesa_y_res, colour);
+    if (iflags.tile_view)
+        vesa_clearmap();
+    vesa_gotoloc(0, 0); /* is this needed? */
+}
+
+/* clear to end of line */
+void
+vesa_cl_end(col, row)
+int col, row;
+{
+    unsigned left = vesa_x_center + col * 8;
+    unsigned top  = vesa_y_center + row * 16;
+    unsigned width = (CO - 1 - col) * 8;
+    unsigned height = 16;
+
+    vesa_FillRect(left, top, width, height, BACKGROUND_VESA_COLOR);
+}
+
+/* clear to end of screen */
+void
+vesa_cl_eos(cy)
+int cy;
+{
+    int count;
+
+    cl_end();
+    if (cy < LI - 1) {
+        unsigned left = vesa_x_center;
+        unsigned top  = vesa_y_center + cy * 16;
+        unsigned width = 640;
+        unsigned height = (LI - 1 - cy) * 16;
+
+        vesa_FillRect(left, top, width, height, BACKGROUND_VESA_COLOR);
+    }
+}
+
+void
+vesa_tty_end_screen()
+{
+    vesa_clear_screen(BACKGROUND_VESA_COLOR);
+    vesa_SwitchMode(MODETEXT);
+}
+
+void
+vesa_tty_startup(wid, hgt)
+int *wid, *hgt;
+{
+    /* code to sense display adapter is required here - MJA */
+
+    vesa_get_scr_size();
+    if (CO && LI) {
+        *wid = CO;
+        *hgt = LI;
+    }
+
+    attrib_gr_normal = ATTRIB_VGA_NORMAL;
+    attrib_gr_intense = ATTRIB_VGA_INTENSE;
+    g_attribute = attrib_gr_normal; /* Give it a starting value */
+}
+
+/*
+ * Screen output routines (these are heavily used).
+ *
+ * These are the 3 routines used to place information on the screen
+ * in the VGA PC tty port of NetHack.  These are the routines
+ * that get called by the general interface routines in video.c.
+ *
+ * vesa_xputs -Writes a c null terminated string at the current location.
+ *
+ * vesa_xputc -Writes a single character at the current location. Since
+ *             various places in the code assume that control characters
+ *             can be used to control, we are forced to interpret some of
+ *             the more common ones, in order to keep things looking correct.
+ *
+ * vesa_xputg -This routine is used to display a graphical representation of a
+ *             NetHack glyph (a tile) at the current location.  For more
+ *             information on NetHack glyphs refer to the comments in
+ *             include/display.h.
+ *
+ */
+
+void
+vesa_xputs(s, col, row)
+const char *s;
+int col, row;
+{
+    if (s != NULL) {
+        vesa_WriteStr(s, strlen(s), col, row, g_attribute);
+    }
+}
+
+/* write out character (and attribute) */
+void
+vesa_xputc(ch, attr)
+char ch;
+int attr;
+{
+    int col, row;
+
+    col = curcol;
+    row = currow;
+
+    switch (ch) {
+    case '\n':
+        col = 0;
+        ++row;
+        break;
+    default:
+        vesa_WriteChar((unsigned char) ch, col, row, attr, FALSE);
+        if (col < (CO - 1))
+            ++col;
+        break;
+    } /* end switch */
+    vesa_gotoloc(col, row);
+}
+
+#if defined(USE_TILES)
+/* Place tile represent. a glyph at current location */
+void
+vesa_xputg(glyphnum, ch,
+          special)
+int glyphnum;
+int ch;
+unsigned special; /* special feature: corpse, invis, detected, pet, ridden -
+                     hack.h */
+{
+    int col, row;
+    int attr;
+    int ry;
+    const struct TileImage *packcell;
+
+    row = currow;
+    col = curcol;
+    if ((col < 0 || col >= COLNO)
+        || (row < TOP_MAP_ROW || row >= (ROWNO + TOP_MAP_ROW)))
+        return;
+    ry = row - TOP_MAP_ROW;
+    map[ry][col].glyph = glyphnum;
+    map[ry][col].ch = ch;
+    map[ry][col].special = special;
+    attr = (g_attribute == 0) ? attrib_gr_normal : g_attribute;
+    map[ry][col].attr = attr;
+    if (iflags.traditional_view) {
+        vesa_WriteChar((unsigned char) ch, col, row, attr, FALSE);
+    } else {
+        if ((col >= clipx) && (col <= clipxmax)) {
+            packcell = get_tile(glyph2tile[glyphnum]);
+            if (!iflags.over_view && map[ry][col].special)
+                decal_packed(packcell, special);
+            vesa_DisplayCell(packcell, col - clipx, row);
+        }
+    }
+    if (col < (CO - 1))
+        ++col;
+    vesa_gotoloc(col, row);
+}
+#endif /* USE_TILES */
+
+/*
+ * Cursor location manipulation, and location information fetching
+ * routines.
+ * These include:
+ *
+ * vesa_gotoloc(x,y)    - Moves the "cursor" on screen to the specified x
+ *                      and y character cell location.  This routine
+ *                       determines the location where screen writes
+ *                       will occur next, it does not change the location
+ *                       of the player on the NetHack level.
+ */
+
+void
+vesa_gotoloc(col, row)
+int col, row;
+{
+    curcol = min(col, CO - 1); /* protection from callers */
+    currow = min(row, LI - 1);
+}
+
+#if defined(USE_TILES) && defined(CLIPPING)
+static void
+vesa_cliparound(x, y)
+int x, y;
+{
+    int oldx = clipx;
+
+    if (!iflags.tile_view || iflags.over_view || iflags.traditional_view)
+        return;
+
+    if (x < clipx + 5) {
+        clipx = max(0, x - (viewport_size / 2));
+        clipxmax = clipx + (viewport_size - 1);
+    } else if (x > clipxmax - 5) {
+        clipxmax = min(COLNO - 1, x + (viewport_size / 2));
+        clipx = clipxmax - (viewport_size - 1);
+    }
+    if (clipx != oldx) {
+        if (on_level(&u.uz0, &u.uz) && !restoring)
+            /* (void) doredraw(); */
+            vesa_redrawmap();
+    }
+}
+
+static void
+vesa_redrawmap()
+{
+    int x, y, t;
+    const struct TileImage *packcell;
+
+    /* y here is in screen rows*/
+    /* Build each row in local memory, then write, to minimize use of the
+       window switch function */
+    for (y = 0; y < ROWNO; ++y) {
+        char buf[TILE_Y][640*2];
+
+        for (x = clipx; x <= clipxmax; ++x) {
+            if (iflags.traditional_view) {
+                vesa_WriteCharInMemory((unsigned char) map[y][x].ch, x,
+                              buf, map[y][x].attr);
+            } else {
+                t = map[y][x].glyph;
+                packcell = get_tile(glyph2tile[t]);
+                if (!iflags.over_view && map[y][x].special)
+                    decal_packed(packcell, map[y][x].special);
+                vesa_DisplayCellInMemory(packcell, x - clipx, buf);
+            }
+        }
+        if (iflags.over_view && vesa_pixel_size != 8) {
+            for (t = 0; t < TILE_Y; ++t) {
+                for (x = 0; x < 640; ++x) {
+                    unsigned long c1 = vesa_palette[buf[t][x * 2 + 0]];
+                    unsigned long c2 = vesa_palette[buf[t][x * 2 + 1]];
+                    unsigned char r1, r2, g1, g2, b1, b2;
+
+                    vesa_GetRGB(c1, &r1, &g1, &b1);
+                    vesa_GetRGB(c2, &r2, &g2, &b2);
+                    r1 = (r1 + r2) / 2;
+                    g1 = (g1 + g2) / 2;
+                    b1 = (b1 + b2) / 2;
+                    vesa_WritePixel32(x, (y + TOP_MAP_ROW) * TILE_Y + t,
+                            vesa_MakeColor(r1, g1, b1));
+                }
+            }
+        } else {
+            for (t = 0; t < TILE_Y; ++t) {
+                for (x = 0; x < 640; ++x) {
+                    vesa_WritePixel(x, (y + TOP_MAP_ROW) * TILE_Y + t, buf[t][x]);
+                }
+            }
+        }
+    }
+}
+#endif /* USE_TILES && CLIPPING */
+
+void
+vesa_userpan(left)
+boolean left;
+{
+    int x;
+
+    /* pline("Into userpan"); */
+    if (iflags.over_view || iflags.traditional_view)
+        return;
+    if (left)
+        x = min(COLNO - 1, clipxmax + 10);
+    else
+        x = max(0, clipx - 10);
+    vesa_cliparound(x, 10); /* y value is irrelevant on VGA clipping */
+    positionbar();
+    vesa_DrawCursor();
+}
+
+void
+vesa_overview(on)
+boolean on;
+{
+    /* vesa_HideCursor(); */
+    if (on) {
+        iflags.over_view = TRUE;
+        clipx = 0;
+        clipxmax = CO - 1;
+    } else {
+        iflags.over_view = FALSE;
+        clipx = max(0, (curcol - viewport_size / 2));
+        if (clipx > ((CO - 1) - viewport_size))
+            clipx = (CO - 1) - viewport_size;
+        clipxmax = clipx + (viewport_size - 1);
+    }
+}
+
+void
+vesa_traditional(on)
+boolean on;
+{
+    /* vesa_HideCursor(); */
+    if (on) {
+        /*             switch_symbols(FALSE); */
+        iflags.traditional_view = TRUE;
+        clipx = 0;
+        clipxmax = CO - 1;
+    } else {
+        iflags.traditional_view = FALSE;
+        if (!iflags.over_view) {
+            clipx = max(0, (curcol - viewport_size / 2));
+            if (clipx > ((CO - 1) - viewport_size))
+                clipx = (CO - 1) - viewport_size;
+            clipxmax = clipx + (viewport_size - 1);
+        }
+    }
+}
+
+void
+vesa_refresh()
+{
+    positionbar();
+    vesa_redrawmap();
+    vesa_DrawCursor();
+}
+
+static void
+decal_packed(gp, special)
+const struct TileImage *gp;
+unsigned special;
+{
+    /* FIXME: the tile array is fixed in memory and should not be changed;
+       if we ever implement this, we'll have to copy the pixels */
+    if (special & MG_CORPSE) {
+    } else if (special & MG_INVIS) {
+    } else if (special & MG_DETECT) {
+    } else if (special & MG_PET) {
+    } else if (special & MG_RIDDEN) {
+    }
+}
+
+/*
+ * Open tile files,
+ * initialize the SCREEN, switch it to graphics mode,
+ * initialize the pointers to the fonts, clear
+ * the screen.
+ *
+ */
+void
+vesa_Init(void)
+{
+    const struct Pixel *paletteptr;
+#ifdef USE_TILES
+    const char *tile_file;
+    int tilefailure = 0;
+    /*
+     * Attempt to open the required tile files. If we can't
+     * don't perform the video mode switch, use TTY code instead.
+     *
+     */
+    tile_file = iflags.wc_tile_file;
+    if (tile_file == NULL || *tile_file == '\0') {
+        tile_file = "nhtiles.bmp";
+    }
+    if (!read_tiles(tile_file, FALSE))
+        tilefailure |= 1;
+    if (get_palette() == NULL)
+        tilefailure |= 4;
+
+    if (tilefailure) {
+        raw_printf("Reverting to TTY mode, tile initialization failure (%d).",
+                   tilefailure);
+        wait_synch();
+        iflags.usevga = 0;
+        iflags.tile_view = FALSE;
+        iflags.over_view = FALSE;
+        CO = 80;
+        LI = 25;
+        /*     clear_screen()  */ /* not vesa_clear_screen() */
+        return;
+    }
+#endif
+
+    if (vesa_mode == 0xFFFF) {
+        vesa_detect();
+    }
+    vesa_SwitchMode(vesa_mode);
+    windowprocs.win_cliparound = vesa_cliparound;
+#ifdef USE_TILES
+    paletteptr = get_palette();
+    iflags.tile_view = TRUE;
+    iflags.over_view = FALSE;
+#else
+    paletteptr = defpalette;
+#endif
+    vesa_SetPalette(paletteptr);
+    g_attribute = attrib_gr_normal;
+    font = vesa_FontPtrs();
+    clear_screen();
+    clipx = 0;
+    clipxmax = clipx + (viewport_size - 1);
+}
+
+/*
+ * Switches modes of the video card.
+ *
+ * If mode == MODETEXT (0x03), then the card is placed into text
+ * mode.  Otherwise, the card is placed in the mode selected by
+ * vesa_detect.  Supported modes are those with packed 8 bit pixels.
+ *
+ */
+static void
+vesa_SwitchMode(mode)
+unsigned mode;
+{
+    __dpmi_regs regs;
+
+    if (mode == MODETEXT) {
+        iflags.grmode = 0;
+        regs.x.ax = mode;
+        (void) __dpmi_int(VIDEO_BIOS, &regs);
+    } else if (mode >= 0x100) {
+        iflags.grmode = 1;
+        regs.x.ax = 0x4F02;
+        regs.x.bx = mode & 0x81FF;
+        (void) __dpmi_int(VIDEO_BIOS, &regs);
+        /* Record that the window position is unknown */
+        vesa_win_pos[0] = 0xFFFFFFFF;
+        vesa_win_pos[1] = 0xFFFFFFFF;
+    } else {
+        iflags.grmode = 0; /* force text mode for error msg */
+        regs.x.ax = MODETEXT;
+        (void) __dpmi_int(VIDEO_BIOS, &regs);
+        g_attribute = attrib_text_normal;
+        impossible("vesa_SwitchMode: Bad video mode requested 0x%X", mode);
+    }
+}
+
+/*
+ * This allows grouping of several tasks to be done when
+ * switching back to text mode. This is a public (extern) function.
+ *
+ */
+void
+vesa_Finish(void)
+{
+    free_tiles();
+    vesa_SwitchMode(MODETEXT);
+    windowprocs.win_cliparound = tty_cliparound;
+    g_attribute = attrib_text_normal;
+    iflags.tile_view = FALSE;
+}
+
+/*
+ *
+ * Returns a far pointer (or flat 32 bit pointer under djgpp) to the
+ * location of the appropriate ROM font for the _current_ video mode
+ * (so you must place the card into the desired video mode before
+ * calling this function).
+ *
+ * This function takes advantage of the video BIOS loading the
+ * address of the appropriate character definition table for
+ * the current graphics mode into interrupt vector 0x43 (0000:010C).
+ */
+static char __far *
+vesa_FontPtrs(void)
+{
+    USHORT __far *tmp;
+    char __far *retval;
+    USHORT fseg, foff;
+    tmp = (USHORT __far *) MK_PTR(((USHORT) FONT_PTR_SEGMENT),
+                                  ((USHORT) FONT_PTR_OFFSET));
+    foff = READ_ABSOLUTE_WORD(tmp);
+    ++tmp;
+    fseg = READ_ABSOLUTE_WORD(tmp);
+    retval = (char __far *) MK_PTR(fseg, foff);
+    return retval;
+}
+
+/*
+ * This will verify the existance of a VGA adapter on the machine.
+ * Video function call 0x4F00 returns 0x004F in AX if successful, and
+ * returns a VbeInfoBlock describing the features of the VESA BIOS.
+ */
+int
+vesa_detect()
+{
+    int vbe_info_sel = -1; /* custodial */
+    int vbe_info_seg;
+    struct VbeInfoBlock vbe_info;
+    __dpmi_regs regs;
+    unsigned long mode_addr;
+    struct ModeInfoBlock mode_info;
+
+    vbe_info_seg = __dpmi_allocate_dos_memory(
+            (sizeof(vbe_info) + 15) / 16,
+            &vbe_info_sel);
+    if (vbe_info_seg < 0) goto error;
+
+    /* Request VBE 2.0 information if it is available */
+    memset(&vbe_info, 0, sizeof(vbe_info));
+    memcpy(vbe_info.VbeSignature, "VBE2", 4);
+    dosmemput(&vbe_info, sizeof(vbe_info), vbe_info_seg * 16L);
+
+    /* Request VESA BIOS information */
+    regs.x.ax = 0x4F00;
+    regs.x.di = 0;
+    regs.x.es = vbe_info_seg;
+    (void) __dpmi_int(VIDEO_BIOS, &regs);
+
+    /* Check for successful completion of function: is VESA BIOS present? */
+    if (regs.x.ax != 0x004F) goto error;
+    dosmemget(vbe_info_seg * 16L, sizeof(vbe_info), &vbe_info);
+    if (memcmp(vbe_info.VbeSignature, "VESA", 4) != 0) goto error;
+
+    /* Get the address of the mode list */
+    /* The mode list may be within the DOS memory area allocated above.
+       That area must remain allocated and must not be rewritten until
+       we're done here. */
+    mode_addr = (vbe_info.VideoModePtr >> 16) * 16L
+              + (vbe_info.VideoModePtr & 0xFFFF);
+
+    /* Scan the mode list for an acceptable mode */
+    vesa_mode = vesa_FindMode(mode_addr, 32);
+    if (vesa_mode == 0xFFFF)
+        vesa_mode = vesa_FindMode(mode_addr, 24);
+    if (vesa_mode == 0xFFFF)
+        vesa_mode = vesa_FindMode(mode_addr, 16);
+    if (vesa_mode == 0xFFFF)
+        vesa_mode = vesa_FindMode(mode_addr, 15);
+    if (vesa_mode == 0xFFFF)
+        vesa_mode = vesa_FindMode(mode_addr,  8);
+    if (vesa_mode == 0xFFFF)
+        goto error;
+
+    /* Set up the variables for the pixel functions */
+    vesa_GetModeInfo(vesa_mode, &mode_info);
+    vesa_x_res = mode_info.XResolution;
+    vesa_y_res = mode_info.YResolution;
+    vesa_x_center = (vesa_x_res - 640) / 2;
+    vesa_y_center = (vesa_y_res - 480) / 2;
+    vesa_scan_line = mode_info.BytesPerScanLine;
+    vesa_win_size = mode_info.WinSize * 1024L;
+    vesa_win_gran = mode_info.WinGranularity * 1024L;
+    vesa_pixel_size = mode_info.BitsPerPixel;
+    vesa_pixel_bytes = (vesa_pixel_size + 7) / 8;
+    if (vbe_info.VbeVersion >= 0x0300) {
+        vesa_red_pos = mode_info.RedFieldPosition;
+        vesa_red_size = mode_info.RedMaskSize;
+        vesa_green_pos = mode_info.GreenFieldPosition;
+        vesa_green_size = mode_info.GreenMaskSize;
+        vesa_blue_pos = mode_info.BlueFieldPosition;
+        vesa_blue_size = mode_info.BlueMaskSize;
+    } else {
+        switch (vesa_pixel_size) {
+        case 15:
+            vesa_blue_pos = 0;
+            vesa_blue_size = 5;
+            vesa_green_pos = 5;
+            vesa_green_size = 5;
+            vesa_red_pos = 10;
+            vesa_red_size = 5;
+            break;
+
+        case 16:
+            vesa_blue_pos = 0;
+            vesa_blue_size = 5;
+            vesa_green_pos = 5;
+            vesa_green_size = 6;
+            vesa_red_pos = 11;
+            vesa_red_size = 5;
+            break;
+
+        case 24:
+        case 32:
+            vesa_blue_pos = 0;
+            vesa_blue_size = 8;
+            vesa_green_pos = 8;
+            vesa_green_size = 8;
+            vesa_red_pos = 16;
+            vesa_red_size = 8;
+            break;
+        }
+    }
+    vesa_win_addr[0] = mode_info.WinASegment * 16L;
+    vesa_win_addr[1] = mode_info.WinBSegment * 16L;
+    vesa_win_pos[0] = 0xFFFFFFFF; /* position unknown */
+    vesa_win_pos[1] = 0xFFFFFFFF;
+    /* Read window */
+    if (mode_info.WinAAttributes & 0x2) {
+        vesa_read_win = 0;
+    } else if (mode_info.WinBAttributes & 0x2) {
+        vesa_read_win = 1;
+    } else {
+        goto error; /* Shouldn't happen */
+    }
+    /* Write window */
+    if (mode_info.WinAAttributes & 0x4) {
+        vesa_write_win = 0;
+    } else if (mode_info.WinBAttributes & 0x4) {
+        vesa_write_win = 1;
+    } else {
+        goto error; /* Shouldn't happen */
+    }
+
+    __dpmi_free_dos_memory(vbe_info_sel);
+    return TRUE;
+
+error:
+    if (vbe_info_sel != -1) __dpmi_free_dos_memory(vbe_info_sel);
+    return FALSE;
+}
+
+static unsigned
+vesa_FindMode(mode_addr, bits)
+unsigned long mode_addr;
+unsigned bits;
+{
+    unsigned selected_mode;
+    struct ModeInfoBlock mode_info0, mode_info;
+    unsigned model = (bits == 8) ? 4 : 6;
+
+    memset(&mode_info, 0, sizeof(mode_info));
+    selected_mode = 0xFFFF;
+    while (1) {
+        unsigned mode = _farpeekw(_dos_ds, mode_addr);
+        if (mode == 0xFFFF) break;
+        mode_addr += 2;
+
+        /* Query the mode info; skip to next if not in fact supported */
+        if (!vesa_GetModeInfo(mode, &mode_info0)) continue;
+
+        /* Check that the mode is acceptable */
+        if (mode_info0.XResolution < 640) continue;
+        if (mode_info0.YResolution < 480) continue;
+        if (mode_info0.NumberOfPlanes != 1) continue;
+        if (mode_info0.BitsPerPixel != bits) continue;
+        if (mode_info0.NumberOfBanks != 1) continue;
+        if (mode_info0.MemoryModel != model) continue;
+        if (mode_info0.ModeAttributes & 0x40) continue;
+
+        /* The mode is OK. Accept it if it is smaller than any previous mode
+           or if no previous mode is accepted. */
+        if (selected_mode == 0xFFFF
+        ||  mode_info0.XResolution * mode_info0.YResolution
+          < mode_info.XResolution * mode_info.YResolution) {
+            selected_mode = mode;
+            mode_info = mode_info0;
+        }
+    }
+
+    return selected_mode;
+}
+
+/*
+ * Write character 'ch', at (x,y) and
+ * do it using the colour 'colour'.
+ *
+ */
+static void
+vesa_WriteChar(chr, col, row, colour, transparent)
+int chr, col, row, colour;
+boolean transparent;
+{
+    int i, j;
+    int pixx, pixy;
+
+    unsigned char __far *fp = font;
+    unsigned char fnt;
+
+    pixx = min(col, (CO - 1)) * 8;  /* min() protects from callers */
+    pixy = min(row, (LI - 1)) * 16; /* assumes 8 x 16 char set */
+    pixx += vesa_x_center;
+    pixy += vesa_y_center;
+
+    for (i = 0; i < MAX_ROWS_PER_CELL; ++i) {
+        fnt = READ_ABSOLUTE((fp + chr * 16 + i));
+        for (j = 0; j < 8; ++j) {
+            if (fnt & (0x80 >> j)) {
+                vesa_WritePixel(pixx + j, pixy + i, colour + FIRST_TEXT_COLOR);
+            } else if (!transparent) {
+                vesa_WritePixel(pixx + j, pixy + i, BACKGROUND_VESA_COLOR);
+            }
+        }
+    }
+}
+
+/*
+ * Like vesa_WriteChar, but draw the character in local memory rather than in
+ * the VGA frame buffer.
+ *
+ * vesa_redrawmap uses this to gather a row of cells in local memory and then
+ * draw them in strict row-major order, minimizing the use of the VESA
+ * windowing function.
+ *
+ */
+static void
+vesa_WriteCharInMemory(chr, col, buf, colour)
+int chr, col;
+char buf[TILE_Y][640*2];
+int colour;
+{
+    int i, j;
+    int pixx;
+
+    unsigned char __far *fp = font;
+    unsigned char fnt;
+
+    pixx = min(col, (CO - 1)) * 8;  /* min() protects from callers */
+
+    for (i = 0; i < MAX_ROWS_PER_CELL; ++i) {
+        fnt = READ_ABSOLUTE((fp + chr * 16 + i));
+        for (j = 0; j < 8; ++j) {
+            if (fnt & (0x80 >> j)) {
+                buf[i][pixx + j] = colour + FIRST_TEXT_COLOR;
+            } else {
+                buf[i][pixx + j] = BACKGROUND_VESA_COLOR;
+            }
+        }
+    }
+}
+
+/*
+ * This is the routine that displays a high-res "cell" pointed to by 'gp'
+ * at the desired location (col,row).
+ *
+ * Note: (col,row) in this case refer to the coordinate location in
+ * NetHack character grid terms, (ie. the 40 x 25 character grid),
+ * not the x,y pixel location.
+ *
+ */
+static void
+vesa_DisplayCell(tile, col, row)
+const struct TileImage *tile;
+int col, row;
+{
+    int i, j, pixx, pixy;
+
+    pixx = col * TILE_X;
+    pixy = row * TILE_Y;
+    if (iflags.over_view) {
+        pixx /= 2;
+        pixx += vesa_x_center;
+        pixy += vesa_y_center;
+        if (vesa_pixel_size != 8) {
+            for (i = 0; i < TILE_Y; ++i) {
+                for (j = 0; j < TILE_X; j += 2) {
+                    unsigned index = i * tile->width + j;
+                    unsigned long c1 = vesa_palette[tile->indexes[index + 0]];
+                    unsigned long c2 = vesa_palette[tile->indexes[index + 1]];
+                    unsigned char r1, r2, g1, g2, b1, b2;
+
+                    vesa_GetRGB(c1, &r1, &g1, &b1);
+                    vesa_GetRGB(c2, &r2, &g2, &b2);
+                    r1 = (r1 + r2) / 2;
+                    g1 = (g1 + g2) / 2;
+                    b1 = (b1 + b2) / 2;
+                    vesa_WritePixel32(pixx + j / 2, pixy + i,
+                            vesa_MakeColor(r1, g1, b1));
+                }
+            }
+        } else {
+            for (i = 0; i < TILE_Y; ++i) {
+                for (j = 0; j < TILE_X; j += 2) {
+                    unsigned index = i * tile->width + j;
+                    vesa_WritePixel(pixx + j / 2, pixy + i, tile->indexes[index]);
+                }
+            }
+        }
+    } else {
+        pixx += vesa_x_center;
+        pixy += vesa_y_center;
+        for (i = 0; i < TILE_Y; ++i) {
+            for (j = 0; j < TILE_X; ++j) {
+                unsigned index = i * tile->width + j;
+                vesa_WritePixel(pixx + j, pixy + i, tile->indexes[index]);
+            }
+        }
+    }
+}
+
+/*
+ * Like vesa_DisplayCell, but draw the tile in local memory rather than in
+ * the VGA frame buffer.
+ *
+ * vesa_redrawmap uses this to gather a row of cells in local memory and then
+ * draw them in strict row-major order, minimizing the use of the VESA
+ * windowing function.
+ *
+ */
+static void
+vesa_DisplayCellInMemory(tile, col, buf)
+const struct TileImage *tile;
+int col;
+char buf[TILE_Y][640*2];
+{
+    int i, j, pixx;
+
+    pixx = col * TILE_X;
+    if (iflags.over_view && vesa_pixel_size == 8) {
+        pixx /= 2;
+        for (i = 0; i < TILE_Y; ++i) {
+            for (j = 0; j < TILE_X; j += 2) {
+                unsigned index = i * tile->width + j;
+                buf[i][pixx + j / 2] = tile->indexes[index];
+            }
+        }
+    } else {
+        for (i = 0; i < TILE_Y; ++i) {
+            for (j = 0; j < TILE_X; ++j) {
+                unsigned index = i * tile->width + j;
+                buf[i][pixx + j] = tile->indexes[index];
+            }
+        }
+    }
+}
+
+/*
+ * Write the character string pointed to by 's', whose maximum length
+ * is 'len' at location (x,y) using the 'colour' colour.
+ *
+ */
+static void
+vesa_WriteStr(s, len, col, row, colour)
+const char *s;
+int len, col, row, colour;
+{
+    const unsigned char *us;
+    int i = 0;
+
+    /* protection from callers */
+    if (row > (LI - 1))
+        return;
+
+    i = 0;
+    us = (const unsigned char *) s;
+    while ((*us != 0) && (i < len) && (col < (CO - 1))) {
+        vesa_WriteChar(*us, col, row, colour, FALSE);
+        ++us;
+        ++i;
+        ++col;
+    }
+}
+
+/*
+ * Initialize the VGA palette with the desired colours. This
+ * must be a series of 720 bytes for use with a card in 256
+ * colour mode at 640 x 480. The first 240 palette entries are
+ * used by the tile set; the last 16 are reserved for text.
+ *
+ */
+static boolean
+vesa_SetPalette(palette)
+const struct Pixel *palette;
+{
+    if (vesa_pixel_size == 8) {
+        vesa_SetHardPalette(palette);
+    } else {
+        vesa_SetSoftPalette(palette);
+    }
+}
+
+static boolean
+vesa_SetHardPalette(palette)
+const struct Pixel *palette;
+{
+    const struct Pixel *p = palette;
+    int palette_sel = -1; /* custodial */
+    int palette_seg;
+    unsigned long palette_ptr;
+    unsigned i, shift;
+    unsigned char r, g, b;
+    unsigned long color;
+    __dpmi_regs regs;
+
+    palette_seg = __dpmi_allocate_dos_memory( 1024 / 16, &palette_sel);
+    if (palette_seg < 0) goto error;
+
+    /* Use 8 bit DACs if we have them */
+    memset(&regs, 0, sizeof(regs));
+    regs.x.ax = 0x4F08;
+    regs.h.bl = 0;
+    regs.h.bh = 8;
+    (void) __dpmi_int(VIDEO_BIOS, &regs);
+    if (regs.x.ax != 0x004F) {
+        shift = 2;
+    } else if (regs.h.bh > 8) {
+        shift = 0;
+    } else {
+        shift = 8 - regs.h.bh;
+    }
+
+    /* Set the tile set and text colors */
+    palette_ptr = palette_seg * 16L;
+#ifdef USE_TILES
+    for (i = 0; i < FIRST_TEXT_COLOR; ++i) {
+        r = p->r >> shift;
+        g = p->g >> shift;
+        b = p->b >> shift;
+        color =   ((unsigned long) r << 16)
+                | ((unsigned long) g <<  8)
+                | ((unsigned long) b <<  0);
+        _farpokel(_dos_ds, palette_ptr, color);
+        palette_ptr += 4;
+        ++p;
+    }
+#else
+    palette_ptr += FIRST_TEXT_COLOR * 4;
+#endif
+    p = defpalette;
+    for (i = FIRST_TEXT_COLOR; i < 256; ++i) {
+        r = p->r >> shift;
+        g = p->g >> shift;
+        b = p->b >> shift;
+        color =   ((unsigned long) r << 16)
+                | ((unsigned long) g <<  8)
+                | ((unsigned long) b <<  0);
+        _farpokel(_dos_ds, palette_ptr, color);
+        palette_ptr += 4;
+        ++p;
+    }
+
+    memset(&regs, 0, sizeof(regs));
+    regs.x.ax = 0x4F09;
+    regs.h.bl = 0;
+    regs.x.cx = 256;
+    regs.x.dx = 0;
+    regs.x.di = 0;
+    regs.x.es = palette_seg;
+    (void) __dpmi_int(VIDEO_BIOS, &regs);
+
+    __dpmi_free_dos_memory(palette_sel);
+    return TRUE;
+
+error:
+    if (palette_sel != -1) __dpmi_free_dos_memory(palette_sel);
+    return FALSE;
+}
+
+static boolean
+vesa_SetSoftPalette(palette)
+const struct Pixel *palette;
+{
+    const struct Pixel *p;
+    unsigned i;
+    unsigned char r, g, b;
+
+    /* Set the tile set and text colors */
+#ifdef USE_TILES
+    p = palette;
+    for (i = 0; i < FIRST_TEXT_COLOR; ++i) {
+        r = p->r;
+        g = p->g;
+        b = p->b;
+        vesa_palette[i] = vesa_MakeColor(r, g, b);
+        ++p;
+    }
+#endif
+    p = defpalette;
+    for (i = FIRST_TEXT_COLOR; i < 256; ++i) {
+        r = p->r;
+        g = p->g;
+        b = p->b;
+        vesa_palette[i] = vesa_MakeColor(r, g, b);
+        ++p;
+    }
+}
+
+#ifdef POSITIONBAR
+
+#define PBAR_ROW (LI - 4)
+#define PBAR_COLOR_ON 16    /* slate grey background colour of tiles */
+#define PBAR_COLOR_OFF 0    /* bluish grey, used in old style only */
+#define PBAR_COLOR_STAIRS CLR_BROWN /* brown */
+#define PBAR_COLOR_HERO CLR_WHITE  /* creamy white */
+
+static unsigned char pbar[COLNO];
+
+void
+vesa_update_positionbar(posbar)
+char *posbar;
+{
+    char *p = pbar;
+    if (posbar)
+        while (*posbar)
+            *p++ = *posbar++;
+    *p = 0;
+}
+
+static void
+positionbar()
+{
+    char *posbar = pbar;
+    int feature, ucol;
+    int k, x, y, colour, row;
+
+    int startk, stopk;
+    boolean nowhere = FALSE;
+    int pixy = (PBAR_ROW * MAX_ROWS_PER_CELL);
+    int tmp;
+
+    if (!iflags.grmode || !iflags.tile_view)
+        return;
+    if ((clipx < 0) || (clipxmax <= 0) || (clipx >= clipxmax))
+        nowhere = TRUE;
+    if (nowhere) {
+#ifdef DEBUG
+        pline("Would have put bar using %d - %d.", clipx, clipxmax);
+#endif
+        return;
+    }
+#ifdef OLD_STYLE
+    for (y = pixy; y < (pixy + MAX_ROWS_PER_CELL); ++y) {
+        for (x = 0; x < 640; ++x) {
+            k = x / 8;
+            if ((k < clipx) || (k > clipxmax)) {
+                colour = PBAR_COLOR_OFF;
+            } else
+                colour = PBAR_COLOR_ON;
+            vesa_WritePixel(x + vesa_x_center, y + vesa_y_center, colour);
+        }
+    }
+#else
+    for (y = pixy, row = 0; y < (pixy + MAX_ROWS_PER_CELL); ++y, ++row) {
+        if ((!row) || (row == (ROWS_PER_CELL - 1))) {
+            startk = 0;
+            stopk = SCREENBYTES;
+        } else {
+            startk = clipx;
+            stopk = clipxmax;
+        }
+        for (x = 0; x < 640; ++x) {
+            k = x / 8;
+            if ((k < startk) || (k > stopk))
+                colour = BACKGROUND_VGA_COLOR;
+            else
+                colour = PBAR_COLOR_ON;
+            vesa_WritePixel(x + vesa_x_center, y + vesa_y_center, colour);
+        }
+    }
+#endif
+    ucol = 0;
+    if (posbar) {
+        while (*posbar != 0) {
+            feature = *posbar++;
+            switch (feature) {
+            case '>':
+                vesa_WriteChar(feature, (int) *posbar++, PBAR_ROW, PBAR_COLOR_STAIRS, TRUE);
+                break;
+            case '<':
+                vesa_WriteChar(feature, (int) *posbar++, PBAR_ROW, PBAR_COLOR_STAIRS, TRUE);
+                break;
+            case '@':
+                ucol = (int) *posbar++;
+                vesa_WriteChar(feature, ucol, PBAR_ROW, PBAR_COLOR_HERO, TRUE);
+                break;
+            default: /* unanticipated symbols */
+                vesa_WriteChar(feature, (int) *posbar++, PBAR_ROW, PBAR_COLOR_STAIRS, TRUE);
+                break;
+            }
+        }
+    }
+#ifdef SIMULATE_CURSOR
+    if (inmap) {
+        tmp = curcol + 1;
+        if ((tmp != ucol) && (curcol >= 0))
+            vesa_WriteChar('_', tmp, PBAR_ROW, PBAR_COLOR_HERO, TRUE);
+    }
+#endif
+}
+
+#endif /*POSITIONBAR*/
+
+#ifdef SIMULATE_CURSOR
+
+static unsigned long undercursor[TILE_Y][TILE_X];
+
+void
+vesa_DrawCursor()
+{
+    unsigned x, y, left, top, right, bottom, width;
+    boolean isrogue = Is_rogue_level(&u.uz);
+    boolean halfwidth =
+        (isrogue || iflags.over_view || iflags.traditional_view || !inmap);
+    int curtyp;
+
+    if (!cursor_type && inmap)
+        return; /* CURSOR_INVIS - nothing to do */
+
+    x = min(curcol, (CO - 1)); /* protection from callers */
+    y = min(currow, (LI - 1)); /* protection from callers */
+    if (!halfwidth && ((x < clipx) || (x > clipxmax)))
+        return;
+    if (inmap)
+        x -= clipx;
+    left = x * TILE_X; /* convert to pixels */
+    top  = y * TILE_Y;
+    if (halfwidth) {
+        left /= 2;
+        width = TILE_X / 2;
+    } else {
+        width = TILE_X;
+    }
+    left += vesa_x_center;
+    top  += vesa_y_center;
+    right = left + width - 1;
+    bottom = top + TILE_Y - 1;
+
+    for (y = 0; y < ROWS_PER_CELL; ++y) {
+        for (x = 0; x < width; ++x) {
+            undercursor[y][x] = vesa_ReadPixel32(left + x, top + y);
+        }
+    }
+
+    /*
+     * Now we have a snapshot of the current cell.
+     * Write the cursor on top of the display.
+     */
+
+    if (inmap)
+        curtyp = cursor_type;
+    else
+        curtyp = CURSOR_UNDERLINE;
+
+    switch (curtyp) {
+    case CURSOR_CORNER:
+        vesa_WritePixel(left     , top       , FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(left  + 1, top       , FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(right - 1, top       , FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(right    , top       , FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(left     , top    + 1, FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(right    , top    + 1, FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(left     , bottom - 1, FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(right    , bottom - 1, FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(left     , bottom    , FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(left  + 1, bottom    , FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(right - 1, bottom    , FIRST_TEXT_COLOR + 15);
+        vesa_WritePixel(right    , bottom    , FIRST_TEXT_COLOR + 15);
+        break;
+
+    case CURSOR_UNDERLINE:
+        for (x = left; x <= right; ++x) {
+            vesa_WritePixel(x, bottom, FIRST_TEXT_COLOR + 15);
+        }
+        break;
+
+    case CURSOR_FRAME:
+
+    /* fall through */
+
+    default:
+        for (x = left; x <= right; ++x) {
+            vesa_WritePixel(x, top, FIRST_TEXT_COLOR + 15);
+        }
+        for (y = top + 1; y <= bottom - 1; ++y) {
+            vesa_WritePixel(left , y, FIRST_TEXT_COLOR + 15);
+            vesa_WritePixel(right, y, FIRST_TEXT_COLOR + 15);
+        }
+        for (x = left; x <= right; ++x) {
+            vesa_WritePixel(x, bottom, FIRST_TEXT_COLOR + 15);
+        }
+        break;
+    }
+#ifdef POSITIONBAR
+    if (inmap)
+        positionbar();
+#endif
+}
+
+void
+vesa_HideCursor()
+{
+    unsigned x, y, left, top, width;
+    boolean isrogue = Is_rogue_level(&u.uz);
+    boolean halfwidth =
+        (isrogue || iflags.over_view || iflags.traditional_view || !inmap);
+    int curtyp;
+
+    if (!cursor_type && inmap)
+        return; /* CURSOR_INVIS - nothing to do */
+
+    x = min(curcol, (CO - 1)); /* protection from callers */
+    y = min(currow, (LI - 1)); /* protection from callers */
+    if (!halfwidth && ((x < clipx) || (x > clipxmax)))
+        return;
+    if (inmap)
+        x -= clipx;
+    left = x * TILE_X; /* convert to pixels */
+    top  = y * TILE_Y;
+    if (halfwidth) {
+        left /= 2;
+        width = TILE_X / 2;
+    } else {
+        width = TILE_X;
+    }
+    left += vesa_x_center;
+    top  += vesa_y_center;
+
+    for (y = 0; y < ROWS_PER_CELL; ++y) {
+        for (x = 0; x < width; ++x) {
+            vesa_WritePixel32(left + x, top + y, undercursor[y][x]);
+        }
+    }
+}
+#endif /* SIMULATE_CURSOR */
+#endif /* SCREEN_VESA */
index 533ce17..4e8a182 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 vidvga.c        $NHDT-Date: 1432512791 2015/05/25 00:13:11 $  $NHDT-Branch: master $:$NHDT-Revision: 1.17 $ */
+/* NetHack 3.6 vidvga.c        $NHDT-Date: 1457207044 2016/03/05 19:44:04 $  $NHDT-Branch: chasonr $:$NHDT-Revision: 1.18 $ */
 /*   Copyright (c) NetHack PC Development Team 1995                 */
 /*   NetHack may be freely redistributed.  See license for details. */
 /*
@@ -10,7 +10,7 @@
 #ifdef SCREEN_VGA /* this file is for SCREEN_VGA only    */
 #include "pcvideo.h"
 #include "tile.h"
-#include "pctiles.h"
+#include "tileset.h"
 
 #include <dos.h>
 #include <ctype.h>
 #include <conio.h>
 #endif
 
+extern short glyph2tile[];
+
 /* STATIC_DCL void FDECL(vga_NoBorder, (int));  */
 void FDECL(vga_gotoloc, (int, int)); /* This should be made a macro */
 void NDECL(vga_backsp);
@@ -109,7 +111,7 @@ void NDECL(vga_backsp);
 STATIC_DCL void FDECL(vga_scrollmap, (BOOLEAN_P));
 #endif
 STATIC_DCL void FDECL(vga_redrawmap, (BOOLEAN_P));
-void FDECL(vga_cliparound, (int, int));
+static void FDECL(vga_cliparound, (int, int));
 STATIC_OVL void FDECL(decal_planar, (struct planar_cell_struct *, unsigned));
 
 #ifdef POSITIONBAR
@@ -117,6 +119,19 @@ STATIC_DCL void NDECL(positionbar);
 static void FDECL(vga_special, (int, int, int));
 #endif
 
+static void FDECL(vga_DisplayCell, (struct planar_cell_struct *, int, int));
+static void FDECL(vga_DisplayCell_O,
+             (struct overview_planar_cell_struct *, int, int));
+static void FDECL(vga_SwitchMode, (unsigned int));
+static void FDECL(vga_SetPalette, (const struct Pixel *));
+static void FDECL(vga_WriteChar, (int, int, int, int));
+static void FDECL(vga_WriteStr, (char *, int, int, int, int));
+
+static void FDECL(read_planar_tile, (unsigned, struct planar_cell_struct *));
+static void FDECL(read_planar_tile_O,
+            (unsigned, struct overview_planar_cell_struct *));
+static void FDECL(read_tile_indexes, (unsigned, unsigned char (*)[TILE_X]));
+
 extern int clipx, clipxmax; /* current clipping column from wintty.c */
 extern boolean clipping;    /* clipping on? from wintty.c */
 extern int savevmode;       /* store the original video mode */
@@ -135,7 +150,7 @@ extern boolean inmap;           /* in the map window */
 STATIC_VAR unsigned char __far *font;
 STATIC_VAR char *screentable[SCREENHEIGHT];
 
-STATIC_VAR char *paletteptr;
+STATIC_VAR const struct Pixel *paletteptr;
 STATIC_VAR struct map_struct {
     int glyph;
     int ch;
@@ -156,8 +171,8 @@ STATIC_VAR struct map_struct {
     }
 #define TOP_MAP_ROW 1
 
-STATIC_VAR int vgacmap[CLR_MAX] = { 0,  3, 5, 9, 4, 8, 12, 14,
-                                    11, 2, 6, 7, 1, 8, 12, 13 };
+STATIC_VAR int vgacmap[CLR_MAX] = {  1, 4, 6, 10, 5, 9, 0, 15,
+                                    12, 3, 7,  8, 2, 9, 0, 14 };
 STATIC_VAR int viewport_size = 40;
 /* STATIC_VAR char masktable[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; */
 /* STATIC_VAR char bittable[8]= {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; */
@@ -187,13 +202,8 @@ int vp[SCREENPLANES] = { 8, 4, 2, 1 };
 #endif
 int vp2[SCREENPLANES] = { 1, 2, 4, 8 };
 
-STATIC_VAR struct planar_cell_struct *planecell;
-STATIC_VAR struct overview_planar_cell_struct *planecell_O;
-
-#if defined(USE_TILES)
-STATIC_VAR struct tibhdr_struct tibheader;
-/* extern FILE *tilefile; */ /* Not needed in here most likely */
-#endif
+STATIC_VAR struct planar_cell_struct planecell;
+STATIC_VAR struct overview_planar_cell_struct planecell_O;
 
 /* STATIC_VAR int  g_attribute;        */ /* Current attribute to use */
 
@@ -365,6 +375,11 @@ unsigned special; /* special feature: corpse, invis, detected, pet, ridden -
     int attr;
     int ry;
 
+    /* If statue glyph, map to the generic statue */
+    if (GLYPH_STATUE_OFF <= glyphnum && glyphnum < GLYPH_STATUE_OFF + NUMMONS) {
+        glyphnum = objnum_to_glyph(STATUE);
+    }
+
     row = currow;
     col = curcol;
     if ((col < 0 || col >= COLNO)
@@ -380,20 +395,14 @@ unsigned special; /* special feature: corpse, invis, detected, pet, ridden -
         vga_WriteChar((unsigned char) ch, col, row, attr);
     } else if (!iflags.over_view) {
         if ((col >= clipx) && (col <= clipxmax)) {
-            if (!ReadPlanarTileFile(glyph2tile[glyphnum], &planecell)) {
-                if (map[ry][col].special)
-                    decal_planar(planecell, special);
-                vga_DisplayCell(planecell, col - clipx, row);
-            } else
-                pline("vga_xputg: Error reading tile (%d,%d) from file",
-                      glyphnum, glyph2tile[glyphnum]);
+            read_planar_tile(glyphnum, &planecell);
+            if (map[ry][col].special)
+                decal_planar(&planecell, special);
+            vga_DisplayCell(&planecell, col - clipx, row);
         }
     } else {
-        if (!ReadPlanarTileFile_O(glyph2tile[glyphnum], &planecell_O))
-            vga_DisplayCell_O(planecell_O, col, row);
-        else
-            pline("vga_xputg: Error reading tile (%d,%d) from file", glyphnum,
-                  glyph2tile[glyphnum]);
+        read_planar_tile_O(glyphnum, &planecell_O);
+        vga_DisplayCell_O(&planecell_O, col, row);
     }
     if (col < (CO - 1))
         ++col;
@@ -422,7 +431,7 @@ int col, row;
 }
 
 #if defined(USE_TILES) && defined(CLIPPING)
-void
+static void
 vga_cliparound(x, y)
 int x, y;
 {
@@ -489,22 +498,13 @@ boolean clearfirst;
                 t = map[y][x].glyph;
                 if (!(clearfirst && t == cmap_to_glyph(S_stone))) {
                     if (!iflags.over_view) {
-                        if (!ReadPlanarTileFile(glyph2tile[t], &planecell)) {
-                            if (map[y][x].special)
-                                decal_planar(planecell, map[y][x].special);
-                            vga_DisplayCell(planecell, x - clipx,
-                                            y + TOP_MAP_ROW);
-                        } else
-                            pline("vga_redrawmap: Error reading tile (%d,%d)",
-                                  t, glyph2tile[t]);
+                        read_planar_tile(t, &planecell);
+                        if (map[y][x].special)
+                            decal_planar(&planecell, map[y][x].special);
+                        vga_DisplayCell(&planecell, x - clipx, y + TOP_MAP_ROW);
                     } else {
-                        if (!ReadPlanarTileFile_O(glyph2tile[t],
-                                                  &planecell_O)) {
-                            vga_DisplayCell_O(planecell_O, x,
-                                              y + TOP_MAP_ROW);
-                        } else
-                            pline("vga_redrawmap: Error reading tile (%d,%d)",
-                                  t, glyph2tile[t]);
+                        read_planar_tile_O(t, &planecell_O);
+                        vga_DisplayCell_O(&planecell_O, x, y + TOP_MAP_ROW);
                     }
                 }
             }
@@ -632,19 +632,98 @@ boolean left;
     for (y = 0; y < ROWNO; ++y) {
         for (x = i; x < j; x += 2) {
             t = map[y][x].glyph;
-            if (!ReadPlanarTileFile(glyph2tile[t], &planecell)) {
-                if (map[y][x].special)
-                    decal_planar(planecell, map[y][x].special);
-                vga_DisplayCell(planecell, x - clipx, y + TOP_MAP_ROW);
-            } else {
-                pline("vga_shiftmap: Error reading tile (%d,%d)", t,
-                      glyph2tile[t]);
-            }
+            read_planar_tile(t, &planecell);
+            if (map[y][x].special)
+                decal_planar(&planecell, map[y][x].special);
+            vga_DisplayCell(&planecell, x - clipx, y + TOP_MAP_ROW);
         }
     }
 }
 #endif /* SCROLLMAP */
 
+static void
+read_planar_tile(glyph, cell)
+unsigned glyph;
+struct planar_cell_struct *cell;
+{
+    unsigned char indexes[TILE_Y][TILE_X];
+    unsigned plane, y, byte, bit;
+
+    read_tile_indexes(glyph, indexes);
+    /* cell->plane[0..3].image[0..15][0..1] */
+    for (plane = 0; plane < SCREENPLANES; ++plane) {
+        for (y = 0; y < TILE_Y; ++y) {
+            for (byte = 0; byte < MAX_BYTES_PER_CELL; ++byte) {
+                unsigned char b = 0;
+                for (bit = 0; bit < 8; ++bit) {
+                    unsigned char x = byte * 8 + bit;
+                    unsigned char i = indexes[y][x];
+                    b <<= 1;
+                    if (i & (0x8 >> plane)) b |= 1;
+                }
+                cell->plane[plane].image[y][byte] = b;
+            }
+        }
+    }
+}
+
+static void
+read_planar_tile_O(glyph, cell)
+unsigned glyph;
+struct overview_planar_cell_struct *cell;
+{
+    unsigned char indexes[TILE_Y][TILE_X];
+    unsigned plane, y, bit;
+
+    read_tile_indexes(glyph, indexes);
+    /* cell->plane[0..3].image[0..15][0..0] */
+    for (plane = 0; plane < SCREENPLANES; ++plane) {
+        for (y = 0; y < TILE_Y; ++y) {
+            unsigned char b = 0;
+            for (bit = 0; bit < 8; ++bit) {
+                unsigned char x = bit * 2;
+                unsigned char i = indexes[y][x];
+                b <<= 1;
+                if (i & (0x8 >> plane)) b |= 1;
+            }
+            cell->plane[plane].image[y][0] = b;
+        }
+    }
+}
+
+static void
+read_tile_indexes(glyph, indexes)
+unsigned glyph;
+unsigned char (*indexes)[TILE_X];
+{
+    const struct TileImage *tile;
+    unsigned x, y;
+
+    /* We don't have enough colors to show the statues */
+    if (glyph >= GLYPH_STATUE_OFF) {
+        glyph = GLYPH_OBJ_OFF + STATUE;
+    }
+
+    /* Get the tile from the image */
+    tile = get_tile(glyph2tile[glyph]);
+
+    /* Map to a 16 bit palette; assume colors laid out as in default tileset */
+    memset(indexes, 0, sizeof(indexes));
+    for (y = 0; y < TILE_Y && y < tile->height; ++y) {
+        for (x = 0; x < TILE_X && x < tile->width; ++x) {
+            unsigned i = tile->indexes[y * tile->width + x];
+            if (i == 28) {
+                i = 0;
+            } else if (i == 16) {
+                i = 13;
+            } else if (i > 15) {
+                i = 15;
+            }
+            indexes[y][x] = i;
+        }
+    }
+}
+
 STATIC_OVL void
 decal_planar(gp, special)
 struct planar_cell_struct *gp;
@@ -671,17 +750,20 @@ vga_Init(void)
     int i;
 
 #ifdef USE_TILES
+    const char *tile_file;
     int tilefailure = 0;
     /*
      * Attempt to open the required tile files. If we can't
      * don't perform the video mode switch, use TTY code instead.
      *
      */
-    if (OpenTileFile(NETHACK_PLANAR_TILEFILE, FALSE))
+    tile_file = iflags.wc_tile_file;
+    if (tile_file == NULL || *tile_file == '\0') {
+        tile_file = "nhtiles.bmp";
+    }
+    if (!read_tiles(tile_file, FALSE))
         tilefailure |= 1;
-    if (OpenTileFile(NETHACK_OVERVIEW_TILEFILE, TRUE))
-        tilefailure |= 2;
-    if (ReadTileFileHeader(&tibheader, FALSE))
+    if (get_palette() == NULL)
         tilefailure |= 4;
 
     if (tilefailure) {
@@ -708,7 +790,7 @@ vga_Init(void)
     /*     vga_NoBorder(BACKGROUND_VGA_COLOR); */ /* Not needed after palette
                                                      mod */
 #ifdef USE_TILES
-    paletteptr = tibheader.palette;
+    paletteptr = get_palette();
     iflags.tile_view = TRUE;
     iflags.over_view = FALSE;
 #else
@@ -730,7 +812,7 @@ vga_Init(void)
  * mode (video mode 0x12). No other modes are currently supported.
  *
  */
-void
+static void
 vga_SwitchMode(unsigned int mode)
 {
     union REGS regs;
@@ -760,8 +842,7 @@ vga_SwitchMode(unsigned int mode)
 void
 vga_Finish(void)
 {
-    CloseTileFile(0);
-    CloseTileFile(1);
+    free_tiles();
     vga_SwitchMode(MODETEXT);
     windowprocs.win_cliparound = tty_cliparound;
     g_attribute = attrib_text_normal;
@@ -853,7 +934,7 @@ vga_detect()
  * do it using the colour 'colour'.
  *
  */
-void
+static void
 vga_WriteChar(chr, col, row, colour)
 int chr, col, row, colour;
 {
@@ -901,7 +982,7 @@ int chr, col, row, colour;
  * not the x,y pixel location.
  *
  */
-void
+static void
 vga_DisplayCell(gp, col, row)
 struct planar_cell_struct *gp;
 int col, row;
@@ -932,7 +1013,7 @@ int col, row;
     egawriteplane(15);
 }
 
-void
+static void
 vga_DisplayCell_O(gp, col, row)
 struct overview_planar_cell_struct *gp;
 int col, row;
@@ -965,7 +1046,7 @@ int col, row;
  * is 'len' at location (x,y) using the 'colour' colour.
  *
  */
-void
+static void
 vga_WriteStr(s, len, col, row, colour)
 char *s;
 int len, col, row, colour;
@@ -993,19 +1074,20 @@ int len, col, row, colour;
  * 16 colour mode at 640 x 480.
  *
  */
-void
+static void
 vga_SetPalette(p)
-char *p;
+const struct Pixel *p;
 {
     union REGS regs;
     int i;
 
     outportb(0x3c6, 0xff);
     for (i = 0; i < COLORDEPTH; ++i) {
+        struct Pixel color = (i == 13) ? p[16] : p[i];
         outportb(0x3c8, i);
-        outportb(0x3c9, (*p++) >> 2);
-        outportb(0x3c9, (*p++) >> 2);
-        outportb(0x3c9, (*p++) >> 2);
+        outportb(0x3c9, color.r >> 2);
+        outportb(0x3c9, color.g >> 2);
+        outportb(0x3c9, color.b >> 2);
     }
     regs.x.bx = 0x0000;
     for (i = 0; i < COLORDEPTH; ++i) {
@@ -1021,10 +1103,10 @@ static unsigned char colorbits[] = { 0x08, 0x04, 0x02, 0x01 };
 #ifdef POSITIONBAR
 
 #define PBAR_ROW (LI - 4)
-#define PBAR_COLOR_ON 15    /* slate grey background colour of tiles */
-#define PBAR_COLOR_OFF 12   /* bluish grey, used in old style only */
-#define PBAR_COLOR_STAIRS 9 /* brown */
-#define PBAR_COLOR_HERO 14  /* creamy white */
+#define PBAR_COLOR_ON 13    /* slate grey background colour of tiles */
+#define PBAR_COLOR_OFF    /* bluish grey, used in old style only */
+#define PBAR_COLOR_STAIRS 10 /* brown */
+#define PBAR_COLOR_HERO 15  /* creamy white */
 
 static unsigned char pbar[COLNO];
 
@@ -1152,7 +1234,7 @@ int chr, col, color;
 
     pixy = PBAR_ROW * MAX_ROWS_PER_CELL;
     for (vplane = 0; vplane < SCREENPLANES; ++vplane) {
-        egareadplane(vplane);
+        egareadplane(SCREENPLANES - 1 - vplane);
         y = pixy;
         for (i = 0; i < ROWS_PER_CELL; ++i) {
             tmp_d = screentable[y++] + col;
index 4cb9b46..b2cf0e6 100644 (file)
@@ -1,7 +1,7 @@
 #      NetHack Copyright (c) NetHack PC Development Team 1993 - 2006
 #      NetHack may be freely redistributed.  See license for details.
 #
-# $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# $NHDT-Date: 1524684112 2018/04/25 19:21:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.12 $
 #
 # A '#' at the beginning of a line means the rest of the line is a comment.
 #
index 9d3e88e..cba44b8 100644 (file)
@@ -1,4 +1,5 @@
-/* NetHack 3.6  cppregex.cpp   $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$ */
+/* NetHack 3.6  cppregex.cpp */
+/* $NHDT-Date: 1524684157 2018/04/25 19:22:37 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.8 $ */
 /* Copyright (c) Sean Hunt  2015.                                 */
 /* NetHack may be freely redistributed.  See license for details. */
 
index 44ddfc5..752fcd5 100644 (file)
@@ -35,6 +35,8 @@ typedef unsigned short int flex_uint16_t;
 
 #define yyconst const
 
+#define FDECL_dummy /*empty*/
+
 /* Returned upon end-of-file. */
 #define YY_NULL 0
 
@@ -217,27 +219,27 @@ static int yy_start = 0;  /* start state number */
  */
 static int yy_did_buffer_switch_on_eof;
 
-void yyrestart FDECL(, (FILE *input_file  ));
-void yy_switch_to_buffer FDECL(, (YY_BUFFER_STATE new_buffer  ));
-YY_BUFFER_STATE yy_create_buffer FDECL(, (FILE *file,int size  ));
-void yy_delete_buffer FDECL(, (YY_BUFFER_STATE b  ));
-void yy_flush_buffer FDECL(, (YY_BUFFER_STATE b  ));
-void yypush_buffer_state FDECL(, (YY_BUFFER_STATE new_buffer  ));
-void yypop_buffer_state FDECL(, (void ));
+void yyrestart FDECL(FDECL_dummy, (FILE *input_file  ));
+void yy_switch_to_buffer FDECL(FDECL_dummy, (YY_BUFFER_STATE new_buffer  ));
+YY_BUFFER_STATE yy_create_buffer FDECL(FDECL_dummy, (FILE *file,int size  ));
+void yy_delete_buffer FDECL(FDECL_dummy, (YY_BUFFER_STATE b  ));
+void yy_flush_buffer FDECL(FDECL_dummy, (YY_BUFFER_STATE b  ));
+void yypush_buffer_state FDECL(FDECL_dummy, (YY_BUFFER_STATE new_buffer  ));
+void yypop_buffer_state FDECL(FDECL_dummy, (void ));
 
-static void yyensure_buffer_stack FDECL(, (void ));
-static void yy_load_buffer_state FDECL(, (void ));
-static void yy_init_buffer FDECL(, (YY_BUFFER_STATE b,FILE *file  ));
+static void yyensure_buffer_stack FDECL(FDECL_dummy, (void ));
+static void yy_load_buffer_state FDECL(FDECL_dummy, (void ));
+static void yy_init_buffer FDECL(FDECL_dummy, (YY_BUFFER_STATE b,FILE *file  ));
 
 #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
 
-YY_BUFFER_STATE yy_scan_buffer FDECL(, (char *base,yy_size_t size  ));
-YY_BUFFER_STATE yy_scan_string FDECL(, (yyconst char *yy_str  ));
-YY_BUFFER_STATE yy_scan_bytes FDECL(, (yyconst char *bytes,yy_size_t len  ));
+YY_BUFFER_STATE yy_scan_buffer FDECL(FDECL_dummy, (char *base,yy_size_t size  ));
+YY_BUFFER_STATE yy_scan_string FDECL(FDECL_dummy, (yyconst char *yy_str  ));
+YY_BUFFER_STATE yy_scan_bytes FDECL(FDECL_dummy, (yyconst char *bytes,yy_size_t len  ));
 
-void *yyalloc FDECL(, (yy_size_t  ));
-void *yyrealloc FDECL(, (void *,yy_size_t  ));
-void yyfree FDECL(, (void *  ));
+void *yyalloc FDECL(FDECL_dummy, (yy_size_t  ));
+void *yyrealloc FDECL(FDECL_dummy, (void *,yy_size_t  ));
+void yyfree FDECL(FDECL_dummy, (void *  ));
 
 #define yy_new_buffer yy_create_buffer
 #define yy_set_interactive(is_interactive) \
@@ -278,10 +280,10 @@ extern char *yytext;
 #endif
 #define yytext_ptr yytext
 
-static yy_state_type yy_get_previous_state FDECL(, (void ));
-static yy_state_type yy_try_NUL_trans FDECL(, (yy_state_type current_state  ));
-static int yy_get_next_buffer FDECL(, (void ));
-static void yy_fatal_error FDECL(, (yyconst char msg[]  )) NORETURN;
+static yy_state_type yy_get_previous_state FDECL(FDECL_dummy, (void ));
+static yy_state_type yy_try_NUL_trans FDECL(FDECL_dummy, (yy_state_type current_state  ));
+static int yy_get_next_buffer FDECL(FDECL_dummy, (void ));
+static void yy_fatal_error FDECL(FDECL_dummy, (yyconst char msg[]  )) NORETURN;
 
 /* Done after the current pattern has been matched and before the
  * corresponding action - sets up yytext.
@@ -501,7 +503,7 @@ int yy_flex_debug = 0;
 #define YY_MORE_ADJ 0
 #define YY_RESTORE_YY_MORE_OFFSET
 char *yytext;
-/* NetHack 3.6  dgn_comp.l     $NHDT-Date: 1449385342 2015/12/06 07:02:22 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
+/* NetHack 3.6  dgn_comp.l     $NHDT-Date: 1522193682 2018/03/27 23:34:42 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */
 /*     Copyright (c) 1989 by Jean-Christophe Collet */
 /*     Copyright (c) 1990 by M. Stephenson          */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -561,6 +563,7 @@ int FDECL(yyoutput, (int));
 #else  /* !FLEX_SCANNER && !FLEXHACK_SCANNER */
 /* most recent flex allows suppressing yyunput() altogether when not needed */
 #define YY_NO_UNPUT
+#define YY_NO_INPUT
 #endif
 
 #if defined(FLEX_SCANNER) || defined(FLEXHACK_SCANNER)
@@ -590,44 +593,44 @@ int nh_line_number = 1;
 /* Accessor methods to globals.
    These are made visible to non-reentrant scanners for convenience. */
 
-int yylex_destroy FDECL(, (void ));
-int yyget_debug FDECL(, (void ));
-void yyset_debug FDECL(, (int debug_flag  ));
-YY_EXTRA_TYPE yyget_extra FDECL(, (void ));
-void yyset_extra FDECL(, (YY_EXTRA_TYPE user_defined  ));
-FILE *yyget_in FDECL(, (void ));
-void yyset_in  FDECL(, (FILE * _in_str  ));
-FILE *yyget_out FDECL(, (void ));
-void yyset_out  FDECL(, (FILE * _out_str  ));
-yy_size_t yyget_leng FDECL(, (void ));
-char *yyget_text FDECL(, (void ));
-int yyget_lineno FDECL(, (void ));
-void yyset_lineno FDECL(, (int _line_number  ));
+int yylex_destroy FDECL(FDECL_dummy, (void ));
+int yyget_debug FDECL(FDECL_dummy, (void ));
+void yyset_debug FDECL(FDECL_dummy, (int debug_flag  ));
+YY_EXTRA_TYPE yyget_extra FDECL(FDECL_dummy, (void ));
+void yyset_extra FDECL(FDECL_dummy, (YY_EXTRA_TYPE user_defined  ));
+FILE *yyget_in FDECL(FDECL_dummy, (void ));
+void yyset_in  FDECL(FDECL_dummy, (FILE * _in_str  ));
+FILE *yyget_out FDECL(FDECL_dummy, (void ));
+void yyset_out  FDECL(FDECL_dummy, (FILE * _out_str  ));
+yy_size_t yyget_leng FDECL(FDECL_dummy, (void ));
+char *yyget_text FDECL(FDECL_dummy, (void ));
+int yyget_lineno FDECL(FDECL_dummy, (void ));
+void yyset_lineno FDECL(FDECL_dummy, (int _line_number  ));
 
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
  */
 
 #ifndef YY_SKIP_YYWRAP
-extern int yywrap FDECL(, (void ));
+extern int yywrap FDECL(FDECL_dummy, (void ));
 #endif
 
 #ifndef YY_NO_UNPUT
 
-static void yyunput FDECL(, (int c,char *buf_ptr  ));
+void yyunput FDECL(FDECL_dummy, (int c,char *buf_ptr  ));
 #endif
 
 #ifndef yytext_ptr
-static void yy_flex_strncpy FDECL(, (char *,yyconst char *,int ));
+static void yy_flex_strncpy FDECL(FDECL_dummy, (char *,yyconst char *,int ));
 #endif
 
 #ifdef YY_NEED_STRLEN
-static int yy_flex_strlen FDECL(, (yyconst char * ));
+static int yy_flex_strlen FDECL(FDECL_dummy, (yyconst char * ));
 #endif
 
 #ifndef YY_NO_INPUT
 
-static int input FDECL(, (void ));
+static int input FDECL(FDECL_dummy, (void ));
 
 #endif
 
@@ -708,7 +711,7 @@ static int input FDECL(, (void ));
 #ifndef YY_DECL
 #define YY_DECL_IS_OURS 1
 
-extern int yylex FDECL(, (void));
+extern int yylex FDECL(FDECL_dummy, (void));
 
 #define YY_DECL int yylex ()
 #endif /* !YY_DECL */
@@ -1147,41 +1150,37 @@ static int yy_get_next_buffer ()
          */
         YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
     } else {
-        yy_size_t num_to_read =
-                YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-        while (num_to_read <= 0) {
+        yy_size_t num_to_read;
+        /* just a shorter name for the current buffer */
+        YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+            /* [pr] This could probably be (b->yy_buf_size < number_to_move)
+             * since the allocated size is actually b->yy_buf_size + 2.
+             * The old code calculated num_to_read above (with same formula
+             * as is used below), then used (num_to_read <= 0) here, which
+             * got broken when num_to_read was changed to an unsigned type. */
+        while (b->yy_buf_size <= number_to_move + 1) {
             /* Not enough room in the buffer - grow it. */
 
-            /* just a shorter name for the current buffer */
-            YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
             int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf);
 
             if ( b->yy_is_our_buffer ) {
-                yy_size_t new_size = b->yy_buf_size * 2;
-
-                if ( new_size <= 0 )
-                    b->yy_buf_size += b->yy_buf_size / 8;
-                else
-                    b->yy_buf_size *= 2;
-
+                b->yy_buf_size += b->yy_buf_size / 4;
                 b->yy_ch_buf = (char *)
-                /* Include room in for 2 EOB chars. */
-                yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+                         /* Include room in for 2 EOB chars. */
+                         yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
             } else
                 /* Can't grow it, we don't own it. */
                 b->yy_ch_buf = 0;
 
             if (! b->yy_ch_buf)
-                YY_FATAL_ERROR("fatal error - scanner input buffer overflow" );
+                YY_FATAL_ERROR("fatal error - scanner input buffer overflow");
 
             (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
 
-            num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-                                number_to_move - 1;
-
         }
 
+        num_to_read = b->yy_buf_size - number_to_move - 1;
         if ( num_to_read > YY_READ_BUF_SIZE )
             num_to_read = YY_READ_BUF_SIZE;
 
@@ -1283,7 +1282,7 @@ static yy_state_type yy_try_NUL_trans (yy_current_state )
 
 #ifndef YY_NO_UNPUT
 
-static void yyunput (c,yy_bp )
+void yyunput (c,yy_bp )
         int c;
         char * yy_bp;
 {
@@ -1470,6 +1469,8 @@ YY_BUFFER_STATE yy_create_buffer (file,size )
        b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
        if ( ! b )
                YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+        if (!size)
+            size = YY_BUF_SIZE;
 
        b->yy_buf_size = (yy_size_t)size;
 
index 9339fd5..5cedec9 100644 (file)
@@ -11,7 +11,7 @@
 #define yyerrok (yyerrflag=0)
 #define YYRECOVERING (yyerrflag!=0)
 #define YYPREFIX "yy"
-/* NetHack 3.6  dgn_comp.y     $NHDT-Date: 1449233106 2015/12/04 12:45:06 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.11 $ */
+/* NetHack 3.6  dgn_comp.y     $NHDT-Date: 1455415237 2016/02/14 02:00:37 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.13 $ */
 /*     Copyright (c) 1989 by Jean-Christophe Collet */
 /*     Copyright (c) 1990 by M. Stephenson                               */
 /* NetHack may be freely redistributed.  See license for details. */
index 3da74b8..8b2c917 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 ioctl.c $NHDT-Date: 1432512788 2015/05/25 00:13:08 $  $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
+/* NetHack 3.6 ioctl.c $NHDT-Date: 1520099308 2018/03/03 17:48:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.13 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* This cannot be part of hack.tty.c (as it was earlier) since on some
@@ -63,9 +64,12 @@ struct termio termio;
 #include <signal.h>
 #endif
 
-#if defined(TIOCGWINSZ)                                    \
-    && (defined(BSD) || defined(ULTRIX) || defined(AIX_31) \
-        || defined(_BULL_SOURCE) || defined(SVR4))
+/* AVOID_WIN_IOCTL can be uncommented in unixconf.h
+ * to force USE_WIN_IOTCL to remain undefined,
+ * instead of the restricted explicit opt-in
+ * logic that used to be here.
+ */
+#if defined(TIOCGWINSZ) && !defined(AVOID_WIN_IOCTL)
 #define USE_WIN_IOCTL
 #include "tcap.h" /* for LI and CO */
 #endif
index b34ae00..02a754e 100644 (file)
@@ -35,6 +35,8 @@ typedef unsigned short int flex_uint16_t;
 
 #define yyconst const
 
+#define FDECL_dummy /*empty*/
+
 /* Returned upon end-of-file. */
 #define YY_NULL 0
 
@@ -217,27 +219,27 @@ static int yy_start = 0;  /* start state number */
  */
 static int yy_did_buffer_switch_on_eof;
 
-void yyrestart FDECL(, (FILE *input_file  ));
-void yy_switch_to_buffer FDECL(, (YY_BUFFER_STATE new_buffer  ));
-YY_BUFFER_STATE yy_create_buffer FDECL(, (FILE *file,int size  ));
-void yy_delete_buffer FDECL(, (YY_BUFFER_STATE b  ));
-void yy_flush_buffer FDECL(, (YY_BUFFER_STATE b  ));
-void yypush_buffer_state FDECL(, (YY_BUFFER_STATE new_buffer  ));
-void yypop_buffer_state FDECL(, (void ));
+void yyrestart FDECL(FDECL_dummy, (FILE *input_file  ));
+void yy_switch_to_buffer FDECL(FDECL_dummy, (YY_BUFFER_STATE new_buffer  ));
+YY_BUFFER_STATE yy_create_buffer FDECL(FDECL_dummy, (FILE *file,int size  ));
+void yy_delete_buffer FDECL(FDECL_dummy, (YY_BUFFER_STATE b  ));
+void yy_flush_buffer FDECL(FDECL_dummy, (YY_BUFFER_STATE b  ));
+void yypush_buffer_state FDECL(FDECL_dummy, (YY_BUFFER_STATE new_buffer  ));
+void yypop_buffer_state FDECL(FDECL_dummy, (void ));
 
-static void yyensure_buffer_stack FDECL(, (void ));
-static void yy_load_buffer_state FDECL(, (void ));
-static void yy_init_buffer FDECL(, (YY_BUFFER_STATE b,FILE *file  ));
+static void yyensure_buffer_stack FDECL(FDECL_dummy, (void ));
+static void yy_load_buffer_state FDECL(FDECL_dummy, (void ));
+static void yy_init_buffer FDECL(FDECL_dummy, (YY_BUFFER_STATE b,FILE *file  ));
 
 #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
 
-YY_BUFFER_STATE yy_scan_buffer FDECL(, (char *base,yy_size_t size  ));
-YY_BUFFER_STATE yy_scan_string FDECL(, (yyconst char *yy_str  ));
-YY_BUFFER_STATE yy_scan_bytes FDECL(, (yyconst char *bytes,yy_size_t len  ));
+YY_BUFFER_STATE yy_scan_buffer FDECL(FDECL_dummy, (char *base,yy_size_t size  ));
+YY_BUFFER_STATE yy_scan_string FDECL(FDECL_dummy, (yyconst char *yy_str  ));
+YY_BUFFER_STATE yy_scan_bytes FDECL(FDECL_dummy, (yyconst char *bytes,yy_size_t len  ));
 
-void *yyalloc FDECL(, (yy_size_t  ));
-void *yyrealloc FDECL(, (void *,yy_size_t  ));
-void yyfree FDECL(, (void *  ));
+void *yyalloc FDECL(FDECL_dummy, (yy_size_t  ));
+void *yyrealloc FDECL(FDECL_dummy, (void *,yy_size_t  ));
+void yyfree FDECL(FDECL_dummy, (void *  ));
 
 #define yy_new_buffer yy_create_buffer
 #define yy_set_interactive(is_interactive) \
@@ -278,10 +280,10 @@ extern char *yytext;
 #endif
 #define yytext_ptr yytext
 
-static yy_state_type yy_get_previous_state FDECL(, (void ));
-static yy_state_type yy_try_NUL_trans FDECL(, (yy_state_type current_state  ));
-static int yy_get_next_buffer FDECL(, (void ));
-static void yy_fatal_error FDECL(, (yyconst char msg[]  )) NORETURN;
+static yy_state_type yy_get_previous_state FDECL(FDECL_dummy, (void ));
+static yy_state_type yy_try_NUL_trans FDECL(FDECL_dummy, (yy_state_type current_state  ));
+static int yy_get_next_buffer FDECL(FDECL_dummy, (void ));
+static void yy_fatal_error FDECL(FDECL_dummy, (yyconst char msg[]  )) NORETURN;
 
 /* Done after the current pattern has been matched and before the
  * corresponding action - sets up yytext.
@@ -1022,7 +1024,7 @@ int yy_flex_debug = 0;
 #define YY_MORE_ADJ 0
 #define YY_RESTORE_YY_MORE_OFFSET
 char *yytext;
-/* NetHack 3.6  lev_comp.l     $NHDT-Date: 1449385344 2015/12/06 07:02:24 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.24 $ */
+/* NetHack 3.6  lev_comp.l     $NHDT-Date: 1522193683 2018/03/27 23:34:43 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.28 $ */
 /*     Copyright (c) 1989 by Jean-Christophe Collet */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1080,6 +1082,7 @@ int FDECL(yyoutput, (int));
 #else  /* !FLEX_SCANNER && !FLEXHACK_SCANNER */
 /* most recent flex allows suppressing yyunput() altogether when not needed */
 #define YY_NO_UNPUT
+#define YY_NO_INPUT
 #endif
 
 #if defined(FLEX_SCANNER) || defined(FLEXHACK_SCANNER)
@@ -1134,44 +1137,44 @@ FILE *orig_yyin = NULL;
 /* Accessor methods to globals.
    These are made visible to non-reentrant scanners for convenience. */
 
-int yylex_destroy FDECL(, (void ));
-int yyget_debug FDECL(, (void ));
-void yyset_debug FDECL(, (int debug_flag  ));
-YY_EXTRA_TYPE yyget_extra FDECL(, (void ));
-void yyset_extra FDECL(, (YY_EXTRA_TYPE user_defined  ));
-FILE *yyget_in FDECL(, (void ));
-void yyset_in  FDECL(, (FILE * _in_str  ));
-FILE *yyget_out FDECL(, (void ));
-void yyset_out  FDECL(, (FILE * _out_str  ));
-yy_size_t yyget_leng FDECL(, (void ));
-char *yyget_text FDECL(, (void ));
-int yyget_lineno FDECL(, (void ));
-void yyset_lineno FDECL(, (int _line_number  ));
+int yylex_destroy FDECL(FDECL_dummy, (void ));
+int yyget_debug FDECL(FDECL_dummy, (void ));
+void yyset_debug FDECL(FDECL_dummy, (int debug_flag  ));
+YY_EXTRA_TYPE yyget_extra FDECL(FDECL_dummy, (void ));
+void yyset_extra FDECL(FDECL_dummy, (YY_EXTRA_TYPE user_defined  ));
+FILE *yyget_in FDECL(FDECL_dummy, (void ));
+void yyset_in  FDECL(FDECL_dummy, (FILE * _in_str  ));
+FILE *yyget_out FDECL(FDECL_dummy, (void ));
+void yyset_out  FDECL(FDECL_dummy, (FILE * _out_str  ));
+yy_size_t yyget_leng FDECL(FDECL_dummy, (void ));
+char *yyget_text FDECL(FDECL_dummy, (void ));
+int yyget_lineno FDECL(FDECL_dummy, (void ));
+void yyset_lineno FDECL(FDECL_dummy, (int _line_number  ));
 
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
  */
 
 #ifndef YY_SKIP_YYWRAP
-extern int yywrap FDECL(, (void ));
+extern int yywrap FDECL(FDECL_dummy, (void ));
 #endif
 
 #ifndef YY_NO_UNPUT
 
-static void yyunput FDECL(, (int c,char *buf_ptr  ));
+void yyunput FDECL(FDECL_dummy, (int c,char *buf_ptr  ));
 #endif
 
 #ifndef yytext_ptr
-static void yy_flex_strncpy FDECL(, (char *,yyconst char *,int ));
+static void yy_flex_strncpy FDECL(FDECL_dummy, (char *,yyconst char *,int ));
 #endif
 
 #ifdef YY_NEED_STRLEN
-static int yy_flex_strlen FDECL(, (yyconst char * ));
+static int yy_flex_strlen FDECL(FDECL_dummy, (yyconst char * ));
 #endif
 
 #ifndef YY_NO_INPUT
 
-static int input FDECL(, (void ));
+static int input FDECL(FDECL_dummy, (void ));
 
 #endif
 
@@ -1252,7 +1255,7 @@ static int input FDECL(, (void ));
 #ifndef YY_DECL
 #define YY_DECL_IS_OURS 1
 
-extern int yylex FDECL(, (void));
+extern int yylex FDECL(FDECL_dummy, (void));
 
 #define YY_DECL int yylex ()
 #endif /* !YY_DECL */
@@ -2390,41 +2393,37 @@ static int yy_get_next_buffer ()
          */
         YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
     } else {
-        yy_size_t num_to_read =
-                YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-        while (num_to_read <= 0) {
+        yy_size_t num_to_read;
+        /* just a shorter name for the current buffer */
+        YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+            /* [pr] This could probably be (b->yy_buf_size < number_to_move)
+             * since the allocated size is actually b->yy_buf_size + 2.
+             * The old code calculated num_to_read above (with same formula
+             * as is used below), then used (num_to_read <= 0) here, which
+             * got broken when num_to_read was changed to an unsigned type. */
+        while (b->yy_buf_size <= number_to_move + 1) {
             /* Not enough room in the buffer - grow it. */
 
-            /* just a shorter name for the current buffer */
-            YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
             int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf);
 
             if ( b->yy_is_our_buffer ) {
-                yy_size_t new_size = b->yy_buf_size * 2;
-
-                if ( new_size <= 0 )
-                    b->yy_buf_size += b->yy_buf_size / 8;
-                else
-                    b->yy_buf_size *= 2;
-
+                b->yy_buf_size += b->yy_buf_size / 4;
                 b->yy_ch_buf = (char *)
-                /* Include room in for 2 EOB chars. */
-                yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+                         /* Include room in for 2 EOB chars. */
+                         yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
             } else
                 /* Can't grow it, we don't own it. */
                 b->yy_ch_buf = 0;
 
             if (! b->yy_ch_buf)
-                YY_FATAL_ERROR("fatal error - scanner input buffer overflow" );
+                YY_FATAL_ERROR("fatal error - scanner input buffer overflow");
 
             (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
 
-            num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-                                number_to_move - 1;
-
         }
 
+        num_to_read = b->yy_buf_size - number_to_move - 1;
         if ( num_to_read > YY_READ_BUF_SIZE )
             num_to_read = YY_READ_BUF_SIZE;
 
@@ -2526,7 +2525,7 @@ static yy_state_type yy_try_NUL_trans (yy_current_state )
 
 #ifndef YY_NO_UNPUT
 
-static void yyunput (c,yy_bp )
+void yyunput (c,yy_bp )
         int c;
         char * yy_bp;
 {
@@ -2713,6 +2712,8 @@ YY_BUFFER_STATE yy_create_buffer (file,size )
        b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
        if ( ! b )
                YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+        if (!size)
+            size = YY_BUF_SIZE;
 
        b->yy_buf_size = (yy_size_t)size;
 
index 62e1f20..19b4232 100644 (file)
@@ -11,8 +11,8 @@
 #define yyerrok (yyerrflag=0)
 #define YYRECOVERING (yyerrflag!=0)
 #define YYPREFIX "yy"
-/* NetHack 3.6  lev_comp.y     $NHDT-Date: 1449233826 2015/12/04 12:57:06 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.19 $ */
-/*     Copyright (c) 1989 by Jean-Christophe Collet */
+/* NetHack 3.6  lev_comp.y     $NHDT-Date: 1455747019 2016/02/17 22:10:19 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.22 $ */
+/*      Copyright (c) 1989 by Jean-Christophe Collet */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
  * and AIX will still see the directive.
  */
 #ifdef _AIX
- #pragma alloca                /* keep leading space! */
+ #pragma alloca         /* keep leading space! */
 #endif
 
 #define SPEC_LEV    /* for USE_OLDARGS (sp_lev.h) */
 #include "hack.h"
 #include "sp_lev.h"
 
-#define ERR            (-1)
+#define ERR             (-1)
 /* many types of things are put in chars for transference to NetHack.
  * since some systems will use signed chars, limit everybody to the
  * same number for portability.
  */
-#define MAX_OF_TYPE    128
+#define MAX_OF_TYPE     128
 
-#define MAX_NESTED_IFS 20
+#define MAX_NESTED_IFS   20
 #define MAX_SWITCH_CASES 20
 
-#define New(type)              \
-       (type *) memset((genericptr_t)alloc(sizeof(type)), 0, sizeof(type))
-#define NewTab(type, size)     (type **) alloc(sizeof(type *) * size)
-#define Free(ptr)              free((genericptr_t)ptr)
+#define New(type) \
+        (type *) memset((genericptr_t) alloc(sizeof (type)), 0, sizeof (type))
+#define NewTab(type, size)      (type **) alloc(sizeof (type *) * size)
+#define Free(ptr)               free((genericptr_t) ptr)
 
 extern void VDECL(lc_error, (const char *, ...));
 extern void VDECL(lc_warning, (const char *, ...));
@@ -70,22 +70,24 @@ extern char FDECL(what_map_char, (CHAR_P));
 extern void FDECL(scan_map, (char *, sp_lev *));
 extern void FDECL(add_opcode, (sp_lev *, int, genericptr_t));
 extern genericptr_t FDECL(get_last_opcode_data1, (sp_lev *, int));
-extern genericptr_t FDECL(get_last_opcode_data2, (sp_lev *, int,int));
+extern genericptr_t FDECL(get_last_opcode_data2, (sp_lev *, int, int));
 extern boolean FDECL(check_subrooms, (sp_lev *));
 extern boolean FDECL(write_level_file, (char *,sp_lev *));
 extern struct opvar *FDECL(set_opvar_int, (struct opvar *, long));
 extern void VDECL(add_opvars, (sp_lev *, const char *, ...));
 extern void FDECL(start_level_def, (sp_lev * *, char *));
 
-extern struct lc_funcdefs *FDECL(funcdef_new,(long,char *));
-extern void FDECL(funcdef_free_all,(struct lc_funcdefs *));
-extern struct lc_funcdefs *FDECL(funcdef_defined,(struct lc_funcdefs *,char *, int));
+extern struct lc_funcdefs *FDECL(funcdef_new, (long,char *));
+extern void FDECL(funcdef_free_all, (struct lc_funcdefs *));
+extern struct lc_funcdefs *FDECL(funcdef_defined, (struct lc_funcdefs *,
+                                                   char *, int));
 extern char *FDECL(funcdef_paramtypes, (struct lc_funcdefs *));
 extern char *FDECL(decode_parm_str, (char *));
 
-extern struct lc_vardefs *FDECL(vardef_new,(long,char *));
-extern void FDECL(vardef_free_all,(struct lc_vardefs *));
-extern struct lc_vardefs *FDECL(vardef_defined,(struct lc_vardefs *,char *, int));
+extern struct lc_vardefs *FDECL(vardef_new, (long,char *));
+extern void FDECL(vardef_free_all, (struct lc_vardefs *));
+extern struct lc_vardefs *FDECL(vardef_defined, (struct lc_vardefs *,
+                                                 char *, int));
 
 extern void NDECL(break_stmt_start);
 extern void FDECL(break_stmt_end, (sp_lev *));
@@ -95,13 +97,14 @@ extern void FDECL(splev_add_from, (sp_lev *, sp_lev *));
 
 extern void FDECL(check_vardef_type, (struct lc_vardefs *, char *, long));
 extern void FDECL(vardef_used, (struct lc_vardefs *, char *));
-extern struct lc_vardefs *FDECL(add_vardef_type, (struct lc_vardefs *, char *, long));
+extern struct lc_vardefs *FDECL(add_vardef_type, (struct lc_vardefs *,
+                                                  char *, long));
 
 extern int FDECL(reverse_jmp_opcode, (int));
 
 struct coord {
-       long x;
-       long y;
+    long x;
+    long y;
 };
 
 struct forloopdef {
@@ -3222,7 +3225,7 @@ case 148:
                      }
 
                      /* first, define a variable for the for-loop end value */
-                     snprintf(buf, 255, "%s end", yyvsp[-4].map);
+                     Sprintf(buf, "%s end", yyvsp[-4].map);
                      /* the value of which is already in stack (the 2nd math_expr) */
                      add_opvars(splev, "iso", VA_PASS3(0, buf, SPO_VAR_INIT));
 
@@ -3232,7 +3235,7 @@ case 148:
                      add_opvars(splev, "iso", VA_PASS3(0, yyvsp[-4].map, SPO_VAR_INIT));
 
                      /* calculate value for the loop "step" variable */
-                     snprintf(buf2, 255, "%s step", yyvsp[-4].map);
+                     Sprintf(buf2, "%s step", yyvsp[-4].map);
                      /* end - start */
                      add_opvars(splev, "vvo",
                                 VA_PASS3(buf, yyvsp[-4].map, SPO_MATH_SUB));
@@ -3258,9 +3261,10 @@ break;
 case 150:
 {
                      char buf[256], buf2[256];
+
                      n_forloops--;
-                     snprintf(buf, 255, "%s step", forloop_list[n_forloops].varname);
-                     snprintf(buf2, 255, "%s end", forloop_list[n_forloops].varname);
+                     Sprintf(buf, "%s step", forloop_list[n_forloops].varname);
+                     Sprintf(buf2, "%s end", forloop_list[n_forloops].varname);
                      /* compare for-loop var to end value */
                      add_opvars(splev, "vvo",
                                 VA_PASS3(forloop_list[n_forloops].varname,
@@ -3993,8 +3997,8 @@ case 253:
                      add_opvars(splev, "iiiii iiiii iiso",
                                 VA_PASS14(yyvsp[-4].lregn.x1, yyvsp[-4].lregn.y1, yyvsp[-4].lregn.x2, yyvsp[-4].lregn.y2, yyvsp[-4].lregn.area,
                                           yyvsp[-2].lregn.x1, yyvsp[-2].lregn.y1, yyvsp[-2].lregn.x2, yyvsp[-2].lregn.y2, yyvsp[-2].lregn.area,
-                                     (long)((yyvsp[0].i) ? LR_UPSTAIR : LR_DOWNSTAIR),
-                                          0, (char *)0, SPO_LEVREGION));
+                                    (long) ((yyvsp[0].i) ? LR_UPSTAIR : LR_DOWNSTAIR),
+                                          0, (char *) 0, SPO_LEVREGION));
                  }
 break;
 case 254:
@@ -4025,8 +4029,8 @@ case 256:
                      add_opvars(splev, "iiiii iiiii iiso",
                                 VA_PASS14(yyvsp[-2].lregn.x1, yyvsp[-2].lregn.y1, yyvsp[-2].lregn.x2, yyvsp[-2].lregn.y2, yyvsp[-2].lregn.area,
                                           yyvsp[0].lregn.x1, yyvsp[0].lregn.y1, yyvsp[0].lregn.x2, yyvsp[0].lregn.y2, yyvsp[0].lregn.area,
-                                          (long)LR_BRANCH, 0,
-                                          (char *)0, SPO_LEVREGION));
+                                          (long) LR_BRANCH, 0,
+                                          (char *) 0, SPO_LEVREGION));
                  }
 break;
 case 257:
@@ -4421,7 +4425,8 @@ case 329:
                           lc_error("Unknown monster \"%s\"!", yyvsp[0].map);
                           yyval.i = -1;
                       } else
-                          yyval.i = SP_MONST_PACK(m, def_monsyms[(int)mons[m].mlet].sym);
+                          yyval.i = SP_MONST_PACK(m,
+                                         def_monsyms[(int) mons[m].mlet].sym);
                       Free(yyvsp[0].map);
                   }
 break;
@@ -4604,16 +4609,23 @@ case 355:
                      } else if (!tmp) {
                          lc_error("Could not alloc function params.");
                      } else {
-                         long vt;
+                         long vt = SPOVAR_NULL;
+
                          tmp->name = strdup(yyvsp[-2].map);
                          tmp->parmtype = (char) yyvsp[0].i;
                          tmp->next = curr_function->params;
                          curr_function->params = tmp;
                          curr_function->n_params++;
                          switch (tmp->parmtype) {
-                         case 'i': vt = SPOVAR_INT; break;
-                         case 's': vt = SPOVAR_STRING; break;
-                         default: lc_error("Unknown func param conversion."); break;
+                         case 'i':
+                              vt = SPOVAR_INT;
+                              break;
+                         case 's':
+                              vt = SPOVAR_STRING;
+                              break;
+                         default:
+                              lc_error("Unknown func param conversion.");
+                              break;
                          }
                          variable_definitions = add_vardef_type(
                                                         variable_definitions,
@@ -4643,7 +4655,7 @@ break;
 case 363:
 {
                              long len = strlen( yyvsp[-2].map );
-                             char *tmp = (char *)alloc(len + 2);
+                             char *tmp = (char *) alloc(len + 2);
                              sprintf(tmp, "%c%s", (char) yyvsp[0].i, yyvsp[-2].map );
                              Free( yyvsp[-2].map );
                              yyval.map = tmp;
@@ -4810,13 +4822,21 @@ break;
 case 404:
 {
                        if (yyvsp[-7].i <= 0 || yyvsp[-7].i >= COLNO)
-                           lc_error("Region (%li,%li,%li,%li) out of level range (x1)!", yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
+                           lc_error(
+                          "Region (%ld,%ld,%ld,%ld) out of level range (x1)!",
+                                     yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
                        else if (yyvsp[-5].i < 0 || yyvsp[-5].i >= ROWNO)
-                           lc_error("Region (%li,%li,%li,%li) out of level range (y1)!", yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
+                           lc_error(
+                          "Region (%ld,%ld,%ld,%ld) out of level range (y1)!",
+                                     yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
                        else if (yyvsp[-3].i <= 0 || yyvsp[-3].i >= COLNO)
-                           lc_error("Region (%li,%li,%li,%li) out of level range (x2)!", yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
+                           lc_error(
+                          "Region (%ld,%ld,%ld,%ld) out of level range (x2)!",
+                                     yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
                        else if (yyvsp[-1].i < 0 || yyvsp[-1].i >= ROWNO)
-                           lc_error("Region (%li,%li,%li,%li) out of level range (y2)!", yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
+                           lc_error(
+                          "Region (%ld,%ld,%ld,%ld) out of level range (y2)!",
+                                     yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
                        yyval.lregn.x1 = yyvsp[-7].i;
                        yyval.lregn.y1 = yyvsp[-5].i;
                        yyval.lregn.x2 = yyvsp[-3].i;
@@ -4828,14 +4848,22 @@ case 405:
 {
 /* This series of if statements is a hack for MSC 5.1.  It seems that its
    tiny little brain cannot compile if these are all one big if statement. */
-                       if (yyvsp[-7].i < 0 || yyvsp[-7].i > (int)max_x_map)
-                           lc_error("Region (%li,%li,%li,%li) out of map range (x1)!", yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
-                       else if (yyvsp[-5].i < 0 || yyvsp[-5].i > (int)max_y_map)
-                           lc_error("Region (%li,%li,%li,%li) out of map range (y1)!", yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
-                       else if (yyvsp[-3].i < 0 || yyvsp[-3].i > (int)max_x_map)
-                           lc_error("Region (%li,%li,%li,%li) out of map range (x2)!", yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
-                       else if (yyvsp[-1].i < 0 || yyvsp[-1].i > (int)max_y_map)
-                           lc_error("Region (%li,%li,%li,%li) out of map range (y2)!", yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
+                       if (yyvsp[-7].i < 0 || yyvsp[-7].i > (int) max_x_map)
+                           lc_error(
+                            "Region (%ld,%ld,%ld,%ld) out of map range (x1)!",
+                                     yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
+                       else if (yyvsp[-5].i < 0 || yyvsp[-5].i > (int) max_y_map)
+                           lc_error(
+                            "Region (%ld,%ld,%ld,%ld) out of map range (y1)!",
+                                     yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
+                       else if (yyvsp[-3].i < 0 || yyvsp[-3].i > (int) max_x_map)
+                           lc_error(
+                            "Region (%ld,%ld,%ld,%ld) out of map range (x2)!",
+                                     yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
+                       else if (yyvsp[-1].i < 0 || yyvsp[-1].i > (int) max_y_map)
+                           lc_error(
+                            "Region (%ld,%ld,%ld,%ld) out of map range (y2)!",
+                                     yyvsp[-7].i, yyvsp[-5].i, yyvsp[-3].i, yyvsp[-1].i);
                        yyval.lregn.area = 0;
                        yyval.lregn.x1 = yyvsp[-7].i;
                        yyval.lregn.y1 = yyvsp[-5].i;
index dc5466c..3094df4 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 pcmain.c        $NHDT-Date: 1449116336 2015/12/03 04:18:56 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.66 $ */
+/* NetHack 3.6 pcmain.c        $NHDT-Date: 1524413707 2018/04/22 16:15:07 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.74 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Derek S. Ray, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* main.c - MSDOS, OS/2, ST, Amiga, and Windows NetHack */
@@ -55,8 +56,12 @@ extern void FDECL(nethack_exit, (int));
 #ifdef WIN32
 extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
 extern int redirect_stdout;       /* from sys/share/pcsys.c */
+extern int GUILaunched;
+HANDLE hStdOut;
 char *NDECL(exename);
 char default_window_sys[] = "mswin";
+boolean NDECL(fakeconsole);
+void NDECL(freefakeconsole);
 #endif
 
 #if defined(MSWIN_GRAPHICS)
@@ -111,9 +116,11 @@ char *argv[];
 {
     register int fd;
     register char *dir;
-#if defined(WIN32)
+#if defined(WIN32) || defined(MSDOS)
     char *envp = NULL;
     char *sptr = NULL;
+#endif
+#if defined(WIN32)
     char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ];
     boolean save_getreturn_status = getreturn_enabled;
 #endif
@@ -133,6 +140,15 @@ char *argv[];
 /* use STDERR by default
 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
+/* Heap Debugging
+    _CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
+        | _CRTDBG_ALLOC_MEM_DF
+        | _CRTDBG_CHECK_ALWAYS_DF
+        | _CRTDBG_CHECK_CRT_DF
+        | _CRTDBG_DELAY_FREE_MEM_DF
+        | _CRTDBG_LEAK_CHECK_DF);
+    _CrtSetBreakAlloc(1423);
+*/
 # endif
 #endif
 
@@ -174,7 +190,33 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
     if (dir == (char *) 0)
         dir = exepath(argv[0]);
 #endif
-    if (dir != (char *) 0) {
+#ifdef _MSC_VER
+    if (IsDebuggerPresent()) {
+        static char exepath[_MAX_PATH];
+        /* check if we're running under the debugger so we can get to the right folder anyway */
+        if (dir != (char *)0) {
+            char *top = (char *)0;
+
+            if (strlen(dir) < (_MAX_PATH - 1))
+                strcpy(exepath, dir);
+            top = strstr(exepath, "\\build\\.\\Debug");
+            if (!top) top = strstr(exepath, "\\build\\.\\Release");
+            if (top) {
+                *top = '\0';
+                if (strlen(exepath) < (_MAX_PATH - (strlen("\\binary\\") + 1))) {
+                    Strcat(exepath, "\\binary\\");
+                    if (strlen(exepath) < (PATHLEN - 1)) {
+                        dir = exepath;
+                    }
+                }
+            }
+        }
+    }
+#endif
+    if (dir != (char *)0) {
+        int fd;
+        boolean have_syscf = FALSE;
+
         (void) strncpy(hackdir, dir, PATHLEN - 1);
         hackdir[PATHLEN - 1] = '\0';
 #ifdef NOCWD_ASSUMPTIONS
@@ -202,6 +244,34 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
                 }
             }
 
+            /* okay so we have the overriding and definitive locaton
+            for sysconf, but only in the event that there is not a 
+            sysconf file there (for whatever reason), check a secondary
+            location rather than abort. */
+
+            /* Is there a SYSCF_FILE there? */
+            fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY);
+            if (fd >= 0) {
+                /* readable */
+                close(fd);
+                have_syscf = TRUE;
+            }
+
+            if (!have_syscf) {
+                /* No SYSCF_FILE where there should be one, and
+                   without an installer, a user may not be able
+                   to place one there. So, let's try somewhere else... */
+                fqn_prefix[SYSCONFPREFIX] = fqn_prefix[0];
+
+                /* Is there a SYSCF_FILE there? */
+                fd = open(fqname(SYSCF_FILE, SYSCONFPREFIX, 0), O_RDONLY);
+                if (fd >= 0) {
+                    /* readable */
+                    close(fd);
+                    have_syscf = TRUE;
+                }
+            }
+
             /* user's home directory should default to this - unless
              * overridden */
             envp = nh_getenv("USERPROFILE");
@@ -238,6 +308,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
     save_getreturn_status = getreturn_enabled;
     raw_clear_screen();
     getreturn_enabled = TRUE;
+    check_recordfile((char *) 0);
 #endif
     initoptions();
 
@@ -260,6 +331,9 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
         Strcpy(hackdir, HACKDIR);
 #endif
     if (argc > 1) {
+        if (argcheck(argc, argv, ARG_VERSION))
+            nethack_exit(EXIT_SUCCESS);
+
         if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
             /* avoid matching "-dec" for DECgraphics; since the man page
              * says -d directory, hope nobody's using -desomething_else
@@ -279,16 +353,30 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
             Strcpy(hackdir, dir);
         }
         if (argc > 1) {
+#if defined(WIN32)
+            int sfd = 0;
+            boolean tmpconsole = FALSE;
+            hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+#endif
             /*
              * Now we know the directory containing 'record' and
              * may do a prscore().
              */
             if (!strncmp(argv[1], "-s", 2)) {
 #if defined(WIN32)
-                int sfd = (int) _fileno(stdout);
+
+#if 0
+                if (!hStdOut) {
+                    tmpconsole = fakeconsole();
+                }
+#endif
+                /*
+                 * Check to see if we're redirecting to a file.
+                 */
+                sfd = (int) _fileno(stdout);
                 redirect_stdout = (sfd >= 0) ? !isatty(sfd) : 0;
 
-                if (!redirect_stdout) {
+                if (!redirect_stdout && !hStdOut) {
                     raw_printf(
                         "-s is not supported for the Graphical Interface\n");
                     nethack_exit(EXIT_SUCCESS);
@@ -302,6 +390,13 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
                 initoptions();
 #endif
                 prscore(argc, argv);
+#ifdef WIN32
+                if (tmpconsole) {
+                    getreturn("to exit");
+                    freefakeconsole();
+                    tmpconsole = FALSE;
+                }
+#endif
                 nethack_exit(EXIT_SUCCESS);
             }
 
@@ -313,7 +408,21 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
 #endif
             /* Don't initialize the window system just to print usage */
             if (!strncmp(argv[1], "-?", 2) || !strncmp(argv[1], "/?", 2)) {
+#if 0
+                if (!hStdOut) {
+                    GUILaunched = 0;
+                    tmpconsole = fakeconsole();
+                }
+#endif
                 nhusage();
+
+#ifdef WIN32
+                if (tmpconsole) {
+                    getreturn("to exit");
+                    freefakeconsole();
+                    tmpconsole = FALSE;
+                }
+#endif
                 nethack_exit(EXIT_SUCCESS);
             }
         }
@@ -693,7 +802,9 @@ char *argv[];
                             NHWinMainInit();
                         }
             */
+            config_error_init(FALSE, "command line", FALSE);
             choose_windows(&argv[0][2]);
+            config_error_done();
             break;
 #endif
         case '@':
@@ -816,6 +927,9 @@ authorize_wizard_mode()
 
 #ifdef WIN32
 static char exenamebuf[PATHLEN];
+extern HANDLE hConIn;
+extern HANDLE hConOut;
+boolean has_fakeconsole;
 
 char *
 exename()
@@ -838,6 +952,42 @@ exename()
     tmp2++;
     return tmp2;
 }
+
+boolean
+fakeconsole(void)
+{
+    if (!hStdOut) {
+        HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+        HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
+
+        if (!hStdOut && !hStdIn) {
+            /* Bool rval; */
+            AllocConsole();
+            AttachConsole(GetCurrentProcessId());
+            /*         rval = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); */
+            freopen("CON", "w", stdout);
+            freopen("CON", "r", stdin);
+        }
+        has_fakeconsole = TRUE;
+    }
+    
+    /* Obtain handles for the standard Console I/O devices */
+    hConIn = GetStdHandle(STD_INPUT_HANDLE);
+    hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
+#if 0
+    if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
+        /* Unable to set control handler */
+        cmode = 0; /* just to have a statement to break on for debugger */
+    }
+#endif
+    return has_fakeconsole;
+}
+void freefakeconsole()
+{
+    if (has_fakeconsole) {
+        FreeConsole();
+    }
+}
 #endif
 
 #define EXEPATHBUFSZ 256
index 47f74a7..71b62c6 100644 (file)
@@ -1,4 +1,5 @@
-/* NetHack 3.6 pcsys.c $NHDT-Date: 1432512787 2015/05/25 00:13:07 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */
+/* NetHack 3.6 pcsys.c $NHDT-Date: 1524689500 2018/04/25 20:51:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.31 $ */
+/*      Copyright (c) 2012 by Michael Allison              */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -299,7 +300,7 @@ int start;
          * whitespace, do not change the value of SAVEF.
          */
         for (bp = buf; *bp; bp++)
-            if (!isspace(*bp)) {
+            if (!isspace((uchar) *bp)) {
                 strncpy(SAVEF, bp, PATHLEN);
                 break;
             }
@@ -546,6 +547,8 @@ msexit()
         getreturn("to end");
     synch_cursor();
 #endif
+    getreturn_enabled = TRUE;
+    wait_synch();
     return;
 }
 #endif /* MICRO || WIN32 || OS2 */
index 567ac03..cd7d655 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 pctty.c $NHDT-Date: 1432512787 2015/05/25 00:13:07 $  $NHDT-Branch: master $:$NHDT-Revision: 1.11 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2005. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* tty.c - (PC) version */
index 24aba02..c20ba79 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 pcunix.c        $NHDT-Date: 1432512787 2015/05/25 00:13:07 $  $NHDT-Branch: master $:$NHDT-Revision: 1.34 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* This file collects some Unix dependencies; pager.c contains some more */
index 3b5814c..6e1cbe1 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 unixtty.c       $NHDT-Date: 1432512788 2015/05/25 00:13:08 $  $NHDT-Branch: master $:$NHDT-Revision: 1.19 $ */
+/* NetHack 3.6 unixtty.c       $NHDT-Date: 1450916700 2015/12/24 00:25:00 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* tty.c - (Unix) version */
index 7870f3f..6e92851 100644 (file)
@@ -290,3 +290,7 @@ Notes:
     packaging on the host.
 
     For recover, you just want the target binary to install on the target.
+
+# NetHack 3.6  Install.unx       $NHDT-Date: 1524689449 2018/04/25 20:50:49 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.11 $
+# Copyright (c) 2012 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
index 245c2c7..c8287da 100644 (file)
@@ -1,5 +1,6 @@
-#      NetHack Makefile.
-# NetHack 3.6  Makefile.dat    $NHDT-Date: 1447844574 2015/11/18 11:02:54 $  $NHDT-Branch: master $:$NHDT-Revision: 1.18 $
+#      NetHack Datafiles Makefile.dat $NHDT-Date: 1447844574 2018/04/25 19:25:54 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.22 $
+# Copyright (c) 2018 by Pasi Kallinen
+# NetHack may be freely redistributed.  See license for details.
 
 # Root of source tree:
 NHSROOT=..
@@ -31,9 +32,11 @@ all: $(VARDAT) spec_levs quest_levs dungeon
        (cd ../util ; $(MAKE) tile2bmp)
 
 x11tiles: ../util/tile2x11 ../win/share/monsters.txt ../win/share/objects.txt \
-                               ../win/share/other.txt
+                               ../win/share/other.txt \
+                                ../win/share/monsters.txt
        ../util/tile2x11 ../win/share/monsters.txt ../win/share/objects.txt \
-                               ../win/share/other.txt
+                               ../win/share/other.txt \
+                                -grayscale ../win/share/monsters.txt
 
 beostiles: ../util/tile2beos ../win/share/monsters.txt \
                                ../win/share/objects.txt \
@@ -48,7 +51,13 @@ nhtiles.bmp: ../util/tile2bmp ../win/share/monsters.txt \
        ../util/tile2bmp $@
 
 JNetHack.ad: ../win/X11/JNetHack.ad
-       cp ../win/X11/JNetHack.ad JNetHack.ad
+# handle "#define foo bar" -lines
+       grep ^#define ../win/X11/JNetHack.ad | \
+               sed -e 's/^#define/s/g' -e 's/  */ /g' \
+                   -e 's/$$/ g/g' > JNetHack.ad.tmp
+       grep -v ^#define ../win/X11/JNetHack.ad | \
+               sed -f JNetHack.ad.tmp > JNetHack.ad
+       -rm -f JNetHack.ad.tmp
 
 pet_mark.xbm: ../win/X11/pet_mark.xbm
        cp ../win/X11/pet_mark.xbm pet_mark.xbm
@@ -160,3 +169,4 @@ spotless:
        -rm -f spec_levs quest_levs *.lev $(VARDAT) dungeon dungeon.pdf
        -rm -f nhdat x11tiles beostiles pet_mark.xbm pilemark.xbm rip.xpm mapbg.xpm
        -rm -f rip.img GEM_RSC.RSC title.img nh16.img NetHack.ad
+       -rm -f nhsplash.xpm nhtiles.bmp
index e2a8131..dd3703b 100644 (file)
@@ -1,5 +1,7 @@
-#      NetHack Makefile.
-# NetHack 3.6  Makefile.doc    $NHDT-Date: 1432512789 2015/05/25 00:13:09 $  $NHDT-Branch: master $:$NHDT-Revision: 1.14 $
+#      NetHack Documentation Makefile.
+# NetHack 3.6  Makefile.doc    $NHDT-Date: 1524689449 2018/04/25 20:50:49 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 # Root of source tree:
 NHSROOT=..
@@ -27,9 +29,11 @@ PSCMD = groff
 # Use the "cat" GUIDECMD if nroff and/or tbl and/or col are not installed
 # Not appropriate for creating Guidebook.txt.
 # GUIDECMD = cat Guidebook.txt
-# The following works better with groff-1.18, eg on Linux
-# GUIDECMD = $(GUIDE_PREFORMAT) | nroff -c -Tascii | $(COLCMD)
-GUIDECMD = $(GUIDE_PREFORMAT) | nroff | $(COLCMD)
+#
+# 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)
 
 # Only generate output for the current configuration:
 NHGREP = $(MAKEDEFS) --grep --input - --output -
index cbad6bc..58864c9 100644 (file)
@@ -1,5 +1,7 @@
 #      NetHack Makefile.
-# NetHack 3.6  Makefile.src    $NHDT-Date: 1447313972 2015/11/12 07:39:32 $  $NHDT-Branch: master $:$NHDT-Revision: 1.45 $
+# NetHack 3.6  Makefile.src    $NHDT-Date: 1524689449 2018/04/25 20:50:49 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.54 $
+# Copyright (c) 2018 by Pasi Kallinen
+# NetHack may be freely redistributed.  See license for details.
 
 # Root of source tree:
 NHSROOT=..
@@ -169,6 +171,11 @@ CXX=g++
 #CXX=arm-linux-g++
 #LINK=arm-linux-gcc
 
+# we specify C preprocessor flags via CFLAGS; files built with default rules
+# might include $(CPPFLAGS) which could get a value from user's environment;
+# we avoid that by forcing it empty rather than by overriding default rules
+CPPFLAGS =
+
 # file for regular expression matching
 REGEXOBJ = posixregex.o
 #REGEXOBJ = pmatchregex.o
@@ -198,6 +205,22 @@ WINX11OBJ = Window.o dialogs.o winX.o winmap.o winmenu.o winmesg.o \
 WINQTSRC = ../win/Qt/qt_win.cpp ../win/Qt/qt_clust.cpp ../win/Qt/qttableview.cpp
 WINQTOBJ = qt_win.o qt_clust.o qttableview.o tile.o
 #
+# Files for a Qt 4 or 5 port
+#
+WINQT4SRC = ../win/Qt4/qt4bind.cpp ../win/Qt4/qt4click.cpp \
+       ../win/Qt4/qt4clust.cpp ../win/Qt4/qt4delay.cpp \
+       ../win/Qt4/qt4glyph.cpp ../win/Qt4/qt4icon.cpp ../win/Qt4/qt4inv.cpp \
+       ../win/Qt4/qt4key.cpp ../win/Qt4/qt4line.cpp ../win/Qt4/qt4main.cpp \
+       ../win/Qt4/qt4map.cpp ../win/Qt4/qt4menu.cpp ../win/Qt4/qt4msg.cpp \
+       ../win/Qt4/qt4plsel.cpp ../win/Qt4/qt4rip.cpp ../win/Qt4/qt4set.cpp \
+       ../win/Qt4/qt4stat.cpp ../win/Qt4/qt4str.cpp ../win/Qt4/qt4streq.cpp \
+       ../win/Qt4/qt4svsel.cpp ../win/Qt4/qt4win.cpp ../win/Qt4/qt4xcmd.cpp \
+       ../win/Qt4/qt4yndlg.cpp
+WINQT4OBJ = qt4bind.o qt4click.o qt4clust.o qt4delay.o qt4glyph.o qt4icon.o \
+       qt4inv.o qt4key.o qt4line.o qt4main.o qt4map.o qt4menu.o qt4msg.o \
+       qt4plsel.o qt4rip.o qt4set.o qt4stat.o qt4str.o qt4streq.o qt4svsel.o \
+       qt4win.o qt4xcmd.o qt4yndlg.o tile.o
+#
 # Files for a Gnome port
 #
 WINGNOMESRC = ../win/gnome/gnaskstr.c ../win/gnome/gnbind.c \
@@ -250,9 +273,12 @@ WINX11LIB = -lXaw -lXmu -lXext -lXt -lX11
 # WINX11LIB = -lXaw -lXmu -lXext -lXt -lXpm -lX11 -lm
 # WINX11LIB = -lXaw -lXmu -lXpm -lXext -lXt -lX11 -lSM -lICE -lm # BSD/OS 2.0
 #
-# libraries for Qt
+# libraries for Qt 3
 WINQTLIB = -L$(QTDIR)/lib -lqt
 #
+# libraries for Qt 4
+WINQT4LIB = `pkg-config QtGui --libs`
+#
 # libraries for KDE (with Qt)
 WINKDELIB = -lkdecore -lkdeui -lXext
 #
@@ -311,6 +337,17 @@ RANDOBJ =
 # used by `make depend' to reconstruct this Makefile; you shouldn't need this
 AWK    = nawk
 
+# when using 'makedefs -v', also force dat/gitinfo.txt to be up to date;
+# changing this to 0 will change the behavior to only make that file if
+# it doesn't already exist; to skip it completely, create an empty file
+# of that name and also set this to 0; there shouldn't be any need to
+# skip it--if nethack's sources don't reside in a git repository than
+# the script which creates that file will fail benignly and 'makedefs -v'
+# will proceed without it
+GITINFO=1
+
+#VERBOSEMAKE = 1
+
 # ----------------------------------------
 #
 # Nothing below this line should have to be changed.
@@ -318,6 +355,34 @@ AWK        = nawk
 # Other things that have to be reconfigured are in config.h,
 # {unixconf.h, pcconf.h, tosconf.h}, and possibly system.h
 
+# Verbosity definitions, begin
+#   Set VERBOSEMAKE=1 to output more stuff.
+#   CC and CXX obey verbosity, LD and LINK don't.
+#   AT is @ when not verbose, empty otherwise
+ACTUAL_CC := $(CC)
+ACTUAL_CXX := $(CXX)
+ACTUAL_LD := $(LD)
+ACTUAL_LINK := $(LINK)
+
+CC_V0 = @echo "[CC] $<"; $(ACTUAL_CC)
+CC_V = $(CC_V0)
+CC_V1 = $(ACTUAL_CC)
+CC = $(CC_V$(VERBOSEMAKE))
+
+CXX_V0 = @echo "[CXX] $<"; $(ACTUAL_CXX)
+CXX_V = $(CXX_V0)
+CXX_V1 = $(ACTUAL_CXX)
+CXX = $(CXX_V$(VERBOSEMAKE))
+
+LD = $(ACTUAL_LD)
+LINK = $(ACTUAL_LINK)
+
+AT_V0 := @
+AT_V := $(AT_V0)
+AT_V1 :=
+AT = $(AT_V$(VERBOSEMAKE))
+# Verbosity, end
+
 MAKEDEFS = ../util/makedefs
 
 # timestamp files to reduce `make' overhead and shorten .o dependency lists
@@ -336,11 +401,11 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \
           mkmaze.c mkobj.c mkroom.c mon.c mondata.c monmove.c monstj.c \
           mplayer.c mthrowu.c muse.c music.c o_init.c objectsj.c objnam.c \
           options.c pager.c pickup.c pline.c polyself.c potion.c pray.c \
-          priest.c quest.c questpgr.c read.c rect.c region.c restore.c rip.c \
-          rnd.c role.c rumors.c save.c shk.c shknam.c sit.c sounds.c sp_lev.c \
-          spell.c steal.c steed.c sys.c teleport.c timeout.c topten.c track.c \
-          trap.c \
-          u_init.c uhitm.c vault.c version.c vision.c weapon.c were.c wield.c \
+          priest.c quest.c questpgr.c read.c rect.c region.c restore.c \
+          rip.c rnd.c role.c rumors.c save.c shk.c shknam.c sit.c sounds.c \
+          sp_lev.c spell.c steal.c steed.c sys.c teleport.c timeout.c \
+          topten.c track.c trap.c u_init.c \
+          uhitm.c vault.c version.c vision.c weapon.c were.c wield.c \
           windows.c wizard.c worm.c worn.c write.c zap.c
 
 # all operating-system-dependent .c (for dependencies and such)
@@ -350,6 +415,7 @@ SYSCSRC = ../sys/atari/tos.c ../sys/share/pcmain.c ../sys/share/pcsys.c \
        ../sys/share/random.c \
        ../sys/share/ioctl.c ../sys/share/unixtty.c ../sys/unix/unixmain.c \
        ../sys/unix/unixunix.c ../sys/unix/unixres.c ../sys/be/bemain.c
+SYSCXXSRC = ../sys/share/cppregex.cpp
 
 # generated source files (tile.c is handled separately via WINxxxSRC)
 GENCSRC = monstr.c vis_tab.c   #tile.c
@@ -357,12 +423,12 @@ GENCSRC = monstr.c vis_tab.c      #tile.c
 # all windowing-system-dependent .c (for dependencies and such)
 WINCSRC = $(WINTTYSRC) $(WINX11SRC) $(WINGNOMESRC) $(WINGEMSRC)
 # all windowing-system-dependent .cpp (for dependencies and such)
-WINCXXSRC = $(WINQTSRC) $(WINBESRC)
+WINCXXSRC = $(WINQTSRC) $(WINQT4SRC) $(WINBESRC)
 
 # Files for window system chaining.  Requires SYSCF; include via HINTSRC/HINTOBJ
-CHAINSRC=../win/chain/wc_chainin.c ../win/chain/wc_chainout.c \
-       ../win/chain/wc_trace.c
-CHAINOBJ=wc_chainin.o wc_chainout.o wc_trace.o
+CHAINSRC = ../win/chain/wc_chainin.c ../win/chain/wc_chainout.c \
+          ../win/chain/wc_trace.c
+CHAINOBJ = wc_chainin.o wc_chainout.o wc_trace.o
 
 # .c files for this version (for date.h)
 VERSOURCES = $(HACKCSRC) $(SYSSRC) $(JSRC) $(WINSRC) $(CHAINSRC) $(GENCSRC)
@@ -381,9 +447,9 @@ HACKINCL = align.h amiconf.h artifact.h artilistj.h attrib.h beconf.h botl.h \
        global.h hack.h lev.h lint.h macconf.h mextra.h mfndpos.h micro.h \
        mkroom.h \
        monattk.h mondata.h monflag.h monst.h monsym.h obj.h objclass.h \
-       os2conf.h patchlevel.h pcconf.h permonst.h prop.h rect.h region.h rm.h \
-       sp_lev.h spell.h sys.h system.h tcap.h timeout.h tosconf.h tradstdc.h \
-       trampoli.h trap.h unixconf.h vision.h vmsconf.h wintty.h \
+       os2conf.h patchlevel.h pcconf.h permonst.h prop.h rect.h region.h \
+       rm.h sp_lev.h spell.h sys.h system.h tcap.h timeout.h tosconf.h \
+       tradstdc.h trampoli.h trap.h unixconf.h vision.h vmsconf.h wintty.h \
        winX.h winprocs.h wintype.h you.h youprop.h
 
 HSOURCES = $(HACKINCL) date.h onames.h pm.h vis_tab.h\
@@ -415,33 +481,33 @@ $(GAME):  $(SYSTEM)
        @echo "$(GAME) is up to date."
 
 Sysunix:       $(HOBJ) Makefile
-       @echo "Loading ..."
-       $(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB) $(LIBS)
+       @echo "Linking $(GAME)."
+       $(AT)$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB) $(LIBS)
        @touch Sysunix
 
 Sys3B2:        $(HOBJ) Makefile
-       @echo "Loading ..."
-       @$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB) -lmalloc
+       @echo "Linking $(GAME)."
+       $(AT)$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB) -lmalloc
        @touch Sys3B2
 
 Sysatt:        $(HOBJ) Makefile
-       @echo "Loading ..."
-       @$(LD) $(LFLAGS) /lib/crt0s.o /lib/shlib.ifile -o $(GAME) $(HOBJ)
+       @echo "Loading $(GAME)."
+       $(AT)$(LD) $(LFLAGS) /lib/crt0s.o /lib/shlib.ifile -o $(GAME) $(HOBJ)
        @touch Sysatt
 
 Systos:        $(HOBJ) Makefile
-       @echo "Loading ..."
-       @$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB)
+       @echo "Linking $(GAME)."
+       $(AT)$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB)
        @touch Systos
 
 SysV-AT:       DUMB.Setup $(HOBJ) Makefile
-       @echo "Loading ..."
-       @$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB)
+       @echo "Linking $(GAME)."
+       $(AT)$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB)
        @touch SysV-AT
 
 SysBe: $(HOBJ) Makefile
-       @echo "Loading ..."
-       @$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB) $(LIBS)
+       @echo "Linking $(GAME)."
+       $(AT)$(LINK) $(LFLAGS) -o $(GAME) $(HOBJ) $(WINLIB) $(LIBS)
        @xres -o $(GAME) ../win/BeOS/nethack.rsrc
        @mimeset -f $(GAME)
        @touch SysBe
@@ -483,7 +549,7 @@ objects.o:
        $(CC) $(CFLAGS) -c objects.c
        @rm -f $(MAKEDEFS)
 
-# Qt windowport meta-object-compiler output
+# Qt windowport meta-object-compiler output
 qt_kde0.moc: ../include/qt_kde0.h
        $(QTDIR)/bin/moc -o qt_kde0.moc ../include/qt_kde0.h
 
@@ -493,23 +559,55 @@ qt_win.moc: ../include/qt_win.h
 qttableview.moc: ../include/qttableview.h
        $(QTDIR)/bin/moc -o qttableview.moc ../include/qttableview.h
 
-$(MAKEDEFS): ../util/makedefs.c  $(CONFIG_H) ../include/permonst.h \
+# Qt 4 windowport meta-object-compiler output
+qt4kde0.moc : ../win/Qt4/qt4kde0.h
+       $(QTDIR)/bin/moc -o qt4kde0.moc ../win/Qt4/qt4kde0.h
+qt4main.moc : ../win/Qt4/qt4main.h
+       $(QTDIR)/bin/moc -o qt4main.moc ../win/Qt4/qt4main.h
+qt4map.moc : ../win/Qt4/qt4map.h
+       $(QTDIR)/bin/moc -o qt4map.moc ../win/Qt4/qt4map.h
+qt4menu.moc : ../win/Qt4/qt4menu.h
+       $(QTDIR)/bin/moc -o qt4menu.moc ../win/Qt4/qt4menu.h
+qt4msg.moc : ../win/Qt4/qt4msg.h
+       $(QTDIR)/bin/moc -o qt4msg.moc ../win/Qt4/qt4msg.h
+qt4plsel.moc : ../win/Qt4/qt4plsel.h
+       $(QTDIR)/bin/moc -o qt4plsel.moc ../win/Qt4/qt4plsel.h
+qt4set.moc : ../win/Qt4/qt4set.h
+       $(QTDIR)/bin/moc -o qt4set.moc ../win/Qt4/qt4set.h
+qt4stat.moc : ../win/Qt4/qt4stat.h
+       $(QTDIR)/bin/moc -o qt4stat.moc ../win/Qt4/qt4stat.h
+qt4xcmd.moc : ../win/Qt4/qt4xcmd.h
+       $(QTDIR)/bin/moc -o qt4xcmd.moc ../win/Qt4/qt4xcmd.h
+qt4yndlg.moc : ../win/Qt4/qt4yndlg.h
+       $(QTDIR)/bin/moc -o qt4yndlg.moc ../win/Qt4/qt4yndlg.h
+
+#      build monst.o and objects.o before executing '$(MAKE) makedefs'
+$(MAKEDEFS): $(FIRSTOBJ) \
+               ../util/makedefs.c $(CONFIG_H) ../include/permonst.h \
                ../include/objclass.h ../include/monsym.h \
                ../include/artilist.h ../include/dungeon.h ../include/obj.h \
                ../include/monst.h ../include/you.h ../include/flag.h \
                ../include/dlb.h ../include/patchlevel.h ../include/qtext.h
-       @( cd ../util ; $(MAKE) makedefs)
-
+       @( cd ../util ; $(MAKE) makedefs )
+
+#      Source files created by 'makedefs' at build time.
+#      Each is given an artificial dependency upon the one before
+#      so that parallel makes will have to build them sequentially.
+#      (More for documentation than effect; 'make' should know not
+#      to try to build $(MAKEDEFS) for bar.h while it is in the
+#      process of building it for foo.h.)
 ../include/onames.h: $(MAKEDEFS)
        @( cd ../util ; $(MAKE) ../include/onames.h )
-../include/pm.h: $(MAKEDEFS)
+../include/pm.h: $(MAKEDEFS) ../include/onames.h
        @( cd ../util ; $(MAKE) ../include/pm.h )
-monstr.c: $(MAKEDEFS)
+monstr.c: $(MAKEDEFS) ../include/pm.h
        @( cd ../util ; $(MAKE) ../src/monstr.c )
-../include/vis_tab.h: $(MAKEDEFS)
+../include/vis_tab.h: $(MAKEDEFS) monstr.c
        @( cd ../util ; $(MAKE) ../include/vis_tab.h )
 # makedefs -z makes both vis_tab.h and vis_tab.c, but writes the .h first
 vis_tab.c: ../include/vis_tab.h
+#      Created at build time for configurations which support tiles,
+#      but not by makedefs so not connected to the others.
 tile.c: ../win/share/tilemap.c $(HACK_H)
        @( cd ../util ; $(MAKE) ../src/tile.c )
 
@@ -521,10 +619,13 @@ tile.c: ../win/share/tilemap.c $(HACK_H)
 #      file far more complex.  Since "hack.h" depends on most of the include
 #      files, we kludge around this by making date.h dependent on hack.h,
 #      even though it doesn't include this file.
+#      Do NOT include ../dat/gitinfo.txt as either a prerequisite or target.
+#      'makedefs -v' processes it when present and ignores it if not.
 #
 #      hack.h depends on makedefs' output, so we know makedefs will be
 #      up to date before being executed
 ../include/date.h:     $(VERSOURCES) $(HACK_H)
+       -$(SHELL) ../sys/unix/gitinfo.sh $(GITINFO) #before 'makedefs -v'
        ../util/makedefs -v
 
 
@@ -554,11 +655,11 @@ spotless: clean
 
 
 depend: ../sys/unix/depend.awk \
-               $(SYSCSRC) $(WINCSRC) $(WINCXXSRC) $(CHAINSRC) $(GENCSRC) \
-               $(HACKCSRC)
+               $(SYSCSRC) $(WINCSRC) $(SYSCXXSRC) $(WINCXXSRC) \
+               $(CHAINSRC) $(GENCSRC) $(HACKCSRC)
        $(AWK) -f ../sys/unix/depend.awk ../include/*.h \
-               $(SYSCSRC) $(WINCSRC) $(WINCXXSRC) $(CHAINSRC) $(GENCSRC) \
-               $(HACKCSRC) >makedep
+               $(SYSCSRC) $(WINCSRC) $(SYSCXXSRC) $(WINCXXSRC) \
+               $(CHAINSRC) $(GENCSRC) $(HACKCSRC) >makedep
        @echo '/^# DO NOT DELETE THIS LINE OR CHANGE ANYTHING BEYOND IT/+2,$$d' >eddep
        @echo '$$r makedep' >>eddep
        @echo 'w' >>eddep
@@ -713,6 +814,8 @@ load_img.o: ../win/gem/load_img.c ../include/load_img.h
 gr_rect.o: ../win/gem/gr_rect.c ../include/gr_rect.h
        $(CC) $(CFLAGS) -c ../win/gem/gr_rect.c
 tile.o: tile.c $(HACK_H)
+cppregex.o: ../sys/share/cppregex.cpp
+       $(CXX) $(CXXFLAGS) -c ../sys/share/cppregex.cpp
 qt_win.o: ../win/Qt/qt_win.cpp $(HACK_H) ../include/func_tab.h \
                ../include/dlb.h ../include/patchlevel.h ../include/tile2x11.h \
                ../include/qt_win.h ../include/qt_clust.h ../include/qt_kde0.h \
@@ -722,6 +825,52 @@ qt_clust.o: ../win/Qt/qt_clust.cpp ../include/qt_clust.h
        $(CXX) $(CXXFLAGS) -c ../win/Qt/qt_clust.cpp
 qttableview.o: ../win/Qt/qttableview.cpp ../include/qttableview.h
        $(CXX) $(CXXFLAGS) -c ../win/Qt/qttableview.cpp
+qt4bind.o : ../win/Qt4/qt4bind.cpp $(HACK_H) ../win/Qt4/qt4bind.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4bind.cpp
+qt4click.o : ../win/Qt4/qt4click.cpp $(HACK_H) ../win/Qt4/qt4click.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4click.cpp
+qt4clust.o : ../win/Qt4/qt4clust.cpp $(HACK_H) ../win/Qt4/qt4clust.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4clust.cpp
+qt4delay.o : ../win/Qt4/qt4delay.cpp $(HACK_H) ../win/Qt4/qt4delay.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4delay.cpp
+qt4glyph.o : ../win/Qt4/qt4glyph.cpp $(HACK_H) ../win/Qt4/qt4glyph.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4glyph.cpp
+qt4icon.o : ../win/Qt4/qt4icon.cpp $(HACK_H) ../win/Qt4/qt4icon.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4icon.cpp
+qt4inv.o : ../win/Qt4/qt4inv.cpp $(HACK_H) ../win/Qt4/qt4inv.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4inv.cpp
+qt4key.o : ../win/Qt4/qt4key.cpp $(HACK_H) ../win/Qt4/qt4key.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4key.cpp
+qt4line.o : ../win/Qt4/qt4line.cpp $(HACK_H) ../win/Qt4/qt4line.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4line.cpp
+qt4main.o : ../win/Qt4/qt4main.cpp $(HACK_H) qt4main.moc ../win/Qt4/qt4main.h qt4kde0.moc
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4main.cpp
+qt4map.o : ../win/Qt4/qt4map.cpp $(HACK_H) qt4map.moc ../win/Qt4/qt4map.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4map.cpp
+qt4menu.o : ../win/Qt4/qt4menu.cpp $(HACK_H) qt4menu.moc ../win/Qt4/qt4menu.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4menu.cpp
+qt4msg.o : ../win/Qt4/qt4msg.cpp $(HACK_H) qt4msg.moc ../win/Qt4/qt4msg.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4msg.cpp
+qt4plsel.o : ../win/Qt4/qt4plsel.cpp $(HACK_H) qt4plsel.moc ../win/Qt4/qt4plsel.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4plsel.cpp
+qt4rip.o : ../win/Qt4/qt4rip.cpp $(HACK_H) ../win/Qt4/qt4rip.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4rip.cpp
+qt4set.o : ../win/Qt4/qt4set.cpp $(HACK_H) qt4set.moc ../win/Qt4/qt4set.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4set.cpp
+qt4stat.o : ../win/Qt4/qt4stat.cpp $(HACK_H) qt4stat.moc ../win/Qt4/qt4stat.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4stat.cpp
+qt4str.o : ../win/Qt4/qt4str.cpp ../win/Qt4/qt4str.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4str.cpp
+qt4streq.o : ../win/Qt4/qt4streq.cpp $(HACK_H) ../win/Qt4/qt4streq.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4streq.cpp
+qt4svsel.o : ../win/Qt4/qt4svsel.cpp $(HACK_H) ../win/Qt4/qt4svsel.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4svsel.cpp
+qt4win.o : ../win/Qt4/qt4win.cpp $(HACK_H) ../win/Qt4/qt4win.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4win.cpp
+qt4xcmd.o : ../win/Qt4/qt4xcmd.cpp $(HACK_H) qt4xcmd.moc ../win/Qt4/qt4xcmd.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4xcmd.cpp
+qt4yndlg.o : ../win/Qt4/qt4yndlg.cpp $(HACK_H) qt4yndlg.moc ../win/Qt4/qt4yndlg.h
+       $(CXX) $(CXXFLAGS) -c ../win/Qt4/qt4yndlg.cpp
 wc_chainin.o: ../win/chain/wc_chainin.c $(HACK_H)
        $(CC) $(CFLAGS) -c ../win/chain/wc_chainin.c
 wc_chainout.o: ../win/chain/wc_chainout.c $(HACK_H)
index 35a2aa0..a46d1b8 100644 (file)
@@ -1,5 +1,7 @@
-#      NetHack Makefile.
-# NetHack 3.6  Makefile.top    $NHDT-Date: 1447844578 2015/11/18 11:02:58 $  $NHDT-Branch: master $:$NHDT-Revision: 1.32 $
+#      NetHack Top-level Makefile.
+# NetHack 3.6  Makefile.top    $NHDT-Date: 1524689449 2018/04/25 20:50:49 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.36 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 # Root of source tree:
 NHSROOT=.
@@ -47,14 +49,14 @@ DIRPERM  = 0755
 
 # per discussion in Install.X11 and Install.Qt
 #VARDATND = 
-# VARDATND = x11tiles NetHack.ad pet_mark.xbm pilemark.xpm
-# VARDATND = x11tiles NetHack.ad pet_mark.xbm pilemark.xpm rip.xpm
+# VARDATND = x11tiles NetHack.ad pet_mark.xbm pilemark.xbm
+# VARDATND = x11tiles NetHack.ad pet_mark.xbm pilemark.xbm rip.xpm
 # for Atari/Gem
 # VARDATND = nh16.img title.img GEM_RSC.RSC rip.img
 # for BeOS
 # VARDATND = beostiles
 # for Gnome
-# VARDATND = x11tiles pet_mark.xbm pilemark.xpm rip.xpm mapbg.xpm
+# VARDATND = x11tiles pet_mark.xbm pilemark.xbm rip.xpm mapbg.xpm
 
 VARDATD = bogusmon data engrave epitaph oracles options quest.dat rumors
 VARDAT = $(VARDATD) $(VARDATND)
@@ -77,7 +79,7 @@ VARDAT = $(VARDATD) $(VARDATND)
 # end of configuration
 #
 
-DATHELP = help hh cmdhelp history opthelp wizhelp
+DATHELP = help hh cmdhelp keyhelp history opthelp wizhelp
 
 SPEC_LEVS = asmodeus.lev baalz.lev bigrm-*.lev castle.lev fakewiz?.lev \
        juiblex.lev knox.lev medusa-?.lev minend-?.lev minefill.lev \
@@ -86,7 +88,7 @@ SPEC_LEVS = asmodeus.lev baalz.lev bigrm-*.lev castle.lev fakewiz?.lev \
        astral.lev air.lev earth.lev fire.lev water.lev
 QUEST_LEVS = ???-goal.lev ???-fil?.lev ???-loca.lev ???-strt.lev
 
-DATNODLB = $(VARDATND) license
+DATNODLB = $(VARDATND) license symbols
 DATDLB = $(DATHELP) dungeon tribute $(SPEC_LEVS) $(QUEST_LEVS) $(VARDATD)
 DAT = $(DATNODLB) $(DATDLB)
 
@@ -187,7 +189,7 @@ check-dlb: options
 
 dlb:
        ( cd util ; $(MAKE) dlb )
-       ( cd dat ; ../util/dlb cf nhdat $(DATDLB) )
+       ( cd dat ; LC_ALL=C ; ../util/dlb cf nhdat $(DATDLB) )
 
 # recover can be used when INSURANCE is defined in include/config.h
 # and the checkpoint option is true
@@ -202,7 +204,6 @@ dofiles:
                -e '}'                                  \
                -e '$$s/.*/nodlb/p' < dat/options` ;    \
        $(MAKE) dofiles-$${target-nodlb}
-       (cd dat ; cp symbols $(INSTDIR) )
        cp src/$(GAME) $(INSTDIR)
        cp util/recover $(INSTDIR)
        -if test -n '$(SHELLDIR)'; then rm -f $(SHELLDIR)/$(GAME); fi
@@ -221,9 +222,6 @@ dofiles:
        if test -n '$(SHELLDIR)'; then \
                $(CHGRP) $(GAMEGRP) $(SHELLDIR)/$(GAME); \
                chmod $(EXEPERM) $(SHELLDIR)/$(GAME); fi
-       -( cd $(INSTDIR) ; $(CHOWN) $(GAMEUID) symbols ; \
-                       $(CHGRP) $(GAMEGRP) symbols ; \
-                       chmod $(FILEPERM) symbols )
 
 dofiles-dlb: check-dlb
        ( cd dat ; cp nhdat $(DATNODLB) $(INSTDIR) )
index d5d3042..9119cef 100644 (file)
@@ -1,5 +1,7 @@
 #      Makefile for NetHack's utility programs.
-# NetHack 3.6  Makefile.utl    $NHDT-Date: 1449386560 2015/12/06 07:22:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.27 $
+# NetHack 3.6  Makefile.utl    $NHDT-Date: 1524689449 2018/04/25 20:50:49 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.35 $
+# Copyright (c) 2018 by Robert Patrick Rankin
+# NetHack may be freely redistributed.  See license for details.
 
 # Root of source tree:
 NHSROOT=..
@@ -95,6 +97,11 @@ NHSROOT=..
 #CFLAGS = -O -I../include
 #LFLAGS =
 
+# we specify C preprocessor flags via CFLAGS; files built with default rules
+# might include $(CPPFLAGS) which could get a value from user's environment;
+# we avoid that by forcing it empty rather than by overriding default rules
+CPPFLAGS =
+
 LIBS =
 
 # If you are cross-compiling, you must use this:
@@ -125,6 +132,31 @@ LEXYYC = lex.yy.c
 #
 # Nothing below this line should have to be changed.
 
+# Verbosity definitions, begin
+ACTUAL_CC := $(CC)
+ACTUAL_CXX := $(CXX)
+ACTUAL_LD := $(LD)
+ACTUAL_LINK := $(LINK)
+
+CC_V0 = @echo "[CC] $<"; $(ACTUAL_CC)
+CC_V = $(CC_V0)
+CC_V1 = $(ACTUAL_CC)
+CC = $(CC_V$(VERBOSEMAKE))
+
+CXX_V0 = @echo "[CXX] $<"; $(ACTUAL_CXX)
+CXX_V = $(CXX_V0)
+CXX_V1 = $(ACTUAL_CXX)
+CXX = $(CXX_V$(VERBOSEMAKE))
+
+LD = $(ACTUAL_LD)
+LINK = $(ACTUAL_LINK)
+
+AT_V0 := @
+AT_V := $(AT_V0)
+AT_V1 :=
+AT = V$(AT_$(VERBOSEMAKE))
+# Verbosity, end
+
 # timestamps for primary header files, matching src/Makefile
 CONFIG_H = ../src/config.h-t
 HACK_H  = ../src/hack.h-t
@@ -227,8 +259,7 @@ lev_main.o:  lev_main.c $(HACK_H) ../include/sp_lev.h ../include/tcap.h \
 # egrep will return failure if it doesn't find anything, but we know there
 # is one "_cplusplus" inside a comment
 lev_lex.o:   lev_lex.c $(HACK_H) ../include/lev_comp.h ../include/sp_lev.h
-       @echo $(CC) -c $(CFLAGS) lev_lex.c
-       @$(CC) -c $(CFLAGS) -DWEIRD_LEX=`egrep -c _cplusplus lev_lex.c` lev_lex.c
+       $(CC) -c $(CFLAGS) -DWEIRD_LEX=`egrep -c _cplusplus lev_lex.c` lev_lex.c
 
 # '$(YACC) -d' generates both $(YTABC) and $(YTABH) in one run
 ../include/lev_comp.h: lev_yacc.c
@@ -242,12 +273,18 @@ lev_yacc.c: lev_comp.y
 
 lev_lex.c: lev_comp.l
        $(LEX) $(FLEXDIST) lev_comp.l
-       sed -e 's#"$(LEXYYC)"#"$@"#' -e 's#  *$$##' $(LEXYYC) > $@ \
+       sed -e 's#"$(LEXYYC)"#"$@"#' -e 's#  *$$##' \
+           -e 's#static void yyunput#void yyunput#' $(LEXYYC) > $@ \
                && rm $(LEXYYC)
 #      note: flex code construction using m4 macros results in some trailing
 #      spaces; <space><space><star> is basic RE substitute for <space><plus>
 #      and we don't bother stripping trailing tabs because that gets messy;
 #      make expands <dollar><dollar> into <dollar> which is RE end-of-line.
+#      flex also creates yyunput() as a static routine, but lev_comp doesn't
+#      use it so compiler complaints can ensue; recent flex versions honor
+#      NO_YY_UNPUT to suppress it, but older ones don't; making it global to
+#      avoid an "unused function" warning is simpler than trying to remove
+#      the whole thing (although full 'lint' may still complain).
 
 # with all of extern.h's functions to complain about, we drown in
 # 'defined but not used' without -u
@@ -265,8 +302,7 @@ dgn_main.o:  dgn_main.c $(CONFIG_H) ../include/dlb.h
 
 # see dgn_comp.l for WEIRD_LEX discussion
 dgn_lex.o:   dgn_lex.c $(CONFIG_H) ../include/dgn_comp.h ../include/dgn_file.h
-       @echo $(CC) -c $(CFLAGS) dgn_lex.c
-       @$(CC) -c $(CFLAGS) -DWEIRD_LEX=`egrep -c _cplusplus dgn_lex.c` dgn_lex.c
+       $(CC) -c $(CFLAGS) -DWEIRD_LEX=`egrep -c _cplusplus dgn_lex.c` dgn_lex.c
 
 # '$(YACC) -d' generates both $(YTABC) and $(YTABH) in one run
 ../include/dgn_comp.h: dgn_yacc.c
@@ -280,7 +316,8 @@ dgn_yacc.c: dgn_comp.y
 
 dgn_lex.c: dgn_comp.l
        $(LEX) $(FLEXDIST) dgn_comp.l
-       sed -e 's#"$(LEXYYC)"#"$@"#' -e 's#  *$$##' $(LEXYYC) > $@ \
+       sed -e 's#"$(LEXYYC)"#"$@"#' -e 's#  *$$##' \
+           -e 's#static void yyunput#void yyunput#' $(LEXYYC) > $@ \
                && rm $(LEXYYC)
 #      note: <space><space><star> is basic RE substitute for <space><plus>
 
@@ -310,7 +347,7 @@ dlb_main.o: dlb_main.c $(CONFIG_H) ../include/dlb.h ../include/date.h
 
 #      dependencies for tile utilities
 #
-TEXT_IO = tiletext.o tiletxt.o $(ONAMING)
+TEXT_IO = tiletext.o tiletxt.o $(OALLOC) $(ONAMING)
 GIFREADERS = gifread.o $(OALLOC)
 PPMWRITERS = ppmwrite.o $(OALLOC)
 
@@ -351,12 +388,12 @@ tilemap: tilemap.o
 tiletext.o: ../win/share/tiletext.c $(CONFIG_H) ../include/tile.h
        $(CC) $(CFLAGS) -c ../win/share/tiletext.c
 tiletxt.c: ./Makefile
-       echo '/* alternate compilation for tilemap.c to create tiletxt.o' > tiletxt.c
-       echo '   that does not rely on "cc -c -o tiletxt.o tilemap.c"'   >> tiletxt.c
-       echo '   since many pre-POSIX compilers did not support that */' >> tiletxt.c
+       @echo '/* alternate compilation for tilemap.c to create tiletxt.o' > tiletxt.c
+       @echo '   that does not rely on "cc -c -o tiletxt.o tilemap.c"'  >> tiletxt.c
+       @echo '   since many pre-POSIX compilers did not support that */' >> tiletxt.c
        echo '#define TILETEXT'                  >> tiletxt.c
        echo '#include "../win/share/tilemap.c"' >> tiletxt.c
-       echo '/*tiletxt.c*/'                     >> tiletxt.c
+       @echo '/*tiletxt.c*/'                    >> tiletxt.c
 tiletxt.o: tiletxt.c ../win/share/tilemap.c $(HACK_H)
        $(CC) $(CFLAGS) -c tiletxt.c
 tilemap.o: ../win/share/tilemap.c $(HACK_H)
@@ -413,7 +450,7 @@ $(OBJDIR)/monst.o: ../src/monst.c $(CONFIG_H)
        $(CC) $(CFLAGS) -c ../src/monst.c -o $@
 $(OBJDIR)/objects.o: ../src/objects.c $(CONFIG_H)
        $(CC) $(CFLAGS) -c ../src/objects.c -o $@
-$(OBJDIR)/dlb.o: ../src/dlb.c $(HACK_H) ../include/dlb.h
+$(OBJDIR)/dlb.o: ../src/dlb.c $(CONFIG_H) ../include/dlb.h
        $(CC) $(CFLAGS) -c ../src/dlb.c -o $@
 
 # make sure hack.h dependencies get transitive information
@@ -453,4 +490,4 @@ spotless: clean
        -rm -f ../include/tile.h tiletxt.c
        -rm -f makedefs lev_comp dgn_comp recover dlb
        -rm -f gif2txt txt2ppm tile2x11 tile2img.ttp xpm2img.ttp \
-               tilemap tileedit
+               tilemap tileedit tile2bmp
index 6fa78a8..b9daf36 100644 (file)
@@ -39,3 +39,7 @@ If you are using the traditional configuration system, see Install.unx.
 
 5. If it all worked, you're done.  If something went wrong, see Install.unx
    for information about the settings the hints file tried to automate.
+
+# NetHack 3.6  NewInstall.unx       $NHDT-Date: 1524689458 2018/04/25 20:50:58 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $
+# Copyright (c) 2009 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
index 0770ab4..01b7926 100644 (file)
@@ -1,6 +1,6 @@
 NetHack 3.6.0 Linux Elf
 
-$NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+$NHDT-Date: 1524684188 2018/04/25 19:23:08 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.22 $
 
 This README provides the instructions for using the official Linux binary,
 system platform requirements, as well as steps used to create that binary.
@@ -22,11 +22,12 @@ preserving permissions to put the NetHack files in /usr/games/nethack and
 home directory you might perform these steps.
     % su
     # cd /
-    # tar xpvzf ~yourlogin/nethack-360-linux-X11.tgz
+    # tar xpvzf ~yourlogin/nethack-361-linux-X11.tgz
 
 If you have old record and logfile entries from a previous NetHack version,
 you might want to save copies before they get overwritten by the new empty
-files; old saved games and bones files from 3.4.x will not work with 3.6.0.
+files; old saved games and bones files from 3.6.0 should work with 3.6.1
+but even older saved games and bones files from 3.4.3 will not.
 If you are installing from the RPM, there is no need to save the old record
 and logfile; they are automatically preserved.
 
index 2220754..8361bec 100644 (file)
@@ -1,6 +1,6 @@
 # depend.awk -- awk script used to construct makefile dependencies
 # for nethack's source files (`make depend' support for Makefile.src).
-# $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# $NHDT-Date: 1524684206 2018/04/25 19:23:26 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.6 $
 #
 # usage:
 #   cd src ; nawk -f depend.awk ../include/*.h list-of-.c/.cpp-files
diff --git a/sys/unix/gitinfo.sh b/sys/unix/gitinfo.sh
new file mode 100644 (file)
index 0000000..9ab309f
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+# NetHack 3.6  gitinfo.sh      $NHDT-Date: 1524689450 2018/04/25 20:50:50 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $
+# Copyright (c) 2018 by Robert Patrick Rankin
+# NetHack may be freely redistributed.  See license for details.
+
+# bring dat/gitinfo.txt up to date; called from Makefile.src
+
+#
+# gitinfo.txt is used during development to augment the version number
+# (for nethack's 'v' command) with more specific information.  That is not
+# necessary when building a released version and it is perfectly OK for
+# this script to be skipped or to run but fail to generate dat/gitinfo.txt.
+#
+
+# try to figure out where we are: top, one level down (expected), or sys/unix
+prefix=.
+if [ -f ../sys/unix/gitinfo.sh ]; then prefix=..; fi
+if [ -f ../../sys/unix/gitinfo.sh ]; then prefix=../..; fi
+
+rungit=0
+if [ $1 -eq 1 ]; then rungit=1; fi
+if [ $1 = "force" ]; then rungit=1; fi
+if [ ! -f $prefix/dat/gitinfo.txt ]; then rungit=1; fi
+
+# try to run a perl script which is part of nethack's git repository
+if [ $rungit -eq 1 ]; then
+  ( cd $prefix; \
+    perl -IDEVEL/hooksdir -MNHgithook -e '&NHgithook::nhversioning' \
+      2> /dev/null ) \
+  || true
+fi
+exit 0
index a9b612e..4dc6b2f 100644 (file)
@@ -20,10 +20,13 @@ VARDIR = $(HACKDIR)
 
 POSTINSTALL=cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
 
-CFLAGS=-g -O -I../include -DNOTPARMDECL $(CFLAGS1) -DDLB
-CFLAGS1=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
+CFLAGS=-g -O -I../include -DNOTPARMDECL -DDLB
+CFLAGS+=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
 CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
+CFLAGS+=-DTIMED_DELAY
 CFLAGS+=-DHACKDIR=\"$(HACKDIR)\"
+CFLAGS+=-DDUMPLOG
+CFLAGS+=-DCONFIG_ERROR_SECURE=FALSE
 
 LINK=$(CC)
 # Only needed for GLIBC stack trace:
index d8af975..eb4fc27 100644 (file)
@@ -1,5 +1,5 @@
 #
-# NetHack 3.5  linux $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# NetHack 3.5  linux $NHDT-Date: 1524684267 2018/04/25 19:24:27 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.1 $
 # NetHack 3.5  linux $Date: 2010/01/15 19:54:37 $  $Revision: 1.8 $
 # Copyright (c) Kenneth Lorber, Kensington, Maryland, 2007.
 # NetHack may be freely redistributed.  See license for details. 
@@ -27,6 +27,7 @@ POSTINSTALL=cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INS
 CFLAGS1=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
 CFLAGS=-g -O -I../include -DNOTPARMDECL $(CFLAGS1) -DDLB
 CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
+CFLAGS+=-DTIMED_DELAY
 CFLAGS+=-DHACKDIR=\"$(HACKDIR)\"
 CFLAGS+=-DVAR_PLAYGROUND=\"$(HACKDIR)/var\"
 
diff --git a/sys/unix/hints/linux-qt4 b/sys/unix/hints/linux-qt4
new file mode 100644 (file)
index 0000000..34c8863
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# NetHack 3.6  linux-qt4 $NHDT-Date: 1432512814 2015/05/25 00:13:34 $  $NHDT-Branch: master $:$NHDT-Revision: 1.12 $
+# Copyright (c) Kenneth Lorber, Kensington, Maryland, 2007.
+# NetHack may be freely redistributed.  See license for details.
+#
+#-PRE
+# Linux hints file
+# This hints file provides a single-user Qt4 build for Linux, specifically
+# for Ubuntu dapper.
+
+
+#PREFIX=/usr
+PREFIX=$(wildcard ~)/nh/install
+HACKDIR=$(PREFIX)/games/lib/$(GAME)dir
+SHELLDIR = $(PREFIX)/games
+INSTDIR=$(HACKDIR)
+VARDIR = $(HACKDIR)
+
+
+POSTINSTALL= cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
+POSTINSTALL+= bdftopcf win/X11/nh10.bdf > $(INSTDIR)/nh10.pcf; (cd $(INSTDIR); mkfontdir);
+
+CFLAGS=-g -O -I../include -DNOTPARMDECL
+CFLAGS+=-DHACKDIR=\"$(HACKDIR)\"
+CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\"
+CFLAGS+=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
+CFLAGS+=-DTIMED_DELAY
+CFLAGS+=-DDUMPLOG
+CFLAGS+=-DCONFIG_ERROR_SECURE=FALSE
+CFLAGS+=-DQT_GRAPHICS -DDEFAULT_WINDOW_SYS=\"Qt\" -DNOTTYGRAPHICS
+CFLAGS+=`pkg-config QtGui --cflags`
+
+LINK=g++
+CXX=g++
+
+WINSRC = $(WINQT4SRC)
+WINOBJ = $(WINQT4OBJ)
+WINLIB = $(WINQT4LIB)
+
+VARDATND = nhtiles.bmp rip.xpm nhsplash.xpm pet_mark.xbm pilemark.xbm
+
+QTDIR=/usr
+
+CHOWN=true
+CHGRP=true
+VARDIRPERM = 0755
+VARFILEPERM = 0600
+GAMEPERM = 0755
+
+# note: needs libxt-dev libxaw7-dev libx11-dev bdftopcf
index 821d53b..ff865c8 100644 (file)
@@ -20,10 +20,12 @@ VARDIR = $(HACKDIR)
 POSTINSTALL= cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
 POSTINSTALL+= bdftopcf win/X11/nh10.bdf > $(INSTDIR)/nh10.pcf; (cd $(INSTDIR); mkfontdir);
 
-CFLAGS=-O -I../include -DNOTPARMDECL $(CFLAGS1) $(CFLAGS3)
+CFLAGS=-g -O -I../include -DNOTPARMDECL
 CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\"
-CFLAGS1=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
-CFLAGS3=-DX11_GRAPHICS -DDEFAULT_WINDOW_SYS=\"X11\" -DNOTTYGRAPHICS -DXI18N -DUSE_XPM -DX11LARGETILE -DINSTALLCOLORMAP
+CFLAGS+=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
+CFLAGS+=-DX11_GRAPHICS -DDEFAULT_WINDOW_SYS=\"X11\" -DNOTTYGRAPHICS  -DXI18N -DUSE_XPM -DX11LARGETILE -DINSTALLCOLORMAP
+CFLAGS+=-DDUMPLOG
+CFLAGS+=-DCONFIG_ERROR_SECURE=FALSE
 
 LINK=$(CC)
 
index 753c9b6..c6cf10c 100644 (file)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# NetHack 3.6  macosx.sh $NHDT-Date: 1432512814 2015/05/25 00:13:34 $  $NHDT-Branch: master $:$NHDT-Revision: 1.11 $
+# NetHack 3.6  macosx.sh $NHDT-Date: 1517231957 2018/01/29 13:19:17 $  $NHDT-Branch: githash $:$NHDT-Revision: 1.20 $
 # Copyright (c) Kenneth Lorber, Kensington, Maryland, 2007.
 # NetHack may be freely redistributed.  See license for details.
 #
@@ -91,6 +91,45 @@ xgroup2)
        fi
        ;;
 
+xeditsysconf)
+       src=$2
+       dest=$3
+       ptg=1
+       # We don't need an LLDB module because any MacOSX new enough to
+       # have no Apple supported gdb is also new enough to get good
+       # stack traces through libc.
+       # NB: xcrun will check $PATH
+       if [[ -x /usr/bin/xcrun && `/usr/bin/xcrun -f gdb 2>/dev/null` ]] ; then
+            gdbpath="GDBPATH="`/usr/bin/xcrun -f gdb`
+       elif [ -f /usr/bin/gdb ]; then
+           gdbpath='GDBPATH=/usr/bin/gdb' #traditional location
+       elif [ -f /opt/local/bin/ggdb ]; then
+           gdbpath='GDBPATH=/opt/local/bin/ggdb' #macports gdb
+       elif [ -f /Developer/usr/bin/gdb ]; then
+           # this one seems to be broken with Xcode 5.1.1 on Mountain Lion
+           gdbpath='GDBPATH=/Developer/usr/bin/gdb' #older Xcode tools
+       else
+           gdbpath='#GDBPATH' #none of the above
+           ptg=0
+       fi
+       if [ -f /bin/grep ]; then
+           greppath='GREPPATH=/bin/grep'
+       elif [ -f /usr/bin/grep ]; then
+           greppath='GREPPATH=/usr/bin/grep'
+       else
+           greppath='#GREPPATH'
+       fi
+       # PANICTRACE_GDB value should only be replaced if gdbpath is '#GDBPATH'
+       if ! [ -e $dest ]; then
+               sed -e "s:^GDBPATH=.*:$gdbpath:" \
+                   -e "s:^GREPPATH=.*:$greppath:" \
+                   -e "s/^PANICTRACE_GDB=./PANICTRACE_GDB=$ptg/" \
+                   -e 's/^#OPTIONS=.*/&\
+OPTIONS=!use_darkgray/' \
+                   $src > $dest
+       fi
+       ;;
+
 #% dscl localhost -read /Search/Groups/wheel
 # AppleMetaNodeLocation: /Local/Default
 # GeneratedUID: ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000000
index 683284c..f320e25 100644 (file)
@@ -1,15 +1,19 @@
 #
-# NetHack 3.6  macosx10.11 $NHDT-Date: 1445622451 2015/10/23 17:47:31 $  $NHDT-Branch: master $:$NHDT-Revision: 1.0 $
+# NetHack 3.6  macosx10.11 $NHDT-Date: 1515549543 2018/01/10 01:59:03 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $
 # Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015.
 # NetHack may be freely redistributed.  See license for details.
 #
 #-PRE
 # Mac OS X (Darwin) hints file
-# This is for Mac OS X 10.10 or later.  If this doesn't work for some other
+# This is for Mac OS X 10.10 or later, and has been tested on 10.11
+# (El Capitan). If this doesn't work for some other
 # version of Mac OS X, make a new file for that OS, don't change this one.
 # And let us know about it.
 # Useful info: http://www.opensource.apple.com/darwinsource/index.html
 
+# You'll need to obtain and install XQuartz if you want X11 support.
+# (Attempting to run X11.app will describe where to get it.)
+
 # This hints file can build several different types of installations.
 # Edit the next section to match the type of build you need.
 
@@ -100,6 +104,8 @@ LFLAGS=-L/opt/X11/lib
 VARDATND = x11tiles NetHack.ad pet_mark.xbm pilemark.xbm
 POSTINSTALL+= bdftopcf win/X11/nh10.bdf > $(HACKDIR)/nh10.pcf; (cd $(HACKDIR); mkfontdir);
 CFLAGS += -DX11_GRAPHICS -I/opt/X11/include
+# avoid repeated complaints about _X_NONNULL(args...) in <X11/Xfuncproto.h>
+CFLAGS += -Wno-variadic-macros
 endif  # WANT_WIN_X11
 
 ifdef WANT_WIN_QT
@@ -154,7 +160,7 @@ ROOTCHECK= [[ `id -u` == 0 ]] || ( echo "Must run install with sudo."; exit 1)
 # XXX it's nice we don't write over sysconf, but we've already erased it
 # make sure we have group GAMEUID and group GAMEGRP
 PREINSTALL= . sys/unix/hints/macosx.sh user2 $(GAMEUID); . sys/unix/hints/macosx.sh group2 $(GAMEGRP); mkdir $(SHELLDIR); chown $(GAMEUID) $(SHELLDIR)
-POSTINSTALL+= cp -n sys/unix/sysconf $(HACKDIR)/sysconf; $(CHOWN) $(GAMEUID) $(HACKDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(HACKDIR)/sysconf; chmod $(VARFILEPERM) $(HACKDIR)/sysconf;
+POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(HACKDIR)/sysconf; $(CHOWN) $(GAMEUID) $(HACKDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(HACKDIR)/sysconf; chmod $(VARFILEPERM) $(HACKDIR)/sysconf;
 CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
 else ifdef WANT_SOURCE_INSTALL
 PREFIX=$(abspath $(NHSROOT))
@@ -166,6 +172,7 @@ CHGRP=/usr/bin/true
 GAMEPERM = 0700
 VARFILEPERM = 0600
 VARDIRPERM = 0700
+POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(HACKDIR)/sysconf;
 # We can use "make all" to build the whole thing - but it misses some things:
 MOREALL=$(MAKE) install
 CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
@@ -182,7 +189,7 @@ ifdef WANT_WIN_X11
 # install nethack.rc as ~/.nethackrc if no ~/.nethackrc exists
 PREINSTALL= cp -n win/X11/nethack.rc ~/.nethackrc
 endif  # WANT_WIN_X11
-POSTINSTALL+= cp -n sys/unix/sysconf $(HACKDIR)/sysconf; $(CHOWN) $(GAMEUID) $(HACKDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(HACKDIR)/sysconf; chmod $(VARFILEPERM) $(HACKDIR)/sysconf;
+POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(HACKDIR)/sysconf; $(CHOWN) $(GAMEUID) $(HACKDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(HACKDIR)/sysconf; chmod $(VARFILEPERM) $(HACKDIR)/sysconf;
 CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
 endif  # !WANT_SOURCE_INSTALL
 
@@ -265,7 +272,7 @@ build_package_root:
        install -p doc/recover.6 $(PKGROOT_UG)/man/man6
        install -p doc/Guidebook $(PKGROOT_UG)/doc
        install -p dat/nhdat $(PKGROOT_UGLN)
-       sed 's/^GDBPATH/#GDBPATH/' sys/unix/sysconf | sed 's/^GREPPATH=\/bin\/grep/GREPPATH=\/usr\/bin\/grep/' | sed 's/^PANICTRACE_GDB=[12]/PANICTRACE_GDB=0/' > $(PKGROOT_UGLN)/sysconf
+       sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(PKGROOT_UGLN)/sysconf
        cd dat; install -p $(DATNODLB) ../$(PKGROOT_UGLN)
 # XXX these files should be somewhere else for good Mac form
        touch $(PKGROOT_UGLN)/perm $(PKGROOT_UGLN)/record $(PKGROOT_UGLN)/logfile $(PKGROOT_UGLN)/xlogfile
@@ -274,6 +281,7 @@ build_package_root:
 
        mkdir -p PKGSCRIPTS
        echo '#!/bin/sh'                              >  PKGSCRIPTS/postinstall
+       echo dseditgroup -o create -r '"Games Group"' -s 3600 $(GAMEGRP) >> PKGSCRIPTS/postinstall
        echo $(CHOWN) -R $(GAMEUID) $(HACKDIR)        >> PKGSCRIPTS/postinstall
        echo $(CHGRP) -R $(GAMEGRP) $(HACKDIR)        >> PKGSCRIPTS/postinstall
        echo $(CHOWN) $(GAMEUID) $(SHELLDIR)/nethack  >> PKGSCRIPTS/postinstall
@@ -282,7 +290,9 @@ build_package_root:
        echo $(CHGRP) $(GAMEGRP) $(SHELLDIR)/recover  >> PKGSCRIPTS/postinstall
        echo chmod $(VARDIRPERM)  $(HACKDIR)          >> PKGSCRIPTS/postinstall
        echo chmod $(VARDIRPERM)  $(HACKDIR)/save     >> PKGSCRIPTS/postinstall
+       echo chmod $(FILEPERM)    $(HACKDIR)/license  >> PKGSCRIPTS/postinstall
        echo chmod $(FILEPERM)    $(HACKDIR)/nhdat    >> PKGSCRIPTS/postinstall
+       echo chmod $(FILEPERM)    $(HACKDIR)/symbols  >> PKGSCRIPTS/postinstall
        echo chmod $(VARFILEPERM) $(HACKDIR)/perm     >> PKGSCRIPTS/postinstall
        echo chmod $(VARFILEPERM) $(HACKDIR)/record   >> PKGSCRIPTS/postinstall
        echo chmod $(VARFILEPERM) $(HACKDIR)/logfile  >> PKGSCRIPTS/postinstall
index 0ee5d7b..d876496 100644 (file)
@@ -141,7 +141,7 @@ ROOTCHECK= [[ `id -u` == 0 ]] || ( echo "Must run install with sudo."; exit 1)
 # XXX it's nice we don't write over sysconf, but we've already erased it
 # make sure we have group GAMEUID and group GAMEGRP
 PREINSTALL= . sys/unix/hints/macosx.sh user2 $(GAMEUID); . sys/unix/hints/macosx.sh group2 $(GAMEGRP); mkdir $(SHELLDIR); chown $(GAMEUID) $(SHELLDIR)
-POSTINSTALL+= cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
+POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
 CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
 else ifdef WANT_SOURCE_INSTALL
 PREFIX=$(abspath $(NHSROOT))
@@ -172,7 +172,7 @@ ifdef WANT_WIN_X11
 # install nethack.rc as ~/.nethackrc if no ~/.nethackrc exists
 PREINSTALL= cp -n win/X11/nethack.rc ~/.nethackrc
 endif  # WANT_WIN_X11
-POSTINSTALL+= cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
+POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
 CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
 endif  # !WANT_SOURCE_INSTALL
 
index f314c9a..707c67d 100644 (file)
@@ -158,7 +158,7 @@ ROOTCHECK= [[ `id -u` == 0 ]] || ( echo "Must run install with sudo."; exit 1)
 # XXX it's nice we don't write over sysconf, but we've already erased it
 # make sure we have group GAMEUID and group GAMEGRP
 PREINSTALL= . sys/unix/hints/macosx.sh user2 $(GAMEUID); . sys/unix/hints/macosx.sh group2 $(GAMEGRP); mkdir $(SHELLDIR); chown $(GAMEUID) $(SHELLDIR)
-POSTINSTALL+= cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
+POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
 CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
 else ifdef WANT_SOURCE_INSTALL
 PREFIX=$(abspath $(NHSROOT))
@@ -190,7 +190,7 @@ ifdef WANT_WIN_X11
 # install nethack.rc as ~/.nethackrc if no ~/.nethackrc exists
 PREINSTALL= cp -n win/X11/nethack.rc ~/.nethackrc
 endif  # WANT_WIN_X11
-POSTINSTALL+= cp -n sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
+POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
 CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
 endif  # !WANT_SOURCE_INSTALL
 
diff --git a/sys/unix/hints/macosx10.8 b/sys/unix/hints/macosx10.8
new file mode 100644 (file)
index 0000000..d2c5034
--- /dev/null
@@ -0,0 +1,327 @@
+#
+# NetHack 3.6  macosx10.8 $NHDT-Date: 1455397109 2016/02/13 20:58:29 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.0 $
+# Copyright (c) Kenneth Lorber, Kensington, Maryland, 2009.
+# NetHack may be freely redistributed.  See license for details.
+#
+#-PRE
+# Mac OS X (Darwin) hints file
+# This is for Mac OS X 10.8, Mountain Lion.
+#
+# X11 is no longer included with OSX.
+# To regain X11, download and install XQuartz.  (Attempting to run X11.app
+# will describe how.)  Xcode (not related to X11) has also changed since
+# earlier versions and some tools are no longer in their previous locations.
+#
+# If this doesn't work for some other version
+# of Mac OS X, make a new file for that OS, don't change this one.  And
+# let us know about it.
+# Useful info: http://www.opensource.apple.com/darwinsource/index.html
+
+# This hints file can build several different types of installations.
+# Edit the next section to match the type of build you need.
+
+# 1. Which window system(s) should be included in this binary?
+WANT_WIN_TTY=1
+#WANT_WIN_X11=1
+#WANT_WIN_QT=1
+
+# 1a. What is the default window system?
+WANT_DEFAULT=tty
+#WANT_DEFAULT=x11
+#WANT_DEFAULT=qt
+
+# 1b. If you set WANT_WIN_QT, you need to
+#  A) set QTDIR either here or in the environment to point to the Qt2 or Qt3
+#     library installation root.  (Qt4 will not work; Qt3 does not presently
+#     compile under Leopard (MacOSX 10.5) out-of-the-box.)
+#  B) set XPMLIB to point to the Xpm library
+ifdef WANT_WIN_QT
+QTDIR=/Developer/Qt
+LIBXPM= -L/opt/X11/lib -lXpm
+endif  # WANT_WIN_QT
+
+# 2. Is this a build for a binary that will be shared among different users
+#    or will it be private to you?
+#    If it is shared:
+#      - it will be owned by the user and group listed
+#      - if the user does not exist, you MUST create it before installing
+#        NetHack
+#      - if the group does not exist, it will be created.
+#        NB: if the group already exists and is being used for something
+#         besides games, you probably want to specify a new group instead
+#        NB: the group will be created locally; if your computer is centrally
+#         administered this may not be what you (or your admin) want.
+#         Consider a non-shared install (WANT_SHARE_INSTALL=0) instead.
+#      - 'make install' must be run as "sudo make install"
+#WANT_SHARE_INSTALL=1
+GAMEUID  = $(USER)
+GAMEGRP  = games
+# build to run in the source tree - primarily for development.  Build with "make all"
+#WANT_SOURCE_INSTALL=1
+
+CC=gcc
+
+# At the moment this is just for debugging, but in the future it could be
+# useful for other things.  Requires SYSCF and an ANSI compiler.
+#WANT_WIN_CHAIN=1
+
+#
+# You shouldn't need to change anything below here.
+#
+
+#CFLAGS+=-W -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wcast-qual -Wwrite-strings -DGCC_WARN
+CFLAGS+=-Wall -Wextra -Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wwrite-strings -DGCC_WARN -ansi -pedantic
+# As of LLVM build 2336.1.00, this gives dozens of spurious messages, so
+# leave it out by default.
+#CFLAGS+=-Wunreachable-code
+
+# XXX -g vs -O should go here, -I../include goes in the makefile
+CFLAGS+=-g -I../include
+# older binaries use NOCLIPPING, but that disables SIGWINCH
+#CFLAGS+=-DNOCLIPPING
+CFLAGS+= -DNOMAIL -DNOTPARMDECL -DHACKDIR=\"$(HACKDIR)\"
+CFLAGS+= -DDEFAULT_WINDOW_SYS=\"$(WANT_DEFAULT)\" -DDLB
+
+CFLAGS+= -DGREPPATH=\"/usr/bin/grep\"
+CFLAGS+= -DGDBPATH=\"/Developer/usr/bin/gdb\"
+
+ifdef WANT_WIN_CHAIN
+CFLAGS+= -DWINCHAIN
+HINTSRC=$(CHAINSRC)
+HINTOBJ=$(CHAINOBJ)
+endif
+
+ifdef WANT_WIN_TTY
+WINSRC = $(WINTTYSRC)
+WINOBJ = $(WINTTYOBJ)
+WINLIB = $(WINTTYLIB)
+WINTTYLIB=-lncurses
+else   # !WANT_WIN_TTY
+CFLAGS += -DNOTTYGRAPHICS
+endif  # !WANT_WIN_TTY
+
+ifdef WANT_WIN_X11
+WINSRC += $(WINX11SRC)
+WINOBJ += $(WINX11OBJ)
+WINLIB += $(WINX11LIB)
+LFLAGS=-L/opt/X11/lib
+VARDATND = x11tiles NetHack.ad pet_mark.xbm pilemark.xbm
+POSTINSTALL+= bdftopcf win/X11/nh10.bdf > $(INSTDIR)/nh10.pcf; (cd $(INSTDIR); mkfontdir);
+CFLAGS += -DX11_GRAPHICS -I/opt/X11/include
+# avoid repeated complaints about _X_NONNULL(args...) in <X11/Xfuncproto.h>
+CFLAGS += -Wno-variadic-macros
+endif  # WANT_WIN_X11
+
+ifdef WANT_WIN_QT
+CFLAGS += -DQT_GRAPHICS -DNOUSER_SOUNDS
+CFLAGS += -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4
+LINK=g++
+WINSRC += $(WINQTSRC)
+WINLIB += $(WINQTLIB) $(LIBXPM)
+WINLIB += -framework Carbon -framework QuickTime -lz -framework OpenGL
+WINLIB += -framework AGL
+ifdef WANT_WIN_X11
+       # prevent duplicate tile.o in WINOBJ
+WINOBJ = $(sort $(WINQTOBJ) $(WINX11OBJ))
+ifdef WANT_WIN_TTY
+WINOBJ += $(WINTTYOBJ)
+endif  # WANT_WIN_TTY
+else   # !WANT_WIN_X11
+WINOBJ += $(WINQTOBJ)
+endif  # !WANT_WIN_X11
+
+# XXX if /Developer/qt exists and QTDIR not set, use that
+ifndef QTDIR
+$(error QTDIR not defined in the environment or Makefile)
+endif  # QTDIR
+# XXX make sure QTDIR points to something reasonable
+else   # !WANT_WIN_QT
+LINK=$(CC)
+endif  # !WANT_WIN_QT
+
+ifdef WANT_SHARE_INSTALL
+# if $GAMEUID is root, we install into roughly proper Mac locations, otherwise
+# we install into ~/nethackdir
+ifeq ($(GAMEUID),root)
+PREFIX:=/Library/NetHack
+SHELLDIR=/usr/local/bin
+HACKDIR=$(PREFIX)/nethackdir
+INSTDIR=$(HACKDIR)
+VARDIR=$(HACKDIR)
+CHOWN=chown
+CHGRP=chgrp
+# We run sgid so the game has access to both HACKDIR and user preferences.
+GAMEPERM = 02755
+else   # ! root
+PREFIX:=/Users/$(GAMEUID)
+SHELLDIR=$(PREFIX)/bin
+HACKDIR=$(PREFIX)/nethackdir
+INSTDIR=$(HACKDIR)
+VARDIR=$(HACKDIR)
+CHOWN=/usr/bin/true
+CHGRP=/usr/bin/true
+GAMEPERM = 0500
+endif  # ! root
+VARFILEPERM = 0664
+VARDIRPERM = 0775
+ROOTCHECK= [[ `id -u` == 0 ]] || ( echo "Must run install with sudo."; exit 1)
+# XXX it's nice we don't write over sysconf, but we've already erased it
+# make sure we have group GAMEUID and group GAMEGRP
+PREINSTALL= . sys/unix/hints/macosx.sh user2 $(GAMEUID); . sys/unix/hints/macosx.sh group2 $(GAMEGRP); mkdir $(SHELLDIR); chown $(GAMEUID) $(SHELLDIR)
+POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
+CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
+else ifdef WANT_SOURCE_INSTALL
+PREFIX=$(abspath $(NHSROOT))
+# suppress nethack.sh
+#SHELLDIR=
+HACKDIR=$(PREFIX)/playground
+INSTDIR=$(HACKDIR)
+VARDIR=$(HACKDIR)
+CHOWN=/usr/bin/true
+CHGRP=/usr/bin/true
+GAMEPERM = 0700
+VARFILEPERM = 0600
+VARDIRPERM = 0700
+# We can use "make all" to build the whole thing - but it misses some things:
+MOREALL=$(MAKE) install
+CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
+else   # !WANT_SOURCE_INSTALL
+PREFIX:=$(wildcard ~)
+SHELLDIR=$(PREFIX)/bin
+HACKDIR=$(PREFIX)/nethackdir
+INSTDIR=$(HACKDIR)
+VARDIR=$(HACKDIR)
+CHOWN=/usr/bin/true
+CHGRP=/usr/bin/true
+GAMEPERM = 0700
+VARFILEPERM = 0600
+VARDIRPERM = 0700
+ifdef WANT_WIN_X11
+# install nethack.rc as ~/.nethackrc if no ~/.nethackrc exists
+PREINSTALL= cp -n win/X11/nethack.rc ~/.nethackrc
+endif  # WANT_WIN_X11
+POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(INSTDIR)/sysconf; $(CHOWN) $(GAMEUID) $(INSTDIR)/sysconf; $(CHGRP) $(GAMEGRP) $(INSTDIR)/sysconf; chmod $(VARFILEPERM) $(INSTDIR)/sysconf;
+CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
+endif  # !WANT_SOURCE_INSTALL
+
+
+# ~/Library/Preferences/NetHack Defaults
+# OPTIONS=name:player,number_pad,menustyle:partial,!time,showexp
+# OPTIONS=hilite_pet,toptenwin,msghistory:200,windowtype:Qt
+#
+# Install.Qt mentions a patch for macos - it's not there (it seems to be in the Qt binary
+# package under the docs directory).
+
+#-POST
+ifdef MAKEFILE_TOP
+###
+### Packaging
+###
+# Notes:
+# 1) The Apple developer utilities must be installed in the default location.
+# 2) Do a normal build before trying to package the game.
+# 3) This matches the 3.4.3 Term package, but there are some things that should
+#    be changed.
+
+ifdef WANT_WIN_TTY
+DEVUTIL=/Developer/Applications/Utilities
+PKGR=$(DEVUTIL)/PackageMaker.app/Contents/MacOS/PackageMaker
+SVS=$(shell $(NHSROOT)/util/makedefs --svs)
+SVSDOT=$(shell $(NHSROOT)/util/makedefs --svs .)
+
+PKGROOT_UG     = PKGROOT/usr/games
+PKGROOT_UGLN   = PKGROOT/usr/games/lib/nethackdir
+build_tty_pkg:
+ifneq (,$(WANT_WIN_X11)$(WANT_WIN_QT))
+       -echo build_tty_pkg only works for a tty-only build
+       exit 1
+else
+       rm -rf NetHack-$(SVS)-mac-Term.pkg NetHack-$(SVS)-mac-Term.dmg
+       $(MAKE) build_package_root
+       rm -rf RESOURCES
+       mkdir RESOURCES
+       #enscript --language=rtf -o - < dat/license >RESOURCES/License.rtf
+       sys/unix/hints/macosx.sh descplist > RESOURCES/Description.plist
+       sys/unix/hints/macosx.sh infoplist > Info.plist
+
+       mkdir PKGROOT/Applications
+       #osacompile -o NetHackQt/NetHackQt.app/nethackdir/NetHackRecover.app \
+       #        win/macosx/NetHackRecover.applescript
+       #cp win/macosx/recover.pl NetHackQt/NetHackQt.app/nethackdir
+       osacompile -o PKGROOT/Applications/NetHackRecover.app \
+                win/macosx/NetHackRecover.applescript
+       cp win/macosx/recover.pl $(PKGROOT_UGLN)
+
+       osacompile -o PKGROOT/Applications/NetHackTerm.app \
+                win/macosx/NetHackTerm.applescript
+
+       # XXX integrate into Makefile.doc
+       (cd doc; cat Guidebook.mn | ../util/makedefs --grep --input - --output - \
+       | tbl tmac.n - | groff |ps2pdf - > Guidebook.pdf)
+       cp doc/Guidebook.pdf $(PKGROOT_UG)/doc/NetHackGuidebook.pdf
+
+       osacompile -o PKGROOT/Applications/NetHackGuidebook.app \
+                win/macosx/NetHackGuidebook.applescript
+
+       $(PKGR) --root PKGROOT --info Info.plist -e RESOURCES -v -o NetHack-$(SVS)-mac-Term.pkg
+       hdiutil create -verbose -srcfolder NetHack-$(SVS)-mac-Term.pkg NetHack-$(SVS)-mac-Term.dmg
+
+build_package_root:
+       cd src/..       # make sure we are at TOP
+       rm -rf PKGROOT
+       mkdir -p $(PKGROOT_UG)/lib $(PKGROOT_UG)/bin $(PKGROOT_UG)/man/man6 $(PKGROOT_UG)/doc $(PKGROOT_UGLN)
+       install -p src/nethack $(PKGROOT_UG)/bin
+       # XXX should this be called nethackrecover?
+       install -p util/recover $(PKGROOT_UG)/bin
+       install -p doc/nethack.6 $(PKGROOT_UG)/man/man6
+       install -p doc/recover.6 $(PKGROOT_UG)/man/man6
+       install -p doc/Guidebook $(PKGROOT_UG)/doc
+       install -p dat/nhdat $(PKGROOT_UGLN)
+       cd dat; install -p $(DATNODLB) ../$(PKGROOT_UGLN)
+# XXX these files should be somewhere else for good Mac form
+       touch $(PKGROOT_UGLN)/perm $(PKGROOT_UGLN)/record $(PKGROOT_UGLN)/logfile
+# XXX may need postinstall script to get perms right for sgid, etc.
+       mkdir $(PKGROOT_UGLN)/save
+# XXX what about a news file?
+endif  # end of build_tty_pkg
+endif  # WANT_WIN_TTY for packaging
+
+ifdef WANT_WIN_QT
+# XXX untested and incomplete (see below)
+build_qt_pkg:
+ifneq (,$(WANT_WIN_X11)$(WANT_WIN_TTY))
+       -echo build_qt_pkg only works for a qt-only build
+       exit 1
+else
+       $(MAKE) build_package_root
+       rm -rf NetHackQt
+       mkdir -p NetHackQt/NetHackQt.app/nethackdir/save
+       mkdir NetHackQt/Documentation
+       cp doc/Guidebook.txt doc/nethack.txt doc/recover.txt NetHackQt/Documentation
+
+       osacompile -o NetHackQt/NetHackQt.app/nethackdir/NetHackRecover.app \
+                win/macosx/NetHackRecover.applescript
+       cp win/macosx/recover.pl NetHackQt/NetHackQt.app/nethackdir
+
+       mkdir -p NetHackQt/NetHackQt.app/Contents/Frameworks
+       cp $(QTDIR)/libqt-mt.3.dylib NetHackQt/NetHackQt.app/Contents/Frameworks
+
+       mkdir NetHackQt/NetHackQt.app/Contents/MacOS
+       mv PKGROOT/nethack NetHackQt/NetHackQt.app/Contents/MacOS
+
+       mv PKGROOT/lib/nethackdir NetHackQt/NetHackQt.app/nethackdir
+
+# XXX still missing:
+#NetHackQt/NetHackQt.app
+# /Contents
+#      Info.plist
+#      Resources/nethack.icns
+#NetHackQt/Documentation
+#NetHackQtRecover.txt
+#NetHack Defaults.txt
+#changes.patch XXX is this still needed?  why isn't it part of the tree?
+#  doesn't go here
+       hdiutil create -verbose -srcfolder NetHackQt NetHack-$(SVS)-macosx-qt.dmg
+endif  # end of build_qt_pkg
+endif  # WANT_WIN_QT for packaging
+endif  # MAKEFILE_TOP
index 47d0da8..7ca7486 100644 (file)
@@ -1,11 +1,11 @@
 #!/bin/sh
-# NetHack 3.6  nethack.sh      $NHDT-Date: 1432512789 2015/05/25 00:13:09 $  $NHDT-Branch: master $:$NHDT-Revision: 1.17 $
+# NetHack 3.6  nethack.sh      $NHDT-Date: 1524689450 2018/04/25 20:50:50 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.19 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 
 HACKDIR=/usr/games/lib/nethackdir
 export HACKDIR
 HACK=$HACKDIR/nethack
-# NB: MAXNROFPLAYERS is deprecated in favor of MAXPLAYERS in SYSCF.
-MAXNROFPLAYERS=4
 
 # Since Nethack.ad is installed in HACKDIR, add it to XUSERFILESEARCHPATH
 case "x$XUSERFILESEARCHPATH" in
@@ -65,11 +65,4 @@ fi
 
 
 cd $HACKDIR
-case $1 in
-       -s*)
-               exec $HACK "$@"
-               ;;
-       *)
-               exec $HACK "$@" $MAXNROFPLAYERS
-               ;;
-esac
+exec $HACK "$@"
index f3319ad..5c21026 100644 (file)
@@ -26,6 +26,11 @@ x)      hints=/dev/null
         ;;
 esac
 
+if [ ! -f "$hints" ]; then
+    echo "Cannot find hints file $hfile"
+    exit 1
+fi
+
 /bin/sh ./mkmkfile.sh Makefile.top TOP ../../Makefile $hints $hfile
 /bin/sh ./mkmkfile.sh Makefile.dat DAT ../../dat/Makefile $hints $hfile
 /bin/sh ./mkmkfile.sh Makefile.doc DOC ../../doc/Makefile $hints $hfile
index 83d33d4..6106538 100644 (file)
@@ -1,4 +1,6 @@
-# NetHack 3.6 sysconf $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$
+# NetHack 3.6 sysconf $NHDT-Date: 1524689450 2018/04/25 20:50:50 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.27 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
 #
 # Sample sysconf file.
 # The sysconf file is only used if NetHack is compiled with SYSCF defined.
@@ -30,7 +32,22 @@ EXPLORERS=*
 # Uses the same syntax as the WIZARDS and EXPLORERS options above.
 #SHELLERS=
 
+# If the user name is found in this list, prompt for username instead.
+# Uses the same syntax as the WIZARDS option above.
+# A public server should probably disable this.
+GENERICUSERS=play player game games nethack nethacker
+
+# Use the player name for matching WIZARDS, EXPLORERS and SHELLERS,
+# instead of the user's login name.
+#CHECK_PLNAME=1
+
 # Limit the number of simultaneous games (see also nethack.sh).
+# Valid values are 0-25.
+# Commenting this out or setting the value to 0 constructs lock files
+# with UID and playername, so each user may have one game at a time,
+# but number of different players is not limited.
+# Setting this to any other value constructs the lock files with
+# letter and "lock" (eg. alock, block, ...)
 MAXPLAYERS=10
 
 # If not null, added to string "To get local support, " in the support
@@ -69,6 +86,28 @@ MAXPLAYERS=10
 # overridden via DEBUGFILES environment variable.
 #DEBUGFILES=*
 
+# Save end of game dump log to this file.
+# Only available if NetHack was compiled with DUMPLOG
+# Allows following placeholders:
+#   %% literal '%'
+#   %v version (eg. "3.6.1-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
+#DUMPLOGFILE=/tmp/nethack.%n.%d.log
+
+# Number of bones file pools.
+# The pool you belong to is determined at game start. You will
+# load and save bones only from that pool. Generally useful
+# for public servers only.
+# Changing this might make existing bones inaccessible.
+# Disabled by setting to 0, or commenting out.
+#BONES_POOLS=10
+
 # Try to get more info in case of a program bug or crash.  Only used
 # if the program is built with the PANICTRACE compile-time option enabled.
 # By default PANICTRACE is enabled if BETA is defined, otherwise disabled.
index 365be06..0dde12e 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 unixmain.c      $NHDT-Date: 1432512788 2015/05/25 00:13:08 $  $NHDT-Branch: master $:$NHDT-Revision: 1.52 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* main.c - Unix NetHack */
@@ -59,6 +60,7 @@ char *argv[];
 #endif
     boolean exact_username;
     boolean resuming = FALSE; /* assume new game */
+    boolean plsel_once = FALSE;
 
     sys_early_init();
 
@@ -104,19 +106,21 @@ char *argv[];
     choose_windows(DEFAULT_WINDOW_SYS);
 
 #ifdef CHDIR /* otherwise no chdir() */
-             /*
-              * See if we must change directory to the playground.
-              * (Perhaps hack runs suid and playground is inaccessible
-              *  for the player.)
-              * The environment variable HACKDIR is overridden by a
-              *  -d command line option (must be the first option given)
-              */
+    /*
+     * See if we must change directory to the playground.
+     * (Perhaps hack runs suid and playground is inaccessible
+     *  for the player.)
+     * The environment variable HACKDIR is overridden by a
+     *  -d command line option (must be the first option given).
+     */
     dir = nh_getenv("NETHACKDIR");
     if (!dir)
         dir = nh_getenv("HACKDIR");
-#endif
+
     if (argc > 1) {
-#ifdef CHDIR
+        if (argcheck(argc, argv, ARG_VERSION))
+            exit(EXIT_SUCCESS);
+
         if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
             /* avoid matching "-dec" for DECgraphics; since the man page
              * says -d directory, hope nobody's using -desomething_else
@@ -134,37 +138,40 @@ char *argv[];
             if (!*dir)
                 error("Flag -d must be followed by a directory name.");
         }
-        if (argc > 1)
+    }
 #endif /* CHDIR */
 
-            /*
-             * Now we know the directory containing 'record' and
-             * may do a prscore().  Exclude `-style' - it's a Qt option.
-             */
-            if (!strncmp(argv[1], "-s", 2) && strncmp(argv[1], "-style", 6)) {
+    if (argc > 1) {
+        /*
+         * Now we know the directory containing 'record' and
+         * may do a prscore().  Exclude `-style' - it's a Qt option.
+         */
+        if (!strncmp(argv[1], "-s", 2) && strncmp(argv[1], "-style", 6)) {
 #ifdef CHDIR
-                chdirx(dir, 0);
+            chdirx(dir, 0);
 #endif
 #ifdef SYSCF
-                initoptions();
+            initoptions();
 #endif
 #ifdef PANICTRACE
-                ARGV0 = argv[0]; /* save for possible stack trace */
+            ARGV0 = hname; /* save for possible stack trace */
 #ifndef NO_SIGNAL
-                panictrace_setsignals(TRUE);
+            panictrace_setsignals(TRUE);
 #endif
 #endif
 #if 0 /*JP*/
-                prscore(argc, argv);
+            prscore(argc, argv);
 #else
-                setkcode('I');
-                initoptions();
-                prscore(argc, argv);
-                jputchar('\0'); /* reset */
-#endif
-                exit(EXIT_SUCCESS);
-            }
-    }
+            setkcode('I');
+            initoptions();
+            prscore(argc, argv);
+            jputchar('\0'); /* reset */
+#endif
+            /* FIXME: shouldn't this be using nh_terminate() to free
+               up any memory allocated by initoptions() */
+            exit(EXIT_SUCCESS);
+        }
+    } /* argc > 1 */
 
 /*
  * Change directories before we initialize the window system so
@@ -189,7 +196,7 @@ char *argv[];
 #endif
     initoptions();
 #ifdef PANICTRACE
-    ARGV0 = argv[0]; /* save for possible stack trace */
+    ARGV0 = hname; /* save for possible stack trace */
 #ifndef NO_SIGNAL
     panictrace_setsignals(TRUE);
 #endif
@@ -238,7 +245,7 @@ char *argv[];
          * dash matches role, race, gender, or alignment.
          */
         /* guard against user names with hyphens in them */
-        int len = strlen(plname);
+        int len = (int) strlen(plname);
         /* append the current role, if any, so that last dash is ours */
         if (++len < (int) sizeof plname)
             (void) strncat(strcat(plname, "-"), pl_character,
@@ -256,6 +263,23 @@ char *argv[];
         (void) signal(SIGQUIT, SIG_IGN);
         (void) signal(SIGINT, SIG_IGN);
     }
+
+    dlb_init(); /* must be before newgame() */
+
+    /*
+     * Initialize the vision system.  This must be before mklev() on a
+     * new game or before a level restore on a saved game.
+     */
+    vision_init();
+
+    display_gamewindows();
+
+    /*
+     * First, try to find and restore a save file for specified character.
+     * We'll return here if new game player_selection() renames the hero.
+     */
+attempt_restore:
+
     /*
      * getlock() complains and quits if there is already a game
      * in progress for current character name (when locknum == 0)
@@ -267,25 +291,12 @@ char *argv[];
      * clock, &c not currently in use in the playground directory
      * (for locknum > 0).
      */
-    getlock();
-    program_state.preserve_locks = 0; /* after getlock() */
-
-    dlb_init(); /* must be before newgame() */
-
-    /*
-     *  Initialize the vision system.  This must be before mklev() on a
-     *  new game or before a level restore on a saved game.
-     */
-    vision_init();
-
-    display_gamewindows();
+    if (*plname) {
+        getlock();
+        program_state.preserve_locks = 0; /* after getlock() */
+    }
 
-/*
- * First, try to find and restore a save file for specified character.
- * We'll return here if new game player_selection() renames the hero.
- */
-attempt_restore:
-    if ((fd = restore_saved_game()) >= 0) {
+    if (*plname && (fd = restore_saved_game()) >= 0) {
         const char *fq_save = fqname(SAVEF, SAVEPREFIX, 1);
 
         (void) chmod(fq_save, 0); /* disallow parallel restores */
@@ -307,12 +318,13 @@ attempt_restore:
             resuming = TRUE; /* not starting new game */
             wd_message();
             if (discover || wizard) {
+                /* this seems like a candidate for paranoid_confirmation... */
 /*JP
-                if (yn("Do you want to keep the save file?") == 'n')
+                if (yn("Do you want to keep the save file?") == 'n') {
 */
-                if (yn("\83Z\81[\83u\83t\83@\83C\83\8b\82ð\8ec\82µ\82Ä\82¨\82«\82Ü\82·\82©\81H") == 'n')
+                if (yn("\83Z\81[\83u\83t\83@\83C\83\8b\82ð\8ec\82µ\82Ä\82¨\82«\82Ü\82·\82©\81H") == 'n') {
                     (void) delete_savefile();
-                else {
+                else {
                     (void) chmod(fq_save, FCMASK); /* back to readable */
                     nh_compress(fq_save);
                 }
@@ -321,12 +333,17 @@ attempt_restore:
     }
 
     if (!resuming) {
+        boolean neednewlock = (!*plname);
         /* new game:  start by choosing role, race, etc;
            player might change the hero's name while doing that,
            in which case we try to restore under the new name
            and skip selection this time if that didn't succeed */
-        if (!iflags.renameinprogress) {
-            player_selection();
+        if (!iflags.renameinprogress || iflags.defer_plname || neednewlock) {
+            if (!plsel_once)
+                player_selection();
+            plsel_once = TRUE;
+            if (neednewlock && *plname)
+                goto attempt_restore;
             if (iflags.renameinprogress) {
                 /* player has renamed the hero while selecting role;
                    if locking alphabetically, the existing lock file
@@ -343,10 +360,12 @@ attempt_restore:
         wd_message();
     }
 
+    /* moveloop() never returns but isn't flagged NORETURN */
     moveloop(resuming);
+
     exit(EXIT_SUCCESS);
     /*NOTREACHED*/
-    return (0);
+    return 0;
 }
 
 static void
@@ -390,22 +409,23 @@ char *argv[];
             break;
 #endif
         case 'u':
-            if (argv[0][2])
+            if (argv[0][2]) {
 #if 0 /*JP*/
-                (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1);
+                (void) strncpy(plname, argv[0] + 2, sizeof plname - 1);
 #else
                 (void) strncpy(plname, str2ic(argv[0] + 2), sizeof(plname) - 1);
 #endif
-            else if (argc > 1) {
+            else if (argc > 1) {
                 argc--;
                 argv++;
 #if 0 /*JP*/
-                (void) strncpy(plname, argv[0], sizeof(plname) - 1);
+                (void) strncpy(plname, argv[0], sizeof plname - 1);
 #else
                 (void) strncpy(plname, str2ic(argv[0]), sizeof(plname) - 1);
 #endif
-            } else
+            } else {
                 raw_print("Player name expected after -u");
+            }
             break;
         case 'I':
         case 'i':
@@ -440,7 +460,9 @@ char *argv[];
             }
             break;
         case 'w': /* windowtype */
+            config_error_init(FALSE, "command line", FALSE);
             choose_windows(&argv[0][2]);
+            config_error_done();
             break;
         case '@':
             flags.randomall = 1;
@@ -454,10 +476,14 @@ char *argv[];
         }
     }
 
-    /* XXX This is deprecated in favor of SYSCF with MAXPLAYERS.  Make
-     * an error in next release. */
+#ifdef SYSCF
+    if (argc > 1)
+        raw_printf("MAXPLAYERS are set in sysconf file.\n");
+#else
+    /* XXX This is deprecated in favor of SYSCF with MAXPLAYERS */
     if (argc > 1)
         locknum = atoi(argv[1]);
+#endif
 #ifdef MAX_NR_OF_PLAYERS
     /* limit to compile-time limit */
     if (!locknum || locknum > MAX_NR_OF_PLAYERS)
@@ -489,10 +515,10 @@ boolean wr;
 #pragma GCC diagnostic pop
 #endif
     } else {
-/* non-default data files is a sign that scores may not be
- * compatible, or perhaps that a binary not fitting this
- * system's layout is being used.
- */
+        /* non-default data files is a sign that scores may not be
        * compatible, or perhaps that a binary not fitting this
        * system's layout is being used.
        */
 #ifdef VAR_PLAYGROUND
         int len = strlen(VAR_PLAYGROUND);
 
@@ -515,9 +541,10 @@ boolean wr;
         error("Cannot chdir to %s.", dir);
     }
 
-    /* warn the player if we can't write the record file */
-    /* perhaps we should also test whether . is writable */
-    /* unfortunately the access system-call is worthless */
+    /* warn the player if we can't write the record file
+     * perhaps we should also test whether . is writable
+     * unfortunately the access system-call is worthless.
+     */
     if (wr) {
 #ifdef VAR_PLAYGROUND
         fqn_prefix[LEVELPREFIX] = fqn_prefix[SCOREPREFIX];
@@ -608,6 +635,7 @@ boolean
 authorize_wizard_mode()
 {
     struct passwd *pw = get_unix_pw();
+
     if (pw && sysopt.wizards && sysopt.wizards[0]) {
         if (check_user_string(sysopt.wizards))
             return TRUE;
@@ -670,11 +698,17 @@ char *optstr;
     struct passwd *pw = get_unix_pw();
     int pwlen;
     char *eop, *w;
+    char *pwname;
+
     if (optstr[0] == '*')
         return TRUE; /* allow any user */
     if (!pw)
         return FALSE;
-    pwlen = strlen(pw->pw_name);
+    if (sysopt.check_plname)
+        pwname = plname;
+    else
+        pwname = pw->pw_name;
+    pwlen = strlen(pwname);
     eop = eos(optstr);
     w = optstr;
     while (w + pwlen <= eop) {
@@ -684,7 +718,7 @@ char *optstr;
             w++;
             continue;
         }
-        if (!strncmp(w, pw->pw_name, pwlen)) {
+        if (!strncmp(w, pwname, pwlen)) {
             if (!w[pwlen] || isspace(w[pwlen]))
                 return TRUE;
         }
@@ -725,4 +759,54 @@ get_unix_pw()
     return pw;
 }
 
+char *
+get_login_name()
+{
+    static char buf[BUFSZ];
+    struct passwd *pw = get_unix_pw();
+
+    buf[0] = '\0';
+
+    if (pw)
+        (void)strcpy(buf, pw->pw_name);
+
+    return buf;
+}
+
+#ifdef __APPLE__
+extern int errno;
+
+void
+port_insert_pastebuf(buf)
+char *buf;
+{
+    /* This should be replaced when there is a Cocoa port. */
+    const char *errfmt;
+    size_t len;
+    FILE *PB = popen("/usr/bin/pbcopy","w");
+    if(!PB){
+       errfmt = "Unable to start pbcopy (%d)\n";
+       goto error;
+    }
+
+    len = strlen(buf);
+    /* Remove the trailing \n, carefully. */
+    if(buf[len-1] == '\n') len--;
+
+    /* XXX Sorry, I'm too lazy to write a loop for output this short. */
+    if(len!=fwrite(buf,1,len,PB)){
+       errfmt = "Error sending data to pbcopy (%d)\n";
+       goto error;
+    }
+
+    if(pclose(PB)!=-1){
+       return;
+    }
+    errfmt = "Error finishing pbcopy (%d)\n";
+
+error:
+    raw_printf(errfmt,strerror(errno));
+}
+#endif
+
 /*unixmain.c*/
index c60df76..cd0954a 100644 (file)
@@ -33,7 +33,7 @@ uid_t *ruid, *euid, *suid;
     if (!f)
         return -1;
 
-    return f(ruid, euid, suid);
+    return (*f)(ruid, euid, suid);
 }
 
 static int
@@ -46,7 +46,7 @@ gid_t *rgid, *egid, *sgid;
     if (!f)
         return -1;
 
-    return f(rgid, egid, sgid);
+    return (*f)(rgid, egid, sgid);
 }
 
 #else
@@ -74,6 +74,7 @@ uid_t *ruid, *euid, *suid;
     int retval;
     int pfd[2];
     struct stat st;
+
     if (pipe(pfd))
         return -1;
     retval = fstat(pfd[0], &st);
@@ -107,6 +108,7 @@ gid_t *rgid, *egid, *sgid;
     int retval;
     int pfd[2];
     struct stat st;
+
     if (pipe(pfd))
         return -1;
     retval = fstat(pfd[0], &st);
@@ -146,6 +148,7 @@ nh_getresuid(ruid, euid, suid)
 uid_t *ruid, *euid, *suid;
 {
     int retval = real_getresuid(ruid, euid, suid);
+
     if (!retval && hiding_privileges)
         *euid = *suid = *ruid;
     return retval;
@@ -155,6 +158,7 @@ uid_t
 nh_getuid()
 {
     uid_t ruid, euid, suid;
+
     (void) real_getresuid(&ruid, &euid, &suid);
     return ruid;
 }
@@ -163,6 +167,7 @@ uid_t
 nh_geteuid()
 {
     uid_t ruid, euid, suid;
+
     (void) real_getresuid(&ruid, &euid, &suid);
     if (hiding_privileges)
         euid = ruid;
@@ -174,6 +179,7 @@ nh_getresgid(rgid, egid, sgid)
 gid_t *rgid, *egid, *sgid;
 {
     int retval = real_getresgid(rgid, egid, sgid);
+
     if (!retval && hiding_privileges)
         *egid = *sgid = *rgid;
     return retval;
@@ -183,6 +189,7 @@ gid_t
 nh_getgid()
 {
     gid_t rgid, egid, sgid;
+
     (void) real_getresgid(&rgid, &egid, &sgid);
     return rgid;
 }
@@ -191,6 +198,7 @@ gid_t
 nh_getegid()
 {
     gid_t rgid, egid, sgid;
+
     (void) real_getresgid(&rgid, &egid, &sgid);
     if (hiding_privileges)
         egid = rgid;
index 541db70..b3807a8 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 unixunix.c      $NHDT-Date: 1432512788 2015/05/25 00:13:08 $  $NHDT-Branch: master $:$NHDT-Revision: 1.22 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* This file collects some Unix dependencies */
@@ -28,7 +29,8 @@ extern int errno;
 
 static struct stat buf;
 
-/* see whether we should throw away this xlock file */
+/* see whether we should throw away this xlock file;
+   if yes, close it, otherwise leave it open */
 static int
 veryold(fd)
 int fd;
@@ -36,10 +38,10 @@ int fd;
     time_t date;
 
     if (fstat(fd, &buf))
-        return (0); /* cannot get status */
+        return 0; /* cannot get status */
 #ifndef INSURANCE
-    if (buf.st_size != sizeof(int))
-        return (0); /* not an xlock file */
+    if (buf.st_size != sizeof (int))
+        return 0; /* not an xlock file */
 #endif
 #if defined(BSD) && !defined(POSIX_TYPES)
     (void) time((long *) (&date));
@@ -49,10 +51,10 @@ int fd;
     if (date - buf.st_mtime < 3L * 24L * 60L * 60L) { /* recent */
         int lockedpid; /* should be the same size as hackpid */
 
-        if (read(fd, (genericptr_t) &lockedpid, sizeof(lockedpid))
-            != sizeof(lockedpid))
+        if (read(fd, (genericptr_t) &lockedpid, sizeof lockedpid)
+            != sizeof lockedpid)
             /* strange ... */
-            return (0);
+            return 0;
 
 /* From: Rick Adams <seismo!rick> */
 /* This will work on 4.1cbsd, 4.2bsd and system 3? & 5. */
@@ -62,10 +64,10 @@ int fd;
            by more than one machine! -pem */
         if (!(kill(lockedpid, 0) == -1 && errno == ESRCH))
 #endif
-            return (0);
+            return 0;
     }
     (void) close(fd);
-    return (1);
+    return 1;
 }
 
 static int
@@ -85,8 +87,8 @@ eraseoldlocks()
     }
     set_levelfile_name(lock, 0);
     if (unlink(fqname(lock, LEVELPREFIX, 0)))
-        return (0); /* cannot remove it */
-    return (1);     /* success! */
+        return 0; /* cannot remove it */
+    return 1;     /* success! */
 }
 
 void
@@ -139,8 +141,8 @@ getlock()
                 error("Cannot open %s", fq_lock);
             }
 
-            if (veryold(fd) /* closes fd if true */
-                && eraseoldlocks())
+            /* veryold() closes fd if true */
+            if (veryold(fd) && eraseoldlocks())
                 goto gotlock;
             (void) close(fd);
         } while (i < locknum);
@@ -157,28 +159,23 @@ getlock()
             error("Cannot open %s", fq_lock);
         }
 
-        if (veryold(fd) /* closes fd if true */ && eraseoldlocks())
+        /* veryold() closes fd if true */
+        if (veryold(fd) && eraseoldlocks())
             goto gotlock;
         (void) close(fd);
 
+      {
+        const char destroy_old_game_prompt[] =
+/*JP
+    "There is already a game in progress under your name.  Destroy old game?";
+*/
+    "\82 \82È\82½\82Ì\96¼\91O\82Å\95s\90³\8fI\97¹\82µ\82½\83Q\81[\83\80\82ª\8ec\82Á\82Ä\82¢\82Ü\82·\81D\94j\8aü\82µ\82Ü\82·\82©\81H";
+
         if (iflags.window_inited) {
-#if 0 /*JP*/
-            c = yn("There is already a game in progress under your name.  "
-                   "Destroy old game?");
-#else
-            c = yn("\82 \82È\82½\82Ì\96¼\91O\82Å\95s\90³\8fI\97¹\82µ\82½\83Q\81[\83\80\82ª\8ec\82Á\82Ä\82¢\82Ü\82·\81D"
-                   "\94j\8aü\82µ\82Ü\82·\82©\81H");
-#endif
+            /* this is a candidate for paranoid_confirmation */
+            c = yn(destroy_old_game_prompt);
         } else {
-#if 0 /*JP*/
-            (void) printf(
-                "\nThere is already a game in progress under your name.");
-            (void) printf("  Destroy old game? [yn] ");
-#else
-            (void) printf(
-                "\n\82 \82È\82½\82Ì\96¼\91O\82Å\95s\90³\8fI\97¹\82µ\82½\83Q\81[\83\80\82ª\8ec\82Á\82Ä\82¢\82Ü\82·\81D");
-            (void) printf("\94j\8aü\82µ\82Ü\82·\82©\81H[yn] ");
-#endif
+            (void) printf("\n%s [yn] ", destroy_old_game_prompt);
             (void) fflush(stdout);
             if ((c = getchar()) != EOF) {
                 int tmp;
@@ -189,10 +186,11 @@ getlock()
                     ; /* eat rest of line and newline */
             }
         }
+      }
         if (c == 'y' || c == 'Y') {
-            if (eraseoldlocks())
+            if (eraseoldlocks()) {
                 goto gotlock;
-            else {
+            else {
                 unlock_file(HLOCK);
                 error("Couldn't destroy old game.");
             }
@@ -208,8 +206,8 @@ gotlock:
     if (fd == -1) {
         error("cannot creat lock file (%s).", fq_lock);
     } else {
-        if (write(fd, (genericptr_t) &hackpid, sizeof(hackpid))
-            != sizeof(hackpid)) {
+        if (write(fd, (genericptr_t) &hackpid, sizeof hackpid)
+            != sizeof hackpid) {
             error("cannot write lock (%s)", fq_lock);
         }
         if (close(fd) == -1) {
@@ -218,13 +216,15 @@ gotlock:
     }
 }
 
-void regularize(s) /* normalize file name - we don't like .'s, /'s, spaces */
+/* normalize file name - we don't like .'s, /'s, spaces */
+void
+regularize(s)
 register char *s;
 {
     register char *lp;
 
-    while ((lp = index(s, '.')) || (lp = index(s, '/'))
-           || (lp = index(s, ' ')))
+    while ((lp = index(s, '.')) != 0 || (lp = index(s, '/')) != 0
+           || (lp = index(s, ' ')) != 0)
         *lp = '_';
 #if defined(SYSV) && !defined(AIX_31) && !defined(SVR4) && !defined(LINUX) \
     && !defined(__APPLE__)
@@ -269,10 +269,13 @@ unsigned msec; /* milliseconds */
 int
 dosh()
 {
-    register char *str;
+    char *str;
+
 #ifdef SYSCF
     if (!sysopt.shellers || !sysopt.shellers[0]
         || !check_user_string(sysopt.shellers)) {
+        /* FIXME: should no longer assume a particular command keystroke,
+           and perhaps ought to say "unavailable" rather than "unknown" */
         Norep("Unknown command '!'.");
         return 0;
     }
@@ -295,6 +298,7 @@ child(wt)
 int wt;
 {
     register int f;
+
     suspend_nhwindows((char *) 0); /* also calls end_screen() */
 #ifdef _M_UNIX
     sco_mapon();
@@ -311,13 +315,13 @@ int wt;
         (void) chdir(getenv("HOME"));
 #endif
 #pragma GCC diagnostic pop
-        return (1);
+        return 1;
     }
     if (f == -1) { /* cannot fork */
         pline("Fork failed.  Try again.");
-        return (0);
+        return 0;
     }
-/* fork succeeded; wait for child to exit */
+    /* fork succeeded; wait for child to exit */
 #ifndef NO_SIGNAL
     (void) signal(SIGINT, SIG_IGN);
     (void) signal(SIGQUIT, SIG_IGN);
@@ -339,9 +343,9 @@ int wt;
         wait_synch();
     }
     resume_nhwindows();
-    return (0);
+    return 0;
 }
-#endif
+#endif /* SHELL || DEF_PAGER || DEF_MAILREADER */
 
 #ifdef GETRES_SUPPORT
 
@@ -352,34 +356,37 @@ extern int FDECL(nh_getresgid, (gid_t *, gid_t *, gid_t *));
 extern gid_t NDECL(nh_getgid);
 extern gid_t NDECL(nh_getegid);
 
-int(getresuid)(ruid, euid, suid)
+/* the following several functions assume __STDC__ where parentheses
+   around the name of a function-like macro prevent macro expansion */
+
+int (getresuid)(ruid, euid, suid)
 uid_t *ruid, *euid, *suid;
 {
     return nh_getresuid(ruid, euid, suid);
 }
 
-uid_t(getuid)()
+uid_t (getuid)()
 {
     return nh_getuid();
 }
 
-uid_t(geteuid)()
+uid_t (geteuid)()
 {
     return nh_geteuid();
 }
 
-int(getresgid)(rgid, egid, sgid)
+int (getresgid)(rgid, egid, sgid)
 gid_t *rgid, *egid, *sgid;
 {
     return nh_getresgid(rgid, egid, sgid);
 }
 
-gid_t(getgid)()
+gid_t (getgid)()
 {
     return nh_getgid();
 }
 
-gid_t(getegid)()
+gid_t (getegid)()
 {
     return nh_getegid();
 }
@@ -389,12 +396,15 @@ gid_t(getegid)()
 /* XXX should be ifdef PANICTRACE_GDB, but there's no such symbol yet */
 #ifdef PANICTRACE
 boolean
-file_exists(const char *path)
+file_exists(path)
+const char *path;
 {
+    struct stat sb;
+
     /* Just see if it's there - trying to figure out if we can actually
      * execute it in all cases is too hard - we really just want to
-     * catch typos in SYSCF. */
-    struct stat sb;
+     * catch typos in SYSCF.
+     */
     if (stat(path, &sb)) {
         return FALSE;
     }
index d8c0b29..e917aef 100644 (file)
@@ -1,4 +1,4 @@
-               Instructions for Building and Installing NetHack 3.6.0
+               Instructions for Building and Installing NetHack 3.6.1
                      on a VMS (aka OpenVMS) system
                =========================================
 
@@ -137,7 +137,8 @@ Notes:
 0.  Version 3.5.x was never publicly released.
 
 1.  Save files and bones files from 3.4.x and earlier versions
-    will not work with 3.6.0. The scoreboard file (RECORD) from
+    will not work with 3.6.1, but save files and bones file from 3.6.0
+    should work. The scoreboard file (RECORD) from 3.6.0 or 
     3.4.x or 3.3.x will work.
 
 2.  To specify user-preference options in your environment, define the
@@ -479,3 +480,7 @@ Notes:
 
 20-OCT-2003
 minimally updated 9-NOV-2015...
+
+# NetHack 3.6  Install.vms       $NHDT-Date: 1524689427 2018/04/25 20:50:27 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.12 $
+# Copyright (c) 2003 by Robert Patrick Rankin
+# NetHack may be freely redistributed.  See license for details.
index e8932f1..755099c 100644 (file)
@@ -1,5 +1,7 @@
 #      NetHack Makefile (VMS) - data files: special levels and other data.
-#      NetHack 3.6     Makefile.dat    $NHDT-Date: 1432512789 2015/05/25 00:13:09 $    $NHDT-Branch: master $:$NHDT-Revision: 1.8 $
+#      NetHack 3.6     Makefile.dat    $NHDT-Date: 1524689428 2018/04/25 20:50:28 $    $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.9 $
+# Copyright (c) 2015 by Mike Stephenson
+# NetHack may be freely redistributed.  See license for details.
 
 #  Copy this file to [.dat]Makefile.; no editing needed.
 
index 352626a..624f5ea 100644 (file)
@@ -1,5 +1,7 @@
 #      NetHack Makefile (VMS) - for the [Unix] documentation.
-#      NetHack 3.6     Makefile.doc    $NHDT-Date: 1432512790 2015/05/25 00:13:10 $    $NHDT-Branch: master $:$NHDT-Revision: 1.8 $
+#      NetHack 3.6     Makefile.doc    $NHDT-Date: 1524689428 2018/04/25 20:50:28 $    $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.9 $
+# Copyright (c) 2011 by Robert Patrick Rankin
+# NetHack may be freely redistributed.  See license for details.
 
 #  Copy this file to [.doc]Makefile. and edit it if needed.
 
index 8274024..1fee34a 100644 (file)
@@ -1,5 +1,7 @@
 #      NetHack Makefile (VMS) - for building nethack itself.
-#      NetHack 3.6     Makefile.src    $NHDT-Date: 1447314365 2015/11/12 07:46:05 $    $NHDT-Branch: master $:$NHDT-Revision: 1.27 $
+#      NetHack 3.6     Makefile.src    $NHDT-Date: 1524689428 2018/04/25 20:50:28 $    $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.29 $
+# Copyright (c) 2011 by Robert Patrick Rankin
+# NetHack may be freely redistributed.  See license for details.
 
 #  Copy this file to [.src]Makefile. and then edit it as needed.
 #  The default configuration is for building with DEC C (aka Compaq C).
@@ -97,7 +99,7 @@ RANDOBJ = random.obj
 # Other things that have to be reconfigured are in vmsconf.h,
 # and config.h
 
-VERSION  = 3.5.0
+VERSION  = 3.6.1
 
 MAKEDEFS = $(UTL)makedefs.exe;
 
index cfc7933..2bdb2c9 100644 (file)
@@ -1,5 +1,7 @@
 #      NetHack Makefile (VMS) - top level for making & installing everything.
-#      NetHack 3.6     Makefile.top    $NHDT-Date: 1432512790 2015/05/25 00:13:10 $    $NHDT-Branch: master $:$NHDT-Revision: 1.9 $
+#      NetHack 3.6     Makefile.top    $NHDT-Date: 1524689428 2018/04/25 20:50:28 $    $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $
+# Copyright (c) 2011 by Robert Patrick Rankin
+# NetHack may be freely redistributed.  See license for details.
 
 #  Copy this file to <top>Makefile.; edit the appropriate values for
 #  GAMEDIR ("playground" location) and GAMEOWNER (UIC or identifier
index 2f74239..a581e9e 100644 (file)
@@ -1,5 +1,7 @@
 #      NetHack Makefile (VMS) - for utility programs.
-#      NetHack 3.6     Makefile.utl    $NHDT-Date: 1432512790 2015/05/25 00:13:10 $    $NHDT-Branch: master $:$NHDT-Revision: 1.13 $
+#      NetHack 3.6     Makefile.utl    $NHDT-Date: 1524689428 2018/04/25 20:50:28 $    $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $
+# Copyright (c) 2011 by Robert Patrick Rankin
+# NetHack may be freely redistributed.  See license for details.
 
 #  Copy this file to [.util]Makefile. and then edit it as needed.
 #  The default configuration is for building with DEC C (aka Compaq C).
@@ -331,7 +333,7 @@ $(SRC)drawing.obj : $(SRC)drawing.c $(HACK_H)
        $(MAKE)$(MAKEFLAGS) drawing.obj
       @ $(CD) $(UTL)
 
-$(SRC)dlb.obj : $(SRC)dlb.c $(HACK_H) $(INC)dlb.h
+$(SRC)dlb.obj : $(SRC)dlb.c $(CONFIG_H) $(INC)dlb.h
        $(CD) $(SRC)
        $(MAKE)$(MAKEFLAGS) dlb.obj
       @ $(CD) $(UTL)
index 21298a9..cb8ae32 100644 (file)
@@ -1,6 +1,9 @@
 $ ! vms/install.com -- set up nethack 'playground'
+$! $NHDT-Date: 1524689428 2018/04/25 20:50:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $
+$! Copyright (c) 2016 by Robert Patrick Rankin
+$! NetHack may be freely redistributed.  See license for details.
 $ !
-$ ! $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+$ ! $NHDT-Date: 1524689428 2018/04/25 20:50:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $
 $ !
 $ ! Use vmsbuild.com to create nethack.exe, makedefs, and lev_comp *first*.
 $ !
@@ -24,7 +27,8 @@ $
 $      ! note: all filespecs contain some punctuation,
 $      !       to avoid inadvertent logical name interaction
 $      play_files = "PERM.,RECORD.,LOGFILE.,PANICLOG."
-$      help_files = "HELP.,HH.,CMDHELP.,WIZHELP.,OPTHELP.,HISTORY.,LICENSE."
+$      help_files = "HELP.,HH.,CMDHELP.,KEYHELP.,WIZHELP.,OPTHELP.," -
+                  + "HISTORY.,LICENSE."
 $      data_files = "DATA.,RUMORS.,ORACLES.,OPTIONS.,QUEST.DAT,TRIBUTE."
 $      sysconf_file = "[.sys.vms]sysconf"
 $      guidebook  = "[.doc]Guidebook.txt"
index d73899a..6cae5b9 100644 (file)
@@ -1,7 +1,9 @@
 $! NetHack.Com -- sample command procedure for invoking NetHack  9-JAN-1993
 $ v = 'f$verify(0)'
 $!
-$! $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+$! $NHDT-Date: 1524689428 2018/04/25 20:50:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.5 $
+$! Copyright (c) 2016 by Robert Patrick Rankin
+$! NetHack may be freely redistributed.  See license for details.
 $!
 $!    Possible command line arguments include
 $!     "-uConan-B"     !play a barbarian named Conan
index 0da5537..fb16f49 100644 (file)
@@ -1,6 +1,8 @@
 $ ! sys/vms/spec_lev.com -- preprocess nethack's special level compiler code
 $ !
-$ ! $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+$ ! $NHDT-Date: 1524689429 2018/04/25 20:50:29 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.5 $
+$! Copyright (c) 2016 by Robert Patrick Rankin
+$! NetHack may be freely redistributed.  See license for details.
 $ !
 $ ! This operation needs to be performed prior to executing vmsbuild.com.
 $ ! Process the scanning and parsing code for NetHack's special level
index 8b52270..21aa347 100644 (file)
@@ -1,4 +1,6 @@
-# NetHack 3.6 sysconf $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$
+# NetHack 3.6 sysconf $NHDT-Date: 1524689429 2018/04/25 20:50:29 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $
+# Copyright (c) 2015 by Robert Patrick Rankin
+# NetHack may be freely redistributed.  See license for details.
 #
 # Sample sysconf file for VMS.
 # The sysconf file is only used if NetHack is compiled with SYSCF defined.
 # Maximum number of score file entries to use for random statue names
 #MAX_STATUENAME_RANK=10
 
+# Number of bones file pools.
+# The pool you belong to is determined at game start. You will
+# load and save bones only from that pool. Generally useful
+# for public servers only.
+# Changing this might make existing bones inaccessible.
+# Disabled by setting to 0, or commenting out.
+#BONES_POOLS=10
+
 # Show debugging information originating from these source files.
 # Use '*' for all, or list source files separated by spaces.
 # Only available if game has been compiled with DEBUG, and can be
index 1ae200e..2bc8176 100644 (file)
@@ -1,6 +1,8 @@
 $ ! vms/vmsbuild.com -- compile and link NetHack 3.6.*                 [pr]
-$      version_number = "3.5.0"
-$ ! $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+$      version_number = "3.6.1"
+$ ! $NHDT-Date: 1524689429 2018/04/25 20:50:29 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.17 $
+# Copyright (c) 2018 by Robert Patrick Rankin
+# NetHack may be freely redistributed.  See license for details.
 $ !
 $ ! usage:
 $ !   $ set default [.src]     !or [-.-.src] if starting from [.sys.vms]
@@ -175,7 +177,7 @@ $ ! final setup
 $      nethacklib = "[-.src]nethack.olb"
 $      create nethack.opt
 ! nethack.opt
-nethack.olb/Library/Include=(vmsmain)
+nethack.olb/Include=(vmsmain)/Library
 sys$library:starlet.olb/Include=(lib$initialize)
 psect_attr=lib$initialize, Con,Usr,noPic,Rel,Gbl,noShr,noExe,Rd,noWrt,Long
 iosegment=128
index a2a98a2..89e6aff 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 vmsfiles.c      $NHDT-Date: 1432512790 2015/05/25 00:13:10 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
+/* NetHack 3.6 vmsfiles.c      $NHDT-Date: 1449801740 2015/12/11 02:42:20 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2007. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -29,7 +30,7 @@ int FDECL(c__translate, (int));
 extern unsigned long sys$parse(), sys$search(), sys$enter(), sys$remove();
 extern int VDECL(lib$match_cond, (int, int, ...));
 
-#define vms_success(sts) ((sts) &1)          /* odd, */
+#define vms_success(sts) ((sts) & 1)         /* odd, */
 #define vms_failure(sts) (!vms_success(sts)) /* even */
 
 /* vms_link() -- create an additional directory for an existing file */
@@ -208,30 +209,30 @@ const char *d1, *d2;
         f2.fab$b_fns = strlen(f2.fab$l_fna = (char *) d2);
         f1.fab$l_nam = (genericptr_t) &n1; /* link nam to fab */
         f2.fab$l_nam = (genericptr_t) &n2;
-        n1.nam$b_nop = n2.nam$b_nop =
-            NAM$M_NOCONCEAL; /* want true device name */
-
-        return (
-            vms_success(sys$parse(&f1)) && vms_success(sys$parse(&f2))
-            && n1.nam$t_dvi[0] == n2.nam$t_dvi[0]
-            && !strncmp(&n1.nam$t_dvi[1], &n2.nam$t_dvi[1], n1.nam$t_dvi[0])
-            && !memcmp((genericptr_t) n1.nam$w_did,
-                       (genericptr_t) n2.nam$w_did,
-                       sizeof n1.nam$w_did)); /*{ short nam$w_did[3]; }*/
+        /* want true device name */
+        n1.nam$b_nop = n2.nam$b_nop = NAM$M_NOCONCEAL;
+
+        return (vms_success(sys$parse(&f1)) && vms_success(sys$parse(&f2))
+                && n1.nam$t_dvi[0] == n2.nam$t_dvi[0]
+                && !strncmp(&n1.nam$t_dvi[1], &n2.nam$t_dvi[1],
+                            n1.nam$t_dvi[0])
+                && !memcmp((genericptr_t) n1.nam$w_did,
+                           (genericptr_t) n2.nam$w_did,
+                           sizeof n1.nam$w_did)); /*{ short nam$w_did[3]; }*/
     }
 }
 
 /*
  * c__translate -- substitute for VAXCRTL routine C$$TRANSLATE.
  *
- *     Try to convert a VMS status code into its Unix equivalent,
- *     then set `errno' to that value; use EVMSERR if there's no
- *     appropriate translation; set `vaxc$errno' to the original
- *     status code regardless.
+ *      Try to convert a VMS status code into its Unix equivalent,
+ *      then set `errno' to that value; use EVMSERR if there's no
+ *      appropriate translation; set `vaxc$errno' to the original
+ *      status code regardless.
  *
- *     These translations match only a subset of VAXCRTL's lookup
- *     table, but work even if the severity has been adjusted or
- *     the inhibit-message bit has been set.
+ *      These translations match only a subset of VAXCRTL's lookup
+ *      table, but work even if the severity has been adjusted or
+ *      the inhibit-message bit has been set.
  */
 #include <errno.h>
 #include <ssdef.h>
@@ -251,37 +252,46 @@ int code;
 {
     register int trans;
 
+/* clang-format off */
+/* *INDENT-OFF* */
     switch ((code & 0x0FFFFFF8) >> 3) { /* strip upper 4 and bottom 3 bits */
-        CASE2(RMS$_PRV, SS$_NOPRIV) : VALUE(EPERM); /* not owner */
-        CASE2(RMS$_DNF, RMS$_DIR)
-            : CASE2(RMS$_FNF, RMS$_FND)
-            : CASE1(SS$_NOSUCHFILE)
-            : VALUE(ENOENT); /* no such file or directory */
-        CASE2(RMS$_IFI, RMS$_ISI) : VALUE(EIO); /* i/o error */
-        CASE1(RMS$_DEV)
-            : CASE2(SS$_NOSUCHDEV, SS$_DEVNOTMOUNT)
-            : VALUE(ENXIO); /* no such device or address codes */
-        CASE1(RMS$_DME)
-            : /* CASE1(LIB$INSVIRMEM): */
-              CASE2(SS$_VASFULL, SS$_INSFWSL)
-            : VALUE(ENOMEM);               /* not enough core */
-        CASE1(SS$_ACCVIO) : VALUE(EFAULT); /* bad address */
-        CASE2(RMS$_DNR, SS$_DEVASSIGN)
-            : CASE2(SS$_DEVALLOC, SS$_DEVALRALLOC)
-            : CASE2(SS$_DEVMOUNT, SS$_DEVACTIVE)
-            : VALUE(EBUSY); /* mount device busy codes to name a few */
-        CASE2(RMS$_FEX, SS$_FILALRACC) : VALUE(EEXIST); /* file exists */
-        CASE2(RMS$_IDR, SS$_BADIRECTORY)
-            : VALUE(ENOTDIR);                /* not a directory */
-        CASE1(SS$_NOIOCHAN) : VALUE(EMFILE); /* too many open files */
-        CASE1(RMS$_FUL)
-            : CASE2(SS$_DEVICEFULL, SS$_EXDISKQUOTA)
-            : VALUE(ENOSPC); /* no space left on disk codes */
-        CASE2(RMS$_WLK, SS$_WRITLCK)
-            : VALUE(EROFS); /* read-only file system */
+    CASE2(RMS$_PRV, SS$_NOPRIV):
+        VALUE(EPERM); /* not owner */
+    CASE2(RMS$_DNF, RMS$_DIR):
+    CASE2(RMS$_FNF, RMS$_FND):
+    CASE1(SS$_NOSUCHFILE):
+        VALUE(ENOENT); /* no such file or directory */
+    CASE2(RMS$_IFI, RMS$_ISI):
+        VALUE(EIO); /* i/o error */
+    CASE1(RMS$_DEV):
+    CASE2(SS$_NOSUCHDEV, SS$_DEVNOTMOUNT):
+        VALUE(ENXIO); /* no such device or address codes */
+    CASE1(RMS$_DME):
+ /* CASE1(LIB$INSVIRMEM): */
+    CASE2(SS$_VASFULL, SS$_INSFWSL):
+        VALUE(ENOMEM); /* not enough core */
+    CASE1(SS$_ACCVIO):
+        VALUE(EFAULT); /* bad address */
+    CASE2(RMS$_DNR, SS$_DEVASSIGN):
+    CASE2(SS$_DEVALLOC, SS$_DEVALRALLOC):
+    CASE2(SS$_DEVMOUNT, SS$_DEVACTIVE):
+        VALUE(EBUSY); /* mount device busy codes to name a few */
+    CASE2(RMS$_FEX, SS$_FILALRACC):
+        VALUE(EEXIST); /* file exists */
+    CASE2(RMS$_IDR, SS$_BADIRECTORY):
+        VALUE(ENOTDIR); /* not a directory */
+    CASE1(SS$_NOIOCHAN):
+        VALUE(EMFILE); /* too many open files */
+    CASE1(RMS$_FUL):
+    CASE2(SS$_DEVICEFULL, SS$_EXDISKQUOTA):
+        VALUE(ENOSPC); /* no space left on disk codes */
+    CASE2(RMS$_WLK, SS$_WRITLCK):
+        VALUE(EROFS); /* read-only file system */
     default:
         VALUE(EVMSERR);
     };
+/* clang-format on */
+/* *INDENT-ON* */
 
     errno = trans;
     vaxc$errno = code;
index e62d2dc..9897756 100644 (file)
@@ -1,5 +1,5 @@
-/* NetHack 3.6 vmsmail.c       $NHDT-Date: 1432512789 2015/05/25 00:13:09 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
-/* Copyright (c) Robert Patrick Rankin, 1991.                    */
+/* NetHack 3.6 vmsmail.c       $NHDT-Date: 1449801741 2015/12/11 02:42:21 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $ */
+/* Copyright (c) Robert Patrick Rankin, 1991.                     */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "config.h"
@@ -25,7 +25,7 @@ struct mail_info *NDECL(parse_next_broadcast);
 #endif /*__GNUC__*/
 #include <signal.h>
 /* #include <string.h> */
-#define vms_ok(sts) ((sts) &1)
+#define vms_ok(sts) ((sts) & 1)
 
 static struct mail_info *FDECL(parse_brdcst, (char *));
 static void FDECL(filter_brdcst, (char *));
@@ -49,7 +49,7 @@ static long pasteboard_id = 0; /* SMG's magic cookie */
 /*
  * Mail (et al) overview:
  *
- *     When a broadcast is asynchronously captured, a volatile counter
+ *      When a broadcast is asynchronously captured, a volatile counter
  * ('broadcasts') is incremented.  Each player turn, ckmailstatus() polls
  * the counter and calls parse_next_broadcast() if it's positive; this
  * returns some display text, object name, and response command, which is
@@ -62,7 +62,7 @@ static long pasteboard_id = 0; /* SMG's magic cookie */
  * If SHELL is undefined, then all broadcasts are treated as 'other'; since
  * no subproceses are allowed, there'd be no way to respond to the scroll.
  *
- *     When a scroll of mail is read by the character, readmail() extracts
+ *      When a scroll of mail is read by the character, readmail() extracts
  * the command string and uses it for the default when prompting the
  * player for a system command to spawn.  The player may enter any command
  * he or she chooses, or just <return> to accept the default or <escape> to
@@ -73,36 +73,36 @@ static long pasteboard_id = 0; /* SMG's magic cookie */
  *
  * Broadcast parsing:
  *
- *     The following broadcast messages are [attempted to be] recognized:
- *    text fragment          name for scroll         default command
- *     New mail                VMSmail                 MAIL
- *     New ALL-IN-1 MAIL       A1mail                  A1M
- *     Software Tools mail     STmail                  MSG [+folder]
- *     MM mail                 MMmail                  MM
- *     WPmail: New mail        WPmail                  OFFICE/MAIL
- *     **M400 mail             M400mail                M400
- *     " mail", ^"mail "       unknown mail            SPAWN
- *     " phoning"              Phone call              PHONE ANSWER
- *     talk-daemon...by...foo  Talk request            TALK[/OLD] foo@bar
- *     (node)user -            Bitnet noise            XYZZY user@node
+ *      The following broadcast messages are [attempted to be] recognized:
+ *    text fragment           name for scroll         default command
+ *      New mail                VMSmail                 MAIL
+ *      New ALL-IN-1 MAIL       A1mail                  A1M
+ *      Software Tools mail     STmail                  MSG [+folder]
+ *      MM mail                 MMmail                  MM
+ *      WPmail: New mail        WPmail                  OFFICE/MAIL
+ *      **M400 mail             M400mail                M400
+ *      " mail", ^"mail "       unknown mail            SPAWN
+ *      " phoning"              Phone call              PHONE ANSWER
+ *      talk-daemon...by...foo  Talk request            TALK[/OLD] foo@bar
+ *      (node)user -            Bitnet noise            XYZZY user@node
  * Anything else results in just the message text being passed along, no
  * scroll of mail so consequently no command to execute when scroll read.
  * The user can set up ``$ XYZZY :== SEND'' prior to invoking NetHack if
  * vanilla JNET responses to Bitnet messages are prefered.
  *
- *     Static return buffers are used because only one broadcast gets
+ *      Static return buffers are used because only one broadcast gets
  * processed at a time, and the essential information in each one is
  * either displayed and discarded or copied into a scroll-of-mail object.
  *
- *     The test driver code below can be used to check out potential new
+ *      The test driver code below can be used to check out potential new
  * entries without rebuilding NetHack itself.  CC/DEFINE="TEST_DRIVER"
  * Link it with hacklib.obj or nethack.olb/incl=hacklib (not nethack/lib).
  */
 
-static struct mail_info msg; /* parse_*()'s return buffer */
-static char nam_buf[63],     /* maximum onamelth, size of ONAME(object) */
-    cmd_buf[99],             /* arbitrary */
-    txt_buf[255 + 1];        /* same size as used for message buf[] */
+static struct mail_info msg;  /* parse_*()'s return buffer */
+static char nam_buf[63],      /* maximum onamelth, size of ONAME(object) */
+            cmd_buf[99],      /* arbitrary */
+            txt_buf[255 + 1]; /* same size as used for message buf[] */
 
 /* try to decipher and categorize broadcast message text
 */
@@ -136,9 +136,9 @@ char *buf;        /* input: filtered broadcast text */
 
         if (!strncmpi(buf, "new mail", 8)) {
             /*
-            New mail [on node FOO] from [SPAM::]BAR [\"personal_name\"]
-            [\(HH:MM:SS\)]
-            */
+             * New mail [on node FOO] from [SPAM::]BAR
+             *  [\"personal_name\"] [\(HH:MM:SS\)]
+             */
             nam = "VMSmail"; /* assume VMSmail */
             cmd = "MAIL";
             if (txt && (p = strrchr(txt, '(')) > txt && /* discard time */
@@ -147,9 +147,9 @@ char *buf;        /* input: filtered broadcast text */
         } else if (!strncmpi(buf, "new all-in-1", 12)) {
             int i;
             /*
-            New ALL-IN-1 MAIL message [on node FOO] from Personal Name
-            \(BAR@SPAM\) [\(DD-MMM-YYYY HH:MM:SS\)]
-            */
+             * New ALL-IN-1 MAIL message [on node FOO] from Personal Name
+             * \(BAR@SPAM\) [\(DD-MMM-YYYY HH:MM:SS\)]
+             */
             nam = "A1mail";
             cmd = "A1M";
             if (txt && (p = strrchr(txt, '(')) > txt
@@ -159,29 +159,29 @@ char *buf;        /* input: filtered broadcast text */
                 *--p = '\0';
         } else if (!strncmpi(buf, "software tools", 14)) {
             /*
-            Software Tools mail has arrived on FOO from \'BAR\' [in SPAM]
-            */
+             * Software Tools mail has arrived on FOO from \'BAR\' [in SPAM]
+             */
             nam = "STmail";
             cmd = "MSG";
             if (txt && (p = strstri(p, " in ")) != 0) /* specific folder */
                 cmd = strcat(strcpy(cmd_buf, "MSG +"), p + 4);
         } else if (q - 2 >= buf && !strncmpi(q - 2, "mm", 2)) {
             /*
-            {MultiNet\ |PMDF\/}MM mail has arrived on FOO from BAR\n
-            [Subject: subject_text] (PMDF only)
-            */
+             * {MultiNet\ |PMDF\/}MM mail has arrived on FOO from BAR\n
+             * [Subject: subject_text] (PMDF only)
+             */
             nam = "MMmail"; /* MultiNet's version of MM */
             cmd = "MM";     /*{ perhaps "MM READ"? }*/
         } else if (!strncmpi(buf, "wpmail:", 7)) {
             /*
-            WPmail: New mail from BAR.  subject_text
-            */
+             * WPmail: New mail from BAR.  subject_text
+             */
             nam = "WPmail"; /* WordPerfect [sic] Office */
             cmd = "OFFICE/MAIL";
         } else if (!strncmpi(buf, "**m400 mail", 7)) {
             /*
-            **M400 mail waiting**
-            */
+             * **M400 mail waiting**
+             */
             nam = "M400mail"; /* Messenger 400 [not seen] */
             cmd = "M400";
         } else {
@@ -193,14 +193,14 @@ char *buf;        /* input: filtered broadcast text */
 
         if (!txt)
             txt = strcat(strcpy(txt_buf, "Mail for you: "), buf);
-        /*
-         :     end of mail recognition; now check for call-type
-         interruptions...
-         */
+
+    /*
+     * end of mail recognition; now check for call-type interruptions...
+     */
     } else if ((q = strstri(buf, " phoning")) != 0) {
         /*
-        BAR is phoning you [on FOO] \(HH:MM:SS\)
-        */
+         * BAR is phoning you [on FOO] \(HH:MM:SS\)
+         */
         typ = MSG_CALL;
         nam = "Phone call";
         cmd = "PHONE ANSWER";
@@ -210,10 +210,10 @@ char *buf;        /* input: filtered broadcast text */
     } else if ((q = strstri(buf, " talk-daemon")) != 0
                || (q = strstri(buf, " talk_daemon")) != 0) {
         /*
-        Message from TALK-DAEMON@FOO at HH:MM:SS\n
-        Connection request by BAR@SPAM\n
-        \[Respond with: TALK[/OLD] BAR@SPAM\]
-        */
+         * Message from TALK-DAEMON@FOO at HH:MM:SS\n
+         * Connection request by BAR@SPAM\n
+         * \[Respond with: TALK[/OLD] BAR@SPAM\]
+         */
         typ = MSG_CALL;
         nam = "Talk request"; /* MultiNet's TALK and/or TALK/OLD */
         cmd = "TALK";
@@ -239,25 +239,27 @@ char *buf;        /* input: filtered broadcast text */
     } else if (is_jnet_send) { /* sscanf(,"(%[^)])%s -%c",,,)==3 */
     jnet_send:
         /*
-        \(SPAM\)BAR - arbitrary_message_text (from BAR@SPAM)
-        */
+         *      \(SPAM\)BAR - arbitrary_message_text (from BAR@SPAM)
+         */
         typ = MSG_CALL;
         nam = "Bitnet noise"; /* RSCS/NJE message received via JNET */
         Sprintf(cmd_buf, "XYZZY %s@%s", user, node);
         cmd = cmd_buf;
         /*{ perhaps just vanilla SEND instead of XYZZY? }*/
         Sprintf(txt_buf, "Message from %s@%s:%s", user, node,
-                &buf[1 + strlen(node) + 1 + strlen(user) + 2
-                     - 1]); /* "(node)user -" */
+                /* "(node)user -" */
+                &buf[1 + strlen(node) + 1 + strlen(user) + 2 - 1]);
         txt = txt_buf;
-        /*
-         :     end of call recognition; anything else is none-of-the-above...
-         */
+
+    /*
+     * end of call recognition; anything else is none-of-the-above...
+     */
     } else {
     other:
 #endif  /* SHELL */
-        /* arbitrary broadcast: batch job completed, system shutdown imminent,
-         * &c */
+        /* arbitrary broadcast: batch job completed, system shutdown
+         * imminent, &c
+         */
         typ = MSG_OTHER;
         nam = (char *) 0; /*"captured broadcast message"*/
         cmd = (char *) 0;
@@ -300,21 +302,22 @@ register char *buf;            /* in: original text; out: filtered text */
     /* filter the text; restrict consecutive spaces or dots to just two */
     for (p = buf_p = buf; *buf_p; buf_p++) {
         c = *buf_p & '\177';
-        if (c == ' ' || c == '\t' || c == '\n')
+        if (c == ' ' || c == '\t' || c == '\n') {
             if (p == buf || /* ignore leading whitespace */
                 (p >= buf + 2 && *(p - 1) == ' ' && *(p - 2) == ' '))
                 continue;
             else
                 c = ' ';
-        else if (c == '.' || c < ' ' || c == '\177')
+        } else if (c == '.' || c < ' ' || c == '\177') {
             if (p == buf || /* skip leading beeps & such */
                 (p >= buf + 2 && *(p - 1) == '.' && *(p - 2) == '.'))
                 continue;
             else
                 c = '.';
-        else if (c == '%' && /* trim %%% OPCOM verbosity %%% */
-                 p >= buf + 2 && *(p - 1) == '%' && *(p - 2) == '%')
+        else if (c == '%' && /* trim %%% OPCOM verbosity %%% */
+                   p >= buf + 2 && *(p - 1) == '%' && *(p - 2) == '%') {
             continue;
+        }
         *p++ = c;
     }
     *p = '\0'; /* terminate, then strip trailing junk */
@@ -326,7 +329,7 @@ register char *buf;            /* in: original text; out: filtered text */
 static char empty_string[] = "";
 
 /* fetch the text of a captured broadcast, then mangle and decipher it
-*/
+ */
 struct mail_info *parse_next_broadcast() /* called by ckmailstatus(mail.c) */
 {
     short length, msg_type;
@@ -349,7 +352,7 @@ struct mail_info *parse_next_broadcast() /* called by ckmailstatus(mail.c) */
 }
 
 /* spit out any pending broadcast messages whenever we leave
-*/
+ */
 static void flush_broadcasts() /* called from disable_broadcast_trapping() */
 {
     if (broadcasts > 0) {
@@ -369,27 +372,26 @@ static void flush_broadcasts() /* called from disable_broadcast_trapping() */
     }
 }
 
-/* AST routine called when the terminal's associated mailbox receives a
- * message
-*/
+/* AST routine called when terminal's associated mailbox receives a message
+ */
 /*ARGSUSED*/
 static void
 broadcast_ast(dummy) /* called asynchronously by terminal driver */
-int dummy;           /* not used */
+int dummy UNUSED;
 {
     broadcasts++;
 }
 
 /* initialize the broadcast manipulation code; SMG makes this easy
 */
-unsigned long init_broadcast_trapping() /* called by setftty() [once only] */
+unsigned long
+init_broadcast_trapping() /* called by setftty() [once only] */
 {
     unsigned long sts, preserve_screen_flag = 1;
 
-    /* we need a pasteboard to pass to the broadcast setup/teardown routines
-     */
-    sts =
-        smg$create_pasteboard(&pasteboard_id, 0, 0, 0, &preserve_screen_flag);
+    /* we need a pasteboard to pass to the broadcast setup/teardown routines */
+    sts = smg$create_pasteboard(&pasteboard_id, 0, 0, 0,
+                                &preserve_screen_flag);
     if (!vms_ok(sts)) {
         errno = EVMSERR, vaxc$errno = sts;
         raw_print("");
@@ -401,8 +403,9 @@ unsigned long init_broadcast_trapping() /* called by setftty() [once only] */
 }
 
 /* set up the terminal driver to deliver $brkthru data to a mailbox device
-*/
-unsigned long enable_broadcast_trapping() /* called by setftty() */
+ */
+unsigned long
+enable_broadcast_trapping() /* called by setftty() */
 {
     unsigned long sts = 1;
 
@@ -422,8 +425,9 @@ unsigned long enable_broadcast_trapping() /* called by setftty() */
 }
 
 /* return to 'normal'; $brkthru data goes straight to the terminal
-*/
-unsigned long disable_broadcast_trapping() /* called by settty() */
+ */
+unsigned long
+disable_broadcast_trapping() /* called by settty() */
 {
     unsigned long sts = 1;
 
@@ -436,7 +440,9 @@ unsigned long disable_broadcast_trapping() /* called by settty() */
     }
     return sts;
 }
+
 #else  /* MAIL */
+
 /* simple stubs for non-mail configuration */
 unsigned long
 init_broadcast_trapping()
@@ -458,6 +464,7 @@ parse_next_broadcast()
 {
     return 0;
 }
+
 #endif /* MAIL */
 
 /*----------------------------------------------------------------------*/
@@ -538,6 +545,7 @@ void
 wait_synch()
 {
     char dummy[BUFSIZ];
+
     printf("\nPress <return> to continue: ");
     fflush(stdout);
     (void) gets(dummy);
index ccc32d9..75f321c 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 vmsmain.c       $NHDT-Date: 1432512790 2015/05/25 00:13:10 $  $NHDT-Branch: master $:$NHDT-Revision: 1.31 $ */
+/* NetHack 3.6 vmsmain.c       $NHDT-Date: 1449801742 2015/12/11 02:42:22 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.32 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 /* main.c - VMS NetHack */
 
@@ -18,7 +19,7 @@ static void NDECL(byebye);
 #define vms_handler_type unsigned int
 #endif
 extern void FDECL(VAXC$ESTABLISH,
-                  (vms_handler_type (*) (genericptr_t, genericptr_t)));
+                         (vms_handler_type (*) (genericptr_t, genericptr_t)));
 static vms_handler_type FDECL(vms_handler, (genericptr_t, genericptr_t));
 #include <ssdef.h> /* system service status codes */
 #endif
@@ -54,13 +55,13 @@ char *argv[];
     choose_windows(DEFAULT_WINDOW_SYS);
 
 #ifdef CHDIR /* otherwise no chdir() */
-             /*
-              * See if we must change directory to the playground.
-              * (Perhaps hack is installed with privs and playground is
-              *  inaccessible for the player.)
-              * The logical name HACKDIR is overridden by a
-              *  -d command line option (must be the first option given)
-              */
+    /*
+     * See if we must change directory to the playground.
+     * (Perhaps hack is installed with privs and playground is
+     *  inaccessible for the player.)
+     * The logical name HACKDIR is overridden by a
+     *  -d command line option (must be the first option given)
+     */
     dir = nh_getenv("NETHACKDIR");
     if (!dir)
         dir = nh_getenv("HACKDIR");
@@ -225,7 +226,7 @@ attempt_restore:
     moveloop(resuming);
     exit(EXIT_SUCCESS);
     /*NOTREACHED*/
-    return (0);
+    return 0;
 }
 
 static void
@@ -357,8 +358,8 @@ static void
 whoami()
 {
     /*
-     * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
-     *                 2. Use lowercase of $USER  (if 1. fails)
+     * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS;
+     *                      2. Use lowercase of $USER (if 1. fails).
      * The resulting name is overridden by command line options.
      * If everything fails, or if the resulting name is some generic
      * account like "games" then eventually we'll ask him.
@@ -404,8 +405,8 @@ byebye()
 /* Condition handler to prevent byebye's hangup simulation
    from saving the game after a fatal error has occurred.  */
 /*ARGSUSED*/
-static vms_handler_type            /* should be `unsigned long', but the -*/
-    vms_handler(sigargs, mechargs) /*+ prototype in <signal.h> is screwed */
+static vms_handler_type         /* should be `unsigned long', but the -*/
+vms_handler(sigargs, mechargs)  /*+ prototype in <signal.h> is screwed */
 genericptr_t sigargs, mechargs; /* [0] is argc, [1..argc] are the real args */
 {
     unsigned long condition = ((unsigned long *) sigargs)[1];
@@ -416,7 +417,7 @@ genericptr_t sigargs, mechargs; /* [0] is argc, [1..argc] are the real args */
         program_state.done_hup = TRUE; /* pretend hangup has been attempted */
 #ifndef BETA
         if (wizard)
-#endif               /* !BETA */
+#endif
             abort(); /* enter the debugger */
     }
     return SS$_RESIGNAL;
@@ -442,10 +443,6 @@ port_help()
 }
 #endif /* PORT_HELP */
 
-/* for KR1ED config, WIZARD is 0 or 1 and WIZARD_NAME is a string;
-   for usual config, WIZARD is the string and vmsconf.h forces WIZARD_NAME
-   to match it, avoiding need to test which one to use in string ops */
-
 /* validate wizard mode if player has requested access to it */
 boolean
 authorize_wizard_mode()
index 02c7fe7..8cb266c 100644 (file)
@@ -1,4 +1,5 @@
-/* NetHack 3.6 vmsmisc.c       $NHDT-Date: 1432512789 2015/05/25 00:13:09 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
+/* NetHack 3.6 vmsmisc.c       $NHDT-Date: 1524689429 2018/04/25 20:50:29 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.11 $ */
+/*      Copyright (c) 2011 by Robert Patrick Rankin              */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "config.h"
index d115a84..44bd027 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 vmstty.c        $NHDT-Date: 1432512790 2015/05/25 00:13:10 $  $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
+/* NetHack 3.6 vmstty.c        $NHDT-Date: 1449801743 2015/12/11 02:42:23 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.17 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 /* tty.c - (VMS) version */
 
@@ -24,7 +25,7 @@
 #define TT$M_NOBRDCST 0x00020000    /* disable broadcast messages, but  */
 #define TT2$M_BRDCSTMBX 0x00000010  /* catch them in associated mailbox */
 #define TT2$M_APP_KEYPAD 0x00800000 /* application vs numeric keypad mode */
-#endif                              /* __GNUC__ */
+#endif /* __GNUC__ */
 #ifdef USE_QIO_INPUT
 #include <ssdef.h>
 #endif
@@ -44,7 +45,7 @@ static void NDECL(resettty);
 
 #define vms_ok(sts) ((sts) &1)
 #define META(c) ((c) | 0x80) /* 8th bit */
-#define CTRL(c) ((c) &0x1F)
+#define CTRL(c) ((c) & 0x1F)
 #define CMASK(c) (1 << CTRL(c))
 #define LIB$M_CLI_CTRLT CMASK('T') /* 0x00100000 */
 #define LIB$M_CLI_CTRLY CMASK('Y') /* 0x02000000 */
@@ -221,10 +222,10 @@ vms_getchar()
         }
     } else {
         /* abnormal input--either SMG didn't initialize properly or
-           vms_getchar() has been called recursively (via SIGINT handler).
+         * vms_getchar() has been called recursively (via SIGINT handler).
          */
         if (kb != 0)               /* must have been a recursive call */
-            smg$cancel_input(&kb); /*  from an interrupt handler          */
+            smg$cancel_input(&kb); /*  from an interrupt handler      */
         key = getchar();
     }
     --recurse;
@@ -247,7 +248,7 @@ vms_getchar()
  * for two reasons:
  *    1) retain support for arrow keys, and
  *    2) treat other VTxxx function keys as <esc> for aborting
- *     various NetHack prompts.
+ *      various NetHack prompts.
  * The second reason is compelling; otherwise remaining chars of
  * an escape sequence get treated as inappropriate user commands.
  *
@@ -257,26 +258,25 @@ vms_getchar()
 /*=
      -- Summary of VTxxx-style keyboards and transmitted escape sequences. --
 Keypad codes are prefixed by 7 bit (\033 O) or 8 bit SS3:
-        keypad:  PF1 PF2 PF3 PF4       codes:  P   Q   R   S
-                  7   8   9   -                        w   x   y   m
-                  4   5   6   .                        t   u   v   n
-                  1   2   3  :en-:             q   r   s  : :
-                 ...0...  ,  :ter:            ...p...  l  :M:
+        keypad:  PF1 PF2 PF3 PF4       codes:   P   Q   R   S
+                  7   8   9   -                 w   x   y   m
+                  4   5   6   .                 t   u   v   n
+                  1   2   3  :en-:              q   r   s  : :
+                 ...0...  ,  :ter:             ...p...  l  :M:
 Arrows are prefixed by either SS3 or CSI (either 7 or 8 bit), depending on
 whether the terminal is in application or numeric mode (ditto for PF keys):
-        arrows: <up> <dwn> <lft> <rgt>         A   B   D   C
-Additional function keys (vk201/vk401) generate CSI nn ~ (nn is 1 or 2
-digits):
+        arrows: <up> <dwn> <lft> <rgt>          A   B   D   C
+Additional function keys (vk201/vk401) generate CSI nn ~ (nn is 1 or 2 digits):
     vk201 keys:  F6 F7 F8 F9 F10   F11 F12 F13 F14  Help Do   F17 F18 F19 F20
    'nn' digits:  17 18 19 20 21    23  24  25  26    28  29   31  32  33  34
-     alternate:  ^C               ^[  ^H  ^J           (when in VT100 mode)
-   edit keypad: <fnd> <ins> <rmv>     digits:  1   2   3
-                <sel> <prv> <nxt>              4   5   6
+     alternate:  ^C                ^[  ^H  ^J           (when in VT100 mode)
+   edit keypad: <fnd> <ins> <rmv>     digits:   1   2   3
+                <sel> <prv> <nxt>               4   5   6
 VT52 mode:  arrows and PF keys send ESCx where x is in A-D or P-S.
 =*/
 
 static const char *arrow_or_PF = "ABCDPQRS", /* suffix char */
-    *smg_keypad_codes = "PQRSpqrstuvwxyMmlnABDC";
+                  *smg_keypad_codes = "PQRSpqrstuvwxyMmlnABDC";
 /* PF1..PF4,KP0..KP9,enter,dash,comma,dot,up-arrow,down,left,right */
 /* Ultimate return value is (index into smg_keypad_codes[] + 256). */
 
@@ -310,6 +310,7 @@ register int c;
     if (vms_ok(sts) || sts == SS$_TIMEOUT) {
         register int cnt = iosb.trm_offset + iosb.trm_siz + inc;
         register char *p = seq_buf;
+
         if (c == ESC) /* check for 7-bit vt100/ANSI, or vt52 */
             if (*p == '[' || *p == 'O')
                 c = META(CTRL(*p++)), cnt--;
@@ -317,6 +318,7 @@ register int c;
                 c = SS3; /*CSI*/
         if (cnt > 0 && (c == SS3 || (c == CSI && strchr(arrow_or_PF, *p)))) {
             register char *q = strchr(smg_keypad_codes, *p);
+
             if (q)
                 result = 256 + (q - smg_keypad_codes);
             p++, --cnt; /* one more char consumed */
@@ -334,6 +336,7 @@ register int c;
                 }; /* note: there are several missing nn in CSI nn ~ values */
             int nn;
             char *q;
+
             *(p + cnt) = '\0'; /* terminate string */
             q = strchr(p, '~');
             if (q && sscanf(p, "%d~", &nn) == 1) {
@@ -373,7 +376,9 @@ setctty()
     }
 }
 
-static void resettty() /* atexit() routine */
+/* atexit() routine */
+static void
+resettty()
 {
     if (settty_needed) {
         bombing = TRUE; /* don't clear screen; preserve traceback info */
@@ -451,7 +456,8 @@ const char *s;
         disable_broadcast_trapping();
 #if 0  /* let SMG's exit handler do the cleanup (as per doc) */
 /* #ifndef USE_QIO_INPUT */
-       if (kb)  smg$delete_virtual_keyboard(&kb),  kb = 0;
+        if (kb)
+            smg$delete_virtual_keyboard(&kb),  kb = 0;
 #endif /* 0 (!USE_QIO_INPUT) */
         if (ctrl_mask)
             (void) lib$enable_ctrl(&ctrl_mask, 0);
@@ -502,12 +508,16 @@ setftty()
     settty_needed = TRUE;
 }
 
-void intron() /* enable kbd interupts if enabled when game started */
+/* enable kbd interupts if enabled when game started */
+void
+intron()
 {
     intr_char = CTRL('C');
 }
 
-void introff() /* disable kbd interrupts if required*/
+/* disable kbd interrupts if required*/
+void
+introff()
 {
     intr_char = 0;
 }
index 0a9edb4..1b75a86 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 vmsunix.c       $NHDT-Date: 1432512790 2015/05/25 00:13:10 $  $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */
+/* NetHack 3.6 vmsunix.c       $NHDT-Date: 1449801743 2015/12/11 02:42:23 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* This file implements things from unixunix.c, plus related stuff */
@@ -28,7 +29,7 @@ extern void VDECL(lib$signal, (unsigned, ...));
 extern unsigned long sys$setprv();
 extern unsigned long lib$getdvi(), lib$getjpi(), lib$spawn(), lib$attach();
 extern unsigned long smg$init_term_table_by_type(), smg$del_term_table();
-#define vms_ok(sts) ((sts) &1) /* odd => success */
+#define vms_ok(sts) ((sts) & 1) /* odd => success */
 
 /* this could be static; it's only used within this file;
    it won't be used at all if C_LIB$INTIALIZE gets commented out below,
@@ -51,10 +52,10 @@ int fd;
     struct stat buf;
 
     if (fstat(fd, &buf))
-        return (0); /* cannot get status */
+        return 0; /* cannot get status */
 #ifndef INSURANCE
     if (buf.st_size != sizeof(int))
-        return (0); /* not an xlock file */
+        return 0; /* not an xlock file */
 #endif
     (void) time(&date);
     if (date - buf.st_mtime < 3L * 24L * 60L * 60L) { /* recent */
@@ -81,8 +82,8 @@ int fd;
     }
     set_levelfile_name(lock, 0);
     if (delete (lock))
-        return (0); /* cannot remove it */
-    return (1);     /* success! */
+        return 0; /* cannot remove it */
+    return 1;     /* success! */
 }
 
 void
@@ -167,7 +168,7 @@ register char *s;
 int
 vms_getuid()
 {
-    return (getgid() << 16) | getuid();
+    return ((getgid() << 16) | getuid());
 }
 
 #ifndef FAB$C_STMLF
@@ -189,7 +190,7 @@ int fd;
 #else
     rfm = buf.st_fab_rfm;
 #endif
-    return rfm == FAB$C_STMLF;
+    return (boolean) (rfm == FAB$C_STMLF);
 }
 
 /*------*/
@@ -303,7 +304,7 @@ verify_term()
             /* strip trailing blanks */
             while (p > smgdevtyp && *--p == ' ')
                 *p = '\0';
-            /* (void)smg$del_term_table(); */
+            /* (void) smg$del_term_table(); */
             term = smgdevtyp;
         }
     }
@@ -398,9 +399,9 @@ boolean screen_manip;
 
 #ifdef SHELL
 unsigned long dosh_pid = 0, /* this should cover any interactive escape */
-    mail_pid = 0;           /* this only covers the last mail or phone; */
-/*(mail & phone commands aren't expected to leave any process hanging
* around)*/
+              mail_pid = 0; /* this only covers the last mail or phone;
+                               (mail & phone commands aren't expected to
                              leave any process hanging around) */
 
 int
 dosh()
@@ -408,20 +409,18 @@ dosh()
     return vms_doshell("", TRUE); /* call for interactive child process */
 }
 
-/* vms_doshell -- called by dosh() and readmail() */
-
-/* If execstring is not a null string, then it will be executed in a spawned
- */
-/* subprocess, which will then return.  It is for handling mail or phone */
-/* interactive commands, which are only available if both MAIL and SHELL are
+/* vms_doshell -- called by dosh() and readmail()
+ *
+ * If execstring is not a null string, then it will be executed in a spawned
+ * subprocess, which will then return.  It is for handling mail or phone
+ * interactive commands, which are only available if both MAIL and SHELL are
+ * #defined, but we don't bother making the support code conditionalized on
+ * MAIL here, just on SHELL being enabled.
+ *
+ * Normally, all output from this interaction will be 'piped' to the user's
+ * screen (SYS$OUTPUT).  However, if 'screenoutput' is set to FALSE, output
+ * will be piped into oblivion.  Used for silent phone call rejection.
  */
-/* #defined, but we don't bother making the support code conditionalized on */
-/* MAIL here, just on SHELL being enabled. */
-
-/* Normally, all output from this interaction will be 'piped' to the user's */
-/* screen (SYS$OUTPUT).  However, if 'screenoutput' is set to FALSE, output */
-/* will be piped into oblivion.  Used for silent phone call rejection. */
-
 int
 vms_doshell(execstring, screenoutput)
 const char *execstring;
@@ -449,9 +448,8 @@ boolean screenoutput;
     }
 
     hack_escape(screenoutput,
-                command ? (const char *) 0 : "  \"Escaping\" into a "
-                                             "subprocess; LOGOUT to "
-                                             "reconnect and resume play. ");
+                command ? (const char *) 0
+ : "  \"Escaping\" into a subprocess; LOGOUT to reconnect and resume play. ");
 
     if (command || !dosh_pid || !vms_ok(status = lib$attach(&dosh_pid))) {
 #ifdef CHDIR
@@ -483,7 +481,7 @@ boolean screenoutput;
 
 #ifdef SUSPEND
 /* dosuspend() -- if we're a subprocess, attach to our parent;
- *             if not, there's nothing we can do.
+ *                if not, there's nothing we can do.
  */
 int
 dosuspend()
@@ -494,15 +492,15 @@ dosuspend()
     if (owner_pid == -1) /* need to check for parent */
         owner_pid = getppid();
     if (owner_pid == 0) {
-        pline("  No parent process.  Use '!' to Spawn, 'S' to Save,  or 'Q' "
             "to Quit. ");
+        pline(
"  No parent process.  Use '!' to Spawn, 'S' to Save, or '#quit' to Quit. ");
         mark_synch();
         return 0;
     }
 
     /* restore normal tty environment & clear screen */
-    hack_escape(1, " Attaching to parent process; use the ATTACH command to "
-                   "resume play. ");
+    hack_escape(1,
+     " Attaching to parent process; use the ATTACH command to resume play. ");
 
     status = lib$attach(&owner_pid); /* connect to parent */
 
@@ -535,7 +533,7 @@ char ***array;
     while (indx >= *asize - 1) {
         oldsize = *asize;
         *asize += 5;
-        newarray = (char **) alloc(*asize * sizeof(char *));
+        newarray = (char **) alloc(*asize * sizeof (char *));
         /* poor man's realloc() */
         for (i = 0; i < *asize; ++i)
             newarray[i] = (i < oldsize) ? (*array)[i] : 0;
@@ -543,7 +541,7 @@ char ***array;
             free((genericptr_t) *array);
         *array = newarray;
     }
-    (*array)[indx] = strcpy((char *) alloc(strlen(name) + 1), name);
+    (*array)[indx] = dupstr(name);
 }
 
 struct dsc {
@@ -551,8 +549,7 @@ struct dsc {
     char *adr;
 };                             /* descriptor */
 typedef unsigned long vmscond; /* vms condition value */
-vmscond FDECL(lib$find_file,
-              (const struct dsc *, struct dsc *, genericptr *));
+vmscond FDECL(lib$find_file, (const struct dsc *, struct dsc *, genericptr *));
 vmscond FDECL(lib$find_file_end, (void **));
 
 /* collect a list of character names from all save files for this player */
@@ -605,15 +602,11 @@ int how; /* 1: exit after traceback; 2: stay in debugger */
     union dbgcmd {
         struct ascic {
             unsigned char len; /* 8-bit length prefix */
-            char
-                str[79]; /* could be up to 255, but we don't need that much */
+            char str[79]; /* could be up to 255, but we don't need so much */
         } cmd_fields;
         char cmd[1 + 79];
     };
-#define DBGCMD(arg)                                  \
-    {                                                \
-        (unsigned char)(sizeof arg - sizeof ""), arg \
-    }
+#define DBGCMD(arg) { (unsigned char) (sizeof arg - sizeof ""), arg }
     static union dbgcmd dbg[3] = {
         /* prologue for less verbose feedback (when combined with
            $ define/User_mode dbg$output _NL: ) */
@@ -709,40 +702,40 @@ struct eiha { /* extended image header activation block, $EIHADEF */
 };
 
 /*
- *     We're going to use lib$initialize, not because we need or
- *     want to be called before main(), but because one of the
- *     arguments passed to a lib$initialize callback is a pointer
- *     to the image header (somewhat complex data structure which
- *     includes the memory location(s) of where to start executing)
- *     of the program being initialized.  It comes in two flavors,
- *     one used by VAX and the other by Alpha and IA64.
+ *      We're going to use lib$initialize, not because we need or
+ *      want to be called before main(), but because one of the
+ *      arguments passed to a lib$initialize callback is a pointer
+ *      to the image header (somewhat complex data structure which
+ *      includes the memory location(s) of where to start executing)
+ *      of the program being initialized.  It comes in two flavors,
+ *      one used by VAX and the other by Alpha and IA64.
  *
- *     An image can have up to three transfer addresses; one of them
- *     decides whether to run under debugger control (RUN/Debug, or
- *     LINK/Debug + plain RUN), another handles lib$initialize calls
- *     if that's used, and the last is to start the program itself
- *     (a jacket built around main() for code compiled with DEC C).
- *     They aren't always all present; some might be zero/null.
- *     A shareable image (pre-linked library) usually won't have any,
- *     but can have a separate initializer (not of interest here).
+ *      An image can have up to three transfer addresses; one of them
+ *      decides whether to run under debugger control (RUN/Debug, or
+ *      LINK/Debug + plain RUN), another handles lib$initialize calls
+ *      if that's used, and the last is to start the program itself
+ *      (a jacket built around main() for code compiled with DEC C).
+ *      They aren't always all present; some might be zero/null.
+ *      A shareable image (pre-linked library) usually won't have any,
+ *      but can have a separate initializer (not of interest here).
  *
- *     The transfer targets don't have fixed slots but do occur in a
- *     particular order:
- *                   link      link     lib$initialize lib$initialize
- *         sharable  /noTrace  /Trace    + /noTrace     + /Traceback
- *     1:  (none)    main      debugger  init-handler   debugger
- *     2:                      main      main           init-handler
- *     3:                                               main
+ *      The transfer targets don't have fixed slots but do occur in a
+ *      particular order:
+ *                    link      link     lib$initialize lib$initialize
+ *          sharable  /noTrace  /Trace    + /noTrace     + /Traceback
+ *      1:  (none)    main      debugger  init-handler   debugger
+ *      2:                      main      main           init-handler
+ *      3:                                               main
  *
- *     We check whether the first transfer address is SYS$IMGSTA().
- *     If it is, the debugger should be available to catch SS$_DEBUG
- *     exception even when we don't start up under debugger control.
- *     One extra complication:  if we *do* start up under debugger
- *     control, the first address in the in-memory copy of the image
- *     header will be changed from sys$imgsta() to a value in system
- *     space.  [I don't know how to reference that one symbolically,
- *     so I'm going to treat any address in system space as meaning
- *     that the debugger is available.  pr]
+ *      We check whether the first transfer address is SYS$IMGSTA().
+ *      If it is, the debugger should be available to catch SS$_DEBUG
+ *      exception even when we don't start up under debugger control.
+ *      One extra complication:  if we *do* start up under debugger
+ *      control, the first address in the in-memory copy of the image
+ *      header will be changed from sys$imgsta() to a value in system
+ *      space.  [I don't know how to reference that one symbolically,
+ *      so I'm going to treat any address in system space as meaning
+ *      that the debugger is available.  pr]
  */
 
 /* called via lib$initialize during image activation:  before main() and
@@ -760,14 +753,15 @@ const unsigned char *imghdr;
     unsigned long trnadr1;
 
     (void) lib$establish(lib$sig_to_ret); /* set up condition handler */
-                                          /*
-                                           * Check the first of three transfer addresses to see whether
-                                           * it is SYS$IMGSTA().  Note that they come from a file,
-                                           * where they reside as longword or quadword integers rather
-                                           * than function pointers.  (Basically just a C type issue;
-                                           * casting back and forth between integer and pointer doesn't
-                                           * change any bits for the architectures VMS runs on.)
-                                           */
+
+    /*
+     * Check the first of three transfer addresses to see whether
+     * it is SYS$IMGSTA().  Note that they come from a file,
+     * where they reside as longword or quadword integers rather
+     * than function pointers.  (Basically just a C type issue;
+     * casting back and forth between integer and pointer doesn't
+     * change any bits for the architectures VMS runs on.)
+     */
     debuggable = 0;
     /* start with a guess rather than bothering to figure out architecture */
     vax_hdr = (struct ihd *) imghdr;
@@ -848,10 +842,11 @@ const unsigned long lib$initialize[] = { (unsigned long) (void *) vmsexeini };
 #ifdef __DECC
 #pragma extern_model restore /* pop previous mode */
 #endif
-/*     We also need to link against a linker options file containing:
+/*      We also need to link against a linker options file containing:
 sys$library:starlet.olb/Include=(lib$initialize)
 psect_attr=lib$initialize, Con,Usr,noPic,Rel,Gbl,noShr,noExe,Rd,noWrt,Long
  */
 #endif /* C_LIB$INITIALIZE */
 /* End of debugger hackery. */
+
 /*vmsunix.c*/
index 1896d45..b3c0689 100644 (file)
@@ -1,3 +1,7 @@
+# $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$
+# Copyright (c) 2007 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
+#
 # Sample config file for win32 NetHack
 # A '#' at the beginning of a line means the rest of the line is a comment.
 #
index 812da47..98730db 100644 (file)
@@ -1,4 +1,5 @@
-/* NetHack 3.6 mhcmd.c $NHDT-Date: 1432512800 2015/05/25 00:13:20 $  $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */
+/* NetHack 3.6 mhcmd.c $NHDT-Date: 1524689383 2018/04/25 20:49:43 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $ */
+/*      Copyright (c) 2009 by Michael Allison              */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "winMS.h"
index feaf605..9a5fada 100644 (file)
@@ -1,3 +1,5 @@
+/* NetHack 3.6  mhcmd.h       $NHDT-Date: 1524689383 2018/04/25 20:49:43 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.2 $ */
+/*      Copyright (c) 2002 by Michael Allison              */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #ifndef MSWINCMDWindow_h
index 58af9f7..98abd01 100644 (file)
@@ -487,7 +487,7 @@ MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
         hangup(1);
 #else
         dosave0();
-        terminate(EXIT_SUCCESS);
+        nh_terminate(EXIT_SUCCESS);
 #endif
     }
         return 0;
@@ -503,7 +503,7 @@ MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
         free((PNHMainWindow) GetWindowLong(hWnd, GWL_USERDATA));
         SetWindowLong(hWnd, GWL_USERDATA, (LONG) 0);
 
-        terminate(EXIT_SUCCESS);
+        nh_terminate(EXIT_SUCCESS);
     } break;
 
     /*-----------------------------------------------------------------------*/
index 4637b3e..4aa5f19 100644 (file)
@@ -1,3 +1,5 @@
+/* NetHack 3.6  mhmenu.c       $NHDT-Date: 1524689398 2018/04/25 20:49:58 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.28 $ */
+/*      Copyright (c) 2009 by Michael Allison              */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "winMS.h"
index 5a0ff98..7137a06 100644 (file)
@@ -73,13 +73,8 @@ struct window_procs mswin_procs = {
     /* other defs that really should go away (they're tty specific) */
     mswin_start_screen, mswin_end_screen, mswin_outrip,
     mswin_preference_update, genl_getmsghistory, genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init, genl_status_finish, genl_status_enablefield,
     genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_no,
 };
 
@@ -680,7 +675,7 @@ mswin_exit_nhwindows(const char *str)
     // Don't do any of this (?) - exit_nhwindows does not terminate
     // the application
     // DestroyWindow(GetNHApp()->hMainWnd);
-    // terminate(EXIT_SUCCESS);
+    // nh_terminate(EXIT_SUCCESS);
 }
 
 /* Prepare the window to be suspended. */
@@ -1726,7 +1721,7 @@ bail(const char *mesg)
 {
     clearlocks();
     mswin_exit_nhwindows(mesg);
-    terminate(EXIT_SUCCESS);
+    nh_terminate(EXIT_SUCCESS);
     /*NOTREACHED*/
 }
 
index 420dfec..917fa39 100644 (file)
@@ -1,3 +1,7 @@
+/* NetHack 3.6  newres.h       $NHDT-Date: 1524689383 2018/04/25 20:49:43 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.3 $ */
+/*      Copyright (c) 2003 by Michael Allison              */
+/* NetHack may be freely redistributed.  See license for details. */
+
 #ifndef __NEWRES_H__
 #define __NEWRES_H__
 
index e33a294..7930206 100644 (file)
@@ -284,8 +284,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 3,5,0,0
- PRODUCTVERSION 3,5,0,0
+ FILEVERSION 3,6,1,0
+ PRODUCTVERSION 3,6,1,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x9L
@@ -300,17 +300,17 @@ BEGIN
     BEGIN
         BLOCK "040904b0"
         BEGIN
-            VALUE "Comments", "NetHack 3.6.0 for Windows CE\0"
+            VALUE "Comments", "NetHack 3.6.1 for Windows CE\0"
             VALUE "CompanyName", " \0"
             VALUE "FileDescription", "nethackm\0"
-            VALUE "FileVersion", "3, 5, 0, 0\0"
+            VALUE "FileVersion", "3, 6, 1, 0\0"
             VALUE "InternalName", "nethackm\0"
-            VALUE "LegalCopyright", "Copyright © 1985-2009\0"
+            VALUE "LegalCopyright", "Copyright © 1985-2018\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "nethackm.exe\0"
             VALUE "PrivateBuild", "090914\0"
             VALUE "ProductName", "NetHack\0"
-            VALUE "ProductVersion", "3, 5, 0, 0\0"
+            VALUE "ProductVersion", "3, 6, 1, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index bcff4d6..094c4f2 100644 (file)
@@ -260,8 +260,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 3,5,0,0
- PRODUCTVERSION 3,5,0,0
+ FILEVERSION 3,6,1,0
+ PRODUCTVERSION 3,6,1,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x9L
@@ -276,17 +276,17 @@ BEGIN
     BEGIN
         BLOCK "040904b0"
         BEGIN
-            VALUE "Comments", "NetHack 3.6.0 for Smartphone 2002\0"
+            VALUE "Comments", "NetHack 3.6.1 for Smartphone 2002\0"
             VALUE "CompanyName", " \0"
             VALUE "FileDescription", "nethackm\0"
-            VALUE "FileVersion", "3, 5, 0, 0\0"
+            VALUE "FileVersion", "3, 6, 1, 0\0"
             VALUE "InternalName", "nethackm\0"
-            VALUE "LegalCopyright", "Copyright © 1985-2010\0"
+            VALUE "LegalCopyright", "Copyright © 1985-2018\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "nethackm.exe\0"
             VALUE "PrivateBuild", "090914\0"
             VALUE "ProductName", "NetHack For Smartphone\0"
-            VALUE "ProductVersion", "3, 5, 0, 0\0"
+            VALUE "ProductVersion", "3, 6, 1, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index 1a66ddc..3551e43 100644 (file)
@@ -1,11 +1,11 @@
-         Copyright (c) NetHack Development Team 1990-2015
+         Copyright (c) NetHack Development Team 1990-2018
          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. XP may work but is untested)
          ==============================================================
-          Last revision: $NHDT-Date: 1447979773 2015/11/20 00:36:13 $
+          Last revision: $NHDT-Date: 1524317622 2018/04/21 13:33:42 $
 
 Credit for the porting of NetHack to the Win32 Console Subsystem goes to 
 the NT Porting Team started by Michael Allison.
@@ -14,60 +14,76 @@ Credit for the Win32 Graphical version of NetHack (aka "NetHack for
 Windows" or NetHackW) goes to Alex Kompel who initially developed and
 contributed the port.
 
-The PC Windows porting team consisting of Michael Allison, David Cohrs, 
-Alex Kompel, Dion Nicolaas, Yitzhak Sapir, and Janet Walz maintained the 
-tty and graphical win32 versions of NetHack 3.6.0.
+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.1.
 
 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 2013 Express
-    The current NetHack code has not been tested with earlier versions 
-    of the compiler.
-    
+  o A copy of Microsoft Visual Studio 2017 Community Edition
+    OR        Microsoft Visual Studio 2015 Express
+
     OR
 
-  o A copy of MinGW. MinGW is a collection of header 
+  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
     Graphical version.
-    
-In addition to the makefiles that allow you to build NetHack from the
-command line, there is also a set of project files and a workspace file
-that allow you to build the Windows Graphical version from Microsoft
-Visual C's IDE (Integrated Development Environment.)
 
+/--------------------------------------------------------\
+| Building And Running Using Visual Studio 2015 or       |
+|                            Visual Studio 2017          |
+\--------------------------------------------------------/
+
+If you are NOT using Visual Studio 2015 or Visual Studio 2017 IDE, or
+you prefer to build using a Make utility and a Makefile proceed
+to "Building Using Make".
+
+When using either Visual Studio 2015 or Visual Studio 2017, you simply 
+need to load the solution file within the IDE, build the solution and 
+run the version of NetHack you wish to run.
+
+The Visual Studio 2015 NetHack solution file can be found here:
+    win\win32\vs2015\NetHack.sln
+
+The Visual Studio 2017 NetHack solution file can be found here:
+    win\win32\vs2017\NetHack.sln
+
+So the steps are:
+    1. Launch the IDE.
+    2. Open the appropriate solution file.
+    3. Select the build configuration you wish to use (Release, Debug, etc.).
+    4. From the build menu, select build solution.
+    5. Type F5 to start debugging.
+
+You can also build all the projects for all platforms and configurations
+using a "build.bat" batch file found in the same directory as the solution.
+
+Open a developer command prompt for the version of Visual Studio you are
+using.  Change to the appropriate directory (i.e. win\win32\vs2015 for
+VS2015 builds, win\win32\vs2017 for VS2017 builds) and run "build.bat".
 
 /-----------------------------------\
-| FIRST STEP - MOVING THINGS AROUND |
+| Building Using Make               |
 \-----------------------------------/
 
-The first step in building either version of NetHack 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
-       nhsetup
+        cd sys\winnt
+        nhsetup
 
 From a Windows explorer window:
-       double-click on nhsetup.bat
-
-A "binary" directory will be created off the top of the NetHack source
-tree to house the completed build.
-
-A build subdirectory will also be created off the top of the NetHack 
-source tree, and many files appropriate for a graphical build will be 
-moved there.
+        double-click on nhsetup.bat
 
 If you wish to build from the command line, proceed to "BUILDING FROM
 THE COMMAND LINE."
 
-If you wish to build using Visual C's IDE, proceed now to "BUILDING
-USING VISUAL C'S IDE."
-
 /--------------------------------\
 | BUILDING FROM THE COMMAND LINE |
 \--------------------------------/
@@ -90,7 +106,7 @@ 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 
 run on the most number of existing Windows environments.
 
-NetHack's save files and bones files in the 3.6.0 release have not 
+NetHack's save files and bones files in the 3.6.1 release have not 
 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.
@@ -103,10 +119,11 @@ I. Dispelling the Myths:
 
     We have provided a Makefile for each of the following compilers:
 
-        o Microsoft Visual Studio 2013 Express Visual C++ Compiler
+        o Microsoft Visual Studio 2015 or 2017 C++ Compiler
+          The Community Editions are fine and available at no cost
         o MinGW 2.0 (with GCC 3.2)
 
-    The Microsoft Visual Studio 2013 Express Makefile was created for use 
+    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. 
@@ -128,67 +145,10 @@ Setting Up
     all the necessary environment variables for the compiler environment
     are set correctly. 
 
-    Visual Studio 2013 Express
-
-    The installation should have placed a command prompt option on the 
-    Start menus that is properly configured for building: 
-                 From
-                     Start | All Programs | Microsoft Visual Studio 2013 Express
-                 Select
-                     Visual Studio Command Prompt 2013
-    Anyway, once you are at a command prompt (cmd.exe) regardless of how you
-    got there, you can use one of the following sets of commands to prepare 
-    your environment for building:
-
-    For a 32-bit x86 build (like the official binary):
-        cd "\Program Files (x86)\Microsoft Visual Studio 12.0\VC"
-        vcvarsall x86
-
-    For a 64-bit x64 build:
-        cd "\Program Files (x86)\Microsoft Visual Studio 12.0\VC"
-        vcvarsall x86_amd64
-
-      -----------------------------------------------------------
-      vcvarsall.bat | Compiler   | Build-computer | Build output
-      argument      |            | architecture   | architecture
-      --------------+------------+----------------+--------------
-      X86           | x86 32-bit | x86, x64       | x86
-                    | native     |                |
-      --------------+------------+----------------+--------------
-      x86_amd64     | x64 on x86 | x86, x64       | x64
-                    | cross      |                |
-      --------------+------------+----------------+--------------
-      amd64         | x64 64-bit | x64            | x64
-                    | native     |                |
-      --------------+------------+----------------+--------------
-      amd64_x86     | x86 on     | x64            | x86
-                    | x64 cross  |                |
-      -----------------------------------------------------------
-
     Change your current directory to the src subfolder of the nethack 
     source tree.
         cd src
 
-    At this time, if you are determined to build an x64 version
-    with the Microsoft Visual Studio 2013 compiler,
-    one extra NetHack-specific step is needed. Edit the Makefile in the src 
-    directory and change this in the section marked as 1.:
-           #
-           # 64 bit
-           #TARGET_CPU=x64
-           #
-           # 32 bit
-           TARGET_CPU=x86
-    to this:
-           #
-           # 64 bit
-           TARGET_CPU=x64
-           #
-           # 32 bit
-           #TARGET_CPU=x86
-    
-
     GCC 
 
     For the GCC Makefile, add <mingw>\bin to your path, where <mingw> 
@@ -236,9 +196,9 @@ Setting Up
                                           |    |          |
                                        share  winnt      win32 
  
-    Check the file "Files" in your top level directory for an exact
-    listing of what file is in which directory.  In order for the
-    Makefiles to work, all the source files must be in the proper
+    Check the file "Files" in your top level directory for a more 
+    complete listing of what file is in which directory.  In order for 
+    the Makefiles to work, all the source files must be in the proper
     locations.
 
     If you downloaded or ftp'd the sources from a UNIX system, the lines
@@ -272,7 +232,7 @@ Compiling
 
 5.  Now that everything is set up...
 
-    For Visual Studio 2013 Express, as mentioned above, you should now be
+    For the Visual Studio compiler, as mentioned above, you should now be
     at the command prompt to carry out the build and your current 
     directory should be the src subdirectory in the NetHack source tree.
 
@@ -323,201 +283,8 @@ Notes:
       - a 64-bit (x64) .exe file, 
         which should run on any 64-bit Windows O/S.
 
-    To run NetHack, proceed to RUNNING NETHACK.
-
-/-------------------------------------------------\
-| BUILDING USING VISUAL STUDIO 2013 EXPRESS IDE   |
-\-------------------------------------------------/
-
-Only the native port built on the Windows API, or Graphical
-NetHack, can be built using the Visual Studo 2013 Express IDE.
-
-I. Dispelling the Myths:
-
-    Compiling NetHack using the Visual C IDE is straightforward, as long
-    as you have your compiler and tools correctly installed.
-
-    It is again assumed that you already changed your directory to
-    sys\winnt and executed:
-       nhsetup
-    as described at the top of this document. If you didn't, you must go
-    back and do so before proceeding.
-
-II. To compile your copy of NetHack for Windows on a Windows machine 
-    using the Visual Studio 2013 Express IDE:
-
-Setting Up
-
-1.  It almost goes without saying that you should make sure that your
-    tools are set up and running correctly. (For the Microsoft Visual
-    Studio 2013 ExpressIDE it should correctly fire up when you choose 
-    it:
-        Start | All Programs | Microsoft Visual Studio 2013 Express
-    and select 
-        Visual C++ 2013 Express
-
-2.  Make sure all the NetHack files are in the appropriate directory
-    structure.  You should have a main directory with subdirectories
-    dat, doc, include, src, sys\share, sys\winnt, util, win\win32, and
-    at this point you should also have a build directory and a binary
-    directory (both created by nhsetup.bat executed from sys\winnt
-    earlier.)
-
-    Other subdirectories may also be included in your distribution, but
-    they are not necessary for building the graphical version of NetHack
-    (you can delete them to save space if you wish.)
-
-    Required Directories for building Graphical NetHack with the Visual
-    C IDE:
-
-                            top
-                             |
-        -----------------------------------------/ /--------------- 
-        |     |    |      |     |   |      |           |       |
-       util  dat  doc  include src sys    win        build    binary
-                                    |      |
-                                  ------   -----
-                                  |    |       |    
-                               share  winnt  win32
-    Those last two (build and binary) are created during the building
-    process.  They are not disributed as part of the NetHack source 
-    distribution.  nhsetup.bat creates the build directory and moves a
-    few files into it, including the Visual C project files.  The
-    "binary" directory will house everything you need to play the game
-    after building is complete.
-
-    Check the file "Files" in your top level directory for an exact
-    listing of what file is in which directory.  In order for the build
-    process to work, all the source files must be in the proper
-    locations.  Remember that nhsetup.bat moves/copies many files around
-    to their intended locations for building NetHack.
-
-    If you downloaded or ftp'd the sources from a UNIX system, the lines
-    will probably end in UNIX-style newlines, instead of the carriage
-    return and line feed pairs used by Windows.  Visual C project files
-    and workspace files (dsp and dsw files) in particular need to have
-    their lines end in carriage-return-line-feed or they won't work
-    properly.
-
-3.  Ready your tool.
-    Note: It's possible to build a graphical version using the Makefile,
-    as explained above. However, the IDE build has full game
-    functionality.
-
-    Start the Visual Studio 2013 Express IDE:
-        Start | All Programs | Microsoft Visual Studio 2013 Express
-    and select 
-        Visual C++ 2013 Express
-
-    In the Visual C++ 2013 Express IDE menus, choose:
-        File | Open Project/Solution
-     
-
-4.  Set up for the build.
-
-    In the Visual C dialog box, navigate to the top of
-    your NetHack source directory.
-
-    In there, highlight "nethack.sln" for Visual C++ 2013 Express Edition 
-    and click on Open.
-
-    Once the workspace or solution has been opened, you should see 
-    the following list in the Visual C selection left pane:
-      + dgncomp
-      + dgnstuff
-      + dlb_main
-      + levcomp
-      + levstuff
-      + makedefs
-      + nethackw
-      + recover
-      + tile2bmp
-      + tilemap
-      + uudecode
-
-    On the Visual C++ 2013 Express IDE menus, NetHackW should be the startup
-    project in bold, but if it isn't make it so by right-clicking and
-    choosing "set as Startup Project."
-
-    In Visual C 2013 Express IDE menus right-click on 
-    "Solution NetHack (14 Projects)" and select "Configuration Manager."
-
-    Set the "Active Solution Configuration" to either 
-        Debug
-    or
-        Release
-    and click the "Close" button.
-
-
-    The Release build of NetHackW which does not contain all the 
-    debugging information and is smaller, and runs slightly quicker.  
-    The Debug build of NetHackW will spend time writing debug information 
-    to the disk as the game is played. Unless you are debugging or 
-    enhancing NetHack for Windows, you probably will want to choose the 
-    Release build.
-
-Building
-    
-5.  Start your build.
-
-    On the Visual C++ Express IDE menus once again, choose:
-        Debug | Build Solution
-    or press <F7> to accomplish the same thing.
-
-    That starts the build.  It is likely that the IDE message window 
-    where you are doing the compiling will be occupied for a while.
-
-6.  If all has gone well to this point, you should now have a NetHack
-    executable called NetHackW.exe in the "binary" directory, along with
-    all the support files that it needs.
-
-/-----------------\
-| RUNNING NETHACK |
-\-----------------/
-
-I. Checking the installation:
-    Make sure all of the support files -- Guidebook.txt, license,
-    Defaults.nh, NetHack.exe or NetHackW.exe, nhdat, and recover.exe --
-    were copied to the game directory.  If not, move them there
-    yourself.
-
-    Edit Defaults.nh to reflect your particular setup and personal 
-    preferences, by following the comments.  As with all releases since
-    3.2.1, HACKDIR defaults to the same directory as that where the
-    NetHack.exe or NetHackW.exe executable resides.  You only need to
-    set HACKDIR in defaults.nh if, for some reason, you wish to override
-    that (be careful).
-  
-II. Executing the game
-
-1.  Running from the command prompt:
-
-    If you add the directory containing the NetHack executable to your
-    PATH, you can just type "nethack" or "nethack -umike" or "nethackw"
-    or "nethackw -umike" to start it up.  Alternatively, you can
-    explicitly invoke it with a command such as
-    "c:\nethack\binary\nethack.exe" or "c:\nethack\binary\nethackw.exe"
-    (specifying whatever drive and directory your NetHack executable
-    resides in) each time.
-
-2.  Running from a Windows shortcut.
-
-    If you will be running it by launching it from a shortcut, just use
-    the following information when setting up the shortcut.
-
-        Description      :  NetHack 3.6.0 Console version
-        Command Line     :  C:\NETHACK\BINARY\NETHACK.EXE
-
-        Description      :  NetHack 3.6.0 Graphical Interface
-         Command Line     :  C:\NETHACK\BINARY\NETHACKW.EXE
-
-   (changing the directory to the appropriate one of course)
-
-III. Play NetHack.  If it works, you're done!
-
+NetHack.exe is the tty version. NetHackW.exe is the graphical version.
+Play NetHack. 
 
 PROBLEMS
 
index e28a3af..5be03e2 100644 (file)
@@ -1,4 +1,6 @@
-# NetHack 3.6  Makefile.gcc    $NHDT-Date: 1434804544 2015/06/20 12:49:04 $  $NHDT-Branch: win32-x64-working $:$NHDT-Revision: 1.53 $
+# NetHack 3.6  Makefile.gcc    $NHDT-Date: 1524689356 2018/04/25 20:49:16 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.54 $
+# Copyright (c) 2010 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
 #
 #==============================================================================
 #
index a5eaa83..f38de13 100644 (file)
@@ -1,5 +1,5 @@
-# NetHack 3.6  Makefile.msc    $NHDT-Date: 1447992736 2015/11/20 04:12:16 $  $NHDT-Branch: master $:$NHDT-Revision: 1.100 $ */
-#       Copyright (c) NetHack PC Development Team 1993-2015
+# NetHack 3.6  Makefile.msc    $NHDT-Date: 1520858848 2018/03/12 12:47:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.112 $ */
+#       Copyright (c) NetHack PC Development Team 1993-2018
 #
 #==============================================================================
 # Build Tools Environment
@@ -9,7 +9,7 @@
 #       Visual Studio Compilers Tested:
 #            - Microsoft Visual Studio 2010 Express, with the Platform SDK
 #            - Microsoft Visual Studio 2013 Express
-#            - Microsoft Visual Studio 2015 Express (pre-release)
+#            - Microsoft Visual Studio 2017 Community Edition
 #
 #==============================================================================
 #   This is used for building two versions of NetHack:
 #
 #   If you have any questions read the sys/winnt/Install.nt file included 
 #   with the distribution.
-#==============================================================================
-# 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.
-#
-
-!IF "$(_NMAKE_VER)" == "14.00.22310.1"
-VSVER=2015
-!ELSEIF "$(_NMAKE_VER)" == "12.00.21005.1"
-VSVER=2013
-!ELSEIF "$(_NMAKE_VER)" == "11.00.50727.1"
-VSVER=2012
-!ELSEIF "$(_NMAKE_VER)" == "10.00.40219.01"
-VSVER=2010
-!ELSE
-VSVER=0000             #untested version
-!ENDIF
-
-#==============================================================================
+#========================================================================================
 # BUILD DECISIONS SECTION
 #
-# There are currently only 3 decisions that you have to make.
-#      1. 32-bit or 64-bit?
-#      2. Where do you want your build to end up?
-#      3. Do you want debug information in the executable?
-#
-#---------------------------------------------------------------
-#==============================================================================
-# 1. 32-bit or 64-bit? (comment/uncomment appropriate TARGET_CPU line)
+# There are currently only 3 decisions that you can choose to make, and none are 
+# required:
+#      1. Where do you want your build to end up?
+#      2. Do you want debug information in the executable?
+#      3. Do you want to explicitly override auto-detection of a 32-bit or 64-bit target?
 #
+#-----------------------------------------------------------------------------------------
+#=========================================================================================
 
-!IF ($(VSVER) >= 2012)
-#
-# 64 bit
-#TARGET_CPU=x64
-#
-# 32 bit
-TARGET_CPU=x86
-
-!ELSE
-# For VS2010 use "setenv /x86" or "setenv /x64" before invoking make process
-# DO NOT DELETE THE FOLLOWING LINE
-!include <win32.mak>
-!ENDIF
-#
 #---------------------------------------------------------------
-# 2. Where do you want the game to be built (which folder)?
-#
-
-GAMEDIR = ..\binary               # Game directory
+# 1. Where do you want the game to be built (which folder)?
 
-#
+GAMEDIR = ..\binary               # Default game build directory
 #---------------------------------------------------------------
-# 3. Do you want debug information in the executable?
-#
+# 2. Do you want debug information available to the executable?
   
 DEBUGINFO = Y
 
+#---------------------------------------------------------------
+# 3. This Makefile will attempt to auto-detect your selected target architecture
+#    based on Visual Studio command prompt configuration settins etc.
+#    However, if you want to manually override generation of a 
+#    32-bit or 64-bit build target, you can uncomment the apppropriate
+#    TARGET_CPU line below.
+#
+#TARGET_CPU=x64
+#TARGET_CPU=x86
+
 #==============================================================================
 # This marks the end of the BUILD DECISIONS section.
 #==============================================================================
@@ -176,24 +150,94 @@ DLBFLG =
 #==========================================
 #==========================================
 
+# 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.
+#
+
+#!MESSAGE $(MAKEFLAGS)
+#!MESSAGE $(MAKEDIR)
+#!MESSAGE $(MAKE)
+
+MAKEVERSION=$(_NMAKE_VER:.= )
+MAKEVERSION=$(MAKEVERSION: =)
+#!MESSAGE $(_NMAKE_VER)
+#!MESSAGE $(MAKEVERSION)
+
+VSNEWEST=2017
+!IF ($(MAKEVERSION) < 1000000000)
+VSVER=0000             #untested ancient version
+!ELSEIF ($(MAKEVERSION) > 1000000000) && ($(MAKEVERSION) < 1100000000)
+VSVER=2010
+!ELSEIF ($(MAKEVERSION) > 1100000000) && ($(MAKEVERSION) < 1200000000)
+VSVER=2012
+!ELSEIF ($(MAKEVERSION) > 1200000000) && ($(MAKEVERSION) < 1400000000)
+VSVER=2013
+!ELSEIF ($(MAKEVERSION) > 1400000000) && ($(MAKEVERSION) < 1411000000)
+VSVER=2015
+!ELSEIF ($(MAKEVERSION) > 1411000000) && ($(MAKEVERSION) < 1412258351)
+VSVER=$(VSNEWEST)
+!ELSEIF ($(MAKEVERSION) > 1412258350)
+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.
+!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
+!MESSAGE Makefile, so we'll stop now.
+!ERROR Untested old Visual Studio version with NMAKE $(_NMAKE_VER).
+!ENDIF
+
+!IF ($(VSVER) == 2010)
+# For VS2010 use "setenv /x86" or "setenv /x64" before invoking make process
+# DO NOT DELETE THE FOLLOWING LINE
+!include <win32.mak>
+! ENDIF
+
+#----------------------------------------------------------------
+
+#These will be in the environment variables with one of the VS2017
+#developer command prompts.
+#VSCMD_ARG_HOST_ARCH=x64
+#VSCMD_ARG_TGT_ARCH=x86
+
+!IFDEF VSCMD_ARG_HOST_ARCH
+!MESSAGE Host architecture is $(VSCMD_ARG_HOST_ARCH)
+!MESSAGE Target architecture is $(VSCMD_ARG_TGT_ARCH)
+! IFNDEF TARGET_CPU
+!  IF "$(VSCMD_ARG_TGT_ARCH)"=="x64"
+TARGET_CPU=x64
+!  ELSE
+TARGET_CPU=x86
+!  ENDIF
+! ENDIF
+!ENDIF
+
 !IF "$(TARGET_CPU)" == ""
 TARGET_CPU=x86
 !ENDIF
 
-!IF "$(_NMAKE_VER)" == "10.00.40219.01"
-CL2013=
+!IF ($(VSVER) == 2010)
+CL_RECENT=
 !ELSE
 ! IF ($(VSVER) > 2010)
-CL2013=-sdl
+CL_RECENT=-sdl
 ! ENDIF
 !ENDIF
 
 ccommon= -c -nologo -D"_CONSOLE" -D"_CRT_NONSTDC_NO_DEPRECATE" -D"_CRT_SECURE_NO_DEPRECATE" \
        -D"_LIB" -D"_SCL_SECURE_NO_DEPRECATE" -D"_VC80_UPGRADE=0x0600" -D"DLB" -D"_MBCS" \
        -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -D"NDEBUG" -D"YY_NO_UNISTD_H" -EHsc -fp:precise -Gd -GF -GS -Gy \
-       $(CL2013) -WX- -Zc:forScope -Zc:wchar_t -Zi
+       $(CL_RECENT) -WX- -Zc:forScope -Zc:wchar_t -Zi
 cdebug= -analyze- -D"_DEBUG" -Gm -MTd -RTC1 -Od
-crelease= -analyze- -D"_MBCS" -errorReport:prompt -GL -Gm- -MT -O2 -Ot -Ox -Oy
+crelease= -analyze- -D"_MBCS" -errorReport:prompt -Gm- -MT -O2 -Ot -Ox -Oy
 
 lcommon= /NOLOGO /INCREMENTAL:NO
 
@@ -202,7 +246,7 @@ ldebug = /DEBUG
 cflags1=$(ccommon) $(cdebug)
 lflags1=$(lcommon) $(ldebug)
 !ELSE
-ldebug=
+ldebug= /DEBUG
 cflags1=$(ccommon) $(crelease)
 lflags1=$(lcommon) $(ldebug)
 !ENDIF
@@ -248,8 +292,8 @@ guilflags = $(lflags) -subsystem:windows,$(EXEVER)
 dlllflags = $(lflags) -entry:_DllMainCRTStartup$(DLLENTRY) -dll
 
 # basic subsystem specific libraries, less the C Run-Time
-baselibs    = kernel32.lib $(optlibs) $(winsocklibs) advapi32.lib
-winlibs     = $(baselibs) user32.lib gdi32.lib comdlg32.lib winspool.lib
+baselibs    = kernel32.lib $(optlibs) $(winsocklibs) advapi32.lib gdi32.lib
+winlibs     = $(baselibs) user32.lib comdlg32.lib winspool.lib
 
 # for Windows applications that use the C Run-Time libraries
 conlibs     = $(baselibs)
@@ -533,7 +577,7 @@ default : install
 
 all :  install
 
-install: envchk $(O)obj.tag $(O)utility.tag $(GAMEDIR)\JNetHack.exe $(GAMEDIR)\JNetHackW.exe $(O)install.tag
+install: $(O)envchk.tag $(O)obj.tag $(O)utility.tag $(GAMEDIR)\JNetHack.exe $(GAMEDIR)\JNetHackW.exe $(O)install.tag
         @echo Done.
 
 $(O)install.tag:       $(DAT)\data     $(DAT)\rumors    $(DAT)\dungeon \
@@ -814,14 +858,6 @@ $(INCL)\vis_tab.h: $(U)makedefs.exe
 $(SRC)\vis_tab.c: $(U)makedefs.exe
        $(U)makedefs -z
 
-$(DAT)\engrave: $(DAT)\engrave.txt $(U)makedefs.exe
-       ..\util\makedefs -s
-$(DAT)\epitaph: $(DAT)\epitaph.txt $(U)makedefs.exe
-       ..\util\makedefs -s
-$(DAT)\bogusmon: $(DAT)\bogusmon.txt $(U)makedefs.exe
-       ..\util\makedefs -s
-
-
 #==========================================
 # uudecode utility and uuencoded targets
 #==========================================
@@ -885,14 +921,19 @@ $(MSWIN)\splash.bmp: $(U)uudecode.exe $(MSWIN)\splash.uu
 # defer to the steps in ..\win\win32\levstuff.mak
 #
 
-$(U)lev_yacc.c $(INCL)\lev_comp.h: $(U)lev_comp.y
-       nmake -nologo -f ..\win\win32\levstuff.mak default
+$(U)lev_yacc.c: $(U)lev_comp.y
+       nmake -nologo -f ..\win\win32\levstuff.mak $(U)lev_yacc.c
+
+$(U)lev_lex.c: $(U)lev_comp.l
+       nmake -nologo -f ..\win\win32\levstuff.mak $(U)lev_lex.c
+
+$(INCL)\lev_comp.h:
+       nmake -nologo -f ..\win\win32\levstuff.mak $(INCL)\lev_comp.h
 
 $(O)lev_yacc.o: $(HACK_H)   $(SP_LEV_H) $(INCL)\lev_comp.h $(U)lev_yacc.c
        @$(cc) $(cflagsBuild) -Fo$@ $(U)lev_yacc.c
 
-$(O)lev_lex.o: $(HACK_H) $(INCL)\lev_comp.h $(SP_LEV_H) \
-               $(U)lev_lex.c
+$(O)lev_lex.o: $(HACK_H) $(INCL)\lev_comp.h $(SP_LEV_H) $(U)lev_lex.c
        @$(cc) $(cflagsBuild) -Fo$@ $(U)lev_lex.c
 
 $(O)lev_main.o:        $(U)lev_main.c $(HACK_H) $(SP_LEV_H)
@@ -911,8 +952,14 @@ $(U)levcomp.exe: $(LEVCOMPOBJS)
 #
 # defer to the steps in ..\win\win32\dgnstuff.mak
 #
-$(U)dgn_yacc.c $(INCL)\dgn_comp.h : $(U)dgn_comp.y
-       nmake -nologo -f ..\win\win32\dgnstuff.mak default
+$(U)dgn_yacc.c: $(U)dgn_comp.y
+       nmake -nologo -f ..\win\win32\dgnstuff.mak $(U)dgn_yacc.c
+
+$(INCL)\dgn_comp.h:
+       nmake -nologo -f ..\win\win32\dgnstuff.mak $(INCL)\dgn_comp.h
+
+$(U)dgn_lex.c: $(U)dgn_comp.l
+       nmake -nologo -f ..\win\win32\dgnstuff.mak $(U)dgn_lex.c
 
 $(O)dgn_yacc.o:        $(HACK_H)   $(DGN_FILE_H) $(INCL)\dgn_comp.h $(U)dgn_yacc.c
        @$(cc) $(cflagsBuild) -Fo$@ $(U)dgn_yacc.c
@@ -946,23 +993,17 @@ $(O)obj.tag:
 # options.
 #==========================================
 
-envchk:
-!      IF ($(VSVER) < 2010)
-       @echo Your Visual Studio version is too old or untested ($(_NMAKE_VER))
-!ERROR Your Visual Studio version is too old or untested ($(_NMAKE_VER))
-!      ENDIF
+$(O)envchk.tag: $(O)obj.tag
 !      IF "$(TARGET_CPU)"=="x64"
-       @echo Windows x64 64-bit build
+       @echo Windows x64 64-bit target build
 !      ELSE
-       @echo Windows x86 32-bit build
+       @echo Windows x86 32-bit target build
 !      ENDIF
 !      IF "$(CL)"!=""
 #         @echo Warning, the CL Environment variable is defined:
 #         @echo CL=$(CL)
 !      ENDIF
-          @echo ----
-          @echo NOTE: This build will include tile support.
-          @echo ----
+        echo envchk >$@
 
 #==========================================
 #=========== SECONDARY TARGETS ============
@@ -1149,63 +1190,78 @@ spotless: clean
        if exist $(GAMEDIR)\JNetHack.pdb del $(GAMEDIR)\JNetHack.pdb
        if exist $(GAMEDIR)\nhdat        del $(GAMEDIR)\nhdat
 ! ENDIF
-       if exist $(INCL)\date.h    del $(INCL)\date.h
-       if exist $(INCL)\onames.h  del $(INCL)\onames.h
-       if exist $(INCL)\pm.h      del $(INCL)\pm.h
-       if exist $(INCL)\vis_tab.h del $(INCL)\vis_tab.h
-       if exist $(SRC)\vis_tab.c  del $(SRC)\vis_tab.c
-       if exist $(SRC)\tile.c     del $(SRC)\tile.c
-       if exist $(U)*.lnk         del $(U)*.lnk
-       if exist $(U)*.map         del $(U)*.map
-       if exist $(DAT)\data       del $(DAT)\data
-       if exist $(DAT)\rumors     del $(DAT)\rumors
-       if exist $(DAT)\engrave    del $(DAT)\engrave
-       if exist $(DAT)\epitaph    del $(DAT)\epitaph
-       if exist $(DAT)\bogusmon   del $(DAT)\bogusmon
-       if exist $(DAT)\???-fil?.lev    del $(DAT)\???-fil?.lev
-       if exist $(DAT)\???-goal.lev    del $(DAT)\???-goal.lev
-       if exist $(DAT)\???-loca.lev    del $(DAT)\???-loca.lev
-       if exist $(DAT)\???-strt.lev    del $(DAT)\???-strt.lev
-       if exist $(DAT)\air.lev         del $(DAT)\air.lev
-       if exist $(DAT)\asmodeus.lev    del $(DAT)\asmodeus.lev
-       if exist $(DAT)\astral.lev      del $(DAT)\astral.lev
-       if exist $(DAT)\baalz.lev       del $(DAT)\baalz.lev
-       if exist $(DAT)\bigrm-*.lev     del $(DAT)\bigrm-*.lev
-       if exist $(DAT)\castle.lev      del $(DAT)\castle.lev
-       if exist $(DAT)\data            del $(DAT)\data
-       if exist $(DAT)\dungeon         del $(DAT)\dungeon
-       if exist $(DAT)\dungeon.pdf     del $(DAT)\dungeon.pdf
-       if exist $(DAT)\earth.lev       del $(DAT)\earth.lev
-       if exist $(DAT)\fakewiz?.lev    del $(DAT)\fakewiz?.lev
-       if exist $(DAT)\fire.lev        del $(DAT)\fire.lev
-       if exist $(DAT)\juiblex.lev     del $(DAT)\juiblex.lev
-       if exist $(DAT)\knox.lev        del $(DAT)\knox.lev
-       if exist $(DAT)\medusa-?.lev    del $(DAT)\medusa-?.lev
-       if exist $(DAT)\mine*.lev       del $(DAT)\mine*.lev
-       if exist $(DAT)\options         del $(DAT)\options
-       if exist $(DAT)\ttyoptions      del $(DAT)\ttyoptions
-       if exist $(DAT)\guioptions      del $(DAT)\guioptions
-       if exist $(DAT)\oracle.lev      del $(DAT)\oracle.lev
-       if exist $(DAT)\oracles         del $(DAT)\oracles
-       if exist $(DAT)\orcus.lev       del $(DAT)\orcus.lev
-       if exist $(DAT)\rumors          del $(DAT)\rumors
-       if exist $(DAT)\quest.dat       del $(DAT)\quest.dat
-       if exist $(DAT)\sanctum.lev     del $(DAT)\sanctum.lev
-       if exist $(DAT)\soko?-?.lev     del $(DAT)\soko?-?.lev
-       if exist $(DAT)\tower?.lev      del $(DAT)\tower?.lev
-       if exist $(DAT)\valley.lev      del $(DAT)\valley.lev
-       if exist $(DAT)\water.lev       del $(DAT)\water.lev
-       if exist $(DAT)\wizard?.lev     del $(DAT)\wizard?.lev
-       if exist $(DAT)\dlb.lst         del $(DAT)\dlb.lst
-       if exist $(O)sp_lev.tag         del $(O)sp_lev.tag
-       if exist $(SRC)\monstr.c        del $(SRC)\monstr.c
-       if exist $(SRC)\vis_tab.c       del $(SRC)\vis_tab.c
-       if exist $(U)recover.exe        del $(U)recover.exe
-       if exist nhdat.                 del nhdat.
-       if exist $(O)obj.tag            del $(O)obj.tag
-       if exist $(O)gamedir.tag        del $(O)gamedir.tag
-       if exist $(O)nh*key.lib         del $(O)nh*key.lib
-       if exist $(O)nh*key.exp         del $(O)nh*key.exp
+       if exist $(INCL)\date.h          del $(INCL)\date.h
+       if exist $(INCL)\onames.h        del $(INCL)\onames.h
+       if exist $(INCL)\pm.h            del $(INCL)\pm.h
+       if exist $(INCL)\vis_tab.h       del $(INCL)\vis_tab.h
+       if exist $(SRC)\vis_tab.c        del $(SRC)\vis_tab.c
+       if exist $(SRC)\tile.c           del $(SRC)\tile.c
+       if exist $(U)*.lnk               del $(U)*.lnk
+       if exist $(U)*.map               del $(U)*.map
+       if exist $(DAT)\data             del $(DAT)\data
+       if exist $(DAT)\rumors           del $(DAT)\rumors
+       if exist $(DAT)\engrave          del $(DAT)\engrave
+       if exist $(DAT)\epitaph          del $(DAT)\epitaph
+       if exist $(DAT)\bogusmon         del $(DAT)\bogusmon
+       if exist $(DAT)\???-fil?.lev     del $(DAT)\???-fil?.lev
+       if exist $(DAT)\???-goal.lev     del $(DAT)\???-goal.lev
+       if exist $(DAT)\???-loca.lev     del $(DAT)\???-loca.lev
+       if exist $(DAT)\???-strt.lev     del $(DAT)\???-strt.lev
+       if exist $(DAT)\air.lev          del $(DAT)\air.lev
+       if exist $(DAT)\asmodeus.lev     del $(DAT)\asmodeus.lev
+       if exist $(DAT)\astral.lev       del $(DAT)\astral.lev
+       if exist $(DAT)\baalz.lev        del $(DAT)\baalz.lev
+       if exist $(DAT)\bigrm-*.lev      del $(DAT)\bigrm-*.lev
+       if exist $(DAT)\castle.lev       del $(DAT)\castle.lev
+       if exist $(DAT)\data             del $(DAT)\data
+       if exist $(DAT)\dungeon          del $(DAT)\dungeon
+       if exist $(DAT)\dungeon.pdf      del $(DAT)\dungeon.pdf
+       if exist $(DAT)\earth.lev        del $(DAT)\earth.lev
+       if exist $(DAT)\fakewiz?.lev     del $(DAT)\fakewiz?.lev
+       if exist $(DAT)\fire.lev         del $(DAT)\fire.lev
+       if exist $(DAT)\juiblex.lev      del $(DAT)\juiblex.lev
+       if exist $(DAT)\knox.lev         del $(DAT)\knox.lev
+       if exist $(DAT)\medusa-?.lev     del $(DAT)\medusa-?.lev
+       if exist $(DAT)\mine*.lev        del $(DAT)\mine*.lev
+       if exist $(DAT)\options          del $(DAT)\options
+       if exist $(DAT)\ttyoptions       del $(DAT)\ttyoptions
+       if exist $(DAT)\guioptions       del $(DAT)\guioptions
+       if exist $(DAT)\oracle.lev       del $(DAT)\oracle.lev
+       if exist $(DAT)\oracles          del $(DAT)\oracles
+       if exist $(DAT)\orcus.lev        del $(DAT)\orcus.lev
+       if exist $(DAT)\rumors           del $(DAT)\rumors
+       if exist $(DAT)\quest.dat        del $(DAT)\quest.dat
+       if exist $(DAT)\sanctum.lev      del $(DAT)\sanctum.lev
+       if exist $(DAT)\soko?-?.lev      del $(DAT)\soko?-?.lev
+       if exist $(DAT)\tower?.lev       del $(DAT)\tower?.lev
+       if exist $(DAT)\valley.lev       del $(DAT)\valley.lev
+       if exist $(DAT)\water.lev        del $(DAT)\water.lev
+       if exist $(DAT)\wizard?.lev      del $(DAT)\wizard?.lev
+       if exist $(DAT)\dlb.lst          del $(DAT)\dlb.lst
+       if exist $(DAT)\porthelp         del $(DAT)\porthelp
+       if exist $(O)sp_lev.tag          del $(O)sp_lev.tag
+       if exist $(SRC)\monstr.c         del $(SRC)\monstr.c
+       if exist $(SRC)\vis_tab.c        del $(SRC)\vis_tab.c
+       if exist nhdat.                  del nhdat.
+       if exist $(O)obj.tag             del $(O)obj.tag
+       if exist $(O)gamedir.tag         del $(O)gamedir.tag
+       if exist $(O)nh*key.lib          del $(O)nh*key.lib
+       if exist $(O)nh*key.exp          del $(O)nh*key.exp
+       if exist $(INCL)\win32api.h      del $(INCL)\win32api.h
+        if exist $(MSWIN)\mnsel.bmp      del $(MSWIN)\mnsel.bmp
+        if exist $(MSWIN)\mnselcnt.bmp   del $(MSWIN)\mnselcnt.bmp
+        if exist $(MSWIN)\mnunsel.bmp    del $(MSWIN)\mnunsel.bmp
+        if exist $(MSWIN)\petmark.bmp    del $(MSWIN)\petmark.bmp
+        if exist $(MSWIN)\pilemark.bmp   del $(MSWIN)\pilemark.bmp
+        if exist $(MSWIN)\rip.bmp        del $(MSWIN)\rip.bmp
+        if exist $(MSWIN)\splash.bmp     del $(MSWIN)\splash.bmp
+        if exist $(MSWIN)\nethack.ico    del $(MSWIN)\nethack.ico
+        if exist $(MSWSYS)\nethack.ico   del $(MSWSYS)\nethack.ico
+       if exist $(U)recover.exe         del $(U)recover.exe
+       if exist $(U)tile2bmp.exe        del $(U)tile2bmp.exe
+       if exist $(U)tilemap.exe         del $(U)tilemap.exe
+       if exist $(U)uudecode.exe        del $(U)uudecode.exe
+       if exist $(U)dlb_main.exe        del $(U)dlb_main.exe
 clean:
        if exist $(O)*.o del $(O)*.o
        if exist $(O)utility.tag   del $(O)utility.tag
@@ -1241,6 +1297,7 @@ clean:
        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
@@ -1253,7 +1310,6 @@ clean:
        rem defer to the steps in ..\win\win32\dgnstuff.mak
        rem
        nmake -nologo -f ..\win\win32\dgnstuff.mak clean
-
        if exist $(TILEBMP16)        del $(TILEBMP16)
        if exist $(TILEBMP32)        del $(TILEBMP32)
 
@@ -1277,6 +1333,15 @@ $(DAT)\quest.dat: $(O)utility.tag  $(DAT)\quest.txt
 $(DAT)\oracles: $(O)utility.tag    $(DAT)\oracles.txt
        $(U)makedefs -h
 
+$(DAT)\engrave: $(DAT)\engrave.txt $(U)makedefs.exe
+       $(U)makedefs -s
+
+$(DAT)\epitaph: $(DAT)\epitaph.txt $(U)makedefs.exe
+       $(U)makedefs -s
+
+$(DAT)\bogusmon: $(DAT)\bogusmon.txt $(U)makedefs.exe
+       $(U)makedefs -s
+
 $(DAT)\dungeon: $(O)utility.tag  $(DAT)\dungeon.def
        $(U)makedefs -e
        cd $(DAT)
index 2057052..1c35e16 100644 (file)
@@ -12,8 +12,8 @@
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 3,5,0,0
- PRODUCTVERSION 3,5,0,0
+ FILEVERSION 3,6,1,0
+ PRODUCTVERSION 3,6,1,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.5.0\0"
+            VALUE "FileVersion", "3.6.1\0"
             VALUE "InternalName", "NetHack\0"
-            VALUE "LegalCopyright", "Copyright (C) 1985 - 2005.  By Stichting Mathematisch Centrum and M. Stephenson.  See license for details.\0"
+            VALUE "LegalCopyright", "Copyright (C) 1985 - 2018.  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.5.0\0"
+            VALUE "ProductVersion", "3.6.1\0"
         END
     END
     BLOCK "VarFileInfo"
index ad37363..8919fe0 100644 (file)
@@ -1,3 +1,7 @@
+# NetHack 3.6  defaults.nh       $NHDT-Date: 1524689357 2018/04/25 20:49:17 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.32 $
+# Copyright (c) 2006 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
+
 # Sample config file for win32 NetHack
 # A '#' at the beginning of a line means the rest of the line is a comment.
 #
@@ -7,7 +11,7 @@
 # To change the configuration, comment out the unwanted lines, and
 # uncomment the configuration you want.
 #
-# $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# $NHDT-Date: 1524689357 2018/04/25 20:49:17 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.32 $
 
 # *** OPTIONS ***
 #
@@ -36,17 +40,41 @@ OPTIONS=symset:default,roguesymset:default
 #OPTIONS=name:Janet,role:Valkyrie,race:Human,gender:female,align:lawful
 #OPTIONS=dogname:Fido,catname:Morris,fruit:guava
 #OPTIONS=horsename:Silver
-#OPTIONS=autopickup,pickup_types:$"=/!?+
+
+# Disable autopickup
+OPTIONS=!autopickup
+
+# When autopickup is on, automatically pick up these types of objects
+#OPTIONS=pickup_types:$"=/!?+
+
 #OPTIONS=packorder:")[%?+/=!(*0_`
 #OPTIONS=scores:10 top/2 around/own
 #OPTIONS=nolegacy,noverbose
 #OPTIONS=menustyle:traditional
-#OPTIONS=hilite_status:hitpoints/30%/bright-magenta/normal
 #OPTIONS=perm_invent
 
-# Turn off all status hilites.
-#OPTIONS=!statushilites
-#
+
+# Highlight menu lines with different colors. You need to define the colors
+# with MENUCOLOR lines.
+#  Toggle menucolor use on or off
+OPTIONS=menucolors
+# Define color used for a certain menu line. Format is
+#    MENUCOLOR="regular expression"=color
+# or
+#    MENUCOLOR="regular expression"=color&attribute
+#  Show all blessed items in green
+MENUCOLOR=" blessed " = green
+#  Show all holy water in green
+MENUCOLOR=" holy " = green
+#  Show all cursed items in red
+MENUCOLOR=" cursed " = red
+#  Show all unholy water in red
+MENUCOLOR=" unholy " = red
+#  Show all cursed worn items in orange and underlined
+MENUCOLOR=" cursed .* (being worn)" = orange&underline
+
+
+
 # General options.  You might also set "silent" so as not to attract
 # the boss's attention.
 #
@@ -54,6 +82,9 @@ OPTIONS=symset:default,roguesymset:default
 # or 2(on,legacy-mode) which causes 5='g', alt-5='G', alt-0='I'
 OPTIONS=time,noshowexp,number_pad:2,lit_corridor
 
+# Make commands that ask for an inventory item pop up a menu
+OPTIONS=force_invmenu
+
 #
 # If you want to get rid of "use #quit to quit..." use:
 OPTIONS=suppress_alert:3.3.1
@@ -71,7 +102,7 @@ OPTIONS=suppress_alert:3.3.1
 # possible map_mode options include: tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|
 #                                    ascii7x12|ascii8x12|ascii16x12|ascii12x16|
 #                                    ascii10x18|fit_to_screen
-OPTIONS=map_mode:tiles,scroll_margin:5
+OPTIONS=map_mode:tiles,scroll_margin:10
 
 # Message window settings
 #OPTIONS=font_message:Arial,font_size_message:9,align_message:top
@@ -100,6 +131,10 @@ OPTIONS=hilite_pet,!toptenwin
 # window, windowframe, windowtext.
 #OPTIONS=windowcolors:status windowtext/window message windowtext/window
 
+# "Nethack mode" colors
+OPTIONS=windowcolors:status white/#000000 message white/#000000 text white/#000000 menu white/#000000 menutext white/#000000
+OPTIONS=vary_msgcount:1
+
 # *** LOCATIONS ***
 # IMPORTANT: If you change any of these locations, the directories they
 # point at must exist.  NetHack will not create them for you.
@@ -156,3 +191,45 @@ OPTIONS=hilite_pet,!toptenwin
 #OPTIONS=palette:bright cyan-0-255-255
 #OPTIONS=palette:white-255-255-255
 
+
+
+# Status hilites
+OPTIONS=statushilites
+# HP
+OPTIONS=hitpointbar
+OPTIONS=hilite_status:hitpoints/100%/gray&normal
+OPTIONS=hilite_status:hitpoints/<100%/green&normal
+OPTIONS=hilite_status:hitpoints/<66%/yellow&normal
+OPTIONS=hilite_status:hitpoints/<50%/orange&normal
+OPTIONS=hilite_status:hitpoints/<33%/red&bold
+OPTIONS=hilite_status:hitpoints/<15%/red&inverse
+
+## Pw
+OPTIONS=hilite_status:power/100%/gray&normal
+OPTIONS=hilite_status:power/<100%/green&normal
+OPTIONS=hilite_status:power/<66%/yellow&normal
+OPTIONS=hilite_status:power/<50%/orange&normal
+OPTIONS=hilite_status:power/<33%/red&bold
+
+## Carry
+OPTIONS=hilite_status:cap/burdened/yellow/stressed/orange/strained/red&bold/overtaxed/red&inverse/overloaded/red&inverse&blink
+
+## Hunger
+OPTIONS=hilite_status:hunger/satiated/yellow/hungry/orange/weak/red&bold/fainting/red&inverse/fainted/red&inverse&blink
+
+## Mental
+OPTIONS=hilite_status:condition/hallu/yellow
+OPTIONS=hilite_status:condition/conf/orange
+OPTIONS=hilite_status:condition/stun/red&bold
+
+## Health
+OPTIONS=hilite_status:condition/termill/red&inverse
+OPTIONS=hilite_status:condition/foodpois/red&inverse
+OPTIONS=hilite_status:condition/slime/red&inverse
+
+# gold
+OPTIONS=hilite_status:gold/up/yellow/down/brown
+
+# St, Dx, Co, In, Wi, Ch
+OPTIONS=hilite_status:characteristics/up/green/down/red
+
index aaa64b7..e163eaf 100644 (file)
@@ -1,5 +1,5 @@
 NAME           NETHACK
-DESCRIPTION    'NetHack 3.6.0 for Windows NT'
+DESCRIPTION    'NetHack 3.6.1 for Windows NT'
 EXETYPE                WINDOWS
 STUB           'WINSTUB.EXE'
 CODE           PRELOAD MOVEABLE DISCARDABLE
index 7d64b38..8d51214 100644 (file)
@@ -153,7 +153,7 @@ int portdebug;
         if (vk == 0xBF)
             ch = M('?');
         else
-            ch = M(tolower(keycode));
+            ch = M(tolower((uchar) keycode));
     }
     if (ch == '\r')
         ch = '\n';
index 0cd06d2..6f7cb25 100644 (file)
@@ -167,7 +167,7 @@ int portdebug;
         if (vk == 0xBF)
             ch = M('?');
         else
-            ch = M(tolower(keycode));
+            ch = M(tolower((uchar) keycode));
     }
 #if 0 /*JP*/
     /* Attempt to work better with international keyboards. */
index 95dfddf..3b0a6ef 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 nhraykey.c      $NHDT-Date: 1432512794 2015/05/25 00:13:14 $  $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
+/* 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.      */
 
@@ -352,7 +352,7 @@ int portdebug;
         if (vk == 0xBF)
             ch = M('?');
         else
-            ch = M(tolower(keycode));
+            ch = M(tolower((uchar) keycode));
     } else if (ch < 32 && !isnumkeypad(scan)) {
         /* Control code; ReadConsole seems to filter some of these,
          * including ESC */
@@ -559,19 +559,24 @@ INPUT_RECORD *ir;
                 scan = ir->Event.KeyEvent.wVirtualScanCode;
                 shiftstate = ir->Event.KeyEvent.dwControlKeyState;
                 vk = ir->Event.KeyEvent.wVirtualKeyCode;
-                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 */
+                if (scan == 0 && vk == 0) {
+                    /* It's the bogus_key.  Discard it */
+                    ReadConsoleInput(hConIn,ir,1,&count);
                 } else {
-                    /* Strange Key event; let's purge it to avoid trouble */
-                    ReadConsoleInput(hConIn, ir, 1, &count);
+                    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
index d477b30..da3fb9e 100644 (file)
@@ -1,44 +1,26 @@
 @REM  NetHack 3.6      nhsetup.bat     $NHDT-Date: 1432512794 2015/05/25 00:13:14 $  $NHDT-Branch: master $:$NHDT-Revision: 1.33 $ */
-@REM  Copyright (c) NetHack PC Development Team 1993-2015
+@REM  Copyright (c) NetHack PC Development Team 1993-2017
 @REM  NetHack may be freely redistributed.  See license for details. 
 @REM  Win32 setup batch file, see Install.nt for details
 @REM
 @echo off
 pushd %~dp0
 set WIN32PATH=..\..\win\win32
-set BUILDPATH=..\..\build
 set BINPATH=..\..\binary
 set VCDir=
 
-:studiocheck
-@REM Set fallbacks here for 32-bit VS2010
-SET REGTREE=HKLM\Software\Microsoft\VCExpress\12.0\Setup\VC
-SET MSVCVERSION=2010
+goto :main
 
-@REM if we're in a 64-bit cmd prompt, gotta include Wow6432Node
-echo Checking for 64-bit environment...
-if "%ProgramFiles%" NEQ "%ProgramFiles(x86)%" SET REGTREE=HKLM\Software\Wow6432Node\Microsoft\VCExpress\12.0\Setup\VC
+:dirname
+rem Get the dirname of the second argument and set the variable who's
+rem name was specified in the first argument.
+call set %~1=%%~dp2
+call set %~1=%%%~1:~0,-1%%
+goto :EOF
 
-@REM i can see your house from here... or at least your VC++ folder
-echo Checking version of VC++ installed...
-echo Checking for VC2013 Express...
-for /f "usebackq skip=2 tokens=1-2*" %%a IN (`reg query %REGTREE% /v ProductDir`) do @set VCDir="%%c"
-if not defined VCDir goto :othereditions
-if not exist %VCDir% goto :othereditions
-
-set MSVCVERSION=2013
-goto :fallback
+:main
 
-:othereditions
-@REM TODO: teach ourselves to detect full versions of Studio, which are under a different registry hive
-echo VC2013 Express not found; dropping back.
-
-:fallback
-echo Using VS%MSVCVERSION%.
-set SRCPATH=%WIN32PATH%\vs%MSVCVERSION%
-
-:nxtcheck
-echo Checking to see if directories are set up properly...
+echo Checking to see if source tree directories are set up properly...
 if not exist ..\..\include\hack.h goto :err_dir
 if not exist ..\..\src\hack.c goto :err_dir
 if not exist ..\..\dat\wizard.des goto :err_dir
@@ -46,6 +28,9 @@ if not exist ..\..\util\makedefs.c goto :err_dir
 if not exist ..\..\sys\winnt\winnt.c goto :err_dir
 echo Directories look ok.
 
+:movemakes
+echo Moving Makefiles into ..\..\src for those not using Visual Studio
+REM Some file movemet for those that still want to use MAKE or NMAKE and a Makefile
 :do_tty
 if NOT exist %BINPATH%\*.* mkdir %BINPATH%
 if NOT exist %BINPATH%\license copy ..\..\dat\license %BINPATH%\license >nul
@@ -71,77 +56,38 @@ echo           ..\..\src\Makefile.gcc-orig
 copy Makefile.gcc ..\..\src\Makefile.gcc >nul
 echo MinGW Makefile copied ok.
 
-:do_win
-if not exist %SRCPATH%\nethack.sln goto :err_win
-
-echo.
-if exist %BUILDPATH%\*.* goto projectcopy
-
-echo Creating %BUILDPATH% directory...
-mkdir %BUILDPATH%
-
-:projectcopy
-
-@REM Visual Studio Express solution file
-if NOT exist %SRCPATH%\nethack.sln goto skipsoln
-echo Copying %SRCPATH%\nethack.sln to ..\..\nethack.sln...
-copy %SRCPATH%\nethack.sln  ..\.. >nul
-:skipsoln
-
-if NOT exist %BINPATH%\*.* echo Creating %BINPATH% directory...
-if NOT exist %BINPATH%\*.* mkdir %BINPATH%
-if NOT exist %BINPATH%\license copy ..\..\dat\license %BINPATH%\license >nul
-
-echo Copying Visual C project files to %BUILDPATH% directory...
-
-copy %WIN32PATH%\dgnstuff.mak  %BUILDPATH% >nul
-copy %WIN32PATH%\levstuff.mak  %BUILDPATH% >nul
-copy %WIN32PATH%\tiles.mak     %BUILDPATH% >nul
-
-@REM Visual C++ 201X Express project files
-:vcexpress
-if NOT exist %SRCPATH%\makedefs.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\tile2bmp.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\tilemap.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\uudecode.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\NetHackW.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\NetHack.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\dgncomp.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\dgnstuff.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\dlb_main.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\levcomp.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\levstuff.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\recover.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\tiles.vcxproj goto skipvcexpress
-if NOT exist %SRCPATH%\nhdefkey.vcxproj goto skipvcexpress
+echo Done copying files.
 
-copy %SRCPATH%\makedefs.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\tile2bmp.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\tilemap.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\uudecode.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\NetHackW.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\NetHack.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\dgncomp.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\dgnstuff.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\dlb_main.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\levcomp.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\levstuff.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\recover.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\tiles.vcxproj %BUILDPATH% >nul
-copy %SRCPATH%\nhdefkey.vcxproj %BUILDPATH% >nul
-echo LIBRARY nhdefkey >%BUILDPATH%\nhdefkey64.def
-echo LIBRARY nhdefkey >%BUILDPATH%\nhdefkey.def
-echo EXPORTS >>%BUILDPATH%\nhdefkey.def
-echo ProcessKeystroke >>%BUILDPATH%\nhdefkey.def
-echo NHkbhit >>%BUILDPATH%\nhdefkey.def
-echo CheckInput >>%BUILDPATH%\nhdefkey.def 
-echo SourceWhere >>%BUILDPATH%\nhdefkey.def
-echo SourceAuthor >>%BUILDPATH%\nhdefkey.def
-echo KeyHandlerName >>%BUILDPATH%\nhdefkey.def
+:vscheck2017
+SET REGTREE=HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7
+@REM i can see your house from here... or at least your VC++ folder
+echo Checking version of VC++ installed...
+echo Checking for VC2017 Community Edition...
+for /f "usebackq skip=2 tokens=1-2*" %%a IN (`reg query %REGTREE% /v 15.0`) do @set VCDir="%%c"
+if not defined VCDir goto :vscheck2015
+if not exist %VCDir% goto :vscheck2015
+set MSVCVERSION=2017
+goto :fallback
 
-echo Done copying files.
-:skipvcexpress
+:vscheck2015
+rem cannot use the registry trick used for vc2017
+rem 14 = 2015
+SET VCVERS=14
+rem Finally, let's determine the root folder for this VC installation.
+set VCROOT=%%VS%VCVERS%0COMNTOOLS%%
+if "%VCROOT:~-1%"=="\" set VCROOT=%VCROOT:~0,-1%
+rem VCROOT=VSDir\Common7\Tools
+call :dirname VCROOT "%VCROOT%"
+rem VCROOT=VSDir\Common7
+call :dirname VCROOT "%VCROOT%"
+rem VCROOT=VSDir
+set VCDir=%VCROOT%\VC
+SET MSVCVERSION=2015
 
+:fallback
+echo Using VS%MSVCVERSION%.
+set SRCPATH=%WIN32PATH%\vs%MSVCVERSION%
+echo NetHack VS%MSVCVERSION% project files are in %SRCPATH%
 goto :done
 
 :err_win
@@ -151,12 +97,6 @@ echo Check "Install.nt" for a list of the steps required
 echo to build NetHack.
 goto :fini
 
-:err_data
-echo A required file ..\..\dat\data.bas seems to be missing.
-echo Check "Files." in the root directory for your NetHack distribution
-echo and make sure that all required files exist.
-goto :fini
-
 :err_dir
 echo Your directories are not set up properly, please re-read the
 echo documentation and sys/winnt/Install.nt.
index c390929..c07d994 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 nttty.c $NHDT-Date: 1431737067 2015/05/16 00:44:27 $  $NHDT-Branch: master $:$NHDT-Revision: 1.63 $ */
+/* NetHack 3.6 nttty.c $NHDT-Date: 1520825872 2018/03/12 03:37:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */
 /* Copyright (c) NetHack PC Development Team 1993    */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include <sys\stat.h>
 #include "win32api.h"
 
-void FDECL(cmov, (int, int));
-void FDECL(nocmov, (int, int));
-int FDECL(process_keystroke,
-          (INPUT_RECORD *, boolean *, BOOLEAN_P numberpad, int portdebug));
-
 /*
  * The following WIN32 Console API routines are used in this file.
  *
@@ -41,6 +36,19 @@ int FDECL(process_keystroke,
  * GetConsoleOutputCP
  */
 
+static BOOL FDECL(CtrlHandler, (DWORD));
+static void FDECL(xputc_core, (char));
+void FDECL(cmov, (int, int));
+void FDECL(nocmov, (int, int));
+int FDECL(process_keystroke,
+          (INPUT_RECORD *, boolean *, BOOLEAN_P numberpad, int portdebug));
+static void NDECL(init_ttycolor);
+static void NDECL(really_move_cursor);
+static void NDECL(check_and_set_font);
+static boolean NDECL(check_font_widths);
+static void NDECL(set_known_good_console_font);
+static void NDECL(restore_original_console_font);
+
 /* Win32 Console handles for input and output */
 HANDLE hConIn;
 HANDLE hConOut;
@@ -50,6 +58,14 @@ CONSOLE_SCREEN_BUFFER_INFO csbi, origcsbi;
 COORD ntcoord;
 INPUT_RECORD ir;
 
+/* Support for changing console font if existing glyph widths are too wide */
+boolean console_font_changed;
+CONSOLE_FONT_INFOEX original_console_font_info;
+UINT original_console_code_page;
+
+extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
+extern int redirect_stdout;
+
 /* Flag for whether NetHack was launched via the GUI, not the command line.
  * The reason we care at all, is so that we can get
  * a final RETURN at the end of the game when launched from the GUI
@@ -58,41 +74,12 @@ INPUT_RECORD ir;
  * from the command line.
  */
 int GUILaunched;
-extern int redirect_stdout;
-static BOOL FDECL(CtrlHandler, (DWORD));
-
 /* Flag for whether unicode is supported */
 static boolean has_unicode;
-
+static boolean init_ttycolor_completed;
 #ifdef PORT_DEBUG
 static boolean display_cursor_info = FALSE;
 #endif
-
-extern boolean getreturn_enabled; /* from sys/share/pcsys.c */
-
-/* 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, int *, coord *);
-
-typedef int(__stdcall *SOURCEWHERE)(char **);
-
-typedef int(__stdcall *SOURCEAUTHOR)(char **);
-
-typedef int(__stdcall *KEYHANDLERNAME)(char **, int);
-
-HANDLE hLibrary;
-PROCESS_KEYSTROKE pProcessKeystroke;
-NHKBHIT pNHkbhit;
-CHECKINPUT pCheckInput;
-SOURCEWHERE pSourceWhere;
-SOURCEAUTHOR pSourceAuthor;
-KEYHANDLERNAME pKeyHandlerName;
-
 #ifdef CHANGE_COLOR
 static void NDECL(adjust_palette);
 static int FDECL(match_color_name, (const char *));
@@ -112,29 +99,57 @@ static COLORREF DefaultColors[CLR_MAX] = {
     0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff
 };
 #endif
-
+struct console_t {
+    WORD background;
+    WORD foreground;
+    WORD attr;
+    int current_nhcolor;
+    int current_nhattr[ATR_INVERSE+1];
+    COORD cursor;
+} console = {
+    0,
+    (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED),
+    (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED),
+    NO_COLOR,
+    {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE},
+    {0, 0}
+};
+static DWORD ccount, acount;
 #ifndef CLR_MAX
 #define CLR_MAX 16
 #endif
+
 int ttycolors[CLR_MAX];
-#ifdef TEXTCOLOR
-static void NDECL(init_ttycolor);
-#endif
-static void NDECL(really_move_cursor);
+int ttycolors_inv[CLR_MAX];
 
 #define MAX_OVERRIDES 256
 unsigned char key_overrides[MAX_OVERRIDES];
-
 static char nullstr[] = "";
 char erase_char, kill_char;
-
 #define DEFTEXTCOLOR ttycolors[7]
-static WORD background = 0;
-static WORD foreground =
-    (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
-static WORD attr = (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
-static DWORD ccount, acount;
-static COORD cursor = { 0, 0 };
+
+/* 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, int *, coord *);
+
+typedef int(__stdcall *SOURCEWHERE)(char **);
+
+typedef int(__stdcall *SOURCEAUTHOR)(char **);
+
+typedef int(__stdcall *KEYHANDLERNAME)(char **, int);
+
+HANDLE hLibrary;
+PROCESS_KEYSTROKE pProcessKeystroke;
+NHKBHIT pNHkbhit;
+CHECKINPUT pCheckInput;
+SOURCEWHERE pSourceWhere;
+SOURCEAUTHOR pSourceAuthor;
+KEYHANDLERNAME pKeyHandlerName;
 
 /*
  * Called after returning from ! or ^Z
@@ -142,6 +157,10 @@ static COORD cursor = { 0, 0 };
 void
 gettty()
 {
+    console_font_changed = FALSE;
+
+    check_and_set_font();
+
 #ifndef TEXTCOLOR
     int k;
 #endif
@@ -152,7 +171,7 @@ gettty()
     init_ttycolor();
 #else
     for (k = 0; k < CLR_MAX; ++k)
-        ttycolors[k] = 7;
+        ttycolors[k] = NO_COLOR;
 #endif
 }
 
@@ -165,6 +184,8 @@ const char *s;
     end_screen();
     if (s)
         raw_print(s);
+
+    restore_original_console_font();
 }
 
 /* called by init_nhwindows() and resume_nhwindows() */
@@ -258,6 +279,8 @@ int mode;
     DWORD cmode;
     long mask;
 
+    GUILaunched = 0;
+
     try :
         /* The following lines of code were suggested by
          * Bob Landau of Microsoft WIN32 Developer support,
@@ -265,14 +288,10 @@ int mode;
          * we were launched from the command prompt, or from
          * the NT program manager. M. Allison
          */
-        hStdOut
-        = GetStdHandle(STD_OUTPUT_HANDLE);
+    hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+
     if (hStdOut) {
         GetConsoleScreenBufferInfo(hStdOut, &origcsbi);
-        GUILaunched = ((origcsbi.dwCursorPosition.X == 0)
-                       && (origcsbi.dwCursorPosition.Y == 0));
-        if ((origcsbi.dwSize.X <= 0) || (origcsbi.dwSize.Y <= 0))
-            GUILaunched = 0;
     } else if (mode) {
         HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
         HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
@@ -286,10 +305,14 @@ int mode;
             freopen("CON", "r", stdin);
         }
         mode = 0;
-        goto try
-            ;
-    } else
+        goto try;
+    } else {
         return;
+    }
+
+    /* Obtain handles for the standard Console I/O devices */
+    hConIn = GetStdHandle(STD_INPUT_HANDLE);
+    hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
 
     load_keyboard_handler();
     /* Initialize the function pointer that points to
@@ -297,20 +320,6 @@ int mode;
     */
     nt_kbhit = nttty_kbhit;
 
-    /* Obtain handles for the standard Console I/O devices */
-    hConIn = GetStdHandle(STD_INPUT_HANDLE);
-    hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
-#if 0
-       hConIn = CreateFile("CONIN$",
-                       GENERIC_READ |GENERIC_WRITE,
-                       FILE_SHARE_READ |FILE_SHARE_WRITE,
-                       0, OPEN_EXISTING, 0, 0);                                        
-       hConOut = CreateFile("CONOUT$",
-                       GENERIC_READ |GENERIC_WRITE,
-                       FILE_SHARE_READ |FILE_SHARE_WRITE,
-                       0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0);
-#endif
-
     GetConsoleMode(hConIn, &cmode);
 #ifdef NO_MOUSE_ALLOWED
     mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_MOUSE_INPUT
@@ -330,7 +339,7 @@ int mode;
         cmode = 0; /* just to have a statement to break on for debugger */
     }
     get_scr_size();
-    cursor.X = cursor.Y = 0;
+    console.cursor.X = console.cursor.Y = 0;
     really_move_cursor();
 }
 
@@ -357,11 +366,16 @@ nttty_kbhit()
 void
 get_scr_size()
 {
+    int lines, cols;
+    
     GetConsoleScreenBufferInfo(hConOut, &csbi);
+    
+    lines = csbi.srWindow.Bottom - (csbi.srWindow.Top + 1);
+    cols = csbi.srWindow.Right - (csbi.srWindow.Left + 1);
 
-    LI = csbi.srWindow.Bottom - (csbi.srWindow.Top + 1);
-    CO = csbi.srWindow.Right - (csbi.srWindow.Left + 1);
-
+    LI = lines;
+    CO = min(cols, 80);
+    
     if ((LI < 25) || (CO < 80)) {
         COORD newcoord;
 
@@ -417,15 +431,15 @@ really_move_cursor()
             oldtitle[39] = '\0';
         }
         Sprintf(newtitle, "%-55s tty=(%02d,%02d) nttty=(%02d,%02d)", oldtitle,
-                ttyDisplay->curx, ttyDisplay->cury, cursor.X, cursor.Y);
+                ttyDisplay->curx, ttyDisplay->cury, console.cursor.X, console.cursor.Y);
         (void) SetConsoleTitle(newtitle);
     }
 #endif
     if (ttyDisplay) {
-        cursor.X = ttyDisplay->curx;
-        cursor.Y = ttyDisplay->cury;
+        console.cursor.X = ttyDisplay->curx;
+        console.cursor.Y = ttyDisplay->cury;
     }
-    SetConsoleCursorPosition(hConOut, cursor);
+    SetConsoleCursorPosition(hConOut, console.cursor);
 }
 
 void
@@ -434,55 +448,26 @@ register int x, y;
 {
     ttyDisplay->cury = y;
     ttyDisplay->curx = x;
-    cursor.X = x;
-    cursor.Y = y;
+    console.cursor.X = x;
+    console.cursor.Y = y;
 }
 
 void
 nocmov(x, y)
 int x, y;
 {
-    cursor.X = x;
-    cursor.Y = y;
+    console.cursor.X = x;
+    console.cursor.Y = y;
     ttyDisplay->curx = x;
     ttyDisplay->cury = y;
 }
 
 void
-xputc_core(ch)
-char ch;
-{
-    switch (ch) {
-    case '\n':
-        cursor.Y++;
-    /* fall through */
-    case '\r':
-        cursor.X = 1;
-        break;
-    case '\b':
-        cursor.X--;
-        break;
-    default:
-        WriteConsoleOutputAttribute(hConOut, &attr, 1, cursor, &acount);
-        if (has_unicode) {
-            /* Avoid bug in ANSI API on WinNT */
-            WCHAR c2[2];
-            int rc;
-            rc = MultiByteToWideChar(GetConsoleOutputCP(), 0, &ch, 1, c2, 2);
-            WriteConsoleOutputCharacterW(hConOut, c2, rc, cursor, &ccount);
-        } else {
-            WriteConsoleOutputCharacterA(hConOut, &ch, 1, cursor, &ccount);
-        }
-        cursor.X++;
-    }
-}
-
-void
 xputc(ch)
 char ch;
 {
-    cursor.X = ttyDisplay->curx;
-    cursor.Y = ttyDisplay->cury;
+    console.cursor.X = ttyDisplay->curx;
+    console.cursor.Y = ttyDisplay->cury;
     xputc_core(ch);
 }
 
@@ -498,13 +483,13 @@ int ch2;
     buf[0] = ch1;
     buf[1] = ch2;
 
-    attrs[0] = attrs[1] = attr;
+    attrs[0] = attrs[1] = console.attr;
 
-    WriteConsoleOutputAttribute(hConOut,(WORD *)(&attrs),2,
-                               cursor,&acount);
-    WriteConsoleOutputCharacter(hConOut,buf,2,
-                               cursor,&ccount);
-    cursor.X += 2;
+    WriteConsoleOutputAttribute(hConOut, (WORD *)(&attrs), 2,
+                                console.cursor, &acount);
+    WriteConsoleOutputCharacter(hConOut, buf, 2,
+                                console.cursor, &ccount);
+    console.cursor.X += 2;
 }
 
 void
@@ -515,8 +500,8 @@ int ch2;
     /* wintty.c \82Å\82Í 1 \83o\83C\83g\96\88\82É curx \82ð\89Á\8eZ\82·\82é\82ª\81A\82±\82±\82Í
        2 \83o\83C\83g\82½\82Ü\82Á\82Ä\82©\82ç\8cÄ\82Ñ\8fo\82³\82ê\82é\82Ì\82Å\81A1 \95\8e\9a\95ª\90æ\82É\90i\82ñ\82Å
       \82µ\82Ü\82Á\82Ä\82¢\82é\81B\8f]\82Á\82Ä 1 \82ð\88ø\82­\81B */
-    cursor.X = ttyDisplay->curx - 1;
-    cursor.Y = ttyDisplay->cury;
+    console.cursor.X = ttyDisplay->curx - 1;
+    console.cursor.Y = ttyDisplay->cury;
 
     xputc2_core(ch1, ch2);
 }
@@ -530,8 +515,8 @@ const char *s;
     int slen = strlen(s);
 
     if (ttyDisplay) {
-        cursor.X = ttyDisplay->curx;
-        cursor.Y = ttyDisplay->cury;
+        console.cursor.X = ttyDisplay->curx;
+        console.cursor.Y = ttyDisplay->cury;
     }
 
     if (s) {
@@ -540,69 +525,121 @@ const char *s;
     }
 }
 
+/* xputc_core() and g_putch() are the only
+ * two routines that actually place output
+ * on the display.
+ */
+void
+xputc_core(ch)
+char ch;
+{
+    boolean inverse = FALSE;
+    switch (ch) {
+    case '\n':
+        console.cursor.Y++;
+    /* fall through */
+    case '\r':
+        console.cursor.X = 1;
+        break;
+    case '\b':
+        console.cursor.X--;
+        break;
+    default:
+        inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
+        console.attr = (inverse) ?
+                        ttycolors_inv[console.current_nhcolor] :
+                        ttycolors[console.current_nhcolor];
+        if (console.current_nhattr[ATR_BOLD])
+                console.attr |= (inverse) ?
+                                BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
+        WriteConsoleOutputAttribute(hConOut, &console.attr, 1, console.cursor, &acount);
+        if (has_unicode) {
+            /* Avoid bug in ANSI API on WinNT */
+            WCHAR c2[2];
+            int rc;
+            rc = MultiByteToWideChar(GetConsoleOutputCP(), 0, &ch, 1, c2, 2);
+            WriteConsoleOutputCharacterW(hConOut, c2, rc, console.cursor, &ccount);
+        } else {
+            WriteConsoleOutputCharacterA(hConOut, &ch, 1, console.cursor, &ccount);
+        }
+        console.cursor.X++;
+    }
+}
+
 /*
  * Overrides wintty.c function of the same name
  * for win32. It is used for glyphs only, not text.
  */
+
+/* CP437 to Unicode mapping according to the Unicode Consortium */
+static const WCHAR cp437[] = {
+    0x0020, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
+    0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
+    0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
+    0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
+    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+    0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+    0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+    0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+    0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+    0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+    0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
+    0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
+    0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+    0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
+    0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
+    0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
+    0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+    0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
+    0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
+    0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
+    0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
+    0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
+    0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
+    0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
+    0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
+    0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
+};
+
 void
 g_putch(in_ch)
 int in_ch;
 {
-    /* CP437 to Unicode mapping according to the Unicode Consortium */
-    static const WCHAR cp437[] = {
-        0x0020, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
-        0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
-        0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
-        0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
-        0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
-        0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
-        0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
-        0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
-        0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
-        0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
-        0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
-        0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
-        0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
-        0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
-        0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
-        0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
-        0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
-        0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
-        0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
-        0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
-        0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
-        0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
-        0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
-        0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
-        0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
-        0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
-        0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
-        0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
-        0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
-        0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
-        0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
-        0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
-    };
+    boolean inverse = FALSE;
     unsigned char ch = (unsigned char) in_ch;
 
-    cursor.X = ttyDisplay->curx;
-    cursor.Y = ttyDisplay->cury;
-    WriteConsoleOutputAttribute(hConOut, &attr, 1, cursor, &acount);
+    console.cursor.X = ttyDisplay->curx;
+    console.cursor.Y = ttyDisplay->cury;
+
+    inverse = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse);
+    console.attr = (console.current_nhattr[ATR_INVERSE] && iflags.wc_inverse) ?
+                    ttycolors_inv[console.current_nhcolor] :
+                    ttycolors[console.current_nhcolor];
+    if (console.current_nhattr[ATR_BOLD])
+        console.attr |= (inverse) ? BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
+    WriteConsoleOutputAttribute(hConOut, &console.attr, 1, console.cursor, &acount);
+
     if (has_unicode)
-        WriteConsoleOutputCharacterW(hConOut, &cp437[ch], 1, cursor, &ccount);
+        WriteConsoleOutputCharacterW(hConOut, &cp437[ch], 1, console.cursor, &ccount);
     else
-        WriteConsoleOutputCharacterA(hConOut, &ch, 1, cursor, &ccount);
+        WriteConsoleOutputCharacterA(hConOut, &ch, 1, console.cursor, &ccount);
 }
 
 void
 cl_end()
 {
     int cx;
-    cursor.X = ttyDisplay->curx;
-    cursor.Y = ttyDisplay->cury;
-    cx = CO - cursor.X;
-    FillConsoleOutputAttribute(hConOut, DEFTEXTCOLOR, cx, cursor, &acount);
-    FillConsoleOutputCharacter(hConOut, ' ', cx, cursor, &ccount);
+    console.cursor.X = ttyDisplay->curx;
+    console.cursor.Y = ttyDisplay->cury;
+    cx = CO - console.cursor.X;
+    FillConsoleOutputAttribute(hConOut, DEFTEXTCOLOR, cx, console.cursor, &acount);
+    FillConsoleOutputCharacter(hConOut, ' ', cx, console.cursor, &ccount);
     tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
 }
 
@@ -633,15 +670,15 @@ clear_screen()
 void
 home()
 {
-    cursor.X = cursor.Y = 0;
+    console.cursor.X = console.cursor.Y = 0;
     ttyDisplay->curx = ttyDisplay->cury = 0;
 }
 
 void
 backsp()
 {
-    cursor.X = ttyDisplay->curx;
-    cursor.Y = ttyDisplay->cury;
+    console.cursor.X = ttyDisplay->curx;
+    console.cursor.Y = ttyDisplay->cury;
     xputc_core('\b');
 }
 
@@ -713,27 +750,53 @@ tty_delay_output()
 static void
 init_ttycolor()
 {
-    ttycolors[CLR_BLACK] = FOREGROUND_INTENSITY; /* fix by Quietust */
-    ttycolors[CLR_RED] = FOREGROUND_RED;
-    ttycolors[CLR_GREEN] = FOREGROUND_GREEN;
-    ttycolors[CLR_BROWN] = FOREGROUND_GREEN | FOREGROUND_RED;
-    ttycolors[CLR_BLUE] = FOREGROUND_BLUE;
-    ttycolors[CLR_MAGENTA] = FOREGROUND_BLUE | FOREGROUND_RED;
-    ttycolors[CLR_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE;
-    ttycolors[CLR_GRAY] = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE;
-    ttycolors[BRIGHT] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED
-                        | FOREGROUND_INTENSITY;
-    ttycolors[CLR_ORANGE] = FOREGROUND_RED | FOREGROUND_INTENSITY;
+#ifdef TEXTCOLOR
+    ttycolors[CLR_BLACK]        = FOREGROUND_INTENSITY; /* fix by Quietust */
+    ttycolors[CLR_RED]          = FOREGROUND_RED;
+    ttycolors[CLR_GREEN]        = FOREGROUND_GREEN;
+    ttycolors[CLR_BROWN]        = FOREGROUND_GREEN | FOREGROUND_RED;
+    ttycolors[CLR_BLUE]         = FOREGROUND_BLUE;
+    ttycolors[CLR_MAGENTA]      = FOREGROUND_BLUE | FOREGROUND_RED;
+    ttycolors[CLR_CYAN]         = FOREGROUND_GREEN | FOREGROUND_BLUE;
+    ttycolors[CLR_GRAY]         = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE;
+    ttycolors[NO_COLOR]         = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
+    ttycolors[CLR_ORANGE]       = FOREGROUND_RED | FOREGROUND_INTENSITY;
     ttycolors[CLR_BRIGHT_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
-    ttycolors[CLR_YELLOW] =
-        FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
-    ttycolors[CLR_BRIGHT_BLUE] = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
-    ttycolors[CLR_BRIGHT_MAGENTA] =
-        FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
-    ttycolors[CLR_BRIGHT_CYAN] =
-        FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
-    ttycolors[CLR_WHITE] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED
-                           | FOREGROUND_INTENSITY;
+    ttycolors[CLR_YELLOW]       = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
+    ttycolors[CLR_BRIGHT_BLUE]  = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
+    ttycolors[CLR_BRIGHT_MAGENTA]=FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
+    ttycolors[CLR_BRIGHT_CYAN]  = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
+    ttycolors[CLR_WHITE]        = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED
+                                    | FOREGROUND_INTENSITY;
+
+    ttycolors_inv[CLR_BLACK]       = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
+                                        | BACKGROUND_INTENSITY;
+    ttycolors_inv[CLR_RED]         = BACKGROUND_RED | BACKGROUND_INTENSITY;
+    ttycolors_inv[CLR_GREEN]       = BACKGROUND_GREEN;
+    ttycolors_inv[CLR_BROWN]       = BACKGROUND_GREEN | BACKGROUND_RED;
+    ttycolors_inv[CLR_BLUE]        = BACKGROUND_BLUE | BACKGROUND_INTENSITY;
+    ttycolors_inv[CLR_MAGENTA]     = BACKGROUND_BLUE | BACKGROUND_RED;
+    ttycolors_inv[CLR_CYAN]        = BACKGROUND_GREEN | BACKGROUND_BLUE;
+    ttycolors_inv[CLR_GRAY]        = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE;
+    ttycolors_inv[NO_COLOR]        = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
+    ttycolors_inv[CLR_ORANGE]      = BACKGROUND_RED | BACKGROUND_INTENSITY;
+    ttycolors_inv[CLR_BRIGHT_GREEN]= BACKGROUND_GREEN | BACKGROUND_INTENSITY;
+    ttycolors_inv[CLR_YELLOW]      = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY;
+    ttycolors_inv[CLR_BRIGHT_BLUE] = BACKGROUND_BLUE | BACKGROUND_INTENSITY;
+    ttycolors_inv[CLR_BRIGHT_MAGENTA] =BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY;
+    ttycolors_inv[CLR_BRIGHT_CYAN] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
+    ttycolors_inv[CLR_WHITE]       = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
+                                       | BACKGROUND_INTENSITY;
+#else
+    int k;
+    ttycolors[0] = FOREGROUND_INTENSITY;
+    ttycolors_inv[0] = BACKGROUND_INTENSITY;
+    for (k = 1; k < SIZE(ttycolors); ++k) {
+        ttycolors[k] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
+        ttycolors_inv[k] = BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
+    }
+#endif
+    init_ttycolor_completed = TRUE;
 }
 #endif /* TEXTCOLOR */
 
@@ -741,64 +804,42 @@ int
 has_color(int color)
 {
 #ifdef TEXTCOLOR
-    return 1;
-#else
-    if (color == CLR_BLACK)
+    if ((color >= 0) && (color < CLR_MAX))
         return 1;
-    else if (color == CLR_WHITE)
+#else
+    if ((color == CLR_BLACK) || (color == CLR_WHITE) || (color == NO_COLOR))
         return 1;
+#endif
     else
         return 0;
-#endif
 }
 
 void
 term_start_attr(int attrib)
 {
-    switch (attrib) {
-    case ATR_INVERSE:
-        if (iflags.wc_inverse) {
-            /* Suggestion by Lee Berger */
-            if ((foreground
-                 & (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED))
-                == (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED))
-                foreground &=
-                    ~(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
-            background =
-                (BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN);
-            break;
-        }
-    /*FALLTHRU*/
-    case ATR_ULINE:
-    case ATR_BLINK:
-    case ATR_BOLD:
-        foreground |= FOREGROUND_INTENSITY;
-        break;
-    default:
-        foreground &= ~FOREGROUND_INTENSITY;
-        break;
-    }
-    attr = (foreground | background);
+    console.current_nhattr[attrib] = TRUE;
+    if (attrib) console.current_nhattr[ATR_NONE] = FALSE;
 }
 
 void
 term_end_attr(int attrib)
 {
+    int k;
+
     switch (attrib) {
     case ATR_INVERSE:
-        if ((foreground
-             & (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED)) == 0)
-            foreground |=
-                (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
-        background = 0;
-        break;
     case ATR_ULINE:
     case ATR_BLINK:
     case ATR_BOLD:
-        foreground &= ~FOREGROUND_INTENSITY;
         break;
     }
-    attr = (foreground | background);
+    console.current_nhattr[attrib] = FALSE;
+    console.current_nhattr[ATR_NONE] = TRUE;
+    /* re-evaluate all attr now for performance at output time */
+    for (k=ATR_NONE; k <= ATR_INVERSE; ++k) {
+        if (console.current_nhattr[k])
+            console.current_nhattr[ATR_NONE] = FALSE;
+    }
 }
 
 void
@@ -818,24 +859,20 @@ term_start_color(int color)
 {
 #ifdef TEXTCOLOR
     if (color >= 0 && color < CLR_MAX) {
-        foreground =
-            (background != 0 && (color == CLR_GRAY || color == CLR_WHITE))
-                ? ttycolors[0]
-                : ttycolors[color];
-    }
-#else
-    foreground = DEFTEXTCOLOR;
+        console.current_nhcolor = color;
+    } else
 #endif
-    attr = (foreground | background);
+    console.current_nhcolor = NO_COLOR;
 }
 
 void
 term_end_color(void)
 {
 #ifdef TEXTCOLOR
-    foreground = DEFTEXTCOLOR;
+    console.foreground = DEFTEXTCOLOR;
 #endif
-    attr = (foreground | background);
+    console.attr = (console.foreground | console.background);
+    console.current_nhcolor = NO_COLOR;
 }
 
 void
@@ -874,6 +911,8 @@ const char *pref;
         toggle_mouse_support();
 #endif
     }
+    if (stricmp(pref, "symset") == 0)
+        check_and_set_font();
     return;
 }
 
@@ -1058,22 +1097,25 @@ VA_DECL(const char *, fmt)
     if (redirect_stdout)
         fprintf(stdout, "%s", buf);
     else {
+        if(!init_ttycolor_completed)
+            init_ttycolor();
+
 #if 0 /*JP*/
         xputs(buf);
 #else
-       if(ttyDisplay){
-           cursor.X = ttyDisplay->curx;
-           cursor.Y = ttyDisplay->cury;
-       }
-       {
-           char *str = buf;
-           while(*str){
-               jbuffer(*(str++), NULL, xputc_core, xputc2_core);
-           }
-       }
+        if(ttyDisplay){
+            console.cursor.X = ttyDisplay->curx;
+            console.cursor.Y = ttyDisplay->cury;
+        }
+        {
+            char *str = buf;
+            while(*str){
+                jbuffer(*(str++), NULL, xputc_core, xputc2_core);
+            }
+        }
 #endif
         if (ttyDisplay)
-            curs(BASE_WINDOW, cursor.X + 1, cursor.Y);
+            curs(BASE_WINDOW, console.cursor.X + 1, console.cursor.Y);
     }
     VA_END();
     return;
@@ -1497,4 +1539,179 @@ GetConsoleHwnd(void)
     return hwndFound;
 }
 #endif /*CHANGE_COLOR*/
+
+static int CALLBACK EnumFontCallback(
+    const LOGFONTW * lf, const TEXTMETRICW * tm, DWORD fontType, LPARAM lParam)
+{
+    LOGFONTW * lf_ptr = (LOGFONTW *) lParam;
+    *lf_ptr = *lf;
+    return 0;
+}
+
+/* check_and_set_font ensures that the current font will render the symbols
+ * that are currently being used correctly.  If they will not be rendered
+ * correctly, then it will change the font to a known good font.
+ */
+void
+check_and_set_font()
+{
+    if (!check_font_widths()) {
+        raw_print("WARNING: glyphs too wide in console font."
+                  "  Changing code page to 437 and font to Consolas\n");
+        set_known_good_console_font();
+    }
+}
+
+/* check_font_widths returns TRUE if all glyphs in current console font
+ * fit within the width of a single console cell.
+ */
+boolean
+check_font_widths()
+{
+    CONSOLE_FONT_INFOEX console_font_info;
+    console_font_info.cbSize = sizeof(console_font_info);
+    BOOL success = GetCurrentConsoleFontEx(hConOut, FALSE,
+                                            &console_font_info);
+
+    /* get console window and DC
+     * NOTE: the DC from the console window does not have the correct
+     *       font selected at this point.
+     */
+    HWND hWnd = GetConsoleWindow();
+    HDC hDC = GetDC(hWnd);
+
+    LOGFONTW logical_font;
+    logical_font.lfCharSet = DEFAULT_CHARSET;
+    wcscpy(logical_font.lfFaceName, console_font_info.FaceName);
+    logical_font.lfPitchAndFamily = 0;
+
+    /* getting matching console font */
+    LOGFONTW matching_log_font = { 0 };
+    EnumFontFamiliesExW(hDC, &logical_font, EnumFontCallback,
+                                        (LPARAM) &matching_log_font, 0);
+
+    if (matching_log_font.lfHeight == 0) {
+        raw_print("Unable to enumerate system fonts\n");
+        return FALSE;
+    }
+
+    /* create font matching console font */
+    LOGFONTW console_font_log_font = matching_log_font;
+    console_font_log_font.lfWeight = console_font_info.FontWeight;
+    console_font_log_font.lfHeight = console_font_info.dwFontSize.Y;
+    console_font_log_font.lfWidth = 0;
+    HFONT console_font = CreateFontIndirectW(&console_font_log_font);
+
+    if (console_font == NULL) {
+        raw_print("Unable to create console font\n");
+        return FALSE;
+    }
+
+    /* select font */
+    HGDIOBJ saved_font = SelectObject(hDC, console_font);
+
+    /* determine whether it is a true type font */
+    TEXTMETRICA tm;
+    success = GetTextMetricsA(hDC, &tm);
+
+    if (!success) {
+        raw_print("Unable to get console font text metrics\n");
+        goto clean_up;
+    }
+
+    boolean isTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0;
+
+    /* determine which glyphs are used */
+    boolean used[256];
+    memset(used, 0, sizeof(used));
+    for (int i = 0; i < SYM_MAX; i++) {
+        used[l_syms[i]] = TRUE;
+        used[r_syms[i]] = TRUE;
+    }
+
+    int wcUsedCount = 0;
+    wchar_t wcUsed[256];
+    for (int i = 0; i < sizeof(used); i++)
+        if (used[i])
+            wcUsed[wcUsedCount++] = cp437[i];
+
+    /* measure the set of used glyphs to ensure they fit */
+    boolean all_glyphs_fit = TRUE;
+
+    for (int i = 0; i < wcUsedCount; i++) {
+        int width;
+        if (isTrueType) {
+            ABC abc;
+            success = GetCharABCWidthsW(hDC, wcUsed[i], wcUsed[i], &abc);
+            width = abc.abcA + abc.abcB + abc.abcC;
+        } else {
+            success = GetCharWidthW(hDC, wcUsed[i], wcUsed[i], &width);
+        }
+
+        if (success && width > console_font_info.dwFontSize.X) {
+            all_glyphs_fit = FALSE;
+            break;
+        }
+    }
+
+clean_up:
+
+    SelectObject(hDC, saved_font);
+    DeleteObject(console_font);
+
+    return all_glyphs_fit;
+}
+
+/* set_known_good_console_font sets the code page and font used by the console
+ * to settings know to work well with NetHack.  It also saves the original
+ * settings so that they can be restored prior to NetHack exit.
+ */
+void
+set_known_good_console_font()
+{
+    CONSOLE_FONT_INFOEX console_font_info;
+    console_font_info.cbSize = sizeof(console_font_info);
+    BOOL success = GetCurrentConsoleFontEx(hConOut, FALSE,
+                                            &console_font_info);
+
+    console_font_changed = TRUE;
+    original_console_font_info = console_font_info;
+    original_console_code_page = GetConsoleOutputCP();
+
+    wcscpy_s(console_font_info.FaceName,
+        sizeof(console_font_info.FaceName)
+            / sizeof(console_font_info.FaceName[0]),
+        L"Consolas");
+
+    success = SetConsoleOutputCP(437);
+    if (!success)
+        raw_print("Unable to set console code page to 437\n");
+
+    success = SetCurrentConsoleFontEx(hConOut, FALSE, &console_font_info);
+    if (!success)
+        raw_print("Unable to set console font to Consolas\n");
+}
+
+/* restore_original_console_font will restore the console font and code page
+ * settings to what they were when NetHack was launched.
+ */
+void
+restore_original_console_font()
+{
+    if (console_font_changed) {
+        BOOL success;
+        raw_print("Restoring original font and code page\n");
+        success = SetConsoleOutputCP(original_console_code_page);
+        if (!success)
+            raw_print("Unable to restore original code page\n");
+
+        success = SetCurrentConsoleFontEx(hConOut, FALSE,
+                                            &original_console_font_info);
+        if (!success)
+            raw_print("Unable to restore original font\n");
+
+        console_font_changed = FALSE;
+    }
+}
+
 #endif /* WIN32 */
index 210297f..38baa4c 100644 (file)
@@ -1,3 +1,7 @@
+/* NetHack 3.6  stubs.c       $NHDT-Date: 1524689357 2018/04/25 20:49:17 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.3 $ */
+/*      Copyright (c) 2015 by Michael Allison              */
+/* NetHack may be freely redistributed.  See license for details. */
+
 #include "hack.h"
 
 #ifdef GUISTUB
@@ -7,6 +11,7 @@
 
 int GUILaunched;
 struct window_procs mswin_procs = { "guistubs" };
+
 void
 mswin_destroy_reg()
 {
@@ -36,6 +41,7 @@ char *argv[];
     return 0;
 }
 #endif
+
 #endif /* GUISTUB */
 
 /* =============================================== */
@@ -43,7 +49,10 @@ char *argv[];
 #ifdef TTYSTUB
 
 #include "hack.h"
+#include "win32api.h"
 
+HANDLE hConIn;
+HANDLE hConOut;
 int GUILaunched;
 struct window_procs tty_procs = { "ttystubs" };
 
index d6cc37a..407aba2 100644 (file)
@@ -1,5 +1,7 @@
 #
-# NetHack 3.6 sysconf $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$
+# NetHack 3.6 sysconf $NHDT-Date: 1524689357 2018/04/25 20:49:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.22 $
+# Copyright (c) 2015 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
 #
 # Sample sysconf file.
 # The sysconf file is only used if NetHack is compiled with SYSCF defined.
@@ -18,6 +20,28 @@ WIZARDS=*
 # Only available if game has been compiled with DEBUG.
 #DEBUGFILES=*
 
+# Save end of game dump log to this file.
+# Only available if NetHack was compiled with DUMPLOG
+# Allows following placeholders:
+#   %% literal '%'
+#   %v version (eg. "3.6.1-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
+#DUMPLOGFILE=nethack-%n-%d.log
+
+# Number of bones file pools.
+# The pool you belong to is determined at game start. You will
+# load and save bones only from that pool. Generally useful
+# for public servers only.
+# Changing this might make existing bones inaccessible.
+# Disabled by setting to 0, or commenting out.
+#BONES_POOLS=10
+
 # Limit the number of simultaneous games (see also nethack.sh).
 #MAXPLAYERS=10
 
index 2b63c80..b4dc7e4 100644 (file)
 
 #define WIN32_LEAN_AND_MEAN
 
+#undef Protection /* We have a global name space collision.  No source file
+                     using win32api.h should be using the Protection macro
+                     from youprop.h.
+                     A better fix would be to ensure we include all window
+                     header files before we start clobbering the global name
+                     space with NetHack specific macros. */
+
 #include <windows.h>
 #include <commctrl.h>
 
index f277679..903aaef 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 winnt.c $NHDT-Date: 1431737068 2015/05/16 00:44:28 $  $NHDT-Branch: master $:$NHDT-Revision: 1.26 $ */
+/* NetHack 3.6 winnt.c $NHDT-Date: 1524321419 2018/04/21 14:36:59 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.30 $ */
 /* Copyright (c) NetHack PC Development Team 1993, 1994 */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -35,6 +35,9 @@
 /* globals required within here */
 HANDLE ffhandle = (HANDLE) 0;
 WIN32_FIND_DATA ffd;
+typedef HWND(WINAPI *GETCONSOLEWINDOW)();
+static HWND GetConsoleHandle(void);
+static HWND GetConsoleHwnd(void);
 
 /* The function pointer nt_kbhit contains a kbhit() equivalent
  * which varies depending on which window port is active.
@@ -119,7 +122,7 @@ char *str;
     char *ptr;
     char drive;
     if ((ptr = index(str, ':')) != (char *) 0) {
-        drive = toupper(*(ptr - 1));
+        drive = toupper((uchar) *(ptr - 1));
         _chdrive((drive - 'A') + 1);
     }
 }
@@ -319,6 +322,118 @@ int interjection_type;
         msmsg(interjection_buf[interjection_type]);
 }
 
+#ifdef RUNTIME_PASTEBUF_SUPPORT
+
+void port_insert_pastebuf(buf)
+char *buf;
+{
+    /* This implementation will utilize the windows clipboard
+     * to accomplish this.
+     */
+
+    char *tmp = buf;
+    HGLOBAL hglbCopy; 
+    WCHAR *w, w2[2];
+    int cc, rc, abytes;
+    LPWSTR lpwstrCopy;
+    HANDLE hresult;
+
+    if (!buf)
+        return; 
+    cc = strlen(buf);
+    /* last arg=0 means "tell me the size of the buffer that I need" */
+    rc = MultiByteToWideChar(GetConsoleOutputCP(), 0, buf, -1, w2, 0);
+    if (!rc) return;
+
+    abytes = rc * sizeof(WCHAR);
+    w = (WCHAR *)alloc(abytes);     
+    /* Housekeeping need: +free(w) */
+
+    rc = MultiByteToWideChar(GetConsoleOutputCP(), 0, buf, -1, w, rc);
+    if (!rc) {
+        free(w);
+        return;
+    }
+    if (!OpenClipboard(NULL)) {
+        free(w);
+        return;
+    }
+    /* Housekeeping need: +CloseClipboard(), free(w) */
+
+    EmptyClipboard(); 
+
+    /* allocate global mem obj to hold the text */
+    hglbCopy = GlobalAlloc(GMEM_MOVEABLE, abytes);
+    if (hglbCopy == NULL) { 
+        CloseClipboard(); 
+        free(w);
+        return;
+    } 
+    /* Housekeeping need: +GlobalFree(hglbCopy), CloseClipboard(), free(w) */
+    lpwstrCopy = (LPWSTR)GlobalLock(hglbCopy);
+    /* Housekeeping need: +GlobalUnlock(hglbCopy), GlobalFree(hglbCopy),
+                            CloseClipboard(), free(w) */
+
+    memcpy(lpwstrCopy, w, abytes);
+    GlobalUnlock(hglbCopy);
+    /* Housekeeping need: GlobalFree(hglbCopy), CloseClipboard(), free(w) */
+
+    /* put it on the clipboard */
+    hresult = SetClipboardData(CF_UNICODETEXT, hglbCopy);
+    if (!hresult) {
+        raw_printf("Error copying to clipboard.\n");
+        GlobalFree(hglbCopy); /* only needed if clipboard didn't accept data */
+    }
+    /* Housekeeping need: CloseClipboard(), free(w) */
+    CloseClipboard(); 
+    free(w);
+    return;
+}
+
+static HWND
+GetConsoleHandle(void)
+{
+    HMODULE hMod = GetModuleHandle("kernel32.dll");
+    GETCONSOLEWINDOW pfnGetConsoleWindow =
+        (GETCONSOLEWINDOW) GetProcAddress(hMod, "GetConsoleWindow");
+    if (pfnGetConsoleWindow)
+        return pfnGetConsoleWindow();
+    else
+        return GetConsoleHwnd();
+}
+
+static HWND
+GetConsoleHwnd(void)
+{
+    int iterations = 0;
+    HWND hwndFound = 0;
+    char OldTitle[1024], NewTitle[1024], TestTitle[1024];
+
+    /* Get current window title */
+    GetConsoleTitle(OldTitle, sizeof OldTitle);
+
+    (void) sprintf(NewTitle, "NETHACK%d/%d", GetTickCount(),
+                   GetCurrentProcessId());
+    SetConsoleTitle(NewTitle);
+
+    GetConsoleTitle(TestTitle, sizeof TestTitle);
+    while (strcmp(TestTitle, NewTitle) != 0) {
+        iterations++;
+        /* sleep(0); */
+        GetConsoleTitle(TestTitle, sizeof TestTitle);
+    }
+    hwndFound = FindWindow(NULL, NewTitle);
+    SetConsoleTitle(OldTitle);
+    /*       printf("%d iterations\n", iterations); */
+    return hwndFound;
+}
+
+#endif
+
 #ifdef RUNTIME_PORT_ID
 /*
  * _M_IX86 is Defined for x86 processors. This is not defined for x64
@@ -329,23 +444,23 @@ int interjection_type;
  */
 #ifndef _M_IX86
 #ifdef _M_X64
-#define TARGET_PORT "(x64) "
+#define TARGET_PORT "x64"
 #endif
 #ifdef _M_IA64
-#define TARGET_PORT "(IA64) "
+#define TARGET_PORT "IA64"
 #endif
 #endif
 
 #ifndef TARGET_PORT
-#define TARGET_PORT "(x86) "
+#define TARGET_PORT "x86"
 #endif
 
-void
-append_port_id(buf)
+char *
+get_port_id(buf)
 char *buf;
 {
-    char *portstr = TARGET_PORT;
-    Sprintf(eos(buf), " %s", portstr);
+    Strcpy(buf, TARGET_PORT);
+    return buf;
 }
 #endif /* RUNTIME_PORT_ID */
 
index a18b5fe..99c8527 100644 (file)
@@ -1,5 +1,5 @@
 %{
-/* NetHack 3.6  dgn_comp.l     $NHDT-Date: 1449385184 2015/12/06 06:59:44 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.12 $ */
+/* NetHack 3.6  dgn_comp.l     $NHDT-Date: 1455415007 2016/02/14 01:56:47 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.13 $ */
 /*     Copyright (c) 1989 by Jean-Christophe Collet */
 /*     Copyright (c) 1990 by M. Stephenson          */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -59,6 +59,7 @@ int FDECL(yyoutput, (int));
 #else  /* !FLEX_SCANNER && !FLEXHACK_SCANNER */
 /* most recent flex allows suppressing yyunput() altogether when not needed */
 #define YY_NO_UNPUT
+#define YY_NO_INPUT
 #endif
 
 #if defined(FLEX_SCANNER) || defined(FLEXHACK_SCANNER)
index 0a4b938..6cda2b3 100644 (file)
@@ -506,7 +506,7 @@ long slen, dir_size, flen;
             (long) DLB_VERS,   /* version of dlb file */
             (long) nfiles + 1, /* # of entries (includes directory) */
                                /* string length + room for nulls */
-            (long) slen + strlen(DLB_DIRECTORY) + nfiles + 1,
+            (long) slen + (long) strlen(DLB_DIRECTORY) + nfiles + 1,
             (long) dir_size,         /* start of first file */
             (long) flen + dir_size); /* total file size */
     Write(out, buf, strlen(buf));
index c70c481..d6ae147 100644 (file)
@@ -1,5 +1,5 @@
 %{
-/* NetHack 3.6  lev_comp.l     $NHDT-Date: 1449385191 2015/12/06 06:59:51 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.22 $ */
+/* NetHack 3.6  lev_comp.l     $NHDT-Date: 1455415007 2016/02/14 01:56:47 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.24 $ */
 /*     Copyright (c) 1989 by Jean-Christophe Collet */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -57,6 +57,7 @@ int FDECL(yyoutput, (int));
 #else  /* !FLEX_SCANNER && !FLEXHACK_SCANNER */
 /* most recent flex allows suppressing yyunput() altogether when not needed */
 #define YY_NO_UNPUT
+#define YY_NO_INPUT
 #endif
 
 #if defined(FLEX_SCANNER) || defined(FLEXHACK_SCANNER)
@@ -102,9 +103,9 @@ FILE *orig_yyin = NULL;
 #define ST_RETF(y, x) do { savetoken(yytext); y; return x; } while (0);
 
 %}
-%e 2000
-%p 5000
-%n 700
+%e 2500
+%p 10000
+%n 1500
 %s MAPC
 %%
 <MAPC>ENDMAP   {
index 6831564..9122ca5 100644 (file)
@@ -1,6 +1,6 @@
 %{
-/* NetHack 3.6  lev_comp.y     $NHDT-Date: 1448074095 2015/11/21 02:48:15 $  $NHDT-Branch: master $:$NHDT-Revision: 1.18 $ */
-/*     Copyright (c) 1989 by Jean-Christophe Collet */
+/* NetHack 3.6  lev_comp.y     $NHDT-Date: 1455746893 2016/02/17 22:08:13 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */
+/*      Copyright (c) 1989 by Jean-Christophe Collet */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
  * and AIX will still see the directive.
  */
 #ifdef _AIX
- #pragma alloca                /* keep leading space! */
+ #pragma alloca         /* keep leading space! */
 #endif
 
 #define SPEC_LEV    /* for USE_OLDARGS (sp_lev.h) */
 #include "hack.h"
 #include "sp_lev.h"
 
-#define ERR            (-1)
+#define ERR             (-1)
 /* many types of things are put in chars for transference to NetHack.
  * since some systems will use signed chars, limit everybody to the
  * same number for portability.
  */
-#define MAX_OF_TYPE    128
+#define MAX_OF_TYPE     128
 
-#define MAX_NESTED_IFS 20
+#define MAX_NESTED_IFS   20
 #define MAX_SWITCH_CASES 20
 
-#define New(type)              \
-       (type *) memset((genericptr_t)alloc(sizeof(type)), 0, sizeof(type))
-#define NewTab(type, size)     (type **) alloc(sizeof(type *) * size)
-#define Free(ptr)              free((genericptr_t)ptr)
+#define New(type) \
+        (type *) memset((genericptr_t) alloc(sizeof (type)), 0, sizeof (type))
+#define NewTab(type, size)      (type **) alloc(sizeof (type *) * size)
+#define Free(ptr)               free((genericptr_t) ptr)
 
 extern void VDECL(lc_error, (const char *, ...));
 extern void VDECL(lc_warning, (const char *, ...));
@@ -58,22 +58,24 @@ extern char FDECL(what_map_char, (CHAR_P));
 extern void FDECL(scan_map, (char *, sp_lev *));
 extern void FDECL(add_opcode, (sp_lev *, int, genericptr_t));
 extern genericptr_t FDECL(get_last_opcode_data1, (sp_lev *, int));
-extern genericptr_t FDECL(get_last_opcode_data2, (sp_lev *, int,int));
+extern genericptr_t FDECL(get_last_opcode_data2, (sp_lev *, int, int));
 extern boolean FDECL(check_subrooms, (sp_lev *));
 extern boolean FDECL(write_level_file, (char *,sp_lev *));
 extern struct opvar *FDECL(set_opvar_int, (struct opvar *, long));
 extern void VDECL(add_opvars, (sp_lev *, const char *, ...));
 extern void FDECL(start_level_def, (sp_lev * *, char *));
 
-extern struct lc_funcdefs *FDECL(funcdef_new,(long,char *));
-extern void FDECL(funcdef_free_all,(struct lc_funcdefs *));
-extern struct lc_funcdefs *FDECL(funcdef_defined,(struct lc_funcdefs *,char *, int));
+extern struct lc_funcdefs *FDECL(funcdef_new, (long,char *));
+extern void FDECL(funcdef_free_all, (struct lc_funcdefs *));
+extern struct lc_funcdefs *FDECL(funcdef_defined, (struct lc_funcdefs *,
+                                                   char *, int));
 extern char *FDECL(funcdef_paramtypes, (struct lc_funcdefs *));
 extern char *FDECL(decode_parm_str, (char *));
 
-extern struct lc_vardefs *FDECL(vardef_new,(long,char *));
-extern void FDECL(vardef_free_all,(struct lc_vardefs *));
-extern struct lc_vardefs *FDECL(vardef_defined,(struct lc_vardefs *,char *, int));
+extern struct lc_vardefs *FDECL(vardef_new, (long,char *));
+extern void FDECL(vardef_free_all, (struct lc_vardefs *));
+extern struct lc_vardefs *FDECL(vardef_defined, (struct lc_vardefs *,
+                                                 char *, int));
 
 extern void NDECL(break_stmt_start);
 extern void FDECL(break_stmt_end, (sp_lev *));
@@ -83,13 +85,14 @@ extern void FDECL(splev_add_from, (sp_lev *, sp_lev *));
 
 extern void FDECL(check_vardef_type, (struct lc_vardefs *, char *, long));
 extern void FDECL(vardef_used, (struct lc_vardefs *, char *));
-extern struct lc_vardefs *FDECL(add_vardef_type, (struct lc_vardefs *, char *, long));
+extern struct lc_vardefs *FDECL(add_vardef_type, (struct lc_vardefs *,
+                                                  char *, long));
 
 extern int FDECL(reverse_jmp_opcode, (int));
 
 struct coord {
-       long x;
-       long y;
+    long x;
+    long y;
 };
 
 struct forloopdef {
@@ -979,7 +982,7 @@ forstmt_start       : FOR_ID any_var_or_unk '=' math_expr_var for_to_span math_expr_va
                      }
 
                      /* first, define a variable for the for-loop end value */
-                     snprintf(buf, 255, "%s end", $2);
+                     Sprintf(buf, "%s end", $2);
                      /* the value of which is already in stack (the 2nd math_expr) */
                      add_opvars(splev, "iso", VA_PASS3(0, buf, SPO_VAR_INIT));
 
@@ -989,7 +992,7 @@ forstmt_start       : FOR_ID any_var_or_unk '=' math_expr_var for_to_span math_expr_va
                      add_opvars(splev, "iso", VA_PASS3(0, $2, SPO_VAR_INIT));
 
                      /* calculate value for the loop "step" variable */
-                     snprintf(buf2, 255, "%s step", $2);
+                     Sprintf(buf2, "%s step", $2);
                      /* end - start */
                      add_opvars(splev, "vvo",
                                 VA_PASS3(buf, $2, SPO_MATH_SUB));
@@ -1015,9 +1018,10 @@ forstatement     : forstmt_start
                 stmt_block
                  {
                      char buf[256], buf2[256];
+
                      n_forloops--;
-                     snprintf(buf, 255, "%s step", forloop_list[n_forloops].varname);
-                     snprintf(buf2, 255, "%s end", forloop_list[n_forloops].varname);
+                     Sprintf(buf, "%s step", forloop_list[n_forloops].varname);
+                     Sprintf(buf2, "%s end", forloop_list[n_forloops].varname);
                      /* compare for-loop var to end value */
                      add_opvars(splev, "vvo",
                                 VA_PASS3(forloop_list[n_forloops].varname,
@@ -1747,8 +1751,8 @@ stair_region      : STAIR_ID ':' lev_region ',' lev_region ',' UP_OR_DOWN
                      add_opvars(splev, "iiiii iiiii iiso",
                                 VA_PASS14($3.x1, $3.y1, $3.x2, $3.y2, $3.area,
                                           $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
-                                     (long)(($7) ? LR_UPSTAIR : LR_DOWNSTAIR),
-                                          0, (char *)0, SPO_LEVREGION));
+                                    (long) (($7) ? LR_UPSTAIR : LR_DOWNSTAIR),
+                                          0, (char *) 0, SPO_LEVREGION));
                  }
                ;
 
@@ -1782,8 +1786,8 @@ branch_region     : BRANCH_ID ':' lev_region ',' lev_region
                      add_opvars(splev, "iiiii iiiii iiso",
                                 VA_PASS14($3.x1, $3.y1, $3.x2, $3.y2, $3.area,
                                           $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
-                                          (long)LR_BRANCH, 0,
-                                          (char *)0, SPO_LEVREGION));
+                                          (long) LR_BRANCH, 0,
+                                          (char *) 0, SPO_LEVREGION));
                  }
                ;
 
@@ -2207,7 +2211,8 @@ encodemonster     : STRING
                           lc_error("Unknown monster \"%s\"!", $1);
                           $$ = -1;
                       } else
-                          $$ = SP_MONST_PACK(m, def_monsyms[(int)mons[m].mlet].sym);
+                          $$ = SP_MONST_PACK(m,
+                                         def_monsyms[(int) mons[m].mlet].sym);
                       Free($1);
                   }
                 | CHAR
@@ -2375,16 +2380,23 @@ func_param_part : any_var_or_arr ':' func_param_type
                      } else if (!tmp) {
                          lc_error("Could not alloc function params.");
                      } else {
-                         long vt;
+                         long vt = SPOVAR_NULL;
+
                          tmp->name = strdup($1);
                          tmp->parmtype = (char) $3;
                          tmp->next = curr_function->params;
                          curr_function->params = tmp;
                          curr_function->n_params++;
                          switch (tmp->parmtype) {
-                         case 'i': vt = SPOVAR_INT; break;
-                         case 's': vt = SPOVAR_STRING; break;
-                         default: lc_error("Unknown func param conversion."); break;
+                         case 'i':
+                              vt = SPOVAR_INT;
+                              break;
+                         case 's':
+                              vt = SPOVAR_STRING;
+                              break;
+                         default:
+                              lc_error("Unknown func param conversion.");
+                              break;
                          }
                          variable_definitions = add_vardef_type(
                                                         variable_definitions,
@@ -2423,7 +2435,7 @@ func_call_param_list      : func_call_param_part
                        | func_call_param_list ',' func_call_param_part
                          {
                              long len = strlen( $1 );
-                             char *tmp = (char *)alloc(len + 2);
+                             char *tmp = (char *) alloc(len + 2);
                              sprintf(tmp, "%c%s", (char) $3, $1 );
                              Free( $1 );
                              $$ = tmp;
@@ -2593,13 +2605,21 @@ lev_region      : region
                | LEV '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
                  {
                        if ($3 <= 0 || $3 >= COLNO)
-                           lc_error("Region (%li,%li,%li,%li) out of level range (x1)!", $3, $5, $7, $9);
+                           lc_error(
+                          "Region (%ld,%ld,%ld,%ld) out of level range (x1)!",
+                                     $3, $5, $7, $9);
                        else if ($5 < 0 || $5 >= ROWNO)
-                           lc_error("Region (%li,%li,%li,%li) out of level range (y1)!", $3, $5, $7, $9);
+                           lc_error(
+                          "Region (%ld,%ld,%ld,%ld) out of level range (y1)!",
+                                     $3, $5, $7, $9);
                        else if ($7 <= 0 || $7 >= COLNO)
-                           lc_error("Region (%li,%li,%li,%li) out of level range (x2)!", $3, $5, $7, $9);
+                           lc_error(
+                          "Region (%ld,%ld,%ld,%ld) out of level range (x2)!",
+                                     $3, $5, $7, $9);
                        else if ($9 < 0 || $9 >= ROWNO)
-                           lc_error("Region (%li,%li,%li,%li) out of level range (y2)!", $3, $5, $7, $9);
+                           lc_error(
+                          "Region (%ld,%ld,%ld,%ld) out of level range (y2)!",
+                                     $3, $5, $7, $9);
                        $$.x1 = $3;
                        $$.y1 = $5;
                        $$.x2 = $7;
@@ -2612,14 +2632,22 @@ region          : '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
                  {
 /* This series of if statements is a hack for MSC 5.1.  It seems that its
    tiny little brain cannot compile if these are all one big if statement. */
-                       if ($2 < 0 || $2 > (int)max_x_map)
-                           lc_error("Region (%li,%li,%li,%li) out of map range (x1)!", $2, $4, $6, $8);
-                       else if ($4 < 0 || $4 > (int)max_y_map)
-                           lc_error("Region (%li,%li,%li,%li) out of map range (y1)!", $2, $4, $6, $8);
-                       else if ($6 < 0 || $6 > (int)max_x_map)
-                           lc_error("Region (%li,%li,%li,%li) out of map range (x2)!", $2, $4, $6, $8);
-                       else if ($8 < 0 || $8 > (int)max_y_map)
-                           lc_error("Region (%li,%li,%li,%li) out of map range (y2)!", $2, $4, $6, $8);
+                       if ($2 < 0 || $2 > (int) max_x_map)
+                           lc_error(
+                            "Region (%ld,%ld,%ld,%ld) out of map range (x1)!",
+                                     $2, $4, $6, $8);
+                       else if ($4 < 0 || $4 > (int) max_y_map)
+                           lc_error(
+                            "Region (%ld,%ld,%ld,%ld) out of map range (y1)!",
+                                     $2, $4, $6, $8);
+                       else if ($6 < 0 || $6 > (int) max_x_map)
+                           lc_error(
+                            "Region (%ld,%ld,%ld,%ld) out of map range (x2)!",
+                                     $2, $4, $6, $8);
+                       else if ($8 < 0 || $8 > (int) max_y_map)
+                           lc_error(
+                            "Region (%ld,%ld,%ld,%ld) out of map range (y2)!",
+                                     $2, $4, $6, $8);
                        $$.area = 0;
                        $$.x1 = $2;
                        $$.y1 = $4;
index d3350e1..ecf7a44 100644 (file)
@@ -1,5 +1,5 @@
-/* NetHack 3.6 lev_main.c      $NHDT-Date: 1448074107 2015/11/21 02:48:27 $  $NHDT-Branch: master $:$NHDT-Revision: 1.43 $ */
-/*     Copyright (c) 1989 by Jean-Christophe Collet */
+/* NetHack 3.6 lev_main.c      $NHDT-Date: 1501723418 2017/08/03 01:23:38 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.47 $ */
+/*      Copyright (c) 1989 by Jean-Christophe Collet */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -281,7 +281,7 @@ char **argv;
             }
             fin = freopen(fname, "r", stdin);
             if (!fin) {
-                lc_pline("Can't open \"%s\" for input.\n", fname);
+                lc_pline("Can't open \"%s\" for input.\n", VA_PASS1(fname));
                 perror(fname);
                 errors_encountered = TRUE;
             } else {
@@ -615,14 +615,14 @@ VA_DECL2(sp_lev *, sp, const char *, fmt)
 #ifdef USE_STDARG
 static void
 vadd_opvars(sp_lev *sp, const char *fmt, va_list the_args)
-{
+
 #else
 static void
 vadd_opvars(sp, fmt, the_args)
 sp_lev *sp;
 const char *fmt;
 va_list the_args;
-{
+
 #endif
 
 #else /* USE_STDARG | USE_VARARG */
@@ -632,7 +632,7 @@ va_list the_args;
 void add_opvars
 VA_DECL2(sp_lev *, sp, const char *, fmt)
 #endif /* USE_STDARG | USE_VARARG */
-
+{
     const char *p, *lp;
     long la;
     /* Do NOT use VA_START and VA_END in here... see above */
@@ -644,56 +644,56 @@ VA_DECL2(sp_lev *, sp, const char *, fmt)
         case 'i': /* integer */
         {
             struct opvar *ov = New(struct opvar);
-            set_opvar_int(ov, VA_NEXT(la, long) );
+            set_opvar_int(ov, VA_NEXT(la, long));
             add_opcode(sp, SPO_PUSH, ov);
             break;
         }
         case 'c': /* coordinate */
         {
             struct opvar *ov = New(struct opvar);
-            set_opvar_coord(ov, VA_NEXT(la, long) );
+            set_opvar_coord(ov, VA_NEXT(la, long));
             add_opcode(sp, SPO_PUSH, ov);
             break;
         }
         case 'r': /* region */
         {
             struct opvar *ov = New(struct opvar);
-            set_opvar_region(ov, VA_NEXT(la, long) );
+            set_opvar_region(ov, VA_NEXT(la, long));
             add_opcode(sp, SPO_PUSH, ov);
             break;
         }
         case 'm': /* mapchar */
         {
             struct opvar *ov = New(struct opvar);
-            set_opvar_mapchar(ov, VA_NEXT(la, long) );
+            set_opvar_mapchar(ov, VA_NEXT(la, long));
             add_opcode(sp, SPO_PUSH, ov);
             break;
         }
         case 'M': /* monster */
         {
             struct opvar *ov = New(struct opvar);
-            set_opvar_monst(ov, VA_NEXT(la, long) );
+            set_opvar_monst(ov, VA_NEXT(la, long));
             add_opcode(sp, SPO_PUSH, ov);
             break;
         }
         case 'O': /* object */
         {
             struct opvar *ov = New(struct opvar);
-            set_opvar_obj(ov, VA_NEXT(la, long) );
+            set_opvar_obj(ov, VA_NEXT(la, long));
             add_opcode(sp, SPO_PUSH, ov);
             break;
         }
         case 's': /* string */
         {
             struct opvar *ov = New(struct opvar);
-            set_opvar_str(ov, VA_NEXT(lp, const char *) );
+            set_opvar_str(ov, VA_NEXT(lp, const char *));
             add_opcode(sp, SPO_PUSH, ov);
             break;
         }
         case 'v': /* variable */
         {
             struct opvar *ov = New(struct opvar);
-            set_opvar_var(ov, VA_NEXT(lp, const char *) );
+            set_opvar_var(ov, VA_NEXT(lp, const char *));
             add_opcode(sp, SPO_PUSH, ov);
             break;
         }
@@ -701,16 +701,21 @@ VA_DECL2(sp_lev *, sp, const char *, fmt)
         {
             long i = VA_NEXT(la, int);
             if (i < 0 || i >= MAX_SP_OPCODES)
-                lc_pline("add_opvars: unknown opcode '%ld'.", i);
+                lc_pline("add_opvars: unknown opcode '%ld'.", VA_PASS1(i));
             add_opcode(sp, i, NULL);
             break;
         }
         default:
-            lc_pline("add_opvars: illegal format character '%c'.", *p);
+            lc_pline("add_opvars: illegal format character '%ld'.",
+                     VA_PASS1((long) *p));
             break;
         }
     }
-    return;
+
+#if !(defined(USE_STDARG) || defined(USE_VARARGS))
+    /* provide closing brace for USE_OLDARGS nested block from VA_DECL2() */
+    VA_END();
+#endif
 }
 
 void
@@ -770,7 +775,8 @@ char *name;
     struct lc_funcdefs *f = New(struct lc_funcdefs);
 
     if (!f) {
-        lc_error("Could not alloc function definition for '%s'.", name);
+        lc_error("Could not alloc function definition for '%s'.",
+                 VA_PASS1(name));
         return NULL;
     }
     f->next = NULL;
@@ -851,7 +857,8 @@ char *name;
     struct lc_vardefs *f = New(struct lc_vardefs);
 
     if (!f) {
-        lc_error("Could not alloc variable definition for '%s'.", name);
+        lc_error("Could not alloc variable definition for '%s'.",
+                 VA_PASS1(name));
         return NULL;
     }
     f->next = NULL;
@@ -870,7 +877,7 @@ struct lc_vardefs *fchain;
 
     while (tmp) {
         if (be_verbose && (tmp->n_used == 0))
-            lc_warning("Unused variable '%s'", tmp->name);
+            lc_warning("Unused variable '%s'", VA_PASS1(tmp->name));
         nxt = tmp->next;
         Free(tmp->name);
         Free(tmp);
@@ -909,7 +916,7 @@ long spovar;
     spovar &= ~SPOVAR_ARRAY;
     switch (spovar) {
     default:
-        lc_error("spovar2str(%ld)", spovar);
+        lc_error("spovar2str(%ld)", VA_PASS1(spovar));
         break;
     case SPOVAR_INT:
         n = "integer";
@@ -939,7 +946,7 @@ long spovar;
 
     togl = ((togl + 1) % 2);
 
-    snprintf(buf[togl], 127, "%s%s", n, (is_array ? " array" : ""));
+    Sprintf(buf[togl], "%s%s", n, (is_array ? " array" : ""));
     return buf[togl];
 }
 
@@ -965,9 +972,11 @@ long vartype;
     if ((tmp = vardef_defined(vd, varname, 1)) != 0) {
         if (tmp->var_type != vartype)
             lc_error("Trying to use variable '%s' as %s, when it is %s.",
-                     varname, spovar2str(vartype), spovar2str(tmp->var_type));
+                     VA_PASS3(varname,
+                              spovar2str(vartype),
+                              spovar2str(tmp->var_type)));
     } else
-        lc_error("Variable '%s' not defined.", varname);
+        lc_error("Variable '%s' not defined.", VA_PASS1(varname));
 }
 
 struct lc_vardefs *
@@ -981,7 +990,9 @@ long vartype;
     if ((tmp = vardef_defined(vd, varname, 1)) != 0) {
         if (tmp->var_type != vartype)
             lc_error("Trying to redefine variable '%s' as %s, when it is %s.",
-                     varname, spovar2str(vartype), spovar2str(tmp->var_type));
+                     VA_PASS3(varname,
+                              spovar2str(vartype),
+                              spovar2str(tmp->var_type)));
     } else {
         tmp = vardef_new(vartype, varname);
         tmp->next = vd;
@@ -1008,7 +1019,8 @@ int opcode;
     case SPO_JGE:
         return SPO_JL;
     default:
-        lc_error("Cannot reverse comparison jmp opcode %d.", opcode);
+        lc_error("Cannot reverse comparison jmp opcode %ld.",
+                 VA_PASS1((long) opcode));
         return SPO_NULL;
     }
 }
@@ -1050,7 +1062,8 @@ struct opvar *ov;
             tmpov->vardata.str[len] = '\0';
         } break;
         default: {
-            lc_error("Unknown opvar_clone value type (%d)!", ov->spovartyp);
+            lc_error("Unknown opvar_clone value type (%ld)!",
+                     VA_PASS1((long) ov->spovartyp));
         } /* default */
         } /* switch */
         return tmpov;
@@ -1079,9 +1092,10 @@ char *ldfname;
     struct lc_funcdefs *f;
 
     if (index(ldfname, '.'))
-        lc_error("Invalid dot ('.') in level name '%s'.", ldfname);
+        lc_error("Invalid dot ('.') in level name '%s'.", VA_PASS1(ldfname));
     if ((int) strlen(ldfname) > 14)
-        lc_error("Level names limited to 14 characters ('%s').", ldfname);
+        lc_error("Level names limited to 14 characters ('%s').",
+                 VA_PASS1(ldfname));
     f = function_definitions;
     while (f) {
         f->n_called = 0;
@@ -1169,8 +1183,8 @@ char c;
         if (!class || class == mons[i].mlet)
             if (!case_insensitive_comp(s, mons[i].mname)) {
                 if (be_verbose)
-                    lc_warning("Monster type \"%s\" matches \"%s\".", s,
-                               mons[i].mname);
+                    lc_warning("Monster type \"%s\" matches \"%s\".",
+                               VA_PASS2(s, mons[i].mname));
                 return i;
             }
     return ERR;
@@ -1205,7 +1219,8 @@ char c; /* class */
         objname = obj_descr[i].oc_name;
         if (objname && !case_insensitive_comp(s, objname)) {
             if (be_verbose)
-                lc_warning("Object type \"%s\" matches \"%s\".", s, objname);
+                lc_warning("Object type \"%s\" matches \"%s\".",
+                           VA_PASS2(s, objname));
             return i;
         }
     }
@@ -1314,14 +1329,14 @@ genericptr_t dat;
     _opcode *tmp;
 
     if ((opc < 0) || (opc >= MAX_SP_OPCODES))
-        lc_error("Unknown opcode '%d'", opc);
+        lc_error("Unknown opcode '%ld'", VA_PASS1((long) opc));
 
     tmp = (_opcode *) alloc(sizeof(_opcode) * (nop + 1));
     if (!tmp) { /* lint suppression */
         /*NOTREACHED*/
 #if 0
         /* not possible; alloc() never returns Null */
-        lc_error("Could not alloc opcode space");
+        lc_error("%s", VA_PASS1("Could not alloc opcode space"));
 #endif
         return;
     }
@@ -1351,7 +1366,7 @@ sp_lev *sp;
     register char *s1, *s2;
     int max_len = 0;
     int max_hig = 0;
-    char *tmpmap[ROWNO];
+    char *tmpmap[MAP_Y_LIM+1];
     int dx, dy;
     char *mbuf;
 
@@ -1378,6 +1393,8 @@ sp_lev *sp;
 
     /* Then parse it now */
     while (map && *map) {
+        if (max_hig > MAP_Y_LIM)
+            break;
         tmpmap[max_hig] = (char *) alloc(max_len);
         s1 = index(map, '\n');
         if (s1) {
@@ -1390,9 +1407,9 @@ sp_lev *sp;
         for (i = 0; i < len; i++)
             if ((tmpmap[max_hig][i] = what_map_char(map[i]))
                 == INVALID_TYPE) {
-                lc_warning("Invalid character '%c' @ (%d, %d) - replacing "
-                           "with stone",
-                           map[i], max_hig, i);
+                lc_warning(
+                "Invalid character '%ld' @ (%ld, %ld) - replacing with stone",
+                           VA_PASS3((long) map[i], (long) max_hig, (long) i));
                 tmpmap[max_hig][i] = STONE;
             }
         while (i < max_len)
@@ -1407,8 +1424,9 @@ sp_lev *sp;
     max_y_map = max_hig - 1;
 
     if (max_len > MAP_X_LIM || max_hig > MAP_Y_LIM) {
-        lc_error("Map too large at (%d x %d), max is (%d x %d)", max_len,
-                 max_hig, MAP_X_LIM, MAP_Y_LIM);
+        lc_error("Map too large at (%ld x %ld), max is (%ld x %ld)",
+                 VA_PASS4((long) max_len, (long) max_hig,
+                          (long) MAP_X_LIM, (long) MAP_Y_LIM));
     }
 
     mbuf = (char *) alloc(((max_hig - 1) * max_len) + (max_len - 1) + 2);
@@ -1418,7 +1436,8 @@ sp_lev *sp;
 
     mbuf[((max_hig - 1) * max_len) + (max_len - 1) + 1] = '\0';
 
-    add_opvars(sp, "siio", VA_PASS4(mbuf, max_hig, max_len, SPO_MAP));
+    add_opvars(sp, "siio", VA_PASS4(mbuf, (long) max_hig, (long) max_len,
+                                    SPO_MAP));
 
     for (dy = 0; dy < max_hig; dy++)
         Free(tmpmap[dy]);
index d2dadd7..0bac757 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6  makedefs.c  $NHDT-Date: 1447062431 2015/11/09 09:47:11 $  $NHDT-Branch: master $:$NHDT-Revision: 1.105 $ */
+/* NetHack 3.6  makedefs.c  $NHDT-Date: 1520022901 2018/03/02 20:35:01 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.121 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */
 /* Copyright (c) M. Stephenson, 1990, 1991.                       */
 /* Copyright (c) Dean Luick, 1990.                                */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -58,7 +59,7 @@
 #endif
 
 #if defined(UNIX) && !defined(LINT) && !defined(GCC_WARN)
-static const char SCCS_Id[] = "@(#)makedefs.c\t3.5\t2004/02/01";
+static const char SCCS_Id[] = "@(#)makedefs.c\t3.6\t2018/03/02";
 #endif
 
 /* names of files to be generated */
@@ -78,6 +79,7 @@ static const char SCCS_Id[] = "@(#)makedefs.c\t3.5\t2004/02/01";
 #define QTXT_O_FILE "quest.dat"
 #define VIS_TAB_H "vis_tab.h"
 #define VIS_TAB_C "vis_tab.c"
+#define GITINFO_FILE "gitinfo.txt"
 /* locations for those files */
 #ifdef AMIGA
 #define FILE_PREFIX
@@ -170,6 +172,12 @@ void NDECL(do_vision);
 extern void NDECL(monst_init);   /* monst.c */
 extern void NDECL(objects_init); /* objects.c */
 
+static void NDECL(link_sanity_check);
+static char *FDECL(name_file, (const char *, const char *));
+static void FDECL(delete_file, (const char *template, const char *));
+static FILE *FDECL(getfp, (const char *, const char *, const char *));
+static void FDECL(do_ext_makedefs, (int, char **));
+
 static void NDECL(make_version);
 static char *FDECL(version_string, (char *, const char *));
 static char *FDECL(version_id_string, (char *, const char *));
@@ -177,13 +185,13 @@ static char *FDECL(bannerc_string, (char *, const char *));
 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 *));
 static boolean FDECL(d_filter, (char *));
 static boolean FDECL(h_filter, (char *));
 static boolean FDECL(ranged_attk, (struct permonst *));
 static int FDECL(mstrength, (struct permonst *));
 static void NDECL(build_savebones_compat_string);
-static void FDECL(do_ext_makedefs, (int, char **));
 static void NDECL(windowing_sanity);
 
 static boolean FDECL(qt_comment, (char *));
@@ -210,6 +218,7 @@ static char *FDECL(fgetline, (FILE*));
 static char *FDECL(tmpdup, (const char *));
 static char *FDECL(limit, (char *, int));
 static char *FDECL(eos, (char *));
+static int FDECL(case_insensitive_comp, (const char *, const char *));
 
 /* input, output, tmp */
 static FILE *ifp, *ofp, *tfp;
@@ -257,11 +266,12 @@ main(argc, argv)
 int argc;
 char *argv[];
 {
-    if ((argc != 2)
+    if ((argc == 1) ||
+        ((argc != 2)
 #ifdef FILE_PREFIX
         && (argc != 3)
 #endif
-        && !(argv[1][0] == '-' && argv[1][1] == '-')) {
+        && !(argv[1][0] == '-' && argv[1][1] == '-'))) {
         Fprintf(stderr, "Bad arg count (%d).\n", argc - 1);
         (void) fflush(stderr);
         return 1;
@@ -374,10 +384,11 @@ char *options;
 }
 
 static char namebuf[1000];
+
 static char *
 name_file(template, tag)
-char *template;
-char *tag;
+const char *template;
+const char *tag;
 {
     Sprintf(namebuf, template, tag);
     return namebuf;
@@ -385,21 +396,23 @@ char *tag;
 
 static void
 delete_file(template, tag)
-char *template;
-char *tag;
+const char *template;
+const char *tag;
 {
     char *name = name_file(template, tag);
+
     Unlink(name);
 }
 
 static FILE *
 getfp(template, tag, mode)
-char *template;
-char *tag;
-char *mode;
+const char *template;
+const char *tag;
+const char *mode;
 {
     char *name = name_file(template, tag);
     FILE *rv = fopen(name, mode);
+
     if (!rv) {
         Fprintf(stderr, "Can't open '%s'.\n", name);
         exit(EXIT_FAILURE);
@@ -419,11 +432,27 @@ struct grep_var {
 /* struct grep_var grep_vars[] and TODO_* constants in include file: */
 #include "mdgrep.h"
 
-static void NDECL(do_grep);
 static void NDECL(do_grep_showvars);
-static struct grep_var *FDECL(grepsearch, (char *));
+static struct grep_var *FDECL(grepsearch, (const char *));
+static int FDECL(grep_check_id, (const char *));
+static void FDECL(grep_show_wstack, (const char *));
+static char *FDECL(do_grep_control, (char *));
+static void NDECL(do_grep);
+static void FDECL(grep0, (FILE *, FILE *));
+
 static int grep_trace = 0;
 
+#define IS_OPTION(str) if (!strcmp(&argv[0][2], str))
+#define CONTINUE    \
+    argv++, argc--; \
+    continue
+#define CONSUME                              \
+    argv++, argc--;                          \
+    if (argc == 0) {                         \
+        Fprintf(stderr, "missing option\n"); \
+        exit(EXIT_FAILURE);                  \
+    }
+
 static void
 do_ext_makedefs(int argc, char **argv)
 {
@@ -441,22 +470,11 @@ do_ext_makedefs(int argc, char **argv)
             Fprintf(stderr, "Can't mix - and -- options.\n");
             exit(EXIT_FAILURE);
         }
-#define IS_OPTION(str) if (!strcmp(&argv[0][2], str))
-#define CONTINUE    \
-    argv++, argc--; \
-    continue
-#define CONSUME                              \
-    argv++, argc--;                          \
-    if (argc == 0) {                         \
-        Fprintf(stderr, "missing option\n"); \
-        exit(EXIT_FAILURE);                  \
-    }
-        IS_OPTION("svs")
-        {
-            /* short version string for packaging - note
-             * no \n */
+        IS_OPTION("svs") {
+            /* short version string for packaging - note no \n */
             char buf[100];
             char delim[10];
+
             argv++; /* not CONSUME */
             delim[0] = '\0';
             if (argv[0])
@@ -464,19 +482,16 @@ do_ext_makedefs(int argc, char **argv)
             Fprintf(stdout, "%s", version_string(buf, delim));
             exit(EXIT_SUCCESS);
         }
-        IS_OPTION("debug")
-        {
+        IS_OPTION("debug") {
             debug = TRUE;
             CONTINUE;
         }
-        IS_OPTION("make")
-        {
+        IS_OPTION("make") {
             CONSUME;
             do_makedefs(argv[0]);
             exit(EXIT_SUCCESS);
         }
-        IS_OPTION("input")
-        {
+        IS_OPTION("input") {
             CONSUME;
             if (!strcmp(argv[0], "-")) {
                 inputfp = stdin;
@@ -489,8 +504,7 @@ do_ext_makedefs(int argc, char **argv)
             }
             CONTINUE;
         }
-        IS_OPTION("output")
-        {
+        IS_OPTION("output") {
             CONSUME;
             if (!strcmp(argv[0], "-")) {
                 outputfp = stdout;
@@ -503,8 +517,7 @@ do_ext_makedefs(int argc, char **argv)
             }
             CONTINUE;
         }
-        IS_OPTION("grep")
-        {
+        IS_OPTION("grep") {
             if (todo) {
                 Fprintf(stderr, "Can't do grep and something else.\n");
                 exit(EXIT_FAILURE);
@@ -512,19 +525,17 @@ do_ext_makedefs(int argc, char **argv)
             todo = TODO_GREP;
             CONTINUE;
         }
-        IS_OPTION("grep-showvars")
-        {
+        IS_OPTION("grep-showvars") {
             do_grep_showvars();
             exit(EXIT_SUCCESS);
         }
-        IS_OPTION("grep-trace")
-        {
+        IS_OPTION("grep-trace") {
             grep_trace = 1;
             CONTINUE;
         }
-        IS_OPTION("grep-define")
-        {
+        IS_OPTION("grep-define") {
             struct grep_var *p;
+
             CONSUME;
             p = grepsearch(argv[0]);
             if (p) {
@@ -535,9 +546,9 @@ do_ext_makedefs(int argc, char **argv)
             }
             CONTINUE;
         }
-        IS_OPTION("grep-undef")
-        {
+        IS_OPTION("grep-undef") {
             struct grep_var *p;
+
             CONSUME;
             p = grepsearch(argv[0]);
             if (p) {
@@ -549,11 +560,9 @@ do_ext_makedefs(int argc, char **argv)
             CONTINUE;
         }
 #ifdef notyet
-        IS_OPTION("help")
-        {
+        IS_OPTION("help") {
         }
 #endif
-#undef IS_OPTION
         Fprintf(stderr, "Unknown option '%s'.\n", argv[0]);
         exit(EXIT_FAILURE);
     }
@@ -575,37 +584,40 @@ do_ext_makedefs(int argc, char **argv)
     }
 }
 
-/*
- Filtering syntax:
- Any line NOT starting with a caret is either suppressed or passed through
- unchanged depending on the current conditional state.
-
- The default conditional state is printing on.
-
- Conditionals may be nested.
-
- makedefs will exit with a EXIT_FAILURE if any errors are detected; as many
- errors as possible are detected before giving up.
-
- Unknown identifiers are treated as TRUE and also as an error to allow
- processing to continue past the unknown identifier (note that "#undef" is
- different than unknown).
-
- Any line starting with a caret is a control line; as in C, zero or more
- spaces
- may be embedded in the line almost anywhere; the caret MUST be in column 1.
- (XXX for the moment, no white space is allowed after the caret because
-  existing lines in the docs look like that)
-
- Control lines:
- ^^     a line starting with a (single) literal caret
- ^#     a comment - the line is ignored
- ^?ID   if defined(ID)
- ^!ID   if !defined(ID)
- ^:     else
- ^.     endif
+#undef IS_OPTION
+#undef CONTINUE
+#undef CONSUME
 
-*/
+/*
+ * Filtering syntax:
+ * Any line NOT starting with a caret is either suppressed or passed
+ * through unchanged depending on the current conditional state.
+ *
+ * The default conditional state is printing on.
+ *
+ * Conditionals may be nested.
+ *
+ * makedefs will exit with a EXIT_FAILURE if any errors are detected;
+ * as many errors as possible are detected before giving up.
+ *
+ * Unknown identifiers are treated as TRUE and also as an error to
+ * allow processing to continue past the unknown identifier (note
+ * that "#undef" is different than unknown).
+ *
+ * Any line starting with a caret is a control line; as in C, zero or
+ * more spaces may be embedded in the line almost anywhere; the caret
+ * MUST be in column 1.
+ * (XXX for the moment, no white space is allowed after the caret because
+ * existing lines in the docs look like that.)
+ *
+ * Control lines:
+ *      ^^      a line starting with a (single) literal caret
+ *      ^#      a comment - the line is ignored
+ *      ^?ID    if defined(ID)
+ *      ^!ID    if !defined(ID)
+ *      ^:      else
+ *      ^.      endif
+ */
 #define GREP_MAGIC '^'
 #define GREP_STACK_SIZE 100
 #ifdef notyet
@@ -614,9 +626,9 @@ static int grep_rewrite = 0; /* need to (possibly) rewrite lines */
 static int grep_writing = 1; /* need to copy lines to output */
 static int grep_errors = 0;
 static int grep_sp = 0;
-#define ST_LD(old, opp) (!!(old) | (!!(opp) << 1))
-#define ST_OLD(v) ((v) &1)
-#define ST_OPP(v) !!((v) &2)
+#define ST_LD(old, opp) (((old) ? 1 : 0) | ((opp) ? 2 : 0))
+#define ST_OLD(v) (((v) & 1) != 0)
+#define ST_OPP(v) (((v) & 2) != 0)
 #define ST_ELSE 4
 static int grep_stack[GREP_STACK_SIZE] = { ST_LD(1, 0) };
 static int grep_lineno = 0;
@@ -625,6 +637,7 @@ static void
 do_grep_showvars()
 {
     int x;
+
     for (x = 0; x < SIZE(grep_vars) - 1; x++) {
         printf("%d\t%s\n", grep_vars[x].is_defined, grep_vars[x].name);
     }
@@ -632,10 +645,11 @@ do_grep_showvars()
 
 static struct grep_var *
 grepsearch(name)
-char *name;
+const char *name;
 {
     /* XXX make into binary search */
     int x = 0;
+
     while (x < SIZE(grep_vars) - 1) {
         if (!strcmp(grep_vars[x].name, name))
             return &grep_vars[x];
@@ -646,10 +660,11 @@ char *name;
 
 static int
 grep_check_id(id)
-char *id;
+const char *id;
 {
     struct grep_var *rv;
-    while (*id && isspace(*id))
+
+    while (*id && isspace((uchar) *id))
         id++;
     if (!*id) {
         Fprintf(stderr, "missing identifier in line %d", grep_lineno);
@@ -675,7 +690,7 @@ char *id;
 
 static void
 grep_show_wstack(tag)
-char *tag;
+const char *tag;
 {
     int x;
 
@@ -696,10 +711,10 @@ char *buf;
     int isif = 1;
     char *buf0 = buf;
 #if 1
-    if (isspace(buf[0]))
+    if (isspace((uchar) buf[0]))
         return &buf[-1]; /* XXX see docs above */
 #else
-    while (buf[0] && isspace(buf[0]))
+    while (buf[0] && isspace((uchar) buf[0]))
         buf++;
 #endif
     switch (buf[0]) {
@@ -749,7 +764,8 @@ char *buf;
         return buf0;
     default: {
         char str[10];
-        if (isprint(buf[0])) {
+
+        if (isprint((uchar) buf[0])) {
             str[0] = buf[0];
             str[1] = '\0';
         } else {
@@ -1160,6 +1176,9 @@ make_version()
     return;
 }
 
+/* REPRODUCIBLE_BUILD will change this to TRUE */
+static boolean date_via_env = FALSE;
+
 static char *
 version_string(outbuf, delim)
 char *outbuf;
@@ -1189,8 +1208,9 @@ const char *build_date;
     Strcat(subbuf, " Beta");
 #endif
 
-    Sprintf(outbuf, "%s NetHack%s Version %s - last build %s.", PORT_ID,
-            subbuf, version_string(versbuf, "."), build_date);
+    Sprintf(outbuf, "%s NetHack%s Version %s - last %s %s.", PORT_ID,
+            subbuf, version_string(versbuf, "."),
+            date_via_env ? "revision" : "build", build_date);
     return outbuf;
 }
 
@@ -1229,8 +1249,9 @@ const char *build_date;
     Strcat(subbuf, " Beta");
 #endif
 
-    Sprintf(outbuf, "         Version %s %s%s, built %s.",
-            version_string(versbuf, "."), PORT_ID, subbuf, &build_date[4]);
+    Sprintf(outbuf, "         Version %s %s%s, %s %s.",
+            version_string(versbuf, "."), PORT_ID, subbuf,
+            date_via_env ? "revised" : "built", &build_date[4]);
 #if 0
     Sprintf(outbuf, "%s NetHack%s %s Copyright 1985-%s (built %s)",
             PORT_ID, subbuf, version_string(versbuf,"."), RELEASE_YEAR,
@@ -1247,6 +1268,7 @@ do_date()
 #else
     time_t clocktim = 0;
 #endif
+    char githash[BUFSZ], gitbranch[BUFSZ];
     char *c, cbuf[60], buf[BUFSZ];
     const char *ul_sfx;
 
@@ -1269,20 +1291,96 @@ do_date()
     Fprintf(ofp, "%s", Dont_Edit_Code);
 
     (void) time(&clocktim);
+#ifdef REPRODUCIBLE_BUILD
+    {
+        /*
+         * Use date+time of latest source file revision (set up in
+         * our environment rather than derived by scanning sources)
+         * instead of current date+time, so that later rebuilds of
+         * the same sources specifying the same configuration will
+         * produce the same result.
+         *
+         * Changing the configuration should be done by modifying
+         * config.h or <port>conf.h and setting SOURCE_DATE_EPOCH
+         * based on whichever changed most recently, not by using
+         *   make CFLAGS='-Dthis -Dthat'
+         * to make alterations on the fly.
+         *
+         * Limited validation is performed to prevent dates in the
+         * future (beyond a leeway of 24 hours) or distant past.
+         *
+         * Assumes the value of time_t is in seconds, which is
+         * fundamental for Unix and mandated by POSIX.  For any ports
+         * where that isn't true, leaving REPRODUCIBLE_BUILD disabled
+         * is probably preferrable to hacking this code....
+         */
+        static struct tm nh360; /* static init should yield UTC timezone */
+        unsigned long sd_num, sd_earliest, sd_latest;
+        const char *sd_str = getenv("SOURCE_DATE_EPOCH");
+
+        if (sd_str) {
+            sd_num = strtoul(sd_str, (char **) 0, 10);
+            /*
+             * Note:  this does not need to be updated for future
+             * releases.  It serves as a sanity check for potentially
+             * mis-set environment, not a hard baseline for when the
+             * current version could have first been built.
+             */
+            /* oldest date we'll accept: 7-Dec-2015 (release of 3.6.0) */
+            nh360.tm_mday = 7;
+            nh360.tm_mon  = 12 - 1;
+            nh360.tm_year = 2015 - 1900;
+            sd_earliest = (unsigned long) mktime(&nh360);
+            /* 'youngest' date we'll accept: 24 hours in the future */
+            sd_latest = (unsigned long) clocktim + 24L * 60L * 60L;
+
+            if (sd_num >= sd_earliest && sd_num <= sd_latest) {
+                /* use SOURCE_DATE_EPOCH value */
+                clocktim = (time_t) sd_num;
+                date_via_env = TRUE;
+            } else {
+                Fprintf(stderr, "? Invalid value for SOURCE_DATE_EPOCH (%lu)",
+                        sd_num);
+                if (sd_num > 0L && sd_num < sd_earliest)
+                    Fprintf(stderr, ", older than %lu", sd_earliest);
+                else if (sd_num > sd_latest)
+                    Fprintf(stderr, ", newer than %lu", sd_latest);
+                Fprintf(stderr, ".\n");
+                Fprintf(stderr, ": Reverting to current date+time (%lu).\n",
+                        (unsigned long) clocktim);
+                (void) fflush(stderr);
+            }
+        } else {
+            /* REPRODUCIBLE_BUILD enabled but SOURCE_DATE_EPOCH is missing */
+            Fprintf(stderr, "? No value for SOURCE_DATE_EPOCH.\n");
+            Fprintf(stderr, ": Using current date+time (%lu).\n",
+                    (unsigned long) clocktim);
+            (void) fflush(stderr);
+        }
+        Strcpy(cbuf, asctime(gmtime(&clocktim)));
+    }
+#else
+    /* ordinary build: use current date+time */
     Strcpy(cbuf, ctime(&clocktim));
+#endif
 
-    for (c = cbuf; *c; c++)
-        if (*c == '\n')
-            break;
-    *c = '\0'; /* strip off the '\n' */
-    Fprintf(ofp, "#define BUILD_DATE \"%s\"\n", cbuf);
-    Fprintf(ofp, "#define BUILD_TIME (%ldL)\n", (long) clocktim);
-    Fprintf(ofp, "\n");
+    if ((c = index(cbuf, '\n')) != 0)
+        *c = '\0'; /* strip off the '\n' */
 #ifdef NHSTDC
     ul_sfx = "UL";
 #else
     ul_sfx = "L";
 #endif
+    if (date_via_env)
+        Fprintf(ofp, "#define SOURCE_DATE_EPOCH (%lu%s) /* via getenv() */\n",
+                (unsigned long) clocktim, ul_sfx);
+    Fprintf(ofp, "#define BUILD_DATE \"%s\"\n", cbuf);
+    if (date_via_env)
+        Fprintf(ofp, "#define BUILD_TIME SOURCE_DATE_EPOCH\n");
+    else
+        Fprintf(ofp, "#define BUILD_TIME (%lu%s)\n",
+                (unsigned long) clocktim, ul_sfx);
+    Fprintf(ofp, "\n");
     Fprintf(ofp, "#define VERSION_NUMBER 0x%08lx%s\n", version.incarnation,
             ul_sfx);
     Fprintf(ofp, "#define VERSION_FEATURES 0x%08lx%s\n", version.feature_set,
@@ -1308,19 +1406,102 @@ do_date()
     Fprintf(ofp, "#define COPYRIGHT_BANNER_C \\\n \"%s\"\n",
             bannerc_string(buf, cbuf));
     Fprintf(ofp, "\n");
+    if (get_gitinfo(githash, gitbranch)) {
+        Fprintf(ofp, "#define NETHACK_GIT_SHA \"%s\"\n", githash);
+        Fprintf(ofp, "#define NETHACK_GIT_BRANCH \"%s\"\n", gitbranch);
+    }
 #ifdef AMIGA
     {
         struct tm *tm = localtime((time_t *) &clocktim);
+
         Fprintf(ofp, "#define AMIGA_VERSION_STRING ");
         Fprintf(ofp, "\"\\0$VER: NetHack %d.%d.%d (%d.%d.%d)\"\n",
-                VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, tm->tm_mday,
-                tm->tm_mon + 1, tm->tm_year + 1900);
+                VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
+                tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900);
     }
 #endif
     Fclose(ofp);
     return;
 }
 
+boolean
+get_gitinfo(githash, gitbranch)
+char *githash, *gitbranch;
+{
+    FILE *gifp;
+    size_t len;
+    char infile[600];
+    char *line, *strval, *opt, *c, *end;
+    boolean havebranch = FALSE, havehash = FALSE;
+
+    if (!githash || !gitbranch) return FALSE;
+
+    Sprintf(infile, DATA_IN_TEMPLATE, GITINFO_FILE);
+    if (!(gifp = fopen(infile, RDTMODE))) {
+        /* perror(infile); */
+        return FALSE;
+    }
+
+    /* read the gitinfo file */
+    while ((line = fgetline(gifp)) != 0) {
+        strval = index(line, '=');
+        if (strval && strlen(strval) < (BUFSZ-1)) {
+            opt = line;
+            *strval++ = '\0';
+            /* strip off the '\n' */
+            if ((c = index(strval, '\n')) != 0)
+                *c = '\0'; 
+            if ((c = index(opt, '\n')) != 0)
+                *c = '\0';
+            /* strip leading and trailing white space */
+            while (*strval == ' ' || *strval == '\t')
+                strval++;
+            end = eos(strval);
+            while (--end >= strval && (*end == ' ' || *end == '\t'))
+            *end = '\0';
+            while (*opt == ' ' || *opt == '\t')
+                opt++;
+            end = eos(opt);
+            while (--end >= opt && (*end == ' ' || *end == '\t'))
+            *end = '\0';
+
+            len = strlen(opt);
+            if ((len >= strlen("gitbranch")) && !case_insensitive_comp(opt, "gitbranch")) {
+                Strcpy(gitbranch, strval);
+                havebranch = TRUE;
+            }
+            if ((len >= strlen("githash")) && !case_insensitive_comp(opt, "githash")) {
+                Strcpy(githash, strval);
+                havehash = TRUE;
+            }
+       }
+    }
+    Fclose(gifp);
+    if (havebranch && havehash)
+        return TRUE;
+    return FALSE;
+}
+
+static int
+case_insensitive_comp(s1, s2)
+const char *s1;
+const char *s2;
+{
+    uchar u1, u2;
+
+    for (;; s1++, s2++) {
+        u1 = (uchar) *s1;
+        if (isupper(u1))
+            u1 = tolower(u1);
+        u2 = (uchar) *s2;
+        if (isupper(u2))
+            u2 = tolower(u2);
+        if (u1 == '\0' || u1 != u2)
+            break;
+    }
+    return u1 - u2;
+}
+
 static char save_bones_compat_buf[BUFSZ];
 
 static void
@@ -1352,6 +1533,9 @@ static const char *build_opts[] = {
 #ifdef TEXTCOLOR
     "color",
 #endif
+#ifdef TTY_TILES_ESCCODES
+    "console escape codes for tile hinting",
+#endif
 #ifdef COM_COMPL
     "command line completion",
 #endif
@@ -1367,18 +1551,30 @@ static const char *build_opts[] = {
 #ifdef DLB
     "data librarian",
 #endif
+#ifdef DUMPLOG
+    "end-of-game dumplogs",
+#endif
+#ifdef HOLD_LOCKFILE_OPEN
+    "exclusive lock on level 0 file",
+#endif
+#if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
+    "external program as a message handler",
+#endif
 #ifdef MFLOPPY
     "floppy drive support",
 #endif
 #ifdef INSURANCE
     "insurance files for recovering from crashes",
 #endif
-#ifdef HOLD_LOCKFILE_OPEN
-    "exclusive lock on level 0 file",
-#endif
 #ifdef LOGFILE
     "log file",
 #endif
+#ifdef XLOGFILE
+    "extended log file",
+#endif
+#ifdef PANICLOG
+    "errors and warnings log file",
+#endif
 #ifdef MAIL
     "mail daemon",
 #endif
@@ -1399,6 +1595,8 @@ static const char *build_opts[] = {
 #endif
 #endif
 #endif
+    /* pattern matching method will be substituted by nethack at run time */
+    "pattern matching via :PATMATCH:",
 #ifdef SELECTSAVED
     "restore saved games via menu",
 #endif
@@ -1428,6 +1626,12 @@ static const char *build_opts[] = {
 #ifdef SHELL
     "shell command",
 #endif
+    "traditional status display",
+#ifdef STATUS_HILITES
+    "status via windowport with highlighting",
+#else
+    "status via windowport without highlighting",
+#endif
 #ifdef SUSPEND
     "suspend command",
 #endif
@@ -1460,7 +1664,8 @@ static const char *build_opts[] = {
 #ifdef SYSCF
     "system configuration at run-time",
 #endif
-    save_bones_compat_buf, "and basic NetHack features"
+    save_bones_compat_buf,
+    "and basic NetHack features"
 };
 
 struct win_info {
@@ -1525,8 +1730,7 @@ windowing_sanity()
         for (i = 0; window_opts[i].id; ++i)
             if (!strcmp(window_opts[i].id, DEFAULT_WINDOW_SYS))
                 break;
-        if (!window_opts[i]
-                 .id) { /* went through whole list without a match */
+        if (!window_opts[i].id) { /* went through whole list without a match */
             Fprintf(stderr, "Configuration error: DEFAULT_WINDOW_SYS (%s)\n",
                     DEFAULT_WINDOW_SYS);
             Fprintf(stderr,
@@ -1570,7 +1774,8 @@ do_options()
     Fprintf(ofp, "\nOptions compiled into this edition:\n");
     length = COLNO + 1; /* force 1st item onto new line */
     for (i = 0; i < SIZE(build_opts); i++) {
-        str = strcpy(buf, build_opts[i]);
+        str = strcat(strcpy(buf, build_opts[i]),
+                     (i < SIZE(build_opts) - 1) ? "," : ".");
         while (*str) {
             word = index(str, ' ');
             if (word)
@@ -1582,7 +1787,6 @@ do_options()
             Fprintf(ofp, "%s", str), length += strlen(str);
             str += strlen(str) + (word ? 1 : 0);
         }
-        Fprintf(ofp, (i < SIZE(build_opts) - 1) ? "," : "."), length++;
     }
 
     winsyscnt = SIZE(window_opts) - 1;
@@ -1985,7 +2189,6 @@ do_oracles()
 void
 do_dungeon()
 {
-    int rcnt = 0;
     char *line;
 
     Sprintf(filename, DATA_IN_TEMPLATE, DGN_I_FILE);
@@ -2011,7 +2214,6 @@ do_dungeon()
     while ((line = fgetline(ifp)) != 0) {
         SpinCursor(3);
 
-        rcnt++;
         if (line[0] == '#') {
             free(line);
             continue; /* discard comments */
@@ -2164,9 +2366,6 @@ do_permonst()
     Fprintf(ofp, "%s", Dont_Edit_Code);
     Fprintf(ofp, "#ifndef PM_H\n#define PM_H\n");
 
-    if (strcmp(mons[0].mname, "playermon") != 0)
-        Fprintf(ofp, "\n#define\tPM_PLAYERMON\t(-1)");
-
     for (i = 0; mons[i].mlet; i++) {
         SpinCursor(3);
 
@@ -2626,6 +2825,7 @@ do_objs()
                 prefix = -1;
                 break;
             }
+            /*FALLTHRU*/
         default:
             Fprintf(ofp, "#define\t");
         }
@@ -2754,7 +2954,7 @@ do_vision()
 #ifdef FILE_PREFIX
     Strcat(filename, file_prefix);
 #endif
-    Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
+    Sprintf(eos(filename), INCLUDE_TEMPLATE, VIS_TAB_H);
     if (!(ofp = fopen(filename, WRTMODE))) {
         perror(filename);
         exit(EXIT_FAILURE);
@@ -2777,10 +2977,15 @@ do_vision()
 #ifdef FILE_PREFIX
     Strcat(filename, file_prefix);
 #endif
-    Sprintf(filename, SOURCE_TEMPLATE, VIS_TAB_C);
+    Sprintf(eos(filename), SOURCE_TEMPLATE, VIS_TAB_C);
     if (!(ofp = fopen(filename, WRTMODE))) {
         perror(filename);
-        Sprintf(filename, INCLUDE_TEMPLATE, VIS_TAB_H);
+        /* creating vis_tab.c failed; remove the vis_tab.h we just made */
+        filename[0] = '\0';
+#ifdef FILE_PREFIX
+        Strcat(filename, file_prefix);
+#endif
+        Sprintf(eos(filename), INCLUDE_TEMPLATE, VIS_TAB_H);
         Unlink(filename);
         exit(EXIT_FAILURE);
     }
index 429c873..0763385 100644 (file)
@@ -1,5 +1,5 @@
 #!perl
-# NetHack 3.6  mdgrep.pl  $NHDT-Date: 1423877528 2015/02/14 01:32:08 $  $NHDT-Branch$:$NHDT-Revision: 1.7 $
+# NetHack 3.6  mdgrep.pl  $NHDT-Date: 1524684408 2018/04/25 19:26:48 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $
 # Copyright (c) Kenneth Lorber, Kensington, Maryland
 # NetHack may be freely redistributed.  See license for details.
 
 
 $outfile = "mdgrep.h";
 sub start_file {
-       ($rev) = ('$NHDT-Revision: 1.7 $') =~ m/: (.*) .$/;
-       my $date = '$NHDT-Date: 1423877529 2015/02/14 01:32:09 $';
-       my $branch = '$NHDT-Branch$';
-       my $revision = '$NHDT-Revision: 1.7 $';
+       ($rev) = ('$NHDT-Revision: 1.16 $') =~ m/: (.*) .$/;
+       my $date = '$NHDT-Date: 1524684408 2018/04/25 19:26:48 $';
+       my $branch = '$NHDT-Branch: NetHack-3.6.0 $';
+       my $revision = '$NHDT-Revision: 1.16 $';
        open(OUT, ">$outfile") || die "open $outfile: $!";
 # NB: Date and Revision below will be modified when mdgrep.h is written to
 # git - this is correct (but it means you must commit changes to mdgrep.pl
index f5a0837..36bd459 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 panic.c $NHDT-Date: 1448210012 2015/11/22 16:33:32 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2015. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
index 5365c10..daac5fc 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 recover.c       $NHDT-Date: 1432512785 2015/05/25 00:13:05 $  $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
+/* NetHack 3.6 recover.c       $NHDT-Date: 1501461282 2017/07/31 00:34:42 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
 /*     Copyright (c) Janet Walz, 1992.                           */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -248,7 +248,7 @@ char *basename;
                     errno);
 #endif
         Fprintf(stderr, "Cannot open level 0 for %s.\n", basename);
-        return (-1);
+        return -1;
     }
     if (read(gfd, (genericptr_t) &hpid, sizeof hpid) != sizeof hpid) {
         Fprintf(
@@ -256,7 +256,7 @@ char *basename;
             "Checkpoint data incompletely written or subsequently clobbered;",
             "recovery for \"", basename, "\" impossible.");
         Close(gfd);
-        return (-1);
+        return -1;
     }
     if (read(gfd, (genericptr_t) &savelev, sizeof(savelev))
         != sizeof(savelev)) {
@@ -264,7 +264,7 @@ char *basename;
                         "impossible.\n",
                 basename);
         Close(gfd);
-        return (-1);
+        return -1;
     }
     if ((read(gfd, (genericptr_t) savename, sizeof savename)
          != sizeof savename)
@@ -276,7 +276,7 @@ char *basename;
         || (read(gfd, (genericptr_t) &plbuf, pltmpsiz) != pltmpsiz)) {
         Fprintf(stderr, "Error reading %s -- can't recover.\n", lock);
         Close(gfd);
-        return (-1);
+        return -1;
     }
 
     /* save file should contain:
@@ -291,7 +291,7 @@ char *basename;
     if (sfd < 0) {
         Fprintf(stderr, "Cannot create savefile %s.\n", savename);
         Close(gfd);
-        return (-1);
+        return -1;
     }
 
     lfd = open_levelfile(savelev);
@@ -299,7 +299,7 @@ char *basename;
         Fprintf(stderr, "Cannot open level of save for %s.\n", basename);
         Close(gfd);
         Close(sfd);
-        return (-1);
+        return -1;
     }
 
     if (write(sfd, (genericptr_t) &version_data, sizeof version_data)
@@ -307,7 +307,8 @@ char *basename;
         Fprintf(stderr, "Error writing %s; recovery failed.\n", savename);
         Close(gfd);
         Close(sfd);
-        return (-1);
+        Close(lfd);
+        return -1;
     }
 
     if (write(sfd, (genericptr_t) &sfi, sizeof sfi) != sizeof sfi) {
@@ -316,7 +317,8 @@ char *basename;
                 savename);
         Close(gfd);
         Close(sfd);
-        return (-1);
+        Close(lfd);
+        return -1;
     }
 
     if (write(sfd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz)
@@ -326,7 +328,8 @@ char *basename;
                 savename);
         Close(gfd);
         Close(sfd);
-        return (-1);
+        Close(lfd);
+        return -1;
     }
 
     if (write(sfd, (genericptr_t) &plbuf, pltmpsiz) != pltmpsiz) {
@@ -334,7 +337,8 @@ char *basename;
                 savename);
         Close(gfd);
         Close(sfd);
-        return (-1);
+        Close(lfd);
+        return -1;
     }
 
     copy_bytes(lfd, sfd);
@@ -370,25 +374,27 @@ char *basename;
 
 #if 0 /* OBSOLETE, HackWB is no longer in use */
 #ifdef AMIGA
-                       /* we need to create an icon for the saved game
-                        * or HackWB won't notice the file.
-                        */
-       {
+    {
+        /* we need to create an icon for the saved game
+         * or HackWB won't notice the file.
+         */
        char iconfile[FILENAME];
        int in, out;
 
        (void) sprintf(iconfile, "%s.info", savename);
        in = open("NetHack:default.icon", O_RDONLY);
        out = open(iconfile, O_WRONLY | O_TRUNC | O_CREAT);
-       if(in > -1 && out > -1){
-               copy_bytes(in,out);
-       }
-       if(in > -1)close(in);
-       if(out > -1)close(out);
+       if (in > -1 && out > -1) {
+            copy_bytes(in, out);
        }
+       if (in > -1)
+            close(in);
+       if (out > -1)
+            close(out);
+    }
+#endif /*AMIGA*/
 #endif
-#endif
-    return (0);
+    return 0;
 }
 
 #ifdef EXEPATH
index b8a81a8..6a3de9c 100644 (file)
@@ -1,6 +1,8 @@
 Installing NetHack with a Qt or KDE interface
 ---------------------------------------------
-$NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+$NHDT-Date: 1524689332 2018/04/25 20:48:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.11 $
+# Copyright (c) 2004 by Warwick Allison
+# NetHack may be freely redistributed.  See license for details.
 
 This document describes the installation of NetHack with a Qt interface
 on UNIX/X11 or Mac OS X. This code should also work with Qt/Windows, but
index 193c52b..c5063a6 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 qt_clust.cpp    $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$ */
+/* NetHack 3.6 qt_clust.cpp    $NHDT-Date: 1524684507 2018/04/25 19:28:27 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.8 $ */
 /* Copyright (c) Warwick Allison, 1999. */
 /* NetHack may be freely redistributed.  See license for details. */
 #include "qt_clust.h"
index 4b3e5dd..c809c48 100644 (file)
@@ -1,4 +1,4 @@
-// NetHack 3.6 qt_win.cpp      $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+// NetHack 3.6 qt_win.cpp      $NHDT-Date: 1524684508 2018/04/25 19:28:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.77 $
 // Copyright (c) Warwick Allison, 1999.
 // NetHack may be freely redistributed.  See license for details.
 
@@ -1379,6 +1379,7 @@ void NetHackQtStringRequestor::SetDefault(const char* d)
 {
     input.setText(d);
 }
+
 bool NetHackQtStringRequestor::Get(char* buffer, int maxchar)
 {
     input.setMaxLength(maxchar);
@@ -1432,6 +1433,7 @@ void NetHackQtStringRequestor::done(int i)
 NetHackQtWindow::NetHackQtWindow()
 {
 }
+
 NetHackQtWindow::~NetHackQtWindow()
 {
 }
@@ -1514,7 +1516,10 @@ void NetHackQtMapWindow::putMessage(int attr, const char* text)
        messages += "\n";
     messages += text;
     QFontMetrics fm = fontMetrics();
-    messages_rect = fm.boundingRect(viewport.contentsX(),viewport.contentsY(),viewport.width(),0, WordBreak|AlignTop|AlignLeft|DontClip, messages);
+    messages_rect = fm.boundingRect(viewport.contentsX(), viewport.contentsY(),
+                                    viewport.width(), 0,
+                                    WordBreak|AlignTop|AlignLeft|DontClip,
+                                    messages);
     update(messages_rect);
 }
 
@@ -1701,7 +1706,9 @@ void NetHackQtMapWindow::paintEvent(QPaintEvent* event)
                    && ::iflags.hilite_pet
 #endif
                ) {
-                   painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
+                   painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(),
+                                              j*qt_settings->glyphs().height()),
+                                       pet_annotation);
                }
            }
        }
@@ -1717,7 +1724,9 @@ void NetHackQtMapWindow::paintEvent(QPaintEvent* event)
                    && ::iflags.hilite_pet
 #endif
                ) {
-                   painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
+                   painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(),
+                                              j*qt_settings->glyphs().height()),
+                                       pet_annotation);
                }
            }
        }
@@ -2827,6 +2836,7 @@ void NetHackQtMenuWindow::Layout()
     invert->setGeometry(x,0,butw,buth); x+=butw; butw=(dialog->width()-x)/1;
     search->setGeometry(x,0,butw,buth);
 }
+
 int NetHackQtMenuWindow::SelectMenu(int h, MENU_ITEM_P **menu_list)
 {
     setFont(str_fixed ?
@@ -2947,6 +2957,7 @@ int NetHackQtMenuWindow::SelectMenu(int h, MENU_ITEM_P **menu_list)
        return -1;
     }
 }
+
 void NetHackQtMenuWindow::keyPressEvent(QKeyEvent* event)
 {
     if (viewHeight() < totalHeight() && !(event->state()&ShiftButton)) {
@@ -2974,12 +2985,14 @@ void NetHackQtMenuWindow::ChooseNone()
        if (item[i].selected) ToggleSelect(i);
     }
 }
+
 void NetHackQtMenuWindow::Invert()
 {
     for (int i=0; i<itemcount; i++) {
        ToggleSelect(i);
     }
 }
+
 void NetHackQtMenuWindow::Search()
 {
     NetHackQtStringRequestor requestor(keysource,"Search for:");
@@ -2991,6 +3004,7 @@ void NetHackQtMenuWindow::Search()
        }
     }
 }
+
 void NetHackQtMenuWindow::ToggleSelect(int i)
 {
     if (item[i].Selectable()) {
@@ -3115,6 +3129,7 @@ void NetHackQtMenuWindow::mousePressEvent(QMouseEvent* event)
        }
     }
 }
+
 void NetHackQtMenuWindow::mouseReleaseEvent(QMouseEvent* event)
 {
     if (pressed>=0) {
@@ -3123,6 +3138,7 @@ void NetHackQtMenuWindow::mouseReleaseEvent(QMouseEvent* event)
        updateCell(p,3);
     }
 }
+
 void NetHackQtMenuWindow::mouseMoveEvent(QMouseEvent* event)
 {
     if (pressed>=0) {
@@ -3292,7 +3308,7 @@ static char** rip_line=0;
     Sprintf(rip_line[GOLD_LINE], "%ld Au", done_money);
 
     /* Put together death description */
-    formatkiller(buf, sizeof buf, how);
+    formatkiller(buf, sizeof buf, how, FALSE);
 
     /* Put death type on stone */
     for (line=DEATH_LINE, dpx = buf; line<YEAR_LINE; line++) {
@@ -4023,7 +4039,7 @@ void NetHackQtMainWindow::closeEvent(QCloseEvent* e)
                if (dosave0()) {
                    u.uhp = -1;
                    NetHackQtBind::qt_exit_nhwindows(0);
-                   terminate(EXIT_SUCCESS);
+                   nh_terminate(EXIT_SUCCESS);
                }
                break;
            case 1:
@@ -4274,8 +4290,9 @@ NetHackQtGlyphs::NetHackQtGlyphs()
        } else {
            tiles_per_row = TILES_PER_ROW;
            if (img.width()%tiles_per_row) {
-               impossible("Tile file \"%s\" has %d columns, not multiple of row count (%d)",
-                  tile_file, img.width(), tiles_per_row);
+               impossible(
+            "Tile file \"%s\" has %d columns, not multiple of row count (%d)",
+                           tile_file, img.width(), tiles_per_row);
            }
        }
     } else {
@@ -4368,18 +4385,30 @@ QWidget* NetHackQtMenuOrTextWindow::Widget()
 // Text
 void NetHackQtMenuOrTextWindow::Clear()
 {
-    if (!actual) impossible("Clear called before we know if Menu or Text");
-    actual->Clear();
+    if (!actual)
+        impossible("Clear called before we know if Menu or Text");
+    else
+        actual->Clear();
 }
+
 void NetHackQtMenuOrTextWindow::Display(bool block)
 {
-    if (!actual) impossible("Display called before we know if Menu or Text");
-    actual->Display(block);
+    if (!actual)
+        impossible("Display called before we know if Menu or Text");
+    else
+        actual->Display(block);
 }
+
 bool NetHackQtMenuOrTextWindow::Destroy()
 {
-    if (!actual) impossible("Destroy called before we know if Menu or Text");
-    return actual->Destroy();
+    bool res = FALSE;
+
+    if (!actual)
+        impossible("Destroy called before we know if Menu or Text");
+    else
+        res = actual->Destroy();
+
+    return res;
 }
 
 void NetHackQtMenuOrTextWindow::PutStr(int attr, const char* text)
@@ -4394,17 +4423,20 @@ void NetHackQtMenuOrTextWindow::StartMenu()
     if (!actual) actual=new NetHackQtMenuWindow(keysource);
     actual->StartMenu();
 }
+
 void NetHackQtMenuOrTextWindow::AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
        const char* str, bool presel)
 {
     if (!actual) impossible("AddMenu called before we know if Menu or Text");
     actual->AddMenu(glyph,identifier,ch,gch,attr,str,presel);
 }
+
 void NetHackQtMenuOrTextWindow::EndMenu(const char* prompt)
 {
     if (!actual) impossible("EndMenu called before we know if Menu or Text");
     actual->EndMenu(prompt);
 }
+
 int NetHackQtMenuOrTextWindow::SelectMenu(int how, MENU_ITEM_P **menu_list)
 {
     if (!actual) impossible("SelectMenu called before we know if Menu or Text");
@@ -4607,7 +4639,7 @@ void NetHackQtBind::qt_askname()
     // Quit
     clearlocks();
     qt_exit_nhwindows(0);
-    terminate(0);
+    nh_terminate(0);
 }
 
 void NetHackQtBind::qt_get_nh_event()
@@ -5254,15 +5286,11 @@ struct window_procs Qt_procs = {
     genl_preference_update,
     genl_getmsghistory,
     genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init,
     genl_status_finish,
     genl_status_enablefield,
     genl_status_update,
-# ifdef STATUS_HILITES
-    genl_status_threshold,
-# endif
-#endif
+    genl_can_suspend_yes,
 };
 
 extern "C" void play_usersound(const char* filename, int volume)
index 0386acd..b53e8a4 100644 (file)
@@ -1,5 +1,5 @@
 /**********************************************************************
-** $NHDT-Branch$:$NHDT-Revision$ $NHDT-Date$
+** $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.4 $ $NHDT-Date: 1524684508 2018/04/25 19:28:28 $
 ** $Id: qttableview.cpp,v 1.2 2002/03/09 03:13:15 jwalz Exp $
 **
 ** Implementation of QtTableView class
index 1259af3..cbde518 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 tileedit.cpp    $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$ */
+/* NetHack 3.6 tileedit.cpp    $NHDT-Date: 1524684508 2018/04/25 19:28:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $ */
 /* Copyright (c) Warwick Allison, 1999. */
 /* NetHack may be freely redistributed.  See license for details. */
 /*
diff --git a/win/Qt4/qt4bind.cpp b/win/Qt4/qt4bind.cpp
new file mode 100644 (file)
index 0000000..2fef131
--- /dev/null
@@ -0,0 +1,808 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4bind.cpp -- bindings between the Qt 4 interface and the main code
+
+extern "C" {
+#include "hack.h"
+}
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#include <QStringList>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#include <QtMultimedia/QSound>
+#else
+#include <QtGui/QSound>
+#endif
+#include "qt4bind.h"
+#include "qt4click.h"
+#ifdef TIMED_DELAY
+#include "qt4delay.h"
+#endif
+#include "qt4xcmd.h"
+#include "qt4key.h"
+#include "qt4map.h"
+#include "qt4menu.h"
+#include "qt4msg.h"
+#include "qt4plsel.h"
+#include "qt4svsel.h"
+#include "qt4set.h"
+#include "qt4stat.h"
+#include "qt4streq.h"
+#include "qt4yndlg.h"
+#include "qt4str.h"
+
+extern "C" {
+#include "dlb.h"
+}
+
+// temporary
+extern int qt_compact_mode;
+// end temporary
+
+namespace nethack_qt4 {
+
+// XXX Should be from Options
+//
+// XXX Hmm.  Tricky part is that perhaps some macros should only be active
+// XXX       when a key is about to be gotten.  For example, the user could
+// XXX       define "-" to do "E-yyyyyyyy\r", but would still need "-" for
+// XXX       other purposes.  Maybe just too bad.
+//
+static struct key_macro_rec {
+    int key;
+    int state;
+    const char* macro;
+} key_macro[]={
+    { Qt::Key_F1, 0, "n100." }, // Rest (x100)
+    { Qt::Key_F2, 0, "n20s" },  // Search (x20)
+    { Qt::Key_Tab, 0, "\001" },
+    { 0, 0, 0 }
+};
+
+NetHackQtBind::NetHackQtBind(int& argc, char** argv) :
+#ifdef KDE
+    KApplication(argc,argv)
+#elif defined(QWS) // not quite the right condition
+    QPEApplication(argc,argv)
+#else
+    QApplication(argc,argv)
+#endif
+{
+    QPixmap pm("nhsplash.xpm");
+    if ( iflags.wc_splash_screen && !pm.isNull() ) {
+       splash = new QFrame(NULL,
+           Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint );
+       QVBoxLayout *vb = new QVBoxLayout(splash);
+       QLabel *lsplash = new QLabel(splash);
+       vb->addWidget(lsplash);
+       lsplash->setAlignment(Qt::AlignCenter);
+       lsplash->setPixmap(pm);
+       QLabel* capt = new QLabel("Loading...",splash);
+       vb->addWidget(capt);
+       capt->setAlignment(Qt::AlignCenter);
+       if ( !pm.isNull() ) {
+           lsplash->setFixedSize(pm.size());
+           lsplash->setMask(pm);
+       }
+       splash->move((QApplication::desktop()->width()-pm.width())/2,
+                     (QApplication::desktop()->height()-pm.height())/2);
+       //splash->setGeometry(0,0,100,100);
+       if ( qt_compact_mode ) {
+           splash->showMaximized();
+       } else {
+           splash->setFrameStyle(QFrame::WinPanel|QFrame::Raised);
+           splash->setLineWidth(10);
+           splash->adjustSize();
+           splash->show();
+       }
+
+       // force content refresh outside event loop
+       splash->repaint();
+       lsplash->repaint();
+       capt->repaint();
+       qApp->flush();
+
+    } else {
+       splash = 0;
+    }
+    main = new NetHackQtMainWindow(keybuffer);
+    connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()));
+    qt_settings=new NetHackQtSettings(main->width(),main->height());
+    msgs_strings = new QStringList();
+    msgs_initd = false;
+    msgs_saved = false;
+}
+
+void NetHackQtBind::qt_init_nhwindows(int* argc, char** argv)
+{
+    iflags.menu_tab_sep = true;
+
+#ifdef UNIX
+// Userid control
+//
+// Michael Hohmuth <hohmuth@inf.tu-dresden.de>...
+//
+// As the game runs setuid games, it must seteuid(getuid()) before
+// calling XOpenDisplay(), and reset the euid afterwards.
+// Otherwise, it can't read the $HOME/.Xauthority file and whines about
+// not being able to open the X display (if a magic-cookie
+// authorization mechanism is being used). 
+
+    uid_t gamesuid=geteuid();
+    seteuid(getuid());
+#endif
+
+    QApplication::setColorSpec(ManyColor);
+    instance=new NetHackQtBind(*argc,argv);
+
+#ifdef UNIX
+    seteuid(gamesuid);
+#endif
+
+#ifdef _WS_WIN_
+    // This nethack engine feature should be moved into windowport API
+    nt_kbhit = NetHackQtBind::qt_kbhit;
+#endif
+}
+
+int NetHackQtBind::qt_kbhit()
+{
+    return !keybuffer.Empty();
+}
+
+
+static bool have_asked = false;
+
+void NetHackQtBind::qt_player_selection()
+{
+    if ( !have_asked )
+       qt_askname();
+}
+
+void NetHackQtBind::qt_askname()
+{
+    have_asked = true;
+
+    // We do it all here, and nothing in askname
+
+    char** saved = get_saved_games();
+    int ch = -1;
+    if ( saved && *saved ) {
+       if ( splash ) splash->hide();
+       NetHackQtSavedGameSelector sgsel((const char**)saved);
+       ch = sgsel.choose();
+       if ( ch >= 0 )
+           str_copy(plname, saved[ch], SIZE(plname));
+    }
+    free_saved_games(saved);
+
+    switch (ch) {
+      case -1:
+       if ( splash ) splash->hide();
+       if (NetHackQtPlayerSelector(keybuffer).Choose())
+           return;
+      case -2:
+       break;
+      default:
+       return;
+    }
+
+    // Quit
+    clearlocks();
+    qt_exit_nhwindows(0);
+    nh_terminate(0);
+}
+
+void NetHackQtBind::qt_get_nh_event()
+{
+}
+
+#if defined(QWS)
+// Kludge to access lastWindowClosed() signal.
+class TApp : public QApplication {
+public:
+    TApp(int& c, char**v) : QApplication(c,v) {}
+    void lwc() { emit lastWindowClosed(); }
+};
+#endif
+void NetHackQtBind::qt_exit_nhwindows(const char *)
+{
+#if defined(QWS)
+    // Avoids bug in SHARP SL5500
+    ((TApp*)qApp)->lwc();
+    qApp->quit();
+#endif
+    delete instance; // ie. qApp
+}
+
+void NetHackQtBind::qt_suspend_nhwindows(const char *)
+{
+}
+
+void NetHackQtBind::qt_resume_nhwindows()
+{
+}
+
+static QVector<NetHackQtWindow*> id_to_window;
+
+winid NetHackQtBind::qt_create_nhwindow(int type)
+{
+    winid id;
+    for (id = 0; id < (winid) id_to_window.size(); id++) {
+       if ( !id_to_window[(int)id] )
+           break;
+    }
+    if ( id == (winid) id_to_window.size() )
+       id_to_window.resize(id+1);
+
+    NetHackQtWindow* window=0;
+
+    switch (type) {
+     case NHW_MAP: {
+       NetHackQtMapWindow2* w=new NetHackQtMapWindow2(clickbuffer);
+       main->AddMapWindow(w);
+       window=w;
+    } break; case NHW_MESSAGE: {
+       NetHackQtMessageWindow* w=new NetHackQtMessageWindow;
+       main->AddMessageWindow(w);
+       window=w;
+    } break; case NHW_STATUS: {
+       NetHackQtStatusWindow* w=new NetHackQtStatusWindow;
+       main->AddStatusWindow(w);
+       window=w;
+    } break; case NHW_MENU:
+       window=new NetHackQtMenuOrTextWindow(mainWidget());
+    break; case NHW_TEXT:
+       window=new NetHackQtTextWindow(mainWidget());
+    }
+
+    window->nhid = id;
+
+    // Note: use of isHidden does not work with Qt 2.1
+    if ( splash 
+#if QT_VERSION >= 300
+        && !main->isHidden()
+#else
+       && main->isVisible()
+#endif
+       )
+    {
+       delete splash;
+       splash = 0;
+    }
+
+    id_to_window[(int)id] = window;
+    return id;
+}
+
+void NetHackQtBind::qt_clear_nhwindow(winid wid)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->Clear();
+}
+
+void NetHackQtBind::qt_display_nhwindow(winid wid, BOOLEAN_P block)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->Display(block);
+}
+
+void NetHackQtBind::qt_destroy_nhwindow(winid wid)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    main->RemoveWindow(window);
+    if (window->Destroy())
+       delete window;
+    id_to_window[(int)wid] = 0;
+}
+
+void NetHackQtBind::qt_curs(winid wid, int x, int y)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->CursorTo(x,y);
+}
+
+void NetHackQtBind::qt_putstr(winid wid, int attr, const char *text)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->PutStr(attr,QString::fromLatin1(text));
+}
+
+void NetHackQtBind::qt_putstr(winid wid, int attr, const std::string& text)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->PutStr(attr,QString::fromLatin1(text.c_str(), text.size()));
+}
+
+void NetHackQtBind::qt_putstr(winid wid, int attr, const QString& text)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->PutStr(attr,text);
+}
+
+void NetHackQtBind::qt_display_file(const char *filename, BOOLEAN_P must_exist)
+{
+    NetHackQtTextWindow* window=new NetHackQtTextWindow(mainWidget());
+    bool complain = false;
+
+    {
+       dlb *f;
+       char buf[BUFSZ];
+       char *cr;
+
+       window->Clear();
+       f = dlb_fopen(filename, "r");
+       if (!f) {
+           complain = must_exist;
+       } else {
+           while (dlb_fgets(buf, BUFSZ, f)) {
+               if ((cr = index(buf, '\n')) != 0) *cr = 0;
+#ifdef MSDOS
+               if ((cr = index(buf, '\r')) != 0) *cr = 0;
+#endif
+               window->PutStr(ATR_NONE, tabexpand(buf));
+           }
+           window->Display(false);
+           (void) dlb_fclose(f);
+       }
+    }
+
+    if (complain) {
+       QString message;
+       message.sprintf("File not found: %s\n",filename);
+       QMessageBox::warning(NULL, "File Error", message, QMessageBox::Ignore);
+    }
+}
+
+void NetHackQtBind::qt_start_menu(winid wid)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->StartMenu();
+}
+
+void NetHackQtBind::qt_add_menu(winid wid, int glyph,
+    const ANY_P * identifier, CHAR_P ch, CHAR_P gch, int attr,
+    const char *str, BOOLEAN_P presel)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->AddMenu(glyph, identifier, ch, gch, attr,
+            QString::fromLatin1(str),
+            presel);
+}
+
+void NetHackQtBind::qt_end_menu(winid wid, const char *prompt)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->EndMenu(prompt);
+}
+
+int NetHackQtBind::qt_select_menu(winid wid, int how, MENU_ITEM_P **menu_list)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    return window->SelectMenu(how,menu_list);
+}
+
+void NetHackQtBind::qt_update_inventory()
+{
+    if (main)
+       main->updateInventory();
+    /* doesn't work yet
+    if (program_state.something_worth_saving && flags.perm_invent)
+        display_inventory(NULL, false);
+    */
+}
+
+void NetHackQtBind::qt_mark_synch()
+{
+}
+
+void NetHackQtBind::qt_wait_synch()
+{
+}
+
+void NetHackQtBind::qt_cliparound(int x, int y)
+{
+    // XXXNH - winid should be a parameter!
+    qt_cliparound_window(WIN_MAP,x,y);
+}
+
+void NetHackQtBind::qt_cliparound_window(winid wid, int x, int y)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->ClipAround(x,y);
+}
+void NetHackQtBind::qt_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph,int bkglyph)
+{
+    /* TODO: bkglyph */
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->PrintGlyph(x,y,glyph);
+}
+//void NetHackQtBind::qt_print_glyph_compose(winid wid,xchar x,xchar y,int glyph1, int glyph2)
+//{
+    //NetHackQtWindow* window=id_to_window[(int)wid];
+    //window->PrintGlyphCompose(x,y,glyph1,glyph2);
+//}
+
+void NetHackQtBind::qt_raw_print(const char *str)
+{
+    puts(str);
+}
+
+void NetHackQtBind::qt_raw_print_bold(const char *str)
+{
+    puts(str);
+}
+
+int NetHackQtBind::qt_nhgetch()
+{
+    if (main)
+       main->fadeHighlighting();
+
+    // Process events until a key arrives.
+    //
+    while (keybuffer.Empty()) {
+       qApp->exec();
+    }
+
+    return keybuffer.GetAscii();
+}
+
+int NetHackQtBind::qt_nh_poskey(int *x, int *y, int *mod)
+{
+    if (main)
+       main->fadeHighlighting();
+
+    // Process events until a key or map-click arrives.
+    //
+    while (keybuffer.Empty() && clickbuffer.Empty()) {
+       qApp->exec();
+    }
+    if (!keybuffer.Empty()) {
+       return keybuffer.GetAscii();
+    } else {
+       *x=clickbuffer.NextX();
+       *y=clickbuffer.NextY();
+       *mod=clickbuffer.NextMod();
+       clickbuffer.Get();
+       return 0;
+    }
+}
+
+void NetHackQtBind::qt_nhbell()
+{
+    QApplication::beep();
+}
+
+int NetHackQtBind::qt_doprev_message()
+{
+    // Don't need it - uses scrollbar
+    // XXX but could make this a shortcut
+    return 0;
+}
+
+char NetHackQtBind::qt_yn_function(const char *question_, const char *choices, CHAR_P def)
+{
+    QString question(QString::fromLatin1(question_));
+    QString message;
+    char yn_esc_map='\033';
+
+    if (choices) {
+        // anything beyond <esc> is hidden>
+        QString choicebuf = choices;
+        size_t cb = choicebuf.indexOf('\033');
+        choicebuf = choicebuf.mid(0U, cb);
+        message = QString("%1 [%2] ").arg(question, choicebuf);
+        if (def) message += QString("(%1) ").arg(QChar(def));
+        // escape maps to 'q' or 'n' or default, in that order
+        yn_esc_map = (index(choices, 'q') ? 'q' :
+                      (index(choices, 'n') ? 'n' : def));
+    } else {
+        message = question;
+    }
+
+    if (qt_settings->ynInMessages() && WIN_MESSAGE!=WIN_ERR) {
+       // Similar to X11 windowport `slow' feature.
+
+       int result = -1;
+
+#ifdef USE_POPUPS
+        if (choices) {
+            if (!strcmp(choices,"ynq"))
+                result = QMessageBox::information (NetHackQtBind::mainWidget(),"NetHack",question,"&Yes","&No","&Quit",0,2);
+            else if (!strcmp(choices,"yn"))
+                result = QMessageBox::information(NetHackQtBind::mainWidget(),"NetHack",question,"&Yes", "&No",0,1);
+            else if (!strcmp(choices, "rl"))
+                result = QMessageBox::information(NetHackQtBind::mainWidget(),"NetHack",question,"&Right", "&Left",0,1);
+
+            if (result >= 0 && result < strlen(choices)) {
+                char yn_resp = choices[result];
+                message += QString(" %1").arg(yn_resp);
+                result = yn_resp;
+            }
+        }
+#endif
+
+       NetHackQtBind::qt_putstr(WIN_MESSAGE, ATR_BOLD, message);
+
+       while (result < 0) {
+           char ch=NetHackQtBind::qt_nhgetch();
+           if (ch=='\033') {
+               result=yn_esc_map;
+           } else if (choices && !index(choices,ch)) {
+               if (def && (ch==' ' || ch=='\r' || ch=='\n')) {
+                   result=def;
+               } else {
+                   NetHackQtBind::qt_nhbell();
+                   // and try again...
+               }
+           } else {
+               result=ch;
+           }
+       }
+
+       NetHackQtBind::qt_clear_nhwindow(WIN_MESSAGE);
+
+       return result;
+    } else {
+       NetHackQtYnDialog dialog(mainWidget(),question,choices,def);
+       char ret = dialog.Exec();
+        if (!(ret == '\0' || ret == '\033') && choices)
+            message += QString(" %1").arg(ret);
+        else if (def)
+            message += QString(" %1").arg(def);
+       NetHackQtBind::qt_putstr(WIN_MESSAGE, ATR_BOLD, message);
+    }
+}
+
+void NetHackQtBind::qt_getlin(const char *prompt, char *line)
+{
+    NetHackQtStringRequestor requestor(mainWidget(),prompt);
+    if (!requestor.Get(line)) {
+       line[0]=0;
+    }
+}
+
+int NetHackQtBind::qt_get_ext_cmd()
+{
+    NetHackQtExtCmdRequestor requestor(mainWidget());
+    return requestor.get();
+}
+
+void NetHackQtBind::qt_number_pad(int)
+{
+    // Ignore.
+}
+
+void NetHackQtBind::qt_delay_output()
+{
+#ifdef TIMED_DELAY
+    NetHackQtDelay delay(50);
+    delay.wait();
+#endif
+}
+
+void NetHackQtBind::qt_start_screen()
+{
+    // Ignore.
+}
+
+void NetHackQtBind::qt_end_screen()
+{
+    // Ignore.
+}
+
+void NetHackQtBind::qt_outrip(winid wid, int how, time_t when)
+{
+    NetHackQtWindow* window=id_to_window[(int)wid];
+    window->UseRIP(how, when);
+}
+
+char * NetHackQtBind::qt_getmsghistory(BOOLEAN_P init)
+{
+    NetHackQtMessageWindow* window = main->GetMessageWindow();
+    if (window)
+        return (char *)window->GetStr(init);
+    return NULL;
+}
+
+void NetHackQtBind::qt_putmsghistory(const char *msg, BOOLEAN_P is_restoring)
+{
+    NetHackQtMessageWindow* window = main->GetMessageWindow();
+    if (!window)
+        return;
+
+    if (is_restoring && !msgs_initd) {
+        /* we're restoring history from the previous session, but new
+           messages have already been issued this session */
+        int i = 0;
+        const char *str;
+
+        while ((str = window->GetStr((i == 0)))) {
+            msgs_strings->append(str);
+            i++;
+        }
+        msgs_initd = true;
+        msgs_saved = (i > 0);
+        window->ClearMessages();
+    }
+
+    if (msg) {
+        //raw_printf("msg='%s'", msg);
+        window->PutStr(ATR_NONE, QString::fromLatin1(msg));
+#ifdef DUMPLOG
+        dumplogmsg(msg);
+#endif
+    } else if (msgs_saved) {
+        /* restore strings */
+        int i;
+        for (i = 0; i < msgs_strings->size(); i++) {
+            window->PutStr(ATR_NONE, msgs_strings->at((i)));
+#ifdef DUMPLOG
+            dumplogmsg(msgs_strings->at(i).toLatin1().constData());
+#endif
+        }
+        delete msgs_strings;
+        msgs_initd = false;
+    }
+}
+
+bool NetHackQtBind::notify(QObject *receiver, QEvent *event)
+{
+    // Ignore Alt-key navigation to menubar, it's annoying when you
+    // use Alt-Direction to move around.
+    if ( main && event->type()==QEvent::KeyRelease && main==receiver
+           && ((QKeyEvent*)event)->key() == Qt::Key_Alt )
+       return true;
+
+    bool result=QApplication::notify(receiver,event);
+    if (event->type()==QEvent::KeyPress) {
+       QKeyEvent* key_event=(QKeyEvent*)event;
+
+       if (!key_event->isAccepted()) {
+           const int k=key_event->key();
+           bool macro=false;
+           for (int i=0; !macro && key_macro[i].key; i++) {
+               if (key_macro[i].key==k
+                && ((key_macro[i].state&key_event->modifiers())==key_macro[i].state))
+               {
+                   keybuffer.Put(key_macro[i].macro);
+                   macro=true;
+               }
+           }
+           QString key=key_event->text();
+           QChar ch = !key.isEmpty() ? key.at(0) : 0;
+           if (ch > 128) ch = 0;
+           if ( ch == 0 && (key_event->modifiers() & Qt::ControlModifier) ) {
+               // On Mac, ascii control codes are not sent, force them.
+               if ( k>=Qt::Key_A && k<=Qt::Key_Z )
+                   ch = k - Qt::Key_A + 1;
+           }
+           if (!macro && ch != 0) {
+               bool alt = (key_event->modifiers()&Qt::AltModifier) ||
+                  (k >= Qt::Key_0 && k <= Qt::Key_9 && (key_event->modifiers()&Qt::ControlModifier));
+               keybuffer.Put(key_event->key(),ch.cell() + (alt ? 128 : 0),
+                   key_event->modifiers());
+               key_event->accept();
+               result=true;
+           }
+
+           if (ch != 0 || macro) {
+               qApp->exit();
+           }
+       }
+    }
+    return result;
+}
+
+NetHackQtBind* NetHackQtBind::instance=0;
+NetHackQtKeyBuffer NetHackQtBind::keybuffer;
+NetHackQtClickBuffer NetHackQtBind::clickbuffer;
+NetHackQtMainWindow* NetHackQtBind::main=0;
+QFrame* NetHackQtBind::splash=0;
+QStringList *NetHackQtBind::msgs_strings;
+boolean NetHackQtBind::msgs_saved = false;
+boolean NetHackQtBind::msgs_initd = false;
+
+static void Qt_positionbar(char *) {}
+
+} // namespace nethack_qt4
+
+struct window_procs Qt_procs = {
+    "Qt",
+    WC_COLOR | WC_HILITE_PET
+    | WC_ASCII_MAP | WC_TILED_MAP
+    | WC_FONT_MAP | WC_TILE_FILE | WC_TILE_WIDTH | WC_TILE_HEIGHT
+    | WC_PLAYER_SELECTION | WC_SPLASH_SCREEN,
+    0L,
+    nethack_qt4::NetHackQtBind::qt_init_nhwindows,
+    nethack_qt4::NetHackQtBind::qt_player_selection,
+    nethack_qt4::NetHackQtBind::qt_askname,
+    nethack_qt4::NetHackQtBind::qt_get_nh_event,
+    nethack_qt4::NetHackQtBind::qt_exit_nhwindows,
+    nethack_qt4::NetHackQtBind::qt_suspend_nhwindows,
+    nethack_qt4::NetHackQtBind::qt_resume_nhwindows,
+    nethack_qt4::NetHackQtBind::qt_create_nhwindow,
+    nethack_qt4::NetHackQtBind::qt_clear_nhwindow,
+    nethack_qt4::NetHackQtBind::qt_display_nhwindow,
+    nethack_qt4::NetHackQtBind::qt_destroy_nhwindow,
+    nethack_qt4::NetHackQtBind::qt_curs,
+    nethack_qt4::NetHackQtBind::qt_putstr,
+    genl_putmixed,
+    nethack_qt4::NetHackQtBind::qt_display_file,
+    nethack_qt4::NetHackQtBind::qt_start_menu,
+    nethack_qt4::NetHackQtBind::qt_add_menu,
+    nethack_qt4::NetHackQtBind::qt_end_menu,
+    nethack_qt4::NetHackQtBind::qt_select_menu,
+    genl_message_menu,      /* no need for X-specific handling */
+    nethack_qt4::NetHackQtBind::qt_update_inventory,
+    nethack_qt4::NetHackQtBind::qt_mark_synch,
+    nethack_qt4::NetHackQtBind::qt_wait_synch,
+#ifdef CLIPPING
+    nethack_qt4::NetHackQtBind::qt_cliparound,
+#endif
+#ifdef POSITIONBAR
+    nethack_qt4::Qt_positionbar,
+#endif
+    nethack_qt4::NetHackQtBind::qt_print_glyph,
+    //NetHackQtBind::qt_print_glyph_compose,
+    nethack_qt4::NetHackQtBind::qt_raw_print,
+    nethack_qt4::NetHackQtBind::qt_raw_print_bold,
+    nethack_qt4::NetHackQtBind::qt_nhgetch,
+    nethack_qt4::NetHackQtBind::qt_nh_poskey,
+    nethack_qt4::NetHackQtBind::qt_nhbell,
+    nethack_qt4::NetHackQtBind::qt_doprev_message,
+    nethack_qt4::NetHackQtBind::qt_yn_function,
+    nethack_qt4::NetHackQtBind::qt_getlin,
+    nethack_qt4::NetHackQtBind::qt_get_ext_cmd,
+    nethack_qt4::NetHackQtBind::qt_number_pad,
+    nethack_qt4::NetHackQtBind::qt_delay_output,
+#ifdef CHANGE_COLOR     /* only a Mac option currently */
+    donull,
+    donull,
+    donull,
+    donull,
+#endif
+    /* other defs that really should go away (they're tty specific) */
+    nethack_qt4::NetHackQtBind::qt_start_screen,
+    nethack_qt4::NetHackQtBind::qt_end_screen,
+#ifdef GRAPHIC_TOMBSTONE
+    nethack_qt4::NetHackQtBind::qt_outrip,
+#else
+    genl_outrip,
+#endif
+    genl_preference_update,
+
+    nethack_qt4::NetHackQtBind::qt_getmsghistory,
+    nethack_qt4::NetHackQtBind::qt_putmsghistory,
+    genl_status_init,
+    genl_status_finish, genl_status_enablefield,
+#ifdef STATUS_HILITES
+    genl_status_update,
+#else
+    genl_status_update,
+#endif
+    genl_can_suspend_yes,
+};
+
+extern "C" void play_usersound(const char* filename, int volume)
+{
+#ifdef USER_SOUNDS
+#ifndef QT_NO_SOUND
+    QSound::play(filename);
+#endif
+#endif
+}
diff --git a/win/Qt4/qt4bind.h b/win/Qt4/qt4bind.h
new file mode 100644 (file)
index 0000000..820341c
--- /dev/null
@@ -0,0 +1,99 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4bind.h -- bindings between the Qt 4 interface and the main code
+
+#ifndef QT4BIND_H
+#define QT4BIND_H
+
+#include "qt4main.h"
+
+namespace nethack_qt4 {
+
+class NetHackQtClickBuffer;
+
+#ifdef KDE
+#define NetHackQtBindBase KApplication
+#elif defined(QWS)
+#define NetHackQtBindBase QPEApplication
+#else
+#define NetHackQtBindBase QApplication
+#endif
+
+class NetHackQtBind : NetHackQtBindBase {
+private:
+       // Single-instance preservation...
+       NetHackQtBind(int& argc, char** argv);
+
+       static NetHackQtBind* instance;
+
+       static NetHackQtKeyBuffer keybuffer;
+       static NetHackQtClickBuffer clickbuffer;
+
+       static QFrame* splash;
+       static NetHackQtMainWindow* main;
+
+public:
+       static void qt_init_nhwindows(int* argc, char** argv);
+       static void qt_player_selection();
+       static void qt_askname();
+       static void qt_get_nh_event();
+       static void qt_exit_nhwindows(const char *);
+       static void qt_suspend_nhwindows(const char *);
+       static void qt_resume_nhwindows();
+       static winid qt_create_nhwindow(int type);
+       static void qt_clear_nhwindow(winid wid);
+       static void qt_display_nhwindow(winid wid, BOOLEAN_P block);
+       static void qt_destroy_nhwindow(winid wid);
+       static void qt_curs(winid wid, int x, int y);
+       static void qt_putstr(winid wid, int attr, const char *text);
+       static void qt_putstr(winid wid, int attr, const std::string& text);
+       static void qt_putstr(winid wid, int attr, const QString& text);
+       static void qt_display_file(const char *filename, BOOLEAN_P must_exist);
+       static void qt_start_menu(winid wid);
+       static void qt_add_menu(winid wid, int glyph,
+               const ANY_P * identifier, CHAR_P ch, CHAR_P gch, int attr,
+               const char *str, BOOLEAN_P presel);
+       static void qt_end_menu(winid wid, const char *prompt);
+       static int qt_select_menu(winid wid, int how, MENU_ITEM_P **menu_list);
+       static void qt_update_inventory();
+       static void qt_mark_synch();
+       static void qt_wait_synch();
+
+       static void qt_cliparound(int x, int y);
+       static void qt_cliparound_window(winid wid, int x, int y);
+       static void qt_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph,int bkglyph);
+       static void qt_raw_print(const char *str);
+       static void qt_raw_print_bold(const char *str);
+       static int qt_nhgetch();
+       static int qt_nh_poskey(int *x, int *y, int *mod);
+       static void qt_nhbell();
+       static int qt_doprev_message();
+       static char qt_yn_function(const char *question, const char *choices, CHAR_P def);
+       static void qt_getlin(const char *prompt, char *line);
+       static int qt_get_ext_cmd();
+       static void qt_number_pad(int);
+       static void qt_delay_output();
+       static void qt_start_screen();
+       static void qt_end_screen();
+
+        static char *qt_getmsghistory(BOOLEAN_P init);
+        static void qt_putmsghistory(const char *msg, BOOLEAN_P is_restoring);
+
+       static void qt_outrip(winid wid, int how, time_t when);
+       static int qt_kbhit();
+
+       static QWidget *mainWidget() { return main; }
+
+private:
+       virtual bool notify(QObject *receiver, QEvent *event);
+
+        static QStringList *msgs_strings;
+        static boolean msgs_saved;
+        static boolean msgs_initd;
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4click.cpp b/win/Qt4/qt4click.cpp
new file mode 100644 (file)
index 0000000..78177a1
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4click.cpp -- a mouse click buffer
+
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#include "qt4click.h"
+
+namespace nethack_qt4 {
+
+NetHackQtClickBuffer::NetHackQtClickBuffer() :
+    in(0), out(0)
+{
+}
+
+bool NetHackQtClickBuffer::Empty() const { return in==out; }
+bool NetHackQtClickBuffer::Full() const { return (in+1)%maxclick==out; }
+
+void NetHackQtClickBuffer::Put(int x, int y, int mod)
+{
+    click[in].x=x;
+    click[in].y=y;
+    click[in].mod=mod;
+    in=(in+1)%maxclick;
+}
+
+int NetHackQtClickBuffer::NextX() const { return click[out].x; }
+int NetHackQtClickBuffer::NextY() const { return click[out].y; }
+int NetHackQtClickBuffer::NextMod() const { return click[out].mod; }
+
+void NetHackQtClickBuffer::Get()
+{
+    out=(out+1)%maxclick;
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4click.h b/win/Qt4/qt4click.h
new file mode 100644 (file)
index 0000000..50fd8b1
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4click.h -- a mouse click buffer
+
+#ifndef QT4CLICK_H
+#define QT4CLICK_H
+
+namespace nethack_qt4 {
+
+class NetHackQtClickBuffer {
+public:
+       NetHackQtClickBuffer();
+
+       bool Empty() const;
+       bool Full() const;
+
+       void Put(int x, int y, int mod);
+
+       int NextX() const;
+       int NextY() const;
+       int NextMod() const;
+
+       void Get();
+
+private:
+       enum { maxclick=64 };
+       struct ClickRec {
+               int x,y,mod;
+       } click[maxclick];
+       int in,out;
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4clust.cpp b/win/Qt4/qt4clust.cpp
new file mode 100644 (file)
index 0000000..1cd080c
--- /dev/null
@@ -0,0 +1,167 @@
+/*     SCCS Id: @(#)qt_clust.cpp       3.4     1999/11/19      */
+/* Copyright (c) Warwick Allison, 1999. */
+/* NetHack may be freely redistributed.  See license for details. */
+#include "qt4clust.h"
+
+static void include(QRect& r, const QRect& rect)
+{
+       if (rect.left()<r.left()) {
+                       r.setLeft(rect.left());
+       }
+       if (rect.right()>r.right()) {
+                       r.setRight(rect.right());
+       }
+       if (rect.top()<r.top()) {
+                       r.setTop(rect.top());
+       }
+       if (rect.bottom()>r.bottom()) {
+                       r.setBottom(rect.bottom());
+       }
+}
+
+/*
+A Clusterizer groups rectangles (QRects) into non-overlapping rectangles
+by a merging heuristic.
+*/
+Clusterizer::Clusterizer(int maxclusters) :
+       cluster(new QRect[maxclusters]),
+       count(0),
+       max(maxclusters)
+{ }
+
+Clusterizer::~Clusterizer()
+{
+       delete [] cluster;
+}
+
+void Clusterizer::clear()
+{
+       count=0;
+}
+
+void Clusterizer::add(int x, int y)
+{
+       add(QRect(x,y,1,1));
+}
+
+void Clusterizer::add(int x, int y, int w, int h)
+{
+       add(QRect(x,y,w,h));
+}
+
+void Clusterizer::add(const QRect& rect)
+{
+       QRect biggerrect(rect.x()-1,rect.y()-1,rect.width()+2,rect.height()+2);
+
+       //assert(rect.width()>0 && rect.height()>0);
+
+       int cursor;
+
+       for (cursor=0; cursor<count; cursor++) {
+               if (cluster[cursor].contains(rect)) {
+                       // Wholly contained already.
+                       return;
+               }
+       }
+
+       int lowestcost=9999999;
+       int cheapest=-1;
+       for (cursor=0; cursor<count; cursor++) {
+               if (cluster[cursor].intersects(biggerrect)) {
+                       QRect larger=cluster[cursor];
+                       include(larger,rect);
+                       int cost=larger.width()*larger.height()
+                                       - cluster[cursor].width()*cluster[cursor].height();
+
+                       if (cost < lowestcost) {
+                               bool bad=false;
+                               for (int c=0; c<count && !bad; c++) {
+                                       bad=cluster[c].intersects(larger) && c!=cursor;
+                               }
+                               if (!bad) {
+                                       cheapest=cursor;
+                                       lowestcost=cost;
+                               }
+                       }
+               }
+       }
+       if (cheapest>=0) {
+               include(cluster[cheapest],rect);
+               return;
+       }
+
+       if (count < max) {
+               cluster[count++]=rect;
+               return;
+       }
+
+       // Do cheapest of:
+       //      add to closest cluster
+       //      do cheapest cluster merge, add to new cluster
+
+       lowestcost=9999999;
+       cheapest=-1;
+       for (cursor=0; cursor<count; cursor++) {
+               QRect larger=cluster[cursor];
+               include(larger,rect);
+               int cost=larger.width()*larger.height()
+                               - cluster[cursor].width()*cluster[cursor].height();
+               if (cost < lowestcost) {
+                       bool bad=false;
+                       for (int c=0; c<count && !bad; c++) {
+                               bad=cluster[c].intersects(larger) && c!=cursor;
+                       }
+                       if (!bad) {
+                               cheapest=cursor;
+                               lowestcost=cost;
+                       }
+               }
+       }
+
+       // XXX could make an heuristic guess as to whether we
+       // XXX need to bother looking for a cheap merge.
+
+       int cheapestmerge1=-1;
+       int cheapestmerge2=-1;
+
+       for (int merge1=0; merge1<count; merge1++) {
+               for (int merge2=0; merge2<count; merge2++) {
+                       if (merge1!=merge2) {
+                               QRect larger=cluster[merge1];
+                               include(larger,cluster[merge2]);
+                               int cost=larger.width()*larger.height()
+                                       - cluster[merge1].width()*cluster[merge1].height()
+                                       - cluster[merge2].width()*cluster[merge2].height();
+                               if (cost < lowestcost) {
+                                       bool bad=false;
+                                       for (int c=0; c<count && !bad; c++) {
+                                               bad=cluster[c].intersects(larger) && c!=cursor;
+                                       }
+                                       if (!bad) {
+                                               cheapestmerge1=merge1;
+                                               cheapestmerge2=merge2;
+                                               lowestcost=cost;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (cheapestmerge1>=0) {
+               include(cluster[cheapestmerge1],cluster[cheapestmerge2]);
+               cluster[cheapestmerge2]=cluster[count--];
+       } else {
+               // if (!cheapest) debugRectangles(rect);
+               include(cluster[cheapest],rect);
+       }
+
+       // NB: clusters do not intersect (or intersection will
+       //       overwrite).  This is a result of the above algorithm,
+       //       given the assumption that (x,y) are ordered topleft
+       //       to bottomright.
+}
+
+const QRect& Clusterizer::operator[](int i)
+{
+       return cluster[i];
+}
diff --git a/win/Qt4/qt4clust.h b/win/Qt4/qt4clust.h
new file mode 100644 (file)
index 0000000..c7112ea
--- /dev/null
@@ -0,0 +1,29 @@
+/*     SCCS Id: @(#)qt_clust.h 3.4     1999/11/19      */
+/* Copyright (c) Warwick Allison, 1999. */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#ifndef clusterizer_H
+#define clusterizer_H
+
+#include <QtCore/QRect>
+
+class Clusterizer {
+public:
+       Clusterizer(int maxclusters);
+       ~Clusterizer();
+
+       void add(int x, int y); // 1x1 rectangle (point)
+       void add(int x, int y, int w, int h);
+       void add(const QRect& rect);
+
+       void clear();
+       int clusters() { return count; }
+       const QRect& operator[](int i);
+
+private:
+       QRect* cluster;
+       int count;
+       const int max;
+};
+
+#endif
diff --git a/win/Qt4/qt4delay.cpp b/win/Qt4/qt4delay.cpp
new file mode 100644 (file)
index 0000000..eadf42a
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4delay.cpp -- implement a delay
+
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#include "qt4delay.h"
+
+namespace nethack_qt4 {
+
+// RLC Can we use QTimer::single_shot for this?
+NetHackQtDelay::NetHackQtDelay(int ms) :
+    msec(ms), m_timer(0), m_loop(this)
+{
+}
+
+void NetHackQtDelay::wait()
+{
+    m_timer = startTimer(msec);
+    m_loop.exec();
+}
+
+void NetHackQtDelay::timerEvent(QTimerEvent* timer)
+{
+    m_loop.exit();
+    killTimer(m_timer);
+    m_timer = 0;
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4delay.h b/win/Qt4/qt4delay.h
new file mode 100644 (file)
index 0000000..2e0085e
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4delay.h -- implement a delay
+
+#ifndef QT4DELAY_H
+#define QT4DELAY_H
+
+namespace nethack_qt4 {
+
+class NetHackQtDelay : QObject {
+private:
+       int msec;
+    int m_timer;
+    QEventLoop m_loop;
+
+public:
+       NetHackQtDelay(int ms);
+       void wait();
+       virtual void timerEvent(QTimerEvent* timer);
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4glyph.cpp b/win/Qt4/qt4glyph.cpp
new file mode 100644 (file)
index 0000000..942f3a1
--- /dev/null
@@ -0,0 +1,141 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4glyph.cpp -- class to manage the glyphs in a tile set
+
+extern "C" {
+#include "hack.h"
+}
+#include "tile2x11.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4glyph.h"
+#include "qt4set.h"
+#include "qt4str.h"
+
+extern short glyph2tile[]; // from tile.c
+
+namespace nethack_qt4 {
+
+static int tilefile_tile_W=16;
+static int tilefile_tile_H=16;
+
+// Debian uses a separate PIXMAPDIR
+#ifndef PIXMAPDIR
+# ifdef HACKDIR
+#  define PIXMAPDIR HACKDIR
+# else
+#  define PIXMAPDIR "."
+# endif
+#endif
+
+NetHackQtGlyphs::NetHackQtGlyphs()
+{
+    const char* tile_file = PIXMAPDIR "/nhtiles.bmp";
+    if ( iflags.wc_tile_file )
+       tile_file = iflags.wc_tile_file;
+
+    if (!img.load(tile_file)) {
+       tile_file = PIXMAPDIR "/x11tiles";
+       if (!img.load(tile_file)) {
+           QString msg;
+           msg.sprintf("Cannot load x11tiles or nhtiles.bmp");
+           QMessageBox::warning(0, "IO Error", msg);
+       } else {
+           tiles_per_row = TILES_PER_ROW;
+           if (img.width()%tiles_per_row) {
+               impossible("Tile file \"%s\" has %d columns, not multiple of row count (%d)",
+                       tile_file, img.width(), tiles_per_row);
+           }
+       }
+    } else {
+       tiles_per_row = 40;
+    }
+
+    if ( iflags.wc_tile_width )
+       tilefile_tile_W = iflags.wc_tile_width;
+    else
+       tilefile_tile_W = img.width() / tiles_per_row;
+    if ( iflags.wc_tile_height )
+       tilefile_tile_H = iflags.wc_tile_height;
+    else
+       tilefile_tile_H = tilefile_tile_W;
+
+    setSize(tilefile_tile_W, tilefile_tile_H);
+}
+
+void NetHackQtGlyphs::drawGlyph(QPainter& painter, int glyph, int x, int y)
+{
+    int tile = glyph2tile[glyph];
+    int px = (tile%tiles_per_row)*width();
+    int py = tile/tiles_per_row*height();
+
+    painter.drawPixmap(
+       x,
+       y,
+       pm,
+       px,py,
+       width(),height()
+    );
+}
+void NetHackQtGlyphs::drawCell(QPainter& painter, int glyph, int cellx, int celly)
+{
+    drawGlyph(painter,glyph,cellx*width(),celly*height());
+}
+QPixmap NetHackQtGlyphs::glyph(int glyph)
+{
+    int tile = glyph2tile[glyph];
+    int px = (tile%tiles_per_row)*tilefile_tile_W;
+    int py = tile/tiles_per_row*tilefile_tile_H;
+
+    return QPixmap::fromImage(img.copy(px, py, tilefile_tile_W, tilefile_tile_H));
+}
+void NetHackQtGlyphs::setSize(int w, int h)
+{
+    if ( size == QSize(w,h) )
+       return;
+
+    bool was1 = size == pm1.size();
+    size = QSize(w,h);
+    if (!w || !h)
+       return; // Still not decided
+
+    if ( size == pm1.size() ) {
+       pm = pm1;
+       return;
+    }
+    if ( size == pm2.size() ) {
+       pm = pm2;
+       return;
+    }
+
+    if (w==tilefile_tile_W && h==tilefile_tile_H) {
+       pm.convertFromImage(img);
+    } else {
+       QApplication::setOverrideCursor( Qt::WaitCursor );
+       QImage scaled = img.scaled(
+           w*img.width()/tilefile_tile_W,
+           h*img.height()/tilefile_tile_H,
+           Qt::IgnoreAspectRatio,
+           Qt::FastTransformation
+       );
+       pm.convertFromImage(scaled,Qt::ThresholdDither|Qt::PreferDither);
+       QApplication::restoreOverrideCursor();
+    }
+    (was1 ? pm2 : pm1) = pm;
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4glyph.h b/win/Qt4/qt4glyph.h
new file mode 100644 (file)
index 0000000..12fd915
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4glyph.h -- class to manage the glyphs in a tile set
+
+#ifndef QT4GLYPH_H
+#define QT4GLYPH_H
+
+namespace nethack_qt4 {
+
+class NetHackQtGlyphs {
+public:
+       NetHackQtGlyphs();
+
+       int width() const { return size.width(); }
+       int height() const { return size.height(); }
+       void toggleSize();
+       void setSize(int w, int h);
+
+       void drawGlyph(QPainter&, int glyph, int pixelx, int pixely);
+       void drawCell(QPainter&, int glyph, int cellx, int celly);
+       QPixmap glyph(int glyph);
+
+private:
+       QImage img;
+       QPixmap pm,pm1, pm2;
+       QSize size;
+       int tiles_per_row;
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4icon.cpp b/win/Qt4/qt4icon.cpp
new file mode 100644 (file)
index 0000000..0876cb5
--- /dev/null
@@ -0,0 +1,203 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4icon.cpp -- a labelled icon
+
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4icon.h"
+
+namespace nethack_qt4 {
+
+NetHackQtLabelledIcon::NetHackQtLabelledIcon(QWidget* parent, const char* l) :
+    QWidget(parent),
+    low_is_good(false),
+    prev_value(-123),
+    turn_count(-1),
+    label(new QLabel(l,this)),
+    icon(0)
+{
+    initHighlight();
+}
+
+NetHackQtLabelledIcon::NetHackQtLabelledIcon(QWidget* parent, const char* l, const QPixmap& i) :
+    QWidget(parent),
+    low_is_good(false),
+    prev_value(-123),
+    turn_count(-1),
+    label(new QLabel(l,this)),
+    icon(new QLabel(this))
+{
+    setIcon(i);
+    initHighlight();
+}
+
+void NetHackQtLabelledIcon::initHighlight()
+{
+    hl_good = "QLabel { background-color : green; color : white }";
+    hl_bad  = "QLabel { background-color : red  ; color : white }";
+}
+
+void NetHackQtLabelledIcon::setLabel(const QString& t, bool lower)
+{
+    if (!label) {
+       label=new QLabel(this);
+       label->setFont(font());
+       resizeEvent(0);
+    }
+    if (label->text() != t) {
+       label->setText(t);
+       highlight(lower==low_is_good ? hl_good : hl_bad);
+    }
+}
+
+void NetHackQtLabelledIcon::setLabel(const QString& t, long v, long cv, const QString& tail)
+{
+    QString buf;
+    if (v==NoNum) {
+       buf = "";
+    } else {
+       buf.sprintf("%ld", v);
+    }
+    setLabel(t + buf + tail, cv < prev_value);
+    prev_value=cv;
+}
+
+void NetHackQtLabelledIcon::setLabel(const QString& t, long v, const QString& tail)
+{
+    setLabel(t,v,v,tail);
+}
+
+void NetHackQtLabelledIcon::setIcon(const QPixmap& i)
+{
+    if (icon) icon->setPixmap(i);
+    else { icon=new QLabel(this); icon->setPixmap(i); resizeEvent(0); }
+    icon->resize(i.width(),i.height());
+}
+
+void NetHackQtLabelledIcon::setFont(const QFont& f)
+{
+    QWidget::setFont(f);
+    if (label) label->setFont(f);
+}
+
+void NetHackQtLabelledIcon::show()
+{
+#if QT_VERSION >= 300
+    if (isHidden())
+#else
+    if (!isVisible())
+#endif
+       highlight(hl_bad);
+    QWidget::show();
+}
+
+QSize NetHackQtLabelledIcon::sizeHint() const
+{
+    QSize iconsize, textsize;
+
+    if (label && !icon) return label->sizeHint();
+    if (icon && !label) return icon->sizeHint();
+    if (!label && !icon) return QWidget::sizeHint();
+
+    iconsize = icon->sizeHint();
+    textsize = label->sizeHint();
+    return QSize(
+       std::max(iconsize.width(), textsize.width()),
+       iconsize.height() + textsize.height());
+}
+
+QSize NetHackQtLabelledIcon::minimumSizeHint() const
+{
+    QSize iconsize, textsize;
+
+    if (label && !icon) return label->minimumSizeHint();
+    if (icon && !label) return icon->minimumSizeHint();
+    if (!label && !icon) return QWidget::minimumSizeHint();
+
+    iconsize = icon->minimumSizeHint();
+    textsize = label->minimumSizeHint();
+    return QSize(
+       std::max(iconsize.width(), textsize.width()),
+       iconsize.height() + textsize.height());
+}
+
+void NetHackQtLabelledIcon::highlightWhenChanging()
+{
+    turn_count=0;
+}
+
+void NetHackQtLabelledIcon::lowIsGood()
+{
+    low_is_good=true;
+}
+
+void NetHackQtLabelledIcon::dissipateHighlight()
+{
+    if (turn_count>0) {
+       turn_count--;
+       if (!turn_count)
+           unhighlight();
+    }
+}
+
+void NetHackQtLabelledIcon::highlight(const QString& hl)
+{
+    if (label) { // Surely it is?!
+       if (turn_count>=0) {
+           label->setStyleSheet(hl);
+           turn_count=4;
+           // `4' includes this turn, so dissipates after
+           // 3 more keypresses.
+       } else {
+           label->setStyleSheet("");
+       }
+    }
+}
+
+void NetHackQtLabelledIcon::unhighlight()
+{
+    if (label) { // Surely it is?!
+       label->setStyleSheet("");
+    }
+}
+
+void NetHackQtLabelledIcon::resizeEvent(QResizeEvent*)
+{
+    setAlignments();
+
+    //int labw=label ? label->fontMetrics().width(label->text()) : 0;
+    int labh=label ? label->fontMetrics().height() : 0;
+    int icoh=icon ? icon->height() : 0;
+    int h=icoh+labh;
+    int icoy=(h>height() ? height()-labh-icoh : height()/2-h/2);
+    int laby=icoy+icoh;
+    if (icon) {
+       icon->setGeometry(0,icoy,width(),icoh);
+    }
+    if (label) {
+       label->setGeometry(0,laby,width(),labh);
+    }
+}
+
+void NetHackQtLabelledIcon::setAlignments()
+{
+    if (label) label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
+    if (icon) icon->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4icon.h b/win/Qt4/qt4icon.h
new file mode 100644 (file)
index 0000000..bdaf818
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4icon.cpp -- a labelled icon
+
+#ifndef QT4ICON_H
+#define QT4ICON_H
+
+namespace nethack_qt4 {
+
+class NetHackQtLabelledIcon : public QWidget {
+public:
+       NetHackQtLabelledIcon(QWidget* parent, const char* label);
+       NetHackQtLabelledIcon(QWidget* parent, const char* label, const QPixmap& icon);
+
+       enum { NoNum=-99999 };
+       void setLabel(const QString&, bool lower=true); // a string
+       void setLabel(const QString&, long, const QString& tail=""); // a number
+       void setLabel(const QString&, long show_value, long comparative_value, const QString& tail="");
+       void setIcon(const QPixmap&);
+       virtual void setFont(const QFont&);
+
+       void highlightWhenChanging();
+       void lowIsGood();
+       void dissipateHighlight();
+
+       virtual void show();
+       virtual QSize sizeHint() const;
+       virtual QSize minimumSizeHint() const;
+
+protected:
+       void resizeEvent(QResizeEvent*);
+
+private:
+       void initHighlight();
+       void setAlignments();
+       void highlight(const QString& highlight);
+       void unhighlight();
+
+       bool low_is_good;
+       int prev_value;
+       int turn_count;         /* last time the value changed */
+       QString hl_good;
+       QString hl_bad;
+
+       QLabel* label;
+       QLabel* icon;
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4inv.cpp b/win/Qt4/qt4inv.cpp
new file mode 100644 (file)
index 0000000..f753ad0
--- /dev/null
@@ -0,0 +1,99 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4inv.cpp -- inventory usage window
+// This is at the top center of the main window
+
+extern "C" {
+#include "hack.h"
+}
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4inv.h"
+#include "qt4glyph.h"
+#include "qt4set.h"
+
+namespace nethack_qt4 {
+
+NetHackQtInvUsageWindow::NetHackQtInvUsageWindow(QWidget* parent) :
+    QWidget(parent)
+{
+    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+}
+
+void NetHackQtInvUsageWindow::drawWorn(QPainter& painter, obj* nhobj, int x, int y, bool canbe)
+{
+    short int glyph;
+    if (nhobj)
+       glyph=obj_to_glyph(nhobj);
+    else if (canbe)
+       glyph=cmap_to_glyph(S_room);
+    else
+       glyph=cmap_to_glyph(S_stone);
+
+    qt_settings->glyphs().drawCell(painter,glyph,x,y);
+}
+
+void NetHackQtInvUsageWindow::paintEvent(QPaintEvent*)
+{
+    //  012
+    //
+    //0 WhB   
+    //1 s"w   
+    //2 gCg   
+    //3 =A=   
+    //4  T    
+    //5  S    
+
+    QPainter painter;
+    painter.begin(this);
+
+    // Blanks
+    drawWorn(painter,0,0,4,false);
+    drawWorn(painter,0,0,5,false);
+    drawWorn(painter,0,2,4,false);
+    drawWorn(painter,0,2,5,false);
+
+    drawWorn(painter,uarm,1,3); // Armour
+    drawWorn(painter,uarmc,1,2); // Cloak
+    drawWorn(painter,uarmh,1,0); // Helmet
+    drawWorn(painter,uarms,0,1); // Shield
+    drawWorn(painter,uarmg,0,2); // Gloves - repeated
+    drawWorn(painter,uarmg,2,2); // Gloves - repeated
+    drawWorn(painter,uarmf,1,5); // Shoes (feet)
+    drawWorn(painter,uarmu,1,4); // Undershirt
+    drawWorn(painter,uleft,0,3); // RingL
+    drawWorn(painter,uright,2,3); // RingR
+
+    drawWorn(painter,uwep,2,1); // Weapon
+    drawWorn(painter,uswapwep,0,0); // Secondary weapon
+    drawWorn(painter,uamul,1,1); // Amulet
+    drawWorn(painter,ublindf,2,0); // Blindfold
+
+    painter.end();
+}
+
+QSize NetHackQtInvUsageWindow::sizeHint(void) const
+{
+    if (qt_settings) {
+       return QSize(qt_settings->glyphs().width()*3,
+                    qt_settings->glyphs().height()*6);
+    } else {
+       return QWidget::sizeHint();
+    }
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4inv.h b/win/Qt4/qt4inv.h
new file mode 100644 (file)
index 0000000..51cdd4d
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4inv.h -- inventory usage window
+// This is at the top center of the main window
+
+#ifndef QT4INV_H
+#define QT4INV_H
+
+namespace nethack_qt4 {
+
+class NetHackQtInvUsageWindow : public QWidget {
+public:
+       NetHackQtInvUsageWindow(QWidget* parent);
+       virtual void paintEvent(QPaintEvent*);
+       virtual QSize sizeHint(void) const;
+
+private:
+       void drawWorn(QPainter& painter, obj*, int x, int y, bool canbe=true);
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4kde0.h b/win/Qt4/qt4kde0.h
new file mode 100644 (file)
index 0000000..27a678c
--- /dev/null
@@ -0,0 +1,14 @@
+/*     SCCS Id: @(#)qt_kde0.h  3.4     1999/11/19      */
+/* Copyright (c) Warwick Allison, 1999. */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#ifndef QT_DUMMYKDE
+#define QT_DUMMYKDE
+namespace nethack_qt4 {
+
+class KTopLevelWidget : public QMainWindow {
+        Q_OBJECT
+};
+
+}
+#endif
diff --git a/win/Qt4/qt4key.cpp b/win/Qt4/qt4key.cpp
new file mode 100644 (file)
index 0000000..ff16616
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4key.cpp -- a key buffer
+
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#include "qt4key.h"
+
+namespace nethack_qt4 {
+
+NetHackQtKeyBuffer::NetHackQtKeyBuffer() :
+    in(0), out(0)
+{
+}
+
+bool NetHackQtKeyBuffer::Empty() const { return in==out; }
+bool NetHackQtKeyBuffer::Full() const { return (in+1)%maxkey==out; }
+
+void NetHackQtKeyBuffer::Put(int k, int a, int state)
+{
+    if ( Full() ) return;      // Safety
+    key[in]=k;
+    ascii[in]=a;
+    in=(in+1)%maxkey;
+}
+
+void NetHackQtKeyBuffer::Put(char a)
+{
+    Put(0,a,0);
+}
+
+void NetHackQtKeyBuffer::Put(const char* str)
+{
+    while (*str) Put(*str++);
+}
+
+int NetHackQtKeyBuffer::GetKey()
+{
+    if ( Empty() ) return 0;
+    int r=TopKey();
+    out=(out+1)%maxkey;
+    return r;
+}
+
+int NetHackQtKeyBuffer::GetAscii()
+{
+    if ( Empty() ) return 0; // Safety
+    int r=TopAscii();
+    out=(out+1)%maxkey;
+    return r;
+}
+
+Qt::KeyboardModifiers NetHackQtKeyBuffer::GetState()
+{
+    if ( Empty() ) return 0;
+    Qt::KeyboardModifiers r=TopState();
+    out=(out+1)%maxkey;
+    return r;
+}
+
+int NetHackQtKeyBuffer::TopKey() const
+{
+    if ( Empty() ) return 0;
+    return key[out];
+}
+
+int NetHackQtKeyBuffer::TopAscii() const
+{
+    if ( Empty() ) return 0;
+    return ascii[out];
+}
+
+Qt::KeyboardModifiers NetHackQtKeyBuffer::TopState() const
+{
+    if ( Empty() ) return 0;
+    return state[out];
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4key.h b/win/Qt4/qt4key.h
new file mode 100644 (file)
index 0000000..0333269
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4key.h -- a key buffer
+
+#ifndef QT4KEY_H
+#define QT4KEY_H
+
+namespace nethack_qt4 {
+
+class NetHackQtKeyBuffer {
+public:
+       NetHackQtKeyBuffer();
+
+       bool Empty() const;
+       bool Full() const;
+
+       void Put(int k, int ascii, int state);
+       void Put(char a);
+       void Put(const char* str);
+       int GetKey();
+       int GetAscii();
+       Qt::KeyboardModifiers GetState();
+
+       int TopKey() const;
+       int TopAscii() const;
+       Qt::KeyboardModifiers TopState() const;
+
+private:
+       enum { maxkey=64 };
+       int key[maxkey];
+       int ascii[maxkey];
+       Qt::KeyboardModifiers state[maxkey];
+       int in,out;
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4line.cpp b/win/Qt4/qt4line.cpp
new file mode 100644 (file)
index 0000000..dd9b18c
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4line.cpp -- a one line input window
+
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4line.h"
+
+namespace nethack_qt4 {
+
+NetHackQtLineEdit::NetHackQtLineEdit() :
+    QLineEdit(0)
+{
+}
+
+NetHackQtLineEdit::NetHackQtLineEdit(QWidget* parent, const char* name) :
+    QLineEdit(parent)
+{
+}
+
+void NetHackQtLineEdit::fakeEvent(int key, int ascii, Qt::KeyboardModifiers state)
+{
+    QKeyEvent fake(QEvent::KeyPress,key,state,QChar(ascii));
+    keyPressEvent(&fake);
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4line.h b/win/Qt4/qt4line.h
new file mode 100644 (file)
index 0000000..bb5067f
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4line.h -- a one line input window
+
+#ifndef QT4LINE_H
+#define QT4LINE_H
+
+namespace nethack_qt4 {
+
+class NetHackQtLineEdit : public QLineEdit {
+public:
+       NetHackQtLineEdit();
+       NetHackQtLineEdit(QWidget* parent, const char* name);
+
+       void fakeEvent(int key, int ascii, Qt::KeyboardModifiers state);
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4main.cpp b/win/Qt4/qt4main.cpp
new file mode 100644 (file)
index 0000000..4fd8d14
--- /dev/null
@@ -0,0 +1,1072 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4main.cpp -- the main window
+
+extern "C" {
+#include "hack.h"
+}
+#include "patchlevel.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4main.h"
+#include "qt4main.moc"
+#include "qt4bind.h"
+#include "qt4glyph.h"
+#include "qt4inv.h"
+#include "qt4key.h"
+#include "qt4map.h"
+#include "qt4msg.h"
+#include "qt4set.h"
+#include "qt4stat.h"
+#include "qt4str.h"
+
+#ifndef KDE
+#include "qt4kde0.moc"
+#endif
+
+// temporary
+extern char *qt_tilewidth;
+extern char *qt_tileheight;
+extern int qt_compact_mode;
+// end temporary
+
+namespace nethack_qt4 {
+
+// temporary
+void centerOnMain( QWidget* w );
+// end temporary
+
+/* XPM */
+static const char * nh_icon[] = {
+"40 40 6 1",
+"      s None c none",
+".     c #ffffff",
+"X     c #dadab6",
+"o     c #6c91b6",
+"O     c #476c6c",
+"+     c #000000",
+"                                        ",
+"                                        ",
+"                                        ",
+"        .      .X..XX.XX      X         ",
+"        ..   .....X.XXXXXX   XX         ",
+"        ... ....X..XX.XXXXX XXX         ",
+"   ..   ..........X.XXXXXXXXXXX   XX    ",
+"   .... ........X..XX.XXXXXXXXX XXXX    ",
+"   .... ..........X.XXXXXXXXXXX XXXX    ",
+"   ooOOO..ooooooOooOOoOOOOOOOXX+++OO++  ",
+"   ooOOO..ooooooooOoOOOOOOOOOXX+++OO++  ",
+"   ....O..ooooooOooOOoOOOOOOOXX+XXXX++  ",
+"   ....O..ooooooooOoOOOOOOOOOXX+XXXX++  ",
+"   ..OOO..ooooooOooOOoOOOOOOOXX+++XX++  ",
+"    ++++..ooooooooOoOOOOOOOOOXX+++ +++  ",
+"     +++..ooooooOooOOoOOOOOOOXX+++  +   ",
+"      ++..ooooooooOoOOOOOOOOOXX+++      ",
+"        ..ooooooOooOOoOOOOOOOXX+++      ",
+"        ..ooooooooOoOOOOOOOOOXX+++      ",
+"        ..ooooooOooOOoOOOOOOOXX+++      ",
+"        ..ooooooooOoOOOOOOOOOXX+++      ",
+"         ..oooooOooOOoOOOOOOXX+++       ",
+"         ..oooooooOoOOOOOOOOXX+++       ",
+"          ..ooooOooOOoOOOOOXX+++        ",
+"          ..ooooooOoOOOOOOOXX++++       ",
+"        ..o..oooOooOOoOOOOXX+XX+++      ",
+"       ...o..oooooOoOOOOOXX++XXX++      ",
+"      ....OO..ooOooOOoOOXX+++XXXX++     ",
+"     ...oo..+..oooOoOOOXX++XXooXXX++    ",
+"    ...ooo..++..OooOOoXX+++XXooOXXX+    ",
+"   ..oooOOXX+++....XXXX++++XXOOoOOXX+   ",
+"   ..oooOOXX+++ ...XXX+++++XXOOooOXX++  ",
+"   ..oooOXXX+++  ..XX+++  +XXOOooOXX++  ",
+"   .....XXX++++             XXXXXXX++   ",
+"    ....XX++++              XXXXXXX+    ",
+"     ...XX+++                XXXXX++    ",
+"                                        ",
+"                                        ",
+"                                        ",
+"                                        "};
+/* XPM */
+static const char * nh_icon_small[] = {
+/* width height ncolors chars_per_pixel */
+"16 16 16 1",
+/* colors */
+"  c #587070",
+". c #D1D5C9",
+"X c #8B8C84",
+"o c #2A2A28",
+"O c #9AABA9",
+"+ c #6A8FB2",
+"@ c #C4CAC4",
+"# c #B6BEB6",
+"$ c None",
+"% c #54564E",
+"& c #476C6C",
+"* c #ADB2AB",
+"= c #ABABA2",
+"- c #5E8295",
+"; c #8B988F",
+": c #E8EAE7",
+/* pixels */
+"$$$$$$$$$$$$$$$$",
+"$$$.$#::.#==*$$$",
+"$.*:::::....#*=$",
+"$@#:..@#*==#;XX;",
+"$@O:+++- &&; X%X",
+"$#%.+++- &&;% oX",
+"$$o.++-- &&;%%X$",
+"$$$:++-- &&;%%$$",
+"$$$.O++- &&=o $$",
+"$$$=:++- & XoX$$",
+"$$*:@O--  ;%Xo$$",
+"$*:O#$+--;oOOX $",
+"$:+ =o::=oo=-;%X",
+"$::.%o$*;X;##@%$",
+"$$@# ;$$$$$=*;X$",
+"$$$$$$$$$$$$$$$$"
+};
+
+#if 0 // RLC
+/* XPM */
+static const char * map_xpm[] = {
+"12 13 4 1",
+".     c None",
+"      c #000000000000",
+"X     c #0000B6DAFFFF",
+"o     c #69A69248B6DA",
+"           .",
+" XXXXX ooo  ",
+" XoooX o    ",
+" XoooX o o  ",
+" XoooX ooo  ",
+" XXoXX o    ",
+"  oooooXXX  ",
+" oo o oooX  ",
+"    o XooX  ",
+" oooo XooX  ",
+" o  o XXXX  ",
+"            ",
+".           "};
+/* XPM */
+static const char * msg_xpm[] = {
+"12 13 4 1",
+".     c None",
+"      c #FFFFFFFFFFFF",
+"X     c #69A69248B6DA",
+"o     c #000000000000",
+"           .",
+" XXX XXX X o",
+"           o",
+" XXXXX XX  o",
+"           o",
+" XX XXXXX  o",
+"           o",
+" XXXXXX    o",
+"           o",
+" XX XXX XX o",
+"           o",
+"           o",
+".ooooooooooo"};
+/* XPM */
+static const char * stat_xpm[] = {
+"12 13 5 1",
+"  c None",
+".     c #FFFF00000000",
+"X     c #000000000000",
+"o     c #FFFFFFFF0000",
+"O     c #69A6FFFF0000",
+"            ",
+"            ",
+"...         ",
+"...X        ",
+"...X    ... ",
+"oooX    oooX",
+"oooXooo oooX",
+"OOOXOOOXOOOX",
+"OOOXOOOXOOOX",
+"OOOXOOOXOOOX",
+"OOOXOOOXOOOX",
+"OOOXOOOXOOOX",
+" XXXXXXXXXXX"};
+#endif
+/* XPM */
+static const char * info_xpm[] = {
+"12 13 4 1",
+"  c None",
+".     c #00000000FFFF",
+"X     c #FFFFFFFFFFFF",
+"o     c #000000000000",
+"    ...     ",
+"  .......   ",
+" ...XXX...  ",
+" .........o ",
+"...XXXX.... ",
+"....XXX....o",
+"....XXX....o",
+"....XXX....o",
+" ...XXX...oo",
+" ..XXXXX..o ",
+"  .......oo ",
+"   o...ooo  ",
+"     ooo    "};
+
+
+/* XPM */
+static const char * again_xpm[] = {
+"12 13 2 1",
+"      c None",
+".     c #000000000000",
+"    ..      ",
+"     ..     ",
+"   .....    ",
+" .......    ",
+"...  ..  .. ",
+"..  ..   .. ",
+"..        ..",
+"..        ..",
+"..        ..",
+" ..      .. ",
+" .......... ",
+"   ......   ",
+"            "};
+/* XPM */
+static const char * kick_xpm[] = {
+"12 13 3 1",
+"      c None",
+".     c #000000000000",
+"X     c #FFFF6DB60000",
+"            ",
+"            ",
+"   .  .  .  ",
+"  ...  .  . ",
+"   ...  .   ",
+"    ...  .  ",
+"     ...    ",
+"XXX   ...   ",
+"XXX.  ...   ",
+"XXX. ...    ",
+"XXX. ..     ",
+" ...        ",
+"            "};
+/* XPM */
+static const char * throw_xpm[] = {
+"12 13 3 1",
+"      c None",
+".     c #FFFF6DB60000",
+"X     c #000000000000",
+"            ",
+"            ",
+"            ",
+"            ",
+"....     X  ",
+"....X     X ",
+"....X XXXXXX",
+"....X     X ",
+" XXXX    X  ",
+"            ",
+"            ",
+"            ",
+"            "};
+/* XPM */
+static const char * fire_xpm[] = {
+"12 13 5 1",
+"      c None",
+".     c #B6DA45140000",
+"X     c #FFFFB6DA9658",
+"o     c #000000000000",
+"O     c #FFFF6DB60000",
+" .          ",
+" X.         ",
+" X .        ",
+" X .o       ",
+" X  .    o  ",
+" X  .o    o ",
+"OOOOOOOOoooo",
+" X  .o    o ",
+" X . o   o  ",
+" X .o       ",
+" X. o       ",
+" . o        ",
+"  o         "};
+/* XPM */
+static const char * get_xpm[] = {
+"12 13 3 1",
+"      c None",
+".     c #000000000000",
+"X     c #FFFF6DB60000",
+"            ",
+"     .      ",
+"    ...     ",
+"   . . .    ",
+"     .      ",
+"     .      ",
+"            ",
+"   XXXXX    ",
+"   XXXXX.   ",
+"   XXXXX.   ",
+"   XXXXX.   ",
+"    .....   ",
+"            "};
+/* XPM */
+static const char * drop_xpm[] = {
+"12 13 3 1",
+"      c None",
+".     c #FFFF6DB60000",
+"X     c #000000000000",
+"            ",
+"   .....    ",
+"   .....X   ",
+"   .....X   ",
+"   .....X   ",
+"    XXXXX   ",
+"            ",
+"      X     ",
+"      X     ",
+"    X X X   ",
+"     XXX    ",
+"      X     ",
+"            "};
+/* XPM */
+static const char * eat_xpm[] = {
+"12 13 4 1",
+"      c None",
+".     c #000000000000",
+"X     c #FFFFB6DA9658",
+"o     c #FFFF6DB60000",
+"  .X.  ..   ",
+"  .X.  ..   ",
+"  .X.  ..   ",
+"  .X.  ..   ",
+"  ...  ..   ",
+"   ..  ..   ",
+"   ..  ..   ",
+"   oo  oo   ",
+"   oo  oo   ",
+"   oo  oo   ",
+"   oo  oo   ",
+"   oo  oo   ",
+"   oo  oo   "};
+/* XPM */
+static const char * rest_xpm[] = {
+"12 13 2 1",
+"      c None",
+".     c #000000000000",
+"  .....     ",
+"     .      ",
+"    .       ",
+"   .    ....",
+"  .....   . ",
+"         .  ",
+"        ....",
+"            ",
+"     ....   ",
+"       .    ",
+"      .     ",
+"     ....   ",
+"            "};
+/* XPM */
+static const char * cast_a_xpm[] = {
+"12 13 3 1",
+"      c None",
+".     c #FFFF6DB60000",
+"X     c #000000000000",
+"    .       ",
+"    .       ",
+"   ..       ",
+"   ..       ",
+"  ..  .     ",
+"  ..  .     ",
+" ......     ",
+" .. ..  XX  ",
+"    .. X  X ",
+"   ..  X  X ",
+"   ..  XXXX ",
+"   .   X  X ",
+"   .   X  X "};
+/* XPM */
+static const char * cast_b_xpm[] = {
+"12 13 3 1",
+"      c None",
+".     c #FFFF6DB60000",
+"X     c #000000000000",
+"    .       ",
+"    .       ",
+"   ..       ",
+"   ..       ",
+"  ..  .     ",
+"  ..  .     ",
+" ......     ",
+" .. .. XXX  ",
+"    .. X  X ",
+"   ..  XXX  ",
+"   ..  X  X ",
+"   .   X  X ",
+"   .   XXX  "};
+/* XPM */
+static const char * cast_c_xpm[] = {
+"12 13 3 1",
+"      c None",
+".     c #FFFF6DB60000",
+"X     c #000000000000",
+"    .       ",
+"    .       ",
+"   ..       ",
+"   ..       ",
+"  ..  .     ",
+"  ..  .     ",
+" ......     ",
+" .. ..  XX  ",
+"    .. X  X ",
+"   ..  X    ",
+"   ..  X    ",
+"   .   X  X ",
+"   .    XX  "};
+
+static QString
+aboutMsg()
+{
+    QString msg;
+    msg.sprintf(
+    "Qt NetHack is a version of NetHack built\n"
+#ifdef KDE
+    "using KDE and the Qt GUI toolkit.\n"
+#else
+    "using the Qt GUI toolkit.\n"
+#endif
+    "This is version %d.%d.%d\n\n"
+    "Homepage:\n     http://trolls.troll.no/warwick/nethack/\n\n"
+#ifdef KDE
+         "KDE:\n     http://www.kde.org\n"
+#endif
+         "Qt:\n     http://www.troll.no",
+       VERSION_MAJOR,
+       VERSION_MINOR,
+       PATCHLEVEL);
+    return msg;
+}
+
+class SmallToolButton : public QToolButton {
+public:
+    SmallToolButton(const QPixmap & pm, const QString &textLabel,
+                 const QString& grouptext,
+                 QObject * receiver, const char* slot,
+                 QWidget * parent) :
+       QToolButton(parent)
+    {
+       setIcon(QIcon(pm));
+       setToolTip(textLabel);
+       setStatusTip(grouptext);
+       connect(this, SIGNAL(clicked(bool)), receiver, slot);
+    }
+
+    QSize sizeHint() const
+    {
+       // get just a couple more pixels for the map
+       return QToolButton::sizeHint()-QSize(0,2);
+    }
+};
+
+NetHackQtMainWindow::NetHackQtMainWindow(NetHackQtKeyBuffer& ks) :
+    message(0), map(0), status(0), invusage(0),
+    hsplitter(0), vsplitter(0),
+    keysink(ks), dirkey(0)
+{
+    QToolBar* toolbar = new QToolBar(this);
+    toolbar->setMovable(false);
+    toolbar->setFocusPolicy(Qt::NoFocus);
+    addToolBar(toolbar);
+    menubar = menuBar();
+
+    setWindowTitle("Qt NetHack");
+    if ( qt_compact_mode )
+       setWindowIcon(QIcon(QPixmap(nh_icon_small)));
+    else
+       setWindowIcon(QIcon(QPixmap(nh_icon)));
+
+    QMenu* game=new QMenu;
+    QMenu* apparel=new QMenu;
+    QMenu* act1=new QMenu;
+    QMenu* act2 = qt_compact_mode ? new QMenu : act1;
+    QMenu* magic=new QMenu;
+    QMenu* info=new QMenu;
+
+    QMenu *help;
+
+#ifdef KDE
+    help = kapp->getHelpMenu( true, "" );
+    help->addSeparator();
+#else
+    help = qt_compact_mode ? info : new QMenu;
+#endif
+
+    enum { OnDesktop=1, OnHandhelds=2 };
+    struct Macro {
+       QMenu* menu;
+       const char* name;
+       int flags;
+        int NDECL((*funct));
+    } item[] = {
+        { game,    0, 3},
+        { game,    "Version",            3, doversion},
+        { game,    "Compilation",        3, doextversion},
+        { game,    "History",            3, dohistory},
+        { game,    "Redraw",             0, doredraw}, // useless
+        { game,    "Options",            3, doset},
+        { game,    "Explore mode",       3, enter_explore_mode},
+        { game,    0, 3},
+        { game,    "Save",               3, dosave},
+        { game,    "Quit",               3, done2},
+
+        { apparel, "Apparel off",        2, doddoremarm},
+        { apparel, "Remove many",        1, doddoremarm},
+        { apparel, 0, 3},
+        { apparel, "Wield weapon",       3, dowield},
+        { apparel, "Exchange weapons",   3, doswapweapon},
+        { apparel, "Two weapon combat",  3, dotwoweapon},
+        { apparel, "Load quiver",        3, dowieldquiver},
+        { apparel, 0, 3},
+        { apparel, "Wear armour",        3, dowear},
+        { apparel, "Take off armour",    3, dotakeoff},
+        { apparel, 0, 3},
+        { apparel, "Put on non-armour",  3, doputon},
+        { apparel, "Remove non-armour",  3, doremring},
+
+        /* { act1,      "Again\tCtrl+A",           "\001", 2},
+        { act1, 0, 0, 3}, */
+        { act1, "Apply",             3, doapply},
+        { act1, "Chat",              3, dotalk},
+        { act1, "Close door",        3, doclose},
+        { act1, "Down",              3, dodown},
+        { act1, "Drop many",         2, doddrop},
+        { act1, "Drop",              2, dodrop},
+        { act1, "Eat",               2, doeat},
+        { act1, "Engrave",           3, doengrave},
+        /* { act1,      "Fight\tShift+F",             "F", 3}, */
+        { act1, "Fire from quiver",  2, dofire},
+        { act1, "Force",             3, doforce},
+        { act1, "Get",               2, dopickup},
+        { act1, "Jump",              3, dojump},
+        { act2, "Kick",              2, dokick},
+        { act2, "Loot",              3, doloot},
+        { act2, "Open door",         3, doopen},
+        { act2, "Pay",               3, dopay},
+        { act2, "Rest",              2, donull},
+        { act2, "Ride",              3, doride},
+        { act2, "Search",            3, dosearch},
+        { act2, "Sit",               3, dosit},
+        { act2, "Throw",             2, dothrow},
+        { act2, "Untrap",            3, dountrap},
+        { act2, "Up",                3, doup},
+        { act2, "Wipe face",         3, dowipe},
+
+        { magic, "Quaff potion",     3, dodrink},
+        { magic, "Read scroll/book", 3, doread},
+        { magic, "Zap wand",         3, dozap},
+        { magic, "Zap spell",        3, docast},
+        { magic, "Dip",              3, dodip},
+        { magic, "Rub",              3, dorub},
+        { magic, "Invoke",           3, doinvoke},
+        { magic, 0, 3},
+        { magic, "Offer",            3, dosacrifice},
+        { magic, "Pray",             3, dopray},
+        { magic, 0, 3},
+        { magic, "Teleport",         3, dotele},
+        { magic, "Monster action",   3, domonability},
+        { magic, "Turn undead",      3, doturn},
+
+        { help,  "Help",             3, dohelp},
+        { help,  0, 3},
+        { help,  "What is here",     3, dolook},
+        { help,  "What is there",    3, doquickwhatis},
+        { help,  "What is...",       2, dowhatis},
+        { help,  0, 1},
+
+        { info,  "Inventory",        3, ddoinv},
+        { info,  "Conduct",          3, doconduct},
+        { info,  "Discoveries",      3, dodiscovered},
+        { info,  "List/reorder spells",  3, dovspell},
+        { info,  "Adjust letters",   2, doorganize},
+        { info,  0, 3},
+        { info,  "Name object or creature", 3, docallcmd},
+        { info,  0, 3},
+        { info,  "Skills",  3, enhance_weapon_skill},
+
+       { 0, 0, 0 }
+    };
+
+    int i;
+
+    game->addAction("Qt settings...",this,SLOT(doQtSettings(bool)));
+    help->addAction("About Qt NetHack...",this,SLOT(doAbout(bool)));
+    //help->addAction("NetHack Guidebook...",this,SLOT(doGuidebook(bool)));
+    help->addSeparator();
+
+    for (i=0; item[i].menu; i++) {
+       if ( item[i].flags & (qt_compact_mode ? 1 : 2) ) {
+           if (item[i].name) {
+                char actchar[32];
+                char menuitem[BUFSZ];
+                actchar[0] = '\0';
+                if (item[i].funct) {
+                    actchar[0] = cmd_from_func(item[i].funct);
+                    actchar[1] = '\0';
+                }
+                if (actchar[0] && !qt_compact_mode)
+                    Sprintf(menuitem, "%s\t%s", item[i].name,
+                            visctrl(actchar[0]));
+                else
+                    Sprintf(menuitem, "%s", item[i].name);
+                if (actchar[0]) {
+                    QString name = menuitem;
+                    QAction *action = item[i].menu->addAction(name);
+                    action->setData(actchar);
+                }
+           } else {
+               item[i].menu->addSeparator();
+           }
+       }
+    }
+
+    game->setTitle("Game");
+    menubar->addMenu(game);
+    apparel->setTitle("Gear");
+    menubar->addMenu(apparel);
+
+    if ( qt_compact_mode ) {
+       act1->setTitle("A-J");
+       menubar->addMenu(act1);
+       act2->setTitle("K-Z");
+       menubar->addMenu(act2);
+       magic->setTitle("Magic");
+       menubar->addMenu(magic);
+       info->setIcon(QIcon(QPixmap(info_xpm)));
+       info->setTitle("Info");
+       menubar->addMenu(info);
+       //menubar->insertItem(QPixmap(map_xpm), this, SLOT(raiseMap()));
+       //menubar->insertItem(QPixmap(msg_xpm), this, SLOT(raiseMessages()));
+       //menubar->insertItem(QPixmap(stat_xpm), this, SLOT(raiseStatus()));
+       info->addSeparator();
+       info->addAction("Map", this, SLOT(raiseMap()));
+       info->addAction("Messages", this, SLOT(raiseMessages()));
+       info->addAction("Status", this, SLOT(raiseStatus()));
+    } else {
+       act1->setTitle("Action");
+       menubar->addMenu(act1);
+       magic->setTitle("Magic");
+       menubar->addMenu(magic);
+       info->setTitle("Info");
+       menubar->addMenu(info);
+       menubar->addSeparator();
+       help->setTitle("Help");
+       menubar->addMenu(help);
+    }
+
+    QSignalMapper* sm = new QSignalMapper(this);
+    connect(sm, SIGNAL(mapped(const QString&)), this, SLOT(doKeys(const QString&)));
+    QToolButton* tb;
+    char actchar[32];
+    tb = new SmallToolButton( QPixmap(again_xpm),"Again","Action", sm, SLOT(map()), toolbar );
+    Sprintf(actchar, "%c", Cmd.spkeys[NHKF_DOAGAIN]);
+    sm->setMapping(tb, actchar );
+    toolbar->addWidget(tb);
+    tb = new SmallToolButton( QPixmap(get_xpm),"Get","Action", sm, SLOT(map()), toolbar );
+    Sprintf(actchar, "%c", cmd_from_func(dopickup));
+    sm->setMapping(tb, actchar );
+    toolbar->addWidget(tb);
+    tb = new SmallToolButton( QPixmap(kick_xpm),"Kick","Action", sm, SLOT(map()), toolbar );
+    Sprintf(actchar, "%c", cmd_from_func(dokick));
+    sm->setMapping(tb, actchar );
+    toolbar->addWidget(tb);
+    tb = new SmallToolButton( QPixmap(throw_xpm),"Throw","Action", sm, SLOT(map()), toolbar );
+    Sprintf(actchar, "%c", cmd_from_func(dothrow));
+    sm->setMapping(tb, actchar );
+    toolbar->addWidget(tb);
+    tb = new SmallToolButton( QPixmap(fire_xpm),"Fire","Action", sm, SLOT(map()), toolbar );
+    Sprintf(actchar, "%c", cmd_from_func(dofire));
+    sm->setMapping(tb, actchar );
+    toolbar->addWidget(tb);
+    tb = new SmallToolButton( QPixmap(drop_xpm),"Drop","Action", sm, SLOT(map()), toolbar );
+    Sprintf(actchar, "%c", cmd_from_func(doddrop));
+    sm->setMapping(tb, actchar );
+    toolbar->addWidget(tb);
+    tb = new SmallToolButton( QPixmap(eat_xpm),"Eat","Action", sm, SLOT(map()), toolbar );
+    Sprintf(actchar, "%c", cmd_from_func(doeat));
+    sm->setMapping(tb, actchar );
+    toolbar->addWidget(tb);
+    tb = new SmallToolButton( QPixmap(rest_xpm),"Rest","Action", sm, SLOT(map()), toolbar );
+    Sprintf(actchar, "%c", cmd_from_func(donull));
+    sm->setMapping(tb, actchar );
+    toolbar->addWidget(tb);
+
+    connect(game,SIGNAL(triggered(QAction *)),this,SLOT(doMenuItem(QAction *)));
+    connect(apparel,SIGNAL(triggered(QAction *)),this,SLOT(doMenuItem(QAction *)));
+    connect(act1,SIGNAL(triggered(QAction *)),this,SLOT(doMenuItem(QAction *)));
+    if (act2 != act1)
+       connect(act2,SIGNAL(triggered(QAction *)),this,SLOT(doMenuItem(QAction *)));
+    connect(magic,SIGNAL(triggered(QAction *)),this,SLOT(doMenuItem(QAction *)));
+    connect(info,SIGNAL(triggered(QAction *)),this,SLOT(doMenuItem(QAction *)));
+    connect(help,SIGNAL(triggered(QAction *)),this,SLOT(doMenuItem(QAction *)));
+
+#ifdef KDE
+    setMenu (menubar);
+#endif
+
+    int x=0,y=0;
+    int w=QApplication::desktop()->width()-10; // XXX arbitrary extra space for frame
+    int h=QApplication::desktop()->height()-50;
+
+    int maxwn;
+    int maxhn;
+    if (qt_tilewidth != NULL) {
+       maxwn = atoi(qt_tilewidth) * COLNO + 10;
+    } else {
+       maxwn = 1400;
+    }
+    if (qt_tileheight != NULL) {
+       maxhn = atoi(qt_tileheight) * ROWNO * 6/4;
+    } else {
+       maxhn = 1024;
+    }
+
+    // Be exactly the size we want to be - full map...
+    if (w>maxwn) {
+       x+=(w-maxwn)/2;
+       w=maxwn; // Doesn't need to be any wider
+    }
+    if (h>maxhn) {
+       y+=(h-maxhn)/2;
+       h=maxhn; // Doesn't need to be any taller
+    }
+
+    setGeometry(x,y,w,h);
+
+    if ( qt_compact_mode ) {
+       stack = new QStackedWidget(this);
+       setCentralWidget(stack);
+    } else {
+       vsplitter = new QSplitter(Qt::Vertical);
+       setCentralWidget(vsplitter);
+       hsplitter = new QSplitter(Qt::Horizontal);
+       invusage = new NetHackQtInvUsageWindow(hsplitter);
+       vsplitter->insertWidget(0, hsplitter);
+       hsplitter->insertWidget(1, invusage);
+    }
+}
+
+void NetHackQtMainWindow::zoomMap()
+{
+    qt_settings->toggleGlyphSize();
+}
+
+void NetHackQtMainWindow::raiseMap()
+{
+    if ( stack->currentWidget() == map->Widget() ) {
+       zoomMap();
+    } else {
+       stack->setCurrentWidget(map->Widget());
+    }
+}
+
+void NetHackQtMainWindow::raiseMessages()
+{
+    stack->setCurrentWidget(message->Widget());
+}
+
+void NetHackQtMainWindow::raiseStatus()
+{
+    stack->setCurrentWidget(status->Widget());
+}
+
+#if 0 // RLC this isn't used
+class NetHackMimeSourceFactory : public Q3MimeSourceFactory {
+public:
+    const QMimeSource* data(const QString& abs_name) const
+    {
+       const QMimeSource* r = 0;
+       if ( (NetHackMimeSourceFactory*)this == Q3MimeSourceFactory::defaultFactory() )
+           r = Q3MimeSourceFactory::data(abs_name);
+       else
+           r = Q3MimeSourceFactory::defaultFactory()->data(abs_name);
+       if ( !r ) {
+           int sl = abs_name.length();
+           do {
+               sl = abs_name.lastIndexOf('/',sl-1);
+               QString name = sl>=0 ? abs_name.mid(sl+1) : abs_name;
+               int dot = name.lastIndexOf('.');
+               if ( dot >= 0 )
+                   name = name.left(dot);
+               if ( name == "map" )
+                   r = new Q3ImageDrag(QImage(map_xpm));
+               else if ( name == "msg" )
+                   r = new Q3ImageDrag(QImage(msg_xpm));
+               else if ( name == "stat" )
+                   r = new Q3ImageDrag(QImage(stat_xpm));
+           } while (!r && sl>0);
+       }
+       return r;
+    }
+};
+#endif
+
+void NetHackQtMainWindow::doMenuItem(QAction *action)
+{
+    doKeys(action->data().toString());
+}
+
+void NetHackQtMainWindow::doQtSettings(bool)
+{
+    centerOnMain(qt_settings);
+    qt_settings->show();
+}
+
+void NetHackQtMainWindow::doAbout(bool)
+{
+    QMessageBox::about(this, "About Qt NetHack", aboutMsg());
+}
+
+#if 0 // RLC this isn't used
+void NetHackQtMainWindow::doGuidebook(bool)
+{
+    QDialog dlg(this);
+    new QVBoxLayout(&dlg);
+    Q3TextBrowser browser(&dlg);
+    NetHackMimeSourceFactory ms;
+    browser.setMimeSourceFactory(&ms);
+    browser.setSource(QDir::currentPath()+"/Guidebook.html");
+    if ( qt_compact_mode )
+       dlg.showMaximized();
+    dlg.exec();
+}
+#endif
+
+void NetHackQtMainWindow::doKeys(const QString& k)
+{
+    keysink.Put(k.toLatin1().constData());
+    qApp->exit();
+}
+
+void NetHackQtMainWindow::AddMessageWindow(NetHackQtMessageWindow* window)
+{
+    message=window;
+    if (!qt_compact_mode)
+        hsplitter->insertWidget(0, message->Widget());
+    ShowIfReady();
+}
+
+NetHackQtMessageWindow * NetHackQtMainWindow::GetMessageWindow()
+{
+    return message;
+}
+
+void NetHackQtMainWindow::AddMapWindow(NetHackQtMapWindow2* window)
+{
+
+    map=window;
+    if (!qt_compact_mode)
+        vsplitter->insertWidget(1, map->Widget());
+    ShowIfReady();
+    connect(map,SIGNAL(resized()),this,SLOT(layout()));
+}
+
+void NetHackQtMainWindow::AddStatusWindow(NetHackQtStatusWindow* window)
+{
+    status=window;
+    if (!qt_compact_mode)
+        hsplitter->insertWidget(2, status->Widget());
+    ShowIfReady();
+}
+
+void NetHackQtMainWindow::RemoveWindow(NetHackQtWindow* window)
+{
+    if (window==status) {
+       status=0;
+       ShowIfReady();
+    } else if (window==map) {
+       map=0;
+       ShowIfReady();
+    } else if (window==message) {
+       message=0;
+       ShowIfReady();
+    }
+}
+
+void NetHackQtMainWindow::updateInventory()
+{
+    if ( invusage )
+       invusage->repaint();
+}
+
+void NetHackQtMainWindow::fadeHighlighting()
+{
+    if (status) {
+       status->fadeHighlighting();
+    }
+}
+
+void NetHackQtMainWindow::layout()
+{
+#if 0
+    if ( qt_compact_mode )
+       return;
+    if (message && map && status) {
+       QSize maxs=map->Widget()->maximumSize();
+       int maph=std::min(height()*2/3,maxs.height());
+
+       QWidget* c = centralWidget();
+       int h=c->height();
+       int toph=h-maph;
+       int iuw=3*qt_settings->glyphs().width();
+       int topw=(c->width()-iuw)/2;
+
+       message->Widget()->setGeometry(0,0,topw,toph);
+       invusage->setGeometry(topw,0,iuw,toph);
+       status->Widget()->setGeometry(topw+iuw,0,topw,toph);
+       map->Widget()->setGeometry(std::max(0,(c->width()-maxs.width())/2),
+                                  toph,c->width(),maph);
+    }
+#endif
+}
+
+void NetHackQtMainWindow::resizeEvent(QResizeEvent*)
+{
+    layout();
+#ifdef KDE
+    updateRects();
+#endif
+}
+
+void NetHackQtMainWindow::keyReleaseEvent(QKeyEvent* event)
+{
+    if ( dirkey ) {
+       doKeys(QString(QChar(dirkey)));
+       if ( !event->isAutoRepeat() )
+           dirkey = 0;
+    }
+}
+
+void NetHackQtMainWindow::keyPressEvent(QKeyEvent* event)
+{
+    // Global key controls
+
+    // For desktop, arrow keys scroll map, since we don't want players
+    // to think that's the way to move. For handhelds, the normal way is to
+    // click-to-travel, so we allow the cursor keys for fine movements.
+
+    //  321
+    //  4 0
+    //  567
+
+    if ( event->isAutoRepeat() &&
+       event->key() >= Qt::Key_Left && event->key() <= Qt::Key_Down )
+       return;
+
+    const char* d = Cmd.dirchars;
+    switch (event->key()) {
+     case Qt::Key_Up:
+       if ( dirkey == d[0] )
+           dirkey = d[1];
+       else if ( dirkey == d[4] )
+           dirkey = d[3];
+       else
+           dirkey = d[2];
+    break; case Qt::Key_Down:
+       if ( dirkey == d[0] )
+           dirkey = d[7];
+       else if ( dirkey == d[4] )
+           dirkey = d[5];
+       else
+           dirkey = d[6];
+    break; case Qt::Key_Left:
+       if ( dirkey == d[2] )
+           dirkey = d[1];
+       else if ( dirkey == d[6] )
+           dirkey = d[7];
+       else
+           dirkey = d[0];
+    break; case Qt::Key_Right:
+       if ( dirkey == d[2] )
+           dirkey = d[3];
+       else if ( dirkey == d[6] )
+           dirkey = d[5];
+       else
+           dirkey = d[4];
+    break; case Qt::Key_PageUp:
+       dirkey = 0;
+       if (message) message->Scroll(0,-1);
+    break; case Qt::Key_PageDown:
+       dirkey = 0;
+       if (message) message->Scroll(0,+1);
+    break; case Qt::Key_Space:
+       if ( flags.rest_on_space ) {
+           event->ignore();
+           return;
+       }
+       case Qt::Key_Enter:
+       if ( map )
+           map->clickCursor();
+    break; default:
+       dirkey = 0;
+       event->ignore();
+    }
+}
+
+void NetHackQtMainWindow::closeEvent(QCloseEvent* e)
+{
+    if ( program_state.something_worth_saving ) {
+       switch ( QMessageBox::information( this, "NetHack",
+           "This will end your NetHack session",
+           "&Save", "&Cancel", 0, 1 ) )
+       {
+           case 0:
+               // See dosave() function
+               if (dosave0()) {
+                   u.uhp = -1;
+                   NetHackQtBind::qt_exit_nhwindows(0);
+                   nh_terminate(EXIT_SUCCESS);
+               }
+               break;
+           case 1:
+               break; // ignore the event
+       }
+    } else {
+       e->accept();
+    }
+}
+
+void NetHackQtMainWindow::ShowIfReady()
+{
+    if (message && map && status) {
+       QWidget* hp = qt_compact_mode ? static_cast<QWidget *>(stack) : static_cast<QWidget *>(hsplitter);
+       QWidget* vp = qt_compact_mode ? static_cast<QWidget *>(stack) : static_cast<QWidget *>(vsplitter);
+       message->Widget()->setParent(hp);
+       map->Widget()->setParent(vp);
+       status->Widget()->setParent(hp);
+       if ( qt_compact_mode ) {
+           message->setMap(map);
+           stack->addWidget(map->Widget());
+           stack->addWidget(message->Widget());
+           stack->addWidget(status->Widget());
+           raiseMap();
+       } else {
+           layout();
+       }
+       showMaximized();
+    } else if (isVisible()) {
+       hide();
+    }
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4main.h b/win/Qt4/qt4main.h
new file mode 100644 (file)
index 0000000..a3ec15a
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4main.h -- the main window
+
+#ifndef QT4MAIN_H
+#define QT4MAIN_H
+
+#ifdef KDE
+#include <kapp.h>
+#include <ktopwidget.h>
+#else
+#include "qt4kde0.h"
+#endif
+
+namespace nethack_qt4 {
+
+class NetHackQtInvUsageWindow;
+class NetHackQtKeyBuffer;
+class NetHackQtMapWindow2;
+class NetHackQtMessageWindow;
+class NetHackQtStatusWindow;
+class NetHackQtWindow;
+
+// This class is the main widget for NetHack
+//
+// It is a collection of Message, Map, and Status windows.  In the current
+// version of nethack there is only one of each, and this class makes this
+// assumption, not showing itself until all are inserted.
+//
+// This class simply knows how to layout such children sensibly.
+//
+// Since it is only responsible for layout, the class does not
+// note the actual class of the windows.
+//
+
+class NetHackQtMainWindow : public KTopLevelWidget {
+       Q_OBJECT
+public:
+       NetHackQtMainWindow(NetHackQtKeyBuffer&);
+
+       void AddMessageWindow(NetHackQtMessageWindow* window);
+       NetHackQtMessageWindow * GetMessageWindow();
+       void AddMapWindow(NetHackQtMapWindow2* window);
+       void AddStatusWindow(NetHackQtStatusWindow* window);
+       void RemoveWindow(NetHackQtWindow* window);
+       void updateInventory();
+
+       void fadeHighlighting();
+
+public slots:
+       void doMenuItem(QAction *);
+       void doQtSettings(bool);
+       void doAbout(bool);
+       //RLC void doGuidebook(bool);
+       void doKeys(const QString&);
+
+protected:
+       virtual void resizeEvent(QResizeEvent*);
+       virtual void keyPressEvent(QKeyEvent*);
+       virtual void keyReleaseEvent(QKeyEvent* event);
+       virtual void closeEvent(QCloseEvent*);
+
+private slots:
+       void layout();
+       void raiseMap();
+       void zoomMap();
+       void raiseMessages();
+       void raiseStatus();
+
+private:
+       void ShowIfReady();
+
+#ifdef KDE
+       KMenuBar* menubar;
+#else
+       QMenuBar* menubar;
+#endif
+       NetHackQtMessageWindow* message;
+       NetHackQtMapWindow2* map;
+       NetHackQtStatusWindow* status;
+       NetHackQtInvUsageWindow* invusage;
+
+       QSplitter *hsplitter;
+       QSplitter *vsplitter;
+
+       NetHackQtKeyBuffer& keysink;
+       QStackedWidget* stack;
+       int dirkey;
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4map.cpp b/win/Qt4/qt4map.cpp
new file mode 100644 (file)
index 0000000..f3425ba
--- /dev/null
@@ -0,0 +1,974 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4map.cpp -- the map window
+
+extern "C" {
+#include "hack.h"
+}
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4map.h"
+#include "qt4map.moc"
+#include "qt4click.h"
+#include "qt4glyph.h"
+#include "qt_xpms.h"
+#include "qt4set.h"
+#include "qt4str.h"
+
+// temporary
+extern int qt_compact_mode;
+// end temporary
+
+namespace nethack_qt4 {
+
+#ifdef TEXTCOLOR
+static const QPen& nhcolor_to_pen(int c)
+{
+    static QPen* pen=0;
+    if ( !pen ) {
+       pen = new QPen[17];
+       pen[0] = QColor(64,64,64);
+       pen[1] = QColor(Qt::red);
+       pen[2] = QColor(0,191,0);
+       pen[3] = QColor(127,127,0);
+       pen[4] = QColor(Qt::blue);
+       pen[5] = QColor(Qt::magenta);
+       pen[6] = QColor(Qt::cyan);
+       pen[7] = QColor(Qt::gray);
+       pen[8] = QColor(Qt::white); // no color
+       pen[9] = QColor(255,127,0);
+       pen[10] = QColor(127,255,127);
+       pen[11] = QColor(Qt::yellow);
+       pen[12] = QColor(127,127,255);
+       pen[13] = QColor(255,127,255);
+       pen[14] = QColor(127,255,255);
+       pen[15] = QColor(Qt::white);
+       pen[16] = QColor(Qt::black);
+    }
+
+    return pen[c];
+}
+#endif
+
+NetHackQtMapViewport::NetHackQtMapViewport(NetHackQtClickBuffer& click_sink) :
+       QWidget(NULL),
+       rogue_font(NULL),
+       clicksink(click_sink),
+       change(10)
+{
+    pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm);
+    pile_annotation = QPixmap(pile_mark_xpm);
+
+    Clear();
+    cursor.setX(0);
+    cursor.setY(0);
+}
+
+NetHackQtMapViewport::~NetHackQtMapViewport(void)
+{
+    delete rogue_font;
+}
+
+void NetHackQtMapViewport::paintEvent(QPaintEvent* event)
+{
+    QRect area=event->rect();
+    QRect garea;
+    garea.setCoords(
+       std::max(0,area.left()/qt_settings->glyphs().width()),
+       std::max(0,area.top()/qt_settings->glyphs().height()),
+       std::min(COLNO-1,area.right()/qt_settings->glyphs().width()),
+       std::min(ROWNO-1,area.bottom()/qt_settings->glyphs().height())
+    );
+
+    QPainter painter;
+
+    painter.begin(this);
+
+    if (Is_rogue_level(&u.uz) || iflags.wc_ascii_map) {
+       // You enter a VERY primitive world!
+
+       painter.setClipRect( event->rect() ); // (normally we don't clip)
+       painter.fillRect( event->rect(), Qt::black );
+
+       if ( !rogue_font ) {
+           // Find font...
+           int pts = 5;
+           QString fontfamily = iflags.wc_font_map
+               ? iflags.wc_font_map : "Monospace";
+           bool bold = false;
+           if ( fontfamily.right(5).toLower() == "-bold" ) {
+               fontfamily.truncate(fontfamily.length()-5);
+               bold = true;
+           }
+           while ( pts < 32 ) {
+               QFont f(fontfamily, pts, bold ? QFont::Bold : QFont::Normal);
+               painter.setFont(QFont(fontfamily, pts));
+               QFontMetrics fm = painter.fontMetrics();
+               if ( fm.width("M") > qt_settings->glyphs().width() )
+                   break;
+               if ( fm.height() > qt_settings->glyphs().height() )
+                   break;
+               pts++;
+           }
+           rogue_font = new QFont(fontfamily,pts-1);
+       }
+       painter.setFont(*rogue_font);
+
+       for (int j=garea.top(); j<=garea.bottom(); j++) {
+           for (int i=garea.left(); i<=garea.right(); i++) {
+               unsigned short g=Glyph(i,j);
+               int color;
+               int ch;
+               unsigned special;
+
+               painter.setPen( Qt::green );
+               /* map glyph to character and color */
+               mapglyph(g, &ch, &color, &special, i, j);
+               ch = cp437(ch);
+#ifdef TEXTCOLOR
+               painter.setPen( nhcolor_to_pen(color) );
+#endif
+               if (!DrawWalls(
+                       painter,
+                       i*qt_settings->glyphs().width(),
+                       j*qt_settings->glyphs().height(),
+                       qt_settings->glyphs().width(),
+                       qt_settings->glyphs().height(),
+                       ch)) {
+                   painter.drawText(
+                       i*qt_settings->glyphs().width(),
+                       j*qt_settings->glyphs().height(),
+                       qt_settings->glyphs().width(),
+                       qt_settings->glyphs().height(),
+                       Qt::AlignCenter,
+                       QString(QChar(ch)).left(1)
+                   );
+               }
+#ifdef TEXTCOLOR
+               if (((special & MG_PET) != 0) && ::iflags.hilite_pet) {
+                    painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
+                } else if (((special & MG_OBJPILE) != 0) && ::iflags.hilite_pile) {
+                    painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pile_annotation);
+                }
+#endif
+            }
+        }
+
+       painter.setFont(font());
+    } else {
+       for (int j=garea.top(); j<=garea.bottom(); j++) {
+           for (int i=garea.left(); i<=garea.right(); i++) {
+               unsigned short g=Glyph(i,j);
+               int color;
+               int ch;
+               unsigned special;
+               mapglyph(g, &ch, &color, &special, i, j);
+               qt_settings->glyphs().drawCell(painter, g, i, j);
+#ifdef TEXTCOLOR
+               if (((special & MG_PET) != 0) && ::iflags.hilite_pet) {
+                    painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
+                } else if (((special & MG_OBJPILE) != 0) && ::iflags.hilite_pile) {
+                    painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pile_annotation);
+                }
+#endif
+           }
+       }
+    }
+
+    if (garea.contains(cursor)) {
+       if (Is_rogue_level(&u.uz)) {
+#ifdef TEXTCOLOR
+           painter.setPen( Qt::white );
+#else
+           painter.setPen( Qt::green ); // REALLY primitive
+#endif
+       } else
+       {
+           int hp100;
+           if (u.mtimedone) {
+               hp100=u.mhmax ? u.mh*100/u.mhmax : 100;
+           } else {
+               hp100=u.uhpmax ? u.uhp*100/u.uhpmax : 100;
+           }
+
+           if (hp100 > 75) painter.setPen(Qt::white);
+           else if (hp100 > 50) painter.setPen(Qt::yellow);
+           else if (hp100 > 25) painter.setPen(QColor(0xff,0xbf,0x00)); // orange
+           else if (hp100 > 10) painter.setPen(Qt::red);
+           else painter.setPen(Qt::magenta);
+       }
+
+       painter.drawRect(
+           cursor.x()*qt_settings->glyphs().width(),cursor.y()*qt_settings->glyphs().height(),
+           qt_settings->glyphs().width()-1,qt_settings->glyphs().height()-1);
+    }
+
+#if 0
+    if (area.intersects(messages_rect)) {
+       painter.setPen(Qt::black);
+       painter.drawText(viewport.contentsX()+1,viewport.contentsY()+1,
+           viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
+       painter.setPen(Qt::white);
+       painter.drawText(viewport.contentsX(),viewport.contentsY(),
+           viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
+    }
+#endif
+
+    painter.end();
+}
+
+bool NetHackQtMapViewport::DrawWalls(
+       QPainter& painter,
+       int x, int y, int w, int h,
+       unsigned ch)
+{
+    enum
+    {
+       w_left      = 0x01,
+       w_right     = 0x02,
+       w_up        = 0x04,
+       w_down      = 0x08,
+       w_sq_top    = 0x10,
+       w_sq_bottom = 0x20,
+       w_sq_left   = 0x40,
+       w_sq_right  = 0x80
+    };
+    unsigned linewidth;
+    unsigned walls;
+    int x1, y1, x2, y2, x3, y3;
+    linewidth = ((w < h) ? w : h)/8;
+    if (linewidth == 0) linewidth = 1;
+
+    // Single walls
+    walls = 0;
+    switch (ch)
+    {
+    case 0x2500: // BOX DRAWINGS LIGHT HORIZONTAL
+       walls = w_left | w_right;
+       break;
+
+    case 0x2502: // BOX DRAWINGS LIGHT VERTICAL
+       walls = w_up | w_down;
+       break;
+
+    case 0x250C: // BOX DRAWINGS LIGHT DOWN AND RIGHT
+       walls = w_down | w_right;
+       break;
+
+    case 0x2510: // BOX DRAWINGS LIGHT DOWN AND LEFT
+       walls = w_down | w_left;
+       break;
+
+    case 0x2514: // BOX DRAWINGS LIGHT UP AND RIGHT
+       walls = w_up | w_right;
+       break;
+
+    case 0x2518: // BOX DRAWINGS LIGHT UP AND LEFT
+       walls = w_up | w_left;
+       break;
+
+    case 0x251C: // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+       walls = w_up | w_down | w_right;
+       break;
+
+    case 0x2524: // BOX DRAWINGS LIGHT VERTICAL AND LEFT
+       walls = w_up | w_down | w_left;
+       break;
+
+    case 0x252C: // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+       walls = w_down | w_left | w_right;
+       break;
+
+    case 0x2534: // BOX DRAWINGS LIGHT UP AND HORIZONTAL
+       walls = w_up | w_left | w_right;
+       break;
+
+    case 0x253C: // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+       walls = w_up | w_down | w_left | w_right;
+       break;
+    }
+
+    if (walls != 0)
+    {
+       x1 = x + w/2;
+       switch (walls & (w_up | w_down))
+       {
+       case w_up:
+           painter.drawLine(x1, y, x1, y+h/2);
+           break;
+
+       case w_down:
+           painter.drawLine(x1, y+h/2, x1, y+h-1);
+           break;
+
+       case w_up | w_down:
+           painter.drawLine(x1, y, x1, y+h-1);
+           break;
+       }
+
+       y1 = y + h/2;
+       switch (walls & (w_left | w_right))
+       {
+       case w_left:
+           painter.drawLine(x, y1, x+w/2, y1);
+           break;
+
+       case w_right:
+           painter.drawLine(x+w/2, y1, x+w-1, y1);
+           break;
+
+       case w_left | w_right:
+           painter.drawLine(x, y1, x+w-1, y1);
+           break;
+       }
+
+       return true;
+    }
+
+    // Double walls
+    walls = 0;
+    switch (ch)
+    {
+    case 0x2550: // BOX DRAWINGS DOUBLE HORIZONTAL
+       walls = w_left | w_right | w_sq_top | w_sq_bottom;
+       break;
+
+    case 0x2551: // BOX DRAWINGS DOUBLE VERTICAL
+       walls = w_up | w_down | w_sq_left | w_sq_right;
+       break;
+
+    case 0x2554: // BOX DRAWINGS DOUBLE DOWN AND RIGHT
+       walls = w_down | w_right | w_sq_top | w_sq_left;
+       break;
+
+    case 0x2557: // BOX DRAWINGS DOUBLE DOWN AND LEFT
+       walls = w_down | w_left | w_sq_top | w_sq_right;
+       break;
+
+    case 0x255A: // BOX DRAWINGS DOUBLE UP AND RIGHT
+       walls = w_up | w_right | w_sq_bottom | w_sq_left;
+       break;
+
+    case 0x255D: // BOX DRAWINGS DOUBLE UP AND LEFT
+       walls = w_up | w_left | w_sq_bottom | w_sq_right;
+       break;
+
+    case 0x2560: // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+       walls = w_up | w_down | w_right | w_sq_left;
+       break;
+
+    case 0x2563: // BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+       walls = w_up | w_down | w_left | w_sq_right;
+       break;
+
+    case 0x2566: // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+       walls = w_down | w_left | w_right | w_sq_top;
+       break;
+
+    case 0x2569: // BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+       walls = w_up | w_left | w_right | w_sq_bottom;
+       break;
+
+    case 0x256C: // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+       walls = w_up | w_down | w_left | w_right;
+       break;
+    }
+    if (walls != 0)
+    {
+       x1 = x + w/2 - linewidth;
+       x2 = x + w/2 + linewidth;
+       x3 = x + w - 1;
+       y1 = y + h/2 - linewidth;
+       y2 = y + h/2 + linewidth;
+       y3 = y + h - 1;
+       if (walls & w_up)
+       {
+           painter.drawLine(x1, y, x1, y1);
+           painter.drawLine(x2, y, x2, y1);
+       }
+       if (walls & w_down)
+       {
+           painter.drawLine(x1, y2, x1, y3);
+           painter.drawLine(x2, y2, x2, y3);
+       }
+       if (walls & w_left)
+       {
+           painter.drawLine(x, y1, x1, y1);
+           painter.drawLine(x, y2, x1, y2);
+       }
+       if (walls & w_right)
+       {
+           painter.drawLine(x2, y1, x3, y1);
+           painter.drawLine(x2, y2, x3, y2);
+       }
+       if (walls & w_sq_top)
+       {
+           painter.drawLine(x1, y1, x2, y1);
+       }
+       if (walls & w_sq_bottom)
+       {
+           painter.drawLine(x1, y2, x2, y2);
+       }
+       if (walls & w_sq_left)
+       {
+           painter.drawLine(x1, y1, x1, y2);
+       }
+       if (walls & w_sq_right)
+       {
+           painter.drawLine(x2, y1, x2, y2);
+       }
+       return true;
+    }
+
+    // Solid blocks
+    if (0x2591 <= ch && ch <= 0x2593)
+    {
+       unsigned shade = ch - 0x2590;
+       QColor rgb(painter.pen().color());
+       QColor rgb2(
+               rgb.red()*shade/4,
+               rgb.green()*shade/4,
+               rgb.blue()*shade/4);
+       painter.fillRect(x, y, w, h, rgb2);
+       return true;
+    }
+
+    return false;
+}
+
+void NetHackQtMapViewport::mousePressEvent(QMouseEvent* event)
+{
+    clicksink.Put(
+       event->pos().x()/qt_settings->glyphs().width(),
+       event->pos().y()/qt_settings->glyphs().height(),
+       event->button()==Qt::LeftButton ? CLICK_1 : CLICK_2
+    );
+    qApp->exit();
+}
+
+void NetHackQtMapViewport::updateTiles()
+{
+    change.clear();
+    change.add(0,0,COLNO,ROWNO);
+    delete rogue_font; rogue_font = NULL;
+}
+
+QSize NetHackQtMapViewport::sizeHint() const
+{
+    return QSize(
+           qt_settings->glyphs().width() * COLNO,
+           qt_settings->glyphs().height() * ROWNO);
+}
+
+QSize NetHackQtMapViewport::minimumSizeHint() const
+{
+    return sizeHint();
+}
+
+void NetHackQtMapViewport::clickCursor()
+{
+    clicksink.Put(cursor.x(),cursor.y(),CLICK_1);
+    qApp->exit();
+}
+
+void NetHackQtMapViewport::Clear()
+{
+    unsigned short stone=cmap_to_glyph(S_stone);
+
+    for (int j=0; j<ROWNO; j++) {
+       for (int i=0; i<COLNO; i++) {
+           Glyph(i,j)=stone;
+       }
+    }
+
+    change.clear();
+    change.add(0,0,COLNO,ROWNO);
+}
+
+void NetHackQtMapViewport::Display(bool block)
+{
+    for (int i=0; i<change.clusters(); i++) {
+       const QRect& ch=change[i];
+       repaint(
+           ch.x()*qt_settings->glyphs().width(),
+           ch.y()*qt_settings->glyphs().height(),
+           ch.width()*qt_settings->glyphs().width(),
+           ch.height()*qt_settings->glyphs().height()
+       );
+    }
+
+    change.clear();
+
+    if (block) {
+       yn_function("Press a key when done viewing",0,'\0');
+    }
+}
+
+void NetHackQtMapViewport::CursorTo(int x,int y)
+{
+    Changed(cursor.x(),cursor.y());
+    cursor.setX(x);
+    cursor.setY(y);
+    Changed(cursor.x(),cursor.y());
+}
+
+void NetHackQtMapViewport::PrintGlyph(int x,int y,int glyph)
+{
+    Glyph(x,y)=glyph;
+    Changed(x,y);
+}
+
+void NetHackQtMapViewport::Changed(int x, int y)
+{
+    change.add(x,y);
+}
+
+NetHackQtMapWindow2::NetHackQtMapWindow2(NetHackQtClickBuffer& click_sink) :
+       QScrollArea(NULL),
+       m_viewport(new NetHackQtMapViewport(click_sink))
+{
+    QPalette palette;
+    palette.setColor(backgroundRole(), Qt::black);
+    setPalette(palette);
+
+    setWidget(m_viewport);
+
+    connect(qt_settings,SIGNAL(tilesChanged()),this,SLOT(updateTiles()));
+    updateTiles();
+}
+
+void NetHackQtMapWindow2::updateTiles()
+{
+    NetHackQtGlyphs& glyphs = qt_settings->glyphs();
+    int gw = glyphs.width();
+    int gh = glyphs.height();
+    // Be exactly the size we want to be - full map...
+    m_viewport->resize(COLNO*gw,ROWNO*gh);
+
+    verticalScrollBar()->setSingleStep(gh);
+    verticalScrollBar()->setPageStep(gh);
+    horizontalScrollBar()->setSingleStep(gw);
+    horizontalScrollBar()->setPageStep(gw);
+
+    m_viewport->updateTiles();
+    Display(false);
+
+    emit resized();
+}
+
+void NetHackQtMapWindow2::clearMessages()
+{
+    messages = "";
+    update(messages_rect);
+    messages_rect = QRect();
+}
+
+void NetHackQtMapWindow2::putMessage(int attr, const QString& text)
+{
+    if ( !messages.isEmpty() )
+       messages += "\n";
+    messages += QString(text).replace(QChar(0x200B), "");
+    QFontMetrics fm = fontMetrics();
+#if 0
+    messages_rect = fm.boundingRect(viewport.contentsX(),viewport.contentsY(),viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
+    update(messages_rect);
+#endif
+}
+
+void NetHackQtMapWindow2::clickCursor()
+{
+    m_viewport->clickCursor();
+}
+
+QWidget *NetHackQtMapWindow2::Widget()
+{
+    return this;
+}
+
+void NetHackQtMapWindow2::Clear()
+{
+    m_viewport->Clear();
+}
+
+void NetHackQtMapWindow2::Display(bool block)
+{
+    m_viewport->Display(block);
+}
+
+void NetHackQtMapWindow2::CursorTo(int x,int y)
+{
+    m_viewport->CursorTo(x, y);
+}
+
+void NetHackQtMapWindow2::PutStr(int attr, const QString& text)
+{
+    puts("unexpected PutStr in MapWindow");
+}
+
+void NetHackQtMapWindow2::ClipAround(int x,int y)
+{
+    // Convert to pixel of center of tile
+    x=x*qt_settings->glyphs().width()+qt_settings->glyphs().width()/2;
+    y=y*qt_settings->glyphs().height()+qt_settings->glyphs().height()/2;
+
+    // Then ensure that pixel is visible
+    ensureVisible(x,y,width()*0.45,height()*0.45);
+}
+
+void NetHackQtMapWindow2::PrintGlyph(int x,int y,int glyph)
+{
+    m_viewport->PrintGlyph(x, y, glyph);
+}
+
+#if 0 //RLC
+// XXX Hmmm... crash after saving bones file if Map window is
+// XXX deleted.  Strange bug somewhere.
+bool NetHackQtMapWindow::Destroy() { return false; }
+
+NetHackQtMapWindow::NetHackQtMapWindow(NetHackQtClickBuffer& click_sink) :
+    clicksink(click_sink),
+    change(10),
+    rogue_font(0)
+{
+    viewport.addChild(this);
+
+    QPalette palette;
+    palette.setColor(backgroundRole(), Qt::black);
+    setPalette(palette);
+    palette.setColor(viewport.backgroundRole(), Qt::black);
+    viewport.setPalette(palette);
+
+    pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm);
+    pile_annotation = QPixmap(pile_mark_xpm);
+
+    cursor.setX(0);
+    cursor.setY(0);
+    Clear();
+
+    connect(qt_settings,SIGNAL(tilesChanged()),this,SLOT(updateTiles()));
+    connect(&viewport, SIGNAL(contentsMoving(int,int)), this,
+               SLOT(moveMessages(int,int)));
+
+    updateTiles();
+    //setFocusPolicy(Qt::StrongFocus);
+}
+
+void NetHackQtMapWindow::moveMessages(int x, int y)
+{
+    QRect u = messages_rect;
+    messages_rect.moveTopLeft(QPoint(x,y));
+    u |= messages_rect;
+    update(u);
+}
+
+void NetHackQtMapWindow::clearMessages()
+{
+    messages = "";
+    update(messages_rect);
+    messages_rect = QRect();
+}
+
+void NetHackQtMapWindow::putMessage(int attr, const QString& text)
+{
+    if ( !messages.isEmpty() )
+       messages += "\n";
+    messages += QString(text).replace(QChar(0x200B), "");
+    QFontMetrics fm = fontMetrics();
+    messages_rect = fm.boundingRect(viewport.contentsX(),viewport.contentsY(),viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
+    update(messages_rect);
+}
+
+void NetHackQtMapWindow::updateTiles()
+{
+    NetHackQtGlyphs& glyphs = qt_settings->glyphs();
+    int gw = glyphs.width();
+    int gh = glyphs.height();
+    // Be exactly the size we want to be - full map...
+    resize(COLNO*gw,ROWNO*gh);
+
+    viewport.verticalScrollBar()->setSingleStep(gh);
+    viewport.verticalScrollBar()->setPageStep(gh);
+    viewport.horizontalScrollBar()->setSingleStep(gw);
+    viewport.horizontalScrollBar()->setPageStep(gw);
+    /*
+    viewport.setMaximumSize(
+       gw*COLNO + viewport.verticalScrollBar()->width(),
+       gh*ROWNO + viewport.horizontalScrollBar()->height()
+    );
+    */
+    viewport.updateScrollBars();
+
+    change.clear();
+    change.add(0,0,COLNO,ROWNO);
+    delete rogue_font; rogue_font = 0;
+    Display(false);
+
+    emit resized();
+}
+
+NetHackQtMapWindow::~NetHackQtMapWindow()
+{
+    // Remove from viewport porthole, since that is a destructible member.
+    viewport.removeChild(this);
+    setParent(0,0);
+}
+
+QWidget* NetHackQtMapWindow::Widget()
+{
+    return &viewport;
+}
+
+void NetHackQtMapWindow::Scroll(int dx, int dy)
+{
+    if (viewport.horizontalScrollBar()->isVisible()) {
+       while (dx<0) { viewport.horizontalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepSub); dx++; }
+       while (dx>0) { viewport.horizontalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepAdd); dx--; }
+    }
+    if (viewport.verticalScrollBar()->isVisible()) {
+       while (dy<0) { viewport.verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepSub); dy++; }
+       while (dy>0) { viewport.verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepAdd); dy--; }
+    }
+}
+
+void NetHackQtMapWindow::Clear()
+{
+    unsigned short stone=cmap_to_glyph(S_stone);
+
+    for (int j=0; j<ROWNO; j++) {
+       for (int i=0; i<COLNO; i++) {
+           Glyph(i,j)=stone;
+       }
+    }
+
+    change.clear();
+    change.add(0,0,COLNO,ROWNO);
+}
+
+void NetHackQtMapWindow::clickCursor()
+{
+    clicksink.Put(cursor.x(),cursor.y(),CLICK_1);
+    qApp->exit();
+}
+
+void NetHackQtMapWindow::mousePressEvent(QMouseEvent* event)
+{
+    clicksink.Put(
+       event->pos().x()/qt_settings->glyphs().width(),
+       event->pos().y()/qt_settings->glyphs().height(),
+       event->button()==Qt::LeftButton ? CLICK_1 : CLICK_2
+    );
+    qApp->exit();
+}
+
+void NetHackQtMapWindow::paintEvent(QPaintEvent* event)
+{
+    QRect area=event->rect();
+    QRect garea;
+    garea.setCoords(
+       std::max(0,area.left()/qt_settings->glyphs().width()),
+       std::max(0,area.top()/qt_settings->glyphs().height()),
+       std::min(COLNO-1,area.right()/qt_settings->glyphs().width()),
+       std::min(ROWNO-1,area.bottom()/qt_settings->glyphs().height())
+    );
+
+    QPainter painter;
+
+    painter.begin(this);
+
+    if (is_rogue_level(&u.uz) || iflags.wc_ascii_map) {
+       // You enter a VERY primitive world!
+
+       painter.setClipRect( event->rect() ); // (normally we don't clip)
+       painter.fillRect( event->rect(), Qt::black );
+
+       if ( !rogue_font ) {
+           // Find font...
+           int pts = 5;
+           QString fontfamily = iflags.wc_font_map
+               ? iflags.wc_font_map : "Courier";
+           bool bold = false;
+           if ( fontfamily.right(5).toLower() == "-bold" ) {
+               fontfamily.truncate(fontfamily.length()-5);
+               bold = true;
+           }
+           while ( pts < 32 ) {
+               QFont f(fontfamily, pts, bold ? QFont::Bold : QFont::Normal);
+               painter.setFont(QFont(fontfamily, pts));
+               QFontMetrics fm = painter.fontMetrics();
+               if ( fm.width("M") > qt_settings->glyphs().width() )
+                   break;
+               if ( fm.height() > qt_settings->glyphs().height() )
+                   break;
+               pts++;
+           }
+           rogue_font = new QFont(fontfamily,pts-1);
+       }
+       painter.setFont(*rogue_font);
+
+       for (int j=garea.top(); j<=garea.bottom(); j++) {
+           for (int i=garea.left(); i<=garea.right(); i++) {
+               unsigned short g=Glyph(i,j);
+               int color;
+               char32_t ch;
+               unsigned special;
+
+               painter.setPen( Qt::green );
+               /* map glyph to character and color */
+               mapglyph(g, &ch, &color, &special, i, j);
+#ifdef TEXTCOLOR
+               painter.setPen( nhcolor_to_pen(color) );
+#endif
+               painter.drawText(
+                   i*qt_settings->glyphs().width(),
+                   j*qt_settings->glyphs().height(),
+                   qt_settings->glyphs().width(),
+                   qt_settings->glyphs().height(),
+                   Qt::AlignCenter,
+                   QString(QChar(ch)).left(1)
+               );
+#ifdef TEXTCOLOR
+               if (((special & MG_PET) != 0) && ::iflags.hilite_pet) {
+                    painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
+                } else if (((special & MG_OBJPILE) != 0) && ::iflags.hilite_pile) {
+                    painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pile_annotation);
+                }
+#endif
+           }
+       }
+
+       painter.setFont(font());
+    } else {
+       for (int j=garea.top(); j<=garea.bottom(); j++) {
+           for (int i=garea.left(); i<=garea.right(); i++) {
+               unsigned short g=Glyph(i,j);
+               int color;
+               int ch;
+               unsigned special;
+               mapglyph(g, &ch, &color, &special, i, j);
+               qt_settings->glyphs().drawCell(painter, g, i, j);
+#ifdef TEXTCOLOR
+               if (((special & MG_PET) != 0) && ::iflags.hilite_pet) {
+                    painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pet_annotation);
+                } else if (((special & MG_OBJPILE) != 0) && ::iflags.hilite_pile) {
+                    painter.drawPixmap(QPoint(i*qt_settings->glyphs().width(), j*qt_settings->glyphs().height()), pile_annotation);
+                }
+#endif
+           }
+       }
+    }
+
+    if (garea.contains(cursor)) {
+       if (Is_rogue_level(&u.uz)) {
+#ifdef TEXTCOLOR
+           painter.setPen( Qt::white );
+#else
+           painter.setPen( Qt::green ); // REALLY primitive
+#endif
+       } else
+       {
+           int hp100;
+           if (u.mtimedone) {
+               hp100=u.mhmax ? u.mh*100/u.mhmax : 100;
+           } else {
+               hp100=u.uhpmax ? u.uhp*100/u.uhpmax : 100;
+           }
+
+           if (hp100 > 75) painter.setPen(Qt::white);
+           else if (hp100 > 50) painter.setPen(Qt::yellow);
+           else if (hp100 > 25) painter.setPen(QColor(0xff,0xbf,0x00)); // orange
+           else if (hp100 > 10) painter.setPen(Qt::red);
+           else painter.setPen(Qt::magenta);
+       }
+
+       painter.drawRect(
+           cursor.x()*qt_settings->glyphs().width(),cursor.y()*qt_settings->glyphs().height(),
+           qt_settings->glyphs().width()-1,qt_settings->glyphs().height()-1);
+    }
+
+    if (area.intersects(messages_rect)) {
+       painter.setPen(Qt::black);
+       painter.drawText(viewport.contentsX()+1,viewport.contentsY()+1,
+           viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
+       painter.setPen(Qt::white);
+       painter.drawText(viewport.contentsX(),viewport.contentsY(),
+           viewport.width(),0, Qt::TextWordWrap|Qt::AlignTop|Qt::AlignLeft|Qt::TextDontClip, messages);
+    }
+
+    painter.end();
+}
+
+void NetHackQtMapWindow::Display(bool block)
+{
+    for (int i=0; i<change.clusters(); i++) {
+       const QRect& ch=change[i];
+       repaint(
+           ch.x()*qt_settings->glyphs().width(),
+           ch.y()*qt_settings->glyphs().height(),
+           ch.width()*qt_settings->glyphs().width(),
+           ch.height()*qt_settings->glyphs().height()
+       );
+    }
+
+    change.clear();
+
+    if (block) {
+       yn_function("Press a key when done viewing",0,'\0');
+    }
+}
+
+void NetHackQtMapWindow::CursorTo(int x,int y)
+{
+    Changed(cursor.x(),cursor.y());
+    cursor.setX(x);
+    cursor.setY(y);
+    Changed(cursor.x(),cursor.y());
+}
+
+void NetHackQtMapWindow::PutStr(int attr, const QString& text)
+{
+    puts("unexpected PutStr in MapWindow");
+}
+
+void NetHackQtMapWindow::ClipAround(int x,int y)
+{
+    // Convert to pixel of center of tile
+    x=x*qt_settings->glyphs().width()+qt_settings->glyphs().width()/2;
+    y=y*qt_settings->glyphs().height()+qt_settings->glyphs().height()/2;
+
+    // Then ensure that pixel is visible
+    viewport.center(x,y,0.45,0.45);
+}
+
+void NetHackQtMapWindow::PrintGlyph(int x,int y,int glyph)
+{
+    Glyph(x,y)=glyph;
+    Changed(x,y);
+}
+
+//void NetHackQtMapWindow::PrintGlyphCompose(int x,int y,int glyph1, int glyph2)
+//{
+    // TODO: composed graphics
+//}
+
+void NetHackQtMapWindow::Changed(int x, int y)
+{
+    change.add(x,y);
+}
+#endif
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4map.h b/win/Qt4/qt4map.h
new file mode 100644 (file)
index 0000000..337a726
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4map.h -- the map window
+
+#ifndef QT4MAP_H
+#define QT4MAP_H
+
+#include "qt4win.h"
+#include "qt4clust.h"
+
+namespace nethack_qt4 {
+
+class NetHackQtClickBuffer;
+
+class NetHackQtMapViewport : public QWidget {
+       Q_OBJECT
+public:
+       NetHackQtMapViewport(NetHackQtClickBuffer& click_sink);
+       ~NetHackQtMapViewport(void);
+
+protected:
+       virtual void paintEvent(QPaintEvent* event);
+       bool DrawWalls(QPainter& painter, int x, int y, int w, int h, unsigned ch);
+       virtual QSize sizeHint() const;
+       virtual QSize minimumSizeHint() const;
+       virtual void mousePressEvent(QMouseEvent* event);
+
+private:
+       QFont *rogue_font;
+       unsigned short glyph[ROWNO][COLNO];
+       unsigned short& Glyph(int x, int y) { return glyph[y][x]; }
+       QPoint cursor;
+       QPixmap pet_annotation;
+        QPixmap pile_annotation;
+       NetHackQtClickBuffer& clicksink;
+       Clusterizer change;
+
+       void clickCursor();
+       void Clear();
+       void Display(bool block);
+       void CursorTo(int x,int y);
+       void PrintGlyph(int x,int y,int glyph);
+       void Changed(int x, int y);
+       void updateTiles();
+
+       // NetHackQtMapWindow2 passes through many calls to the viewport
+       friend class NetHackQtMapWindow2;
+};
+
+class NetHackQtMapWindow2 : public QScrollArea, public NetHackQtWindow {
+       Q_OBJECT
+public:
+       NetHackQtMapWindow2(NetHackQtClickBuffer& click_sink);
+       void clearMessages();
+       void putMessage(int attr, const QString& text);
+       void clickCursor();
+       virtual QWidget *Widget();
+
+       virtual void Clear();
+       virtual void Display(bool block);
+       virtual void CursorTo(int x,int y);
+       virtual void PutStr(int attr, const QString& text);
+       virtual void ClipAround(int x,int y);
+       virtual void PrintGlyph(int x,int y,int glyph);
+
+signals:
+       void resized();
+
+private slots:
+       void updateTiles();
+
+private:
+       NetHackQtMapViewport *m_viewport;
+       QRect messages_rect;
+       QString messages;
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4menu.cpp b/win/Qt4/qt4menu.cpp
new file mode 100644 (file)
index 0000000..5ab0538
--- /dev/null
@@ -0,0 +1,830 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4menu.cpp -- a menu or text-list widget
+
+extern "C" {
+#include "hack.h"
+}
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4menu.h"
+#include "qt4menu.moc"
+#include "qt4glyph.h"
+#include "qt4set.h"
+#include "qt4streq.h"
+#include "qt4str.h"
+
+// temporary
+extern "C" int qt_compact_mode;
+// end temporary
+
+extern "C" struct menucoloring *menu_colorings;
+
+namespace nethack_qt4 {
+
+// temporary
+void centerOnMain( QWidget* w );
+// end temporary
+
+QSize NetHackQtTextListBox::sizeHint() const
+{
+    QScrollBar *hscroll = horizontalScrollBar();
+    int hsize = hscroll ? hscroll->height() : 0;
+    return QSize(TotalWidth()+hsize, TotalHeight()+hsize);
+}
+
+int NetHackQtMenuListBox::TotalWidth() const
+{
+    int width = 0;
+
+    for (int col = 0; col < columnCount(); ++col) {
+       width += columnWidth(col);
+    }
+    return width;
+}
+
+int NetHackQtMenuListBox::TotalHeight() const
+{
+    int height = 0;
+
+    for (int row = 0; row < rowCount(); ++row) {
+       height += rowHeight(row);
+    }
+    return height;
+}
+
+QSize NetHackQtMenuListBox::sizeHint() const
+{
+    QScrollBar *hscroll = horizontalScrollBar();
+    int hsize = hscroll ? hscroll->height() : 0;
+    return QSize(TotalWidth()+hsize, TotalHeight()+hsize);
+}
+
+// Table view columns:
+// 
+// [pick-count] [accel] [glyph] [string]
+// 
+// Maybe accel should be near string.  We'll see.
+// pick-count normally blank.
+//   double-clicking or click-on-count gives pop-up entry
+// string is green when selected
+//
+NetHackQtMenuWindow::NetHackQtMenuWindow(QWidget *parent) :
+    QDialog(parent),
+    table(new NetHackQtMenuListBox()),
+    prompt(0),
+    counting(false)
+{
+    QGridLayout *grid = new QGridLayout();
+    table->setColumnCount(5);
+    table->setFrameStyle(QFrame::Panel|QFrame::Sunken);
+    table->setLineWidth(2);
+    table->setShowGrid(false);
+    table->horizontalHeader()->hide();
+    table->verticalHeader()->hide();
+
+    ok=new QPushButton("Ok");
+    connect(ok,SIGNAL(clicked()),this,SLOT(accept()));
+
+    cancel=new QPushButton("Cancel");
+    connect(cancel,SIGNAL(clicked()),this,SLOT(reject()));
+
+    all=new QPushButton("All");
+    connect(all,SIGNAL(clicked()),this,SLOT(All()));
+
+    none=new QPushButton("None");
+    connect(none,SIGNAL(clicked()),this,SLOT(ChooseNone()));
+
+    invert=new QPushButton("Invert");
+    connect(invert,SIGNAL(clicked()),this,SLOT(Invert()));
+
+    search=new QPushButton("Search");
+    connect(search,SIGNAL(clicked()),this,SLOT(Search()));
+
+    QPoint pos(0,ok->height());
+    move(pos);
+    prompt.setParent(this,0);
+    prompt.move(pos);
+
+    grid->addWidget(ok, 0, 0);
+    grid->addWidget(cancel, 0, 1);
+    grid->addWidget(all, 0, 2);
+    grid->addWidget(none, 0, 3);
+    grid->addWidget(invert, 0, 4);
+    grid->addWidget(search, 0, 5);
+    grid->addWidget(&prompt, 1, 0, 1, 7);
+    grid->addWidget(table, 2, 0, 1, 7);
+    grid->setColumnStretch(6, 1);
+    grid->setRowStretch(2, 1);
+    setFocusPolicy(Qt::StrongFocus);
+    table->setFocusPolicy(Qt::NoFocus);
+    connect(table, SIGNAL(cellClicked(int,int)), this, SLOT(cellToggleSelect(int,int)));
+
+    setLayout(grid);
+}
+
+NetHackQtMenuWindow::~NetHackQtMenuWindow()
+{
+}
+
+QWidget* NetHackQtMenuWindow::Widget() { return this; }
+
+void NetHackQtMenuWindow::StartMenu()
+{
+    table->setRowCount((itemcount=0));
+    next_accel=0;
+    has_glyphs=false;
+}
+
+NetHackQtMenuWindow::MenuItem::MenuItem() :
+    str("")
+{
+}
+
+NetHackQtMenuWindow::MenuItem::~MenuItem()
+{
+}
+
+void NetHackQtMenuWindow::AddMenu(int glyph, const ANY_P* identifier,
+       char ch, char gch, int attr, const QString& str, bool presel)
+{
+    if (!ch && identifier->a_void!=0) {
+       // Supply a keyboard accelerator.  Limited supply.
+       static char accel[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+       if (accel[next_accel]) {
+           ch=accel[next_accel++];
+       }
+    }
+
+    if ((int)itemlist.size() < itemcount+1) {
+       itemlist.resize(itemcount*4+10);
+    }
+    itemlist[itemcount].glyph=glyph;
+    itemlist[itemcount].identifier=*identifier;
+    itemlist[itemcount].ch=ch;
+    itemlist[itemcount].gch=gch;
+    itemlist[itemcount].attr=attr;
+    itemlist[itemcount].str=str;
+    itemlist[itemcount].selected=presel;
+    itemlist[itemcount].count=-1;
+    itemlist[itemcount].color = -1;
+    // Display the boulder symbol correctly
+    if (str.left(8) == "boulder\t") {
+       int bracket = str.indexOf('[');
+       if (bracket != -1) {
+           itemlist[itemcount].str = str.left(bracket+1)
+               + QChar(cp437(str.at(bracket+1).unicode()))
+               + str.mid(bracket+2);
+       }
+    }
+    int mcolor, mattr;
+    if (attr == 0
+        && get_menu_coloring(str.toLatin1().constData(), &mcolor, &mattr)) {
+       itemlist[itemcount].attr = mattr;
+       itemlist[itemcount].color = mcolor;
+    }
+    ++itemcount;
+
+    if (glyph!=NO_GLYPH) has_glyphs=true;
+}
+
+void NetHackQtMenuWindow::EndMenu(const QString& p)
+{
+    prompt.setText(p);
+    promptstr = p;
+}
+
+int NetHackQtMenuWindow::SelectMenu(int h, MENU_ITEM_P **menu_list)
+{
+    QFont tablefont(qt_settings->normalFont());
+    table->setFont(tablefont);
+
+    table->setRowCount(itemcount);
+
+    how=h;
+
+    ok->setEnabled(how!=PICK_ONE);ok->setDefault(how!=PICK_ONE);
+    cancel->setEnabled(how!=PICK_NONE);
+    all->setEnabled(how==PICK_ANY);
+    none->setEnabled(how==PICK_ANY);
+    invert->setEnabled(how==PICK_ANY);
+    search->setEnabled(how!=PICK_NONE);
+
+    setResult(-1);
+
+    // Set contents of table
+    QFontMetrics fm(table->font());
+    for (int i = 0; i < 5; i++) {
+       table->setColumnWidth(i, 0);
+    }
+    for (int i = 0; i < itemcount; i++) {
+       AddRow(i, itemlist[i]);
+    }
+
+    // Determine column widths
+    std::vector<int> col_widths;
+    for (std::size_t i = 0; i < itemlist.size(); ++i) {
+       QStringList columns = itemlist[i].str.split("\t");
+        if (!itemlist[i].Selectable() && columns.size() == 1)
+        {
+            // Nonselectable line with no column dividers
+            // Assume this is a section header
+            continue;
+        }
+       for (std::size_t j = 0U; j < columns.size(); ++j) {
+           int w = fm.width(columns[j] + "  \t");
+           if (j >= col_widths.size()) {
+               col_widths.push_back(w);
+           } else if (col_widths[j] < w) {
+               col_widths[j] = w;
+           }
+       }
+    }
+
+    // Pad each column to its column width
+    for (std::size_t i = 0U; i < itemlist.size(); ++i) {
+       QTableWidgetItem *twi = table->item(i, 4);
+       if (twi == NULL) { continue; }
+       QString text = twi->text();
+       QStringList columns = text.split("\t");
+       for (std::size_t j = 0U; j+1U < columns.size(); ++j) {
+           columns[j] += "\t";
+           int width = col_widths[j];
+           while (fm.width(columns[j]) < width) {
+               columns[j] += "\t";
+           }
+       }
+       text = columns.join("");
+       twi->setText(text);
+       WidenColumn(4, fm.width(text));
+    }
+
+    // FIXME:  size for compact mode
+    //resize(this->width(), parent()->height()*7/8);
+    move(0, 0);
+    adjustSize();
+    centerOnMain(this);
+    exec();
+    int result=this->result();
+
+    *menu_list=0;
+    if (result>0 && how!=PICK_NONE) {
+       if (how==PICK_ONE) {
+           int i;
+           for (i=0; i<itemcount && !isSelected(i); i++)
+               ;
+           if (i<itemcount) {
+               *menu_list=(MENU_ITEM_P *)alloc(sizeof(MENU_ITEM_P)*1);
+               (*menu_list)[0].item=itemlist[i].identifier;
+               (*menu_list)[0].count=count(i);
+               return 1;
+           } else {
+               return 0;
+           }
+       } else {
+           int selcount=0;
+           for (int i=0; i<itemcount; i++)
+               if (isSelected(i)) selcount++;
+           if (selcount) {
+               *menu_list=(MENU_ITEM_P *)alloc(sizeof(MENU_ITEM_P)*selcount);
+               int j=0;
+               for (int i=0; i<itemcount; i++) {
+                   if (isSelected(i)) {
+                       (*menu_list)[j].item=itemlist[i].identifier;
+                       (*menu_list)[j].count=count(i);
+                       j++;
+                   }
+               }
+               return selcount;
+           } else {
+               return 0;
+           }
+       }
+    } else {
+       return -1;
+    }
+}
+
+void NetHackQtMenuWindow::AddRow(int row, const MenuItem& mi)
+{
+    static const QColor colors[] = {
+       QColor(64, 64, 64),
+       QColor(Qt::red),
+       QColor(0, 191, 0),
+       QColor(127, 127, 0),
+       QColor(Qt::blue),
+       QColor(Qt::magenta),
+       QColor(Qt::cyan),
+       QColor(Qt::gray),
+       QColor(Qt::white),
+       QColor(255, 127, 0),
+       QColor(127, 255, 127),
+       QColor(Qt::yellow),
+       QColor(127, 127, 255),
+       QColor(255, 127, 255),
+       QColor(127, 255, 255),
+       QColor(Qt::white)
+    };
+    QFontMetrics fm(table->font());
+    QTableWidgetItem *twi;
+
+    if (mi.Selectable() && how != PICK_NONE) {
+       // Count
+       twi = new QTableWidgetItem("");
+       table->setItem(row, 0, twi);
+       twi->setFlags(Qt::ItemIsEnabled);
+       WidenColumn(0, fm.width("999999"));
+       // Check box, set if selected
+       QCheckBox *cb = new QCheckBox();
+       cb->setChecked(mi.selected);
+       cb->setFocusPolicy(Qt::NoFocus);
+       if (how == PICK_ONE)
+           connect(cb, SIGNAL(clicked(bool)), this, SLOT(DoSelection(bool)));
+       table->setCellWidget(row, 1, cb);
+       WidenColumn(1, cb->width());
+    }
+    if (mi.glyph != NO_GLYPH) {
+       // Icon
+       QPixmap pm(qt_settings->glyphs().glyph(mi.glyph));
+       twi = new QTableWidgetItem(QIcon(pm), "");
+       table->setItem(row, 2, twi);
+       twi->setFlags(Qt::ItemIsEnabled);
+       WidenColumn(2, pm.width());
+    }
+    QString letter, text(mi.str);
+    if (mi.ch != 0) {
+       // Letter specified
+       letter = QString(mi.ch) + " - ";
+    }
+    else {
+       // Letter is left blank, except for skills display when # and * are
+       // presented
+       if (text.startsWith("    ")) {
+           // If mi.str starts with "    ", it's meant to line up with lines
+           // that have a letter; we don't want that here
+           text = text.mid(4);
+       } else if (text.startsWith("   #") || text.startsWith("   *")) {
+           // Put the * or # in the letter column
+           letter = text.left(4);
+           text = text.mid(4);
+       }
+    }
+    twi = new QTableWidgetItem(letter);
+    table->setItem(row, 3, twi);
+    table->item(row, 3)->setFlags(Qt::ItemIsEnabled);
+    WidenColumn(3, fm.width(letter));
+    twi = new QTableWidgetItem(text);
+    table->setItem(row, 4, twi);
+    table->item(row, 4)->setFlags(Qt::ItemIsEnabled);
+    WidenColumn(4, fm.width(text));
+
+    if (mi.color != -1) {
+       twi->setForeground(colors[mi.color]);
+    }
+
+    QFont itemfont(table->font());
+    switch (mi.attr) {
+    case ATR_BOLD:
+       itemfont.setWeight(QFont::Bold);
+       twi->setFont(itemfont);
+       break;
+
+    case ATR_DIM:
+       twi->setFlags(Qt::NoItemFlags);
+       break;
+
+    case ATR_ULINE:
+       itemfont.setUnderline(true);
+       twi->setFont(itemfont);
+       break;
+
+    case ATR_INVERSE:
+       {
+           QBrush fg = twi->foreground();
+           QBrush bg = twi->background();
+           if (fg == bg) {
+               // default foreground and background come up the same for
+               // some unknown reason
+               twi->setForeground(Qt::white);
+               twi->setBackground(Qt::black);
+           } else {
+               twi->setForeground(bg);
+               twi->setBackground(fg);
+           }
+       }
+       break;
+    }
+}
+
+void NetHackQtMenuWindow::WidenColumn(int column, int width)
+{
+    // need to add a bit so the whole column displays
+    width += 7;
+    if (table->columnWidth(column) < width) {
+       table->setColumnWidth(column, width);
+    }
+}
+
+void NetHackQtMenuWindow::InputCount(char key)
+{
+    if (key == '\b')
+    {
+       if (counting)
+       {
+           if (countstr.isEmpty())
+               ClearCount();
+           else
+               countstr = countstr.mid(0, countstr.size() - 1);
+       }
+    }
+    else
+    {
+       counting = true;
+       countstr += QChar(key);
+    }
+    if (counting)
+       prompt.setText("Count: " + countstr);
+}
+
+void NetHackQtMenuWindow::ClearCount(void)
+{
+    counting = false;
+    prompt.setText(promptstr);
+    countstr = "";
+}
+
+void NetHackQtMenuWindow::keyPressEvent(QKeyEvent* event)
+{
+    QString text = event->text();
+
+    const QChar *uni = text.unicode();
+    for (unsigned k = 0; uni[k] != 0; k++) {
+       unsigned key = uni[k].unicode();
+       if (key=='\033') {
+           if (counting)
+               ClearCount();
+           else
+               reject();
+       } else if (key=='\r' || key=='\n' || key==' ')
+           accept();
+       else if (key==MENU_SEARCH)
+           Search();
+       else if (key==MENU_SELECT_ALL || key==MENU_SELECT_PAGE)
+           All();
+       else if (key==MENU_INVERT_ALL || key==MENU_INVERT_PAGE)
+           Invert();
+       else if (key==MENU_UNSELECT_ALL || key==MENU_UNSELECT_PAGE)
+           ChooseNone();
+       else if (('0' <= key && key <= '9') || key == '\b')
+           InputCount(key);
+       else {
+           for (int i=0; i<itemcount; i++) {
+               if (itemlist[i].ch == key || itemlist[i].gch == key)
+                   ToggleSelect(i);
+           }
+       }
+    }
+}
+
+void NetHackQtMenuWindow::All()
+{
+    if (how != PICK_ANY)
+        return;
+
+    for (int i=0; i<itemcount; i++) {
+       QTableWidgetItem *count = table->item(i, 0);
+       if (count != NULL) count->setText("");
+
+       QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
+       if (cb != NULL) cb->setChecked(true);
+    }
+}
+void NetHackQtMenuWindow::ChooseNone()
+{
+    if (how != PICK_ANY)
+        return;
+
+    for (int i=0; i<itemcount; i++) {
+       QTableWidgetItem *count = table->item(i, 0);
+       if (count != NULL) count->setText("");
+
+       QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
+       if (cb != NULL) cb->setChecked(false);
+    }
+}
+void NetHackQtMenuWindow::Invert()
+{
+    if (how != PICK_ANY)
+        return;
+
+    for (int i=0; i<itemcount; i++) {
+       QTableWidgetItem *count = table->item(i, 0);
+       if (count != NULL) count->setText("");
+
+       QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
+       if (cb != NULL) cb->setChecked(cb->checkState() == Qt::Unchecked);
+    }
+}
+void NetHackQtMenuWindow::Search()
+{
+    if (how == PICK_NONE)
+        return;
+
+    NetHackQtStringRequestor requestor(this, "Search for:");
+    char line[256];
+    if (requestor.Get(line)) {
+       for (int i=0; i<itemcount; i++) {
+           if (itemlist[i].str.contains(line))
+               ToggleSelect(i);
+       }
+    }
+}
+void NetHackQtMenuWindow::ToggleSelect(int i)
+{
+    if (itemlist[i].Selectable()) {
+       QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(i, 1));
+       if (cb == NULL) return;
+
+       cb->setChecked((counting && !countstr.isEmpty())
+                   || cb->checkState() == Qt::Unchecked);
+
+       QTableWidgetItem *count = table->item(i, 0);
+       if (count != NULL) count->setText(countstr);
+
+       ClearCount();
+
+       if (how==PICK_ONE) {
+           accept();
+       }
+    }
+}
+
+void NetHackQtMenuWindow::cellToggleSelect(int i, int j)
+{
+    ToggleSelect(i);
+}
+
+void NetHackQtMenuWindow::DoSelection(bool)
+{
+    if (how == PICK_ONE) {
+       accept();
+    }
+}
+
+bool NetHackQtMenuWindow::isSelected(int row)
+{
+    QCheckBox *cb = dynamic_cast<QCheckBox *>(table->cellWidget(row, 1));
+    return cb != NULL && cb->checkState() != Qt::Unchecked;
+}
+
+int NetHackQtMenuWindow::count(int row)
+{
+    QTableWidgetItem *count = table->item(row, 0);
+    if (count == NULL) return -1;
+    QString cstr = count->text();
+    return cstr.isEmpty() ? -1 : cstr.toInt();
+}
+
+NetHackQtTextWindow::NetHackQtTextWindow(QWidget *parent) :
+    QDialog(parent),
+    use_rip(false),
+    str_fixed(false),
+    ok("Dismiss",this),
+    search("Search",this),
+    lines(new NetHackQtTextListBox(this)),
+    rip(this)
+{
+    ok.setDefault(true);
+    connect(&ok,SIGNAL(clicked()),this,SLOT(accept()));
+    connect(&search,SIGNAL(clicked()),this,SLOT(Search()));
+    connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(doUpdate()));
+
+    QVBoxLayout* vb = new QVBoxLayout(this);
+    vb->addWidget(&rip);
+    QHBoxLayout* hb = new QHBoxLayout();
+    vb->addLayout(hb);
+    hb->addWidget(&ok);
+    hb->addWidget(&search);
+    vb->addWidget(lines);
+}
+
+void NetHackQtTextWindow::doUpdate()
+{
+    update();
+}
+
+
+NetHackQtTextWindow::~NetHackQtTextWindow()
+{
+
+}
+
+QWidget* NetHackQtTextWindow::Widget()
+{
+    return this;
+}
+
+bool NetHackQtTextWindow::Destroy()
+{
+    return !isVisible();
+}
+
+void NetHackQtTextWindow::UseRIP(int how, time_t when)
+{
+// Code from X11 windowport
+#define STONE_LINE_LEN 16    /* # chars that fit on one line */
+#define NAME_LINE 0    /* line # for player name */
+#define GOLD_LINE 1    /* line # for amount of gold */
+#define DEATH_LINE 2   /* line # for death description */
+#define YEAR_LINE 6    /* line # for year */
+
+static char** rip_line=0;
+    if (!rip_line) {
+       rip_line=new char*[YEAR_LINE+1];
+       for (int i=0; i<YEAR_LINE+1; i++) {
+           rip_line[i]=new char[STONE_LINE_LEN+1];
+       }
+    }
+
+    /* Follows same algorithm as genl_outrip() */
+
+    char buf[BUFSZ];
+    char *dpx;
+    int line;
+
+    /* Put name on stone */
+    snprintf(rip_line[NAME_LINE], STONE_LINE_LEN+1, "%s", plname);
+
+    /* Put $ on stone */
+    snprintf(rip_line[GOLD_LINE], STONE_LINE_LEN+1, "%ld Au", money_cnt(invent));
+
+    /* Put together death description */
+    formatkiller(buf, sizeof buf, how, FALSE);
+    //str_copy(buf, killer, SIZE(buf));
+
+    /* Put death type on stone */
+    for (line=DEATH_LINE, dpx = buf; line<YEAR_LINE; line++) {
+       int i,i0;
+       char tmpchar;
+
+       if ( (i0=strlen(dpx)) > STONE_LINE_LEN) {
+           for(i = STONE_LINE_LEN;
+               ((i0 > STONE_LINE_LEN) && i); i--)
+               if(dpx[i] == ' ') i0 = i;
+           if(!i) i0 = STONE_LINE_LEN;
+       }
+       tmpchar = dpx[i0];
+       dpx[i0] = 0;
+       str_copy(rip_line[line], dpx, STONE_LINE_LEN+1);
+       if (tmpchar != ' ') {
+           dpx[i0] = tmpchar;
+           dpx= &dpx[i0];
+       } else  dpx= &dpx[i0+1];
+    }
+
+    /* Put year on stone */
+    snprintf(rip_line[YEAR_LINE], STONE_LINE_LEN+1, "%4d", getyear());
+
+    rip.setLines(rip_line,YEAR_LINE+1);
+
+    use_rip=true;
+}
+
+void NetHackQtTextWindow::Clear()
+{
+    lines->clear();
+    use_rip=false;
+    str_fixed=false;
+}
+
+void NetHackQtTextWindow::Display(bool block)
+{
+    if (str_fixed) {
+       lines->setFont(qt_settings->normalFixedFont());
+    } else {
+       lines->setFont(qt_settings->normalFont());
+    }
+
+    int h=0;
+    if (use_rip) {
+       h+=rip.height();
+       ok.hide();
+       search.hide();
+       rip.show();
+    } else {
+       h+=ok.height()*2 + 7;
+       ok.show();
+       search.show();
+       rip.hide();
+    }
+    int mh = QApplication::desktop()->height()*3/5;
+    if ( (qt_compact_mode && lines->TotalHeight() > mh) || use_rip ) {
+       // big, so make it fill
+       showMaximized();
+    } else {
+       move(0, 0);
+       adjustSize();
+       centerOnMain(this);
+       show();
+    }
+    exec();
+}
+
+void NetHackQtTextWindow::PutStr(int attr, const QString& text)
+{
+    str_fixed=str_fixed || text.contains("    ");
+    lines->addItem(text);
+}
+
+void NetHackQtTextWindow::Search()
+{
+    NetHackQtStringRequestor requestor(this, "Search for:");
+    static char line[256]="";
+    requestor.SetDefault(line);
+    if (requestor.Get(line)) {
+       int current=lines->currentRow();
+       for (int i=1; i<lines->count(); i++) {
+           int lnum=(i+current)%lines->count();
+           QString str=lines->item(lnum)->text();
+           if (str.contains(line)) {
+               lines->setCurrentRow(lnum);
+               return;
+           }
+       }
+       lines->setCurrentItem(NULL);
+    }
+}
+
+NetHackQtMenuOrTextWindow::NetHackQtMenuOrTextWindow(QWidget *parent_) :
+    actual(0),
+    parent(parent_)
+{
+}
+
+QWidget* NetHackQtMenuOrTextWindow::Widget()
+{
+    if (!actual) impossible("Widget called before we know if Menu or Text");
+    return actual->Widget();
+}
+
+// Text
+void NetHackQtMenuOrTextWindow::Clear()
+{
+    if (!actual) impossible("Clear called before we know if Menu or Text");
+    actual->Clear();
+}
+void NetHackQtMenuOrTextWindow::Display(bool block)
+{
+    if (!actual) impossible("Display called before we know if Menu or Text");
+    actual->Display(block);
+}
+bool NetHackQtMenuOrTextWindow::Destroy()
+{
+    if (!actual) impossible("Destroy called before we know if Menu or Text");
+    return actual->Destroy();
+}
+
+void NetHackQtMenuOrTextWindow::PutStr(int attr, const QString& text)
+{
+    if (!actual) actual=new NetHackQtTextWindow(parent);
+    actual->PutStr(attr,text);
+}
+
+// Menu
+void NetHackQtMenuOrTextWindow::StartMenu()
+{
+    if (!actual) actual=new NetHackQtMenuWindow(parent);
+    actual->StartMenu();
+}
+void NetHackQtMenuOrTextWindow::AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
+       const QString& str, bool presel)
+{
+    if (!actual) impossible("AddMenu called before we know if Menu or Text");
+    actual->AddMenu(glyph,identifier,ch,gch,attr,str,presel);
+}
+void NetHackQtMenuOrTextWindow::EndMenu(const QString& prompt)
+{
+    if (!actual) impossible("EndMenu called before we know if Menu or Text");
+    actual->EndMenu(prompt);
+}
+int NetHackQtMenuOrTextWindow::SelectMenu(int how, MENU_ITEM_P **menu_list)
+{
+    if (!actual) impossible("SelectMenu called before we know if Menu or Text");
+    return actual->SelectMenu(how,menu_list);
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4menu.h b/win/Qt4/qt4menu.h
new file mode 100644 (file)
index 0000000..5bc2659
--- /dev/null
@@ -0,0 +1,183 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4menu.cpp -- a menu or text-list widget
+
+#ifndef QT4MENU_H
+#define QT4MENU_H
+
+#include "qt4win.h"
+#include "qt4rip.h"
+
+namespace nethack_qt4 {
+
+class NetHackQtTextListBox : public QListWidget {
+public:
+    NetHackQtTextListBox(QWidget* parent = NULL) : QListWidget(parent) { }
+
+    int TotalWidth() const
+    {
+       int width = 0;
+       QFontMetrics fm(font());
+       for (int i = 0; i < count(); i++) {
+           int lwidth = fm.width(item(i)->text());
+           width = std::max(width, lwidth);
+       }
+       return width;
+    }
+    int TotalHeight() const
+    {
+       QFontMetrics fm(font());
+       return fm.height() * count();
+    }
+
+    virtual QSize sizeHint() const;
+};
+
+class NetHackQtMenuListBox : public QTableWidget {
+public:
+    NetHackQtMenuListBox(QWidget* parent = NULL) : QTableWidget(parent) { }
+
+    int TotalWidth() const;
+    int TotalHeight() const;
+
+    virtual QSize sizeHint() const;
+};
+
+class NetHackQtMenuWindow : public QDialog, public NetHackQtWindow {
+       Q_OBJECT
+public:
+       NetHackQtMenuWindow(QWidget *parent = NULL);
+       ~NetHackQtMenuWindow();
+
+       virtual QWidget* Widget();
+
+       virtual void StartMenu();
+       virtual void AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
+                       const QString& str, bool presel);
+       virtual void EndMenu(const QString& prompt);
+       virtual int SelectMenu(int how, MENU_ITEM_P **menu_list);
+
+public slots:
+       void All();
+       void ChooseNone();
+       void Invert();
+       void Search();
+
+       void ToggleSelect(int);
+        void cellToggleSelect(int, int);
+       void DoSelection(bool);
+
+protected:
+       virtual void keyPressEvent(QKeyEvent*);
+
+private:
+       struct MenuItem {
+               MenuItem();
+               ~MenuItem();
+
+               int glyph;
+               ANY_P identifier;
+               int attr;
+               QString str;
+               int count;
+               char ch;
+                char gch;
+               bool selected;
+                unsigned color;
+
+               bool Selectable() const { return identifier.a_void!=0; }
+       };
+
+       QVector<MenuItem> itemlist;
+
+       int itemcount;
+       int next_accel;
+
+       QTableWidget* table;
+       QPushButton* ok;
+       QPushButton* cancel;
+       QPushButton* all;
+       QPushButton* none;
+       QPushButton* invert;
+       QPushButton* search;
+       QLabel prompt;
+
+       // Count replaces prompt while it is being input
+       QString promptstr;
+       QString countstr;
+       bool counting;
+       void InputCount(char key);
+       void ClearCount(void);
+
+       int how;
+
+       bool has_glyphs;
+
+       bool isSelected(int row);
+       int count(int row);
+
+       void AddRow(int row, const MenuItem& mi);
+       void WidenColumn(int column, int width);
+};
+
+class NetHackQtTextWindow : public QDialog, public NetHackQtWindow {
+       Q_OBJECT
+public:
+       NetHackQtTextWindow(QWidget *parent = NULL);
+       ~NetHackQtTextWindow();
+
+       virtual QWidget* Widget();
+
+       virtual void Clear();
+       virtual bool Destroy();
+       virtual void Display(bool block);
+       virtual void PutStr(int attr, const QString& text);
+       virtual void UseRIP(int how, time_t when);
+
+public slots:
+       void Search();
+
+private slots:
+       void doUpdate();
+
+private:
+       bool use_rip;
+       bool str_fixed;
+
+       QPushButton ok;
+       QPushButton search;
+       NetHackQtTextListBox* lines;
+
+       NetHackQtRIP rip;
+};
+
+class NetHackQtMenuOrTextWindow : public NetHackQtWindow {
+private:
+       NetHackQtWindow* actual;
+    QWidget *parent;
+
+public:
+       NetHackQtMenuOrTextWindow(QWidget *parent = NULL);
+
+       virtual QWidget* Widget();
+
+       // Text
+       virtual void Clear();
+       virtual bool Destroy();
+       virtual void Display(bool block);
+       virtual void PutStr(int attr, const QString& text);
+
+       // Menu
+       virtual void StartMenu();
+       virtual void AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
+                       const QString& str, bool presel);
+       virtual void EndMenu(const QString& prompt);
+       virtual int SelectMenu(int how, MENU_ITEM_P **menu_list);
+
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4msg.cpp b/win/Qt4/qt4msg.cpp
new file mode 100644 (file)
index 0000000..d82e102
--- /dev/null
@@ -0,0 +1,155 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4msg.cpp -- a message window
+
+extern "C" {
+#include "hack.h"
+}
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4msg.h"
+#include "qt4msg.moc"
+#include "qt4map.h"
+#include "qt4set.h"
+#include "qt4str.h"
+
+namespace nethack_qt4 {
+
+NetHackQtMessageWindow::NetHackQtMessageWindow() :
+    list(new QListWidget())
+{
+    list->setFocusPolicy(Qt::NoFocus);
+    ::iflags.window_inited = 1;
+    map = 0;
+    currgetmsg = 0;
+    connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(updateFont()));
+    updateFont();
+}
+
+NetHackQtMessageWindow::~NetHackQtMessageWindow()
+{
+    ::iflags.window_inited = 0;
+    delete list;
+}
+
+QWidget* NetHackQtMessageWindow::Widget() { return list; }
+
+void NetHackQtMessageWindow::setMap(NetHackQtMapWindow2* m)
+{
+    map = m;
+    updateFont();
+}
+
+void NetHackQtMessageWindow::updateFont()
+{
+    list->setFont(qt_settings->normalFont());
+    if ( map )
+       map->setFont(qt_settings->normalFont());
+}
+
+void NetHackQtMessageWindow::Scroll(int dx, int dy)
+{
+    //RLC Is this necessary?
+    //RLC list->Scroll(dx,dy);
+}
+
+void NetHackQtMessageWindow::Clear()
+{
+    if ( map )
+       map->clearMessages();
+}
+
+void NetHackQtMessageWindow::ClearMessages()
+{
+    if (list)
+        list->clear();
+}
+
+void NetHackQtMessageWindow::Display(bool block)
+{
+    if (changed) {
+       list->repaint();
+       changed=false;
+    }
+}
+
+const char * NetHackQtMessageWindow::GetStr(bool init)
+{
+    if (init)
+        currgetmsg = 0;
+
+    QListWidgetItem *item = list->item(currgetmsg++);
+    if (item) {
+        QString str = item->text();
+        //raw_printf("getstr[%i]='%s'", currgetmsg, str.toLatin1().constData());
+        return str.toLatin1().constData();
+    }
+    return NULL;
+}
+
+void NetHackQtMessageWindow::PutStr(int attr, const QString& text)
+{
+#ifdef USER_SOUNDS
+    play_sound_for_message(text.toLatin1().constData());
+#endif
+
+    changed=true;
+
+    // If the line is output from the "/" command, map the first character
+    // as a symbol
+    QString text2;
+    if (text.mid(1, 3) == "   ") {
+       text2 = QChar(cp437(text.at(0).unicode())) + text.mid(1);
+    } else {
+       text2 = text;
+    }
+#if 0
+    QListWidgetItem *item = new QListWidgetItem(text2);
+
+    QFont font = item->font();
+    font.setUnderline(attr == ATR_ULINE);
+    font.setWeight((attr == ATR_BOLD) ? QFont::Bold : QFont::Normal);
+    item->setFont(font);
+
+    QColor fg = item->foreground().color();
+    QColor bg = item->background().color();
+    if (attr == ATR_DIM)
+    {
+       fg.setAlpha(fg.alpha() / 2);
+    }
+    if (attr == ATR_INVERSE)
+    {
+       QColor swap;
+       swap = fg; fg = bg; bg = swap;
+    }
+    item->setForeground(fg);
+    item->setBackground(bg);
+#endif
+
+    // ATR_BLINK not supported
+    if (list->count() >= ::iflags.msg_history)
+       delete list->item(0);
+    list->addItem(text2);
+
+    // Force scrollbar to bottom
+    list->setCurrentRow(list->count()-1);
+
+    if ( map )
+       map->putMessage(attr, text2);
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4msg.h b/win/Qt4/qt4msg.h
new file mode 100644 (file)
index 0000000..f4091ad
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4msg.h -- a message window
+
+#ifndef QT4MSG_H
+#define QT4MSG_H
+
+#include "qt4win.h"
+
+namespace nethack_qt4 {
+
+class NetHackQtMapWindow2;
+
+class NetHackQtMessageWindow : QObject, public NetHackQtWindow {
+       Q_OBJECT
+public:
+       NetHackQtMessageWindow();
+       ~NetHackQtMessageWindow();
+
+       virtual QWidget* Widget();
+       virtual void Clear();
+       virtual void Display(bool block);
+        virtual const char *GetStr(bool init);
+       virtual void PutStr(int attr, const QString& text);
+
+       void Scroll(int dx, int dy);
+        void ClearMessages();
+
+       void setMap(NetHackQtMapWindow2*);
+
+private:
+       QListWidget* list;
+       bool changed;
+        int currgetmsg;
+       NetHackQtMapWindow2* map;
+
+private slots:
+       void updateFont();
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4plsel.cpp b/win/Qt4/qt4plsel.cpp
new file mode 100644 (file)
index 0000000..81bf5f0
--- /dev/null
@@ -0,0 +1,536 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4plsel.cpp -- player selector dialog
+
+extern "C" {
+#include "hack.h"
+}
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4plsel.h"
+#include "qt4plsel.moc"
+#include "qt4bind.h"
+#include "qt4glyph.h"
+#include "qt4set.h"
+#include "qt4str.h"
+
+// Warwick prefers it this way...
+#define QT_CHOOSE_RACE_FIRST
+
+namespace nethack_qt4 {
+
+// temporary
+void centerOnMain( QWidget* w );
+// end temporary
+
+static const char nh_attribution[] = "<center><big>NetHack %1</big>"
+       "<br><small>by the NetHack DevTeam</small></center>";
+
+class NhPSListViewItem : public QTableWidgetItem {
+public:
+    NhPSListViewItem( QTableWidget* parent, const QString& name ) :
+       QTableWidgetItem(name)
+    {
+    }
+
+    void setGlyph(int g)
+    {
+       NetHackQtGlyphs& glyphs = qt_settings->glyphs();
+       int gw = glyphs.width();
+       int gh = glyphs.height();
+       QPixmap pm(gw,gh);
+       QPainter p(&pm);
+       glyphs.drawGlyph(p, g, 0, 0);
+       p.end();
+       setIcon(QIcon(pm));
+       //RLC setHeight(std::max(pm.height()+1,height()));
+    }
+
+#if 0 //RLC
+    void paintCell( QPainter *p, const QColorGroup &cg,
+                   int column, int width, int alignment )
+    {
+       if ( isSelectable() ) {
+           QTableWidgetItem::paintCell( p, cg, column, width, alignment );
+       } else {
+           QColorGroup disabled(
+               cg.foreground().light(),
+               cg.button().light(),
+               cg.light(), cg.dark(), cg.mid(),
+               Qt::gray, cg.base() );
+           QTableWidgetItem::paintCell( p, disabled, column, width, alignment );
+       }
+    }
+#endif
+};
+
+class NhPSListViewRole : public NhPSListViewItem {
+public:
+    NhPSListViewRole( QTableWidget* parent, int id ) :
+       NhPSListViewItem(parent,
+#ifdef QT_CHOOSE_RACE_FIRST // Lowerize - looks better
+           QString(roles[id].name.m).toLower()
+#else
+           roles[id].name.m
+#endif
+       )
+    {
+       setGlyph(monnum_to_glyph(roles[id].malenum));
+    }
+};
+
+class NhPSListViewRace : public NhPSListViewItem {
+public:
+    NhPSListViewRace( QTableWidget* parent, int id ) :
+       NhPSListViewItem(parent,
+#ifdef QT_CHOOSE_RACE_FIRST // Capitalize - looks better
+           str_titlecase(races[id].noun)
+#else
+           races[id].noun
+#endif
+       )
+    {
+       setGlyph(monnum_to_glyph(races[id].malenum));
+    }
+};
+
+class NhPSListView : public QTableWidget {
+public:
+    NhPSListView( QWidget* parent ) :
+       QTableWidget(parent)
+    {
+       setColumnCount(1);
+       verticalHeader()->hide();
+#if QT_VERSION >= 0x050000
+       horizontalHeader()->setSectionsClickable(false);
+#else
+       horizontalHeader()->setClickable(false);
+#endif
+    }
+
+    QSizePolicy sizePolicy() const
+    {
+       return QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
+    }
+
+    QSize minimumSizeHint() const
+    {
+       return sizeHint();
+    }
+
+    QSize sizeHint() const
+    {
+       return QSize(columnWidth(0), QTableWidget::sizeHint().height());
+    }
+};
+
+NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) :
+    QDialog(NetHackQtBind::mainWidget()),
+    fully_specified_role(true)
+{
+    /*
+               0             1             2
+         + Name ------------------------------------+
+       0 |                                          |
+         + ---- ------------------------------------+
+         + Role ---+   + Race ---+   + Gender ------+
+         |         |   |         |   |  * Male      |
+       1 |         |   |         |   |  * Female    |
+         |         |   |         |   +--------------+
+         |         |   |         |   
+         |         |   |         |   + Alignment ---+
+       2 |         |   |         |   |  * Male      |
+         |         |   |         |   |  * Female    |
+         |         |   |         |   +--------------+
+       3 |         |   |         |   ...stretch...
+         |         |   |         |   
+       4 |         |   |         |   [ Random ]
+       5 |         |   |         |   [  Play  ]
+       6 |         |   |         |   [  Quit  ]
+         +---------+   +---------+   
+    */
+
+    QGridLayout *l = new QGridLayout(this);
+    l->setColumnStretch(2, 1);
+    sizePolicy().setHorizontalPolicy(QSizePolicy::Minimum);
+
+    QGroupBox* namebox = new QGroupBox("Name", this);
+    QVBoxLayout *namelayout = new QVBoxLayout(namebox);
+    QLineEdit* name = new QLineEdit(namebox);
+    namelayout->addWidget(name);
+    name->setMaxLength(sizeof(plname)-1);
+    if ( strncmp(plname,"player",6) && strncmp(plname,"games",5) )
+       name->setText(plname);
+    connect(name, SIGNAL(textChanged(const QString&)),
+           this, SLOT(selectName(const QString&)) );
+    name->setFocus();
+    QGroupBox* genderbox = new QGroupBox("Gender",this);
+    QButtonGroup *gendergroup = new QButtonGroup(this);
+    QGroupBox* alignbox = new QGroupBox("Alignment",this);
+    QButtonGroup *aligngroup = new QButtonGroup(this);
+    QVBoxLayout* vbgb = new QVBoxLayout(genderbox);
+    QVBoxLayout* vbab = new QVBoxLayout(alignbox);
+    char versionbuf[QBUFSZ];
+    QLabel* logo = new QLabel(QString(nh_attribution).arg(version_string(versionbuf)), this);
+
+    l->addWidget( namebox, 0,0,1,3 );
+#ifdef QT_CHOOSE_RACE_FIRST
+    race = new NhPSListView(this);
+    role = new NhPSListView(this);
+    l->addWidget( race, 1,0,6,1 );
+    l->addWidget( role, 1,1,6,1 );
+#else
+    role = new NhPSListView(this);
+    race = new NhPSListView(this);
+    l->addWidget( role, 1,0,6,1 );
+    l->addWidget( race, 1,1,6,1 );
+#endif
+
+    l->addWidget( genderbox, 1, 2 );
+    l->addWidget( alignbox, 2, 2 );
+    l->addWidget( logo, 3, 2, Qt::AlignCenter );
+    l->setRowStretch( 3, 6 );
+
+    int i;
+    int nrole;
+
+    chosen_gend = flags.initgend;
+    chosen_align = flags.initalign;
+
+    // XXX QListView unsorted goes in rev.
+    for (nrole=0; roles[nrole].name.m; nrole++)
+       ;
+    role->setRowCount(nrole);
+    for (i=0; roles[i].name.m; i++) {
+       QTableWidgetItem *item = new QTableWidgetItem(
+               QIcon(qt_settings->glyphs().glyph(roles[i].malenum)),
+               roles[i].name.m);
+       item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
+       role->setItem(i, 0, item);
+    }
+    connect( role, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(selectRole(int, int, int, int)) );
+    role->setHorizontalHeaderLabels(QStringList("Role"));
+    role->resizeColumnToContents(0);
+
+    int nrace;
+    for (nrace=0; races[nrace].noun; nrace++)
+       ;
+    race->setRowCount(nrace);
+    for (i=0; races[i].noun; i++) {
+       QTableWidgetItem *item = new QTableWidgetItem(
+               QIcon(qt_settings->glyphs().glyph(races[i].malenum)),
+               races[i].noun);
+       item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
+       race->setItem(i, 0, item);
+    }
+    connect( race, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(selectRace(int, int, int, int)) );
+    race->setHorizontalHeaderLabels(QStringList("Race"));
+    race->resizeColumnToContents(0);
+
+    gender = new QRadioButton*[ROLE_GENDERS];
+    for (i=0; i<ROLE_GENDERS; i++) {
+       gender[i] = new QRadioButton( genders[i].adj, genderbox );
+       genderbox->layout()->addWidget(gender[i]);
+       gendergroup->addButton(gender[i], i);
+    }
+    connect( gendergroup, SIGNAL(buttonPressed(int)), this, SLOT(selectGender(int)) );
+
+    alignment = new QRadioButton*[ROLE_ALIGNS];
+    for (i=0; i<ROLE_ALIGNS; i++) {
+       alignment[i] = new QRadioButton( aligns[i].adj, alignbox );
+       alignbox->layout()->addWidget(alignment[i]);
+       aligngroup->addButton(alignment[i], i);
+    }
+    connect( aligngroup, SIGNAL(buttonPressed(int)), this, SLOT(selectAlignment(int)) );
+
+    QPushButton* rnd = new QPushButton("Random",this);
+    l->addWidget( rnd, 4, 2 );
+    rnd->setDefault(false);
+    connect( rnd, SIGNAL(clicked()), this, SLOT(Randomize()) );
+
+    QPushButton* ok = new QPushButton("Play",this);
+    l->addWidget( ok, 5, 2 );
+    ok->setDefault(true);
+    connect( ok, SIGNAL(clicked()), this, SLOT(accept()) );
+
+    QPushButton* cancel = new QPushButton("Quit",this);
+    l->addWidget( cancel, 6, 2 );
+    connect( cancel, SIGNAL(clicked()), this, SLOT(reject()) );
+
+    Randomize();
+}
+
+void NetHackQtPlayerSelector::Randomize()
+{
+    int nrole = role->rowCount();
+    int nrace = race->rowCount();
+
+    boolean picksomething = (flags.initrole == ROLE_NONE
+                             || flags.initrace == ROLE_NONE
+                             || flags.initgend == ROLE_NONE
+                             || flags.initalign == ROLE_NONE);
+
+    if (flags.randomall && picksomething) {
+        if (flags.initrole == ROLE_NONE)
+            flags.initrole = ROLE_RANDOM;
+        if (flags.initrace == ROLE_NONE)
+            flags.initrace = ROLE_RANDOM;
+        if (flags.initgend == ROLE_NONE)
+            flags.initgend = ROLE_RANDOM;
+        if (flags.initalign == ROLE_NONE)
+            flags.initalign = ROLE_RANDOM;
+    }
+
+    rigid_role_checks();
+
+    // Randomize race and role, unless specified in config
+    int ro = flags.initrole;
+    if (ro == ROLE_NONE || ro == ROLE_RANDOM) {
+       ro = rn2(nrole);
+       if (flags.initrole != ROLE_RANDOM) {
+           fully_specified_role = false;
+       }
+    }
+    int ra = flags.initrace;
+    if (ra == ROLE_NONE || ra == ROLE_RANDOM) {
+       ra = rn2(nrace);
+       if (flags.initrace != ROLE_RANDOM) {
+           fully_specified_role = false;
+       }
+    }
+
+    // make sure we have a valid combination, honoring
+    // the users request if possible.
+    bool choose_race_first;
+#ifdef QT_CHOOSE_RACE_FIRST
+    choose_race_first = true;
+    if (flags.initrole >= 0 && flags.initrace < 0) {
+       choose_race_first = false;
+    }
+#else
+    choose_race_first = false;
+    if (flags.initrace >= 0 && flags.initrole < 0) {
+       choose_race_first = true;
+    }
+#endif
+    while (!validrace(ro,ra)) {
+       if (choose_race_first) {
+           ro = rn2(nrole);
+           if (flags.initrole != ROLE_RANDOM) {
+               fully_specified_role = false;
+           }
+       } else {
+           ra = rn2(nrace);
+           if (flags.initrace != ROLE_RANDOM) {
+               fully_specified_role = false;
+           }
+       }
+    }
+
+    int g = flags.initgend;
+    if (g == -1) {
+       g = rn2(ROLE_GENDERS);
+       fully_specified_role = false;
+    }
+    while (!validgend(ro,ra,g)) {
+       g = rn2(ROLE_GENDERS);
+    }
+    gender[g]->setChecked(true);
+    selectGender(g);
+
+    int a = flags.initalign;
+    if (a == -1) {
+       a = rn2(ROLE_ALIGNS);
+       fully_specified_role = false;
+    }
+    while (!validalign(ro,ra,a)) {
+       a = rn2(ROLE_ALIGNS);
+    }
+    alignment[a]->setChecked(true);
+    selectAlignment(a);
+
+    role->setCurrentCell(ro, 0);
+
+    race->setCurrentCell(ra, 0);
+}
+
+void NetHackQtPlayerSelector::selectName(const QString& n)
+{
+    str_copy(plname,n.toLatin1().constData(),SIZE(plname));
+}
+
+void NetHackQtPlayerSelector::selectRole(int crow, int ccol, int prow, int pcol)
+{
+    int ra = race->currentRow();
+    int ro = role->currentRow();
+    if (ra == -1 || ro == -1) return;
+    QTableWidgetItem* item;
+    item = role->item(prow, 0);
+    if (item != NULL)
+       item->setSelected(false);
+
+#ifdef QT_CHOOSE_RACE_FIRST
+    selectRace(crow, ccol, prow, pcol);
+#else
+    QTableWidgetItem* i=role->currentItem();
+    QTableWidgetItem* valid=0;
+    int j;
+    for (j=0; roles[j].name.m; j++) {
+       bool v = validrace(j,ra);
+       item = role->item(j, 0);
+       item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
+       if ( !valid && v ) valid = item;
+    }
+    if ( !validrace(role->currentRow(),ra) )
+       i = valid;
+    role->setCurrentItem(i, 0);
+    for (j=0; roles[j].name.m; j++) {
+       item = role->item(j, 0);
+       item->setSelected(item == i);
+       bool v = validrace(j,ra);
+       item->setFlags(
+               v ? Qt::ItemIsEnabled|Qt::ItemIsSelectable
+                 : Qt::NoItemFlags);
+    }
+#endif
+
+    //flags.initrole = role->currentRow();
+    setupOthers();
+}
+
+void NetHackQtPlayerSelector::selectRace(int crow, int ccol, int prow, int pcol)
+{
+    int ra = race->currentRow();
+    int ro = role->currentRow();
+    if (ra == -1 || ro == -1) return;
+    QTableWidgetItem* item;
+    item = race->item(prow, 0);
+    if (item != NULL)
+       item->setSelected(false);
+
+#ifndef QT_CHOOSE_RACE_FIRST
+    selectRole(crow, ccol, prow, pcol);
+#else
+    QTableWidgetItem* i=race->currentItem();
+    QTableWidgetItem* valid=0;
+    int j;
+    for (j=0; races[j].noun; j++) {
+       bool v = validrace(ro,j);
+       item = race->item(j, 0);
+       item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
+       if ( !valid && v ) valid = item;
+    }
+    if ( !validrace(ro,race->currentRow()) )
+       i = valid;
+    for (j=0; races[j].noun; j++) {
+       item = race->item(j, 0);
+       item->setSelected(item == i);
+       bool v = validrace(ro,j);
+       item->setFlags(
+               v ? Qt::ItemIsEnabled|Qt::ItemIsSelectable
+                 : Qt::NoItemFlags);
+    }
+#endif
+
+    //flags.initrace = race->currentRow();
+    setupOthers();
+}
+
+void NetHackQtPlayerSelector::setupOthers()
+{
+    int ro = role->currentRow();
+    int ra = race->currentRow();
+    int valid=-1;
+    int c=0;
+    int j;
+    for (j=0; j<ROLE_GENDERS; j++) {
+       bool v = validgend(ro,ra,j);
+       if ( gender[j]->isChecked() )
+           c = j;
+       gender[j]->setEnabled(v);
+       if ( valid<0 && v ) valid = j;
+    }
+    if ( !validgend(ro,ra,c) )
+       c = valid;
+    int k;
+    for (k=0; k<ROLE_GENDERS; k++) {
+       gender[k]->setChecked(c==k);
+    }
+    selectGender(c);
+
+    valid=-1;
+    for (j=0; j<ROLE_ALIGNS; j++) {
+       bool v = validalign(ro,ra,j);
+       if ( alignment[j]->isChecked() )
+           c = j;
+       alignment[j]->setEnabled(v);
+       if ( valid<0 && v ) valid = j;
+    }
+    if ( !validalign(ro,ra,c) )
+       c = valid;
+    for (k=0; k<ROLE_ALIGNS; k++) {
+       alignment[k]->setChecked(c==k);
+    }
+    selectAlignment(c);
+}
+
+void NetHackQtPlayerSelector::selectGender(int i)
+{
+    chosen_gend = i;
+}
+
+void NetHackQtPlayerSelector::selectAlignment(int i)
+{
+    chosen_align = i;
+}
+
+void NetHackQtPlayerSelector::Quit()
+{
+    done(R_Quit);
+}
+
+void NetHackQtPlayerSelector::Random()
+{
+    done(R_Rand);
+}
+
+bool NetHackQtPlayerSelector::Choose()
+{
+    if (fully_specified_role) return true;
+
+#if defined(QWS) // probably safe with Qt 3, too (where show!=exec in QDialog).
+    if ( qt_compact_mode ) {
+       showMaximized();
+    } else
+#endif
+    {
+       adjustSize();
+       centerOnMain(this);
+    }
+
+    if ( exec() ) {
+        flags.initrace = race->currentRow();
+        flags.initrole = role->currentRow();
+        flags.initgend = chosen_gend;
+        flags.initalign = chosen_align;
+       return true;
+    } else {
+       return false;
+    }
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4plsel.h b/win/Qt4/qt4plsel.h
new file mode 100644 (file)
index 0000000..de070d1
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4plsel.h -- player selector dialog
+
+#ifndef QT4PLSEL_H
+#define QT4PLSEL_H
+
+namespace nethack_qt4 {
+
+class NetHackQtKeyBuffer;
+
+class NetHackQtPlayerSelector : private QDialog {
+       Q_OBJECT
+public:
+       enum { R_None=-1, R_Quit=-2, R_Rand=-3 };
+
+       NetHackQtPlayerSelector(NetHackQtKeyBuffer&);
+
+public slots:
+       void Quit();
+       void Random();
+        void Randomize();
+
+       void selectName(const QString& n);
+       void selectRole(int current, int, int previous, int);
+       void selectRace(int current, int, int previous, int);
+       void setupOthers();
+       void selectGender(int);
+       void selectAlignment(int);
+
+public:
+       bool Choose();
+
+private:
+       QTableWidget* role;
+       QTableWidget* race;
+       QRadioButton **gender;
+       QRadioButton **alignment;
+       bool fully_specified_role;
+        int chosen_gend;
+        int chosen_align;
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4rip.cpp b/win/Qt4/qt4rip.cpp
new file mode 100644 (file)
index 0000000..d509f88
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4rip.cpp -- tombstone window
+
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4rip.h"
+#include "qt4bind.h"
+#include "qt4str.h"
+
+namespace nethack_qt4 {
+
+QPixmap* NetHackQtRIP::pixmap=0;
+
+// Debian uses a separate PIXMAPDIR
+#ifndef PIXMAPDIR
+# ifdef HACKDIR
+#  define PIXMAPDIR HACKDIR
+# else
+#  define PIXMAPDIR "."
+# endif
+#endif
+
+static void
+tryload(QPixmap& pm, const char* fn)
+{
+    if (!pm.load(fn)) {
+       QString msg;
+       msg.sprintf("Cannot load \"%s\"", fn);
+       QMessageBox::warning(NetHackQtBind::mainWidget(), "IO Error", msg);
+    }
+}
+
+NetHackQtRIP::NetHackQtRIP(QWidget* parent) :
+    QWidget(parent)
+{
+    if (!pixmap) {
+       pixmap=new QPixmap;
+       tryload(*pixmap, PIXMAPDIR "/rip.xpm");
+    }
+    riplines=0;
+    resize(pixmap->width(),pixmap->height());
+    setFont(QFont("times",12)); // XXX may need to be configurable
+}
+
+void NetHackQtRIP::setLines(char** l, int n)
+{
+    line=l;
+    riplines=n;
+}
+
+QSize NetHackQtRIP::sizeHint() const
+{
+    return pixmap->size();
+}
+
+void NetHackQtRIP::paintEvent(QPaintEvent* event)
+{
+    if ( riplines ) {
+       int pix_x=(width()-pixmap->width())/2;
+       int pix_y=(height()-pixmap->height())/2;
+
+       // XXX positions based on RIP image
+       int rip_text_x=pix_x+156;
+       int rip_text_y=pix_y+67;
+       int rip_text_h=94/riplines;
+
+       QPainter painter;
+       painter.begin(this);
+       painter.drawPixmap(pix_x,pix_y,*pixmap);
+       for (int i=0; i<riplines; i++) {
+           painter.drawText(rip_text_x-i/2,rip_text_y+i*rip_text_h,
+               1,1,Qt::TextDontClip|Qt::AlignHCenter,line[i]);
+       }
+       painter.end();
+    }
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4rip.h b/win/Qt4/qt4rip.h
new file mode 100644 (file)
index 0000000..792a4e3
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4rip.h -- tombstone window
+
+#ifndef QT4RIP_H
+#define QT4RIP_H
+
+namespace nethack_qt4 {
+
+class NetHackQtRIP : public QWidget {
+private:
+       static QPixmap* pixmap;
+       char** line;
+       int riplines;
+
+public:
+       NetHackQtRIP(QWidget* parent);
+
+       void setLines(char** l, int n);
+
+protected:
+       virtual void paintEvent(QPaintEvent* event);
+       QSize sizeHint() const;
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4set.cpp b/win/Qt4/qt4set.cpp
new file mode 100644 (file)
index 0000000..03de1f6
--- /dev/null
@@ -0,0 +1,186 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4set.cpp -- the Qt settings
+
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4set.h"
+#include "qt4set.moc"
+#include "qt4glyph.h"
+#include "qt4str.h"
+
+/* Used by tile/font-size patch below and in ../../src/files.c */
+char *qt_tilewidth=NULL;
+char *qt_tileheight=NULL;
+char *qt_fontsize=NULL;
+#if defined(QWS)
+int qt_compact_mode = 1;
+#else
+int qt_compact_mode = 0;
+#endif
+
+namespace nethack_qt4 {
+
+#define TILEWMIN 1
+#define TILEHMIN 1
+
+NetHackQtSettings::NetHackQtSettings(int w, int h) :
+    tilewidth(this),
+    tileheight(this),
+    widthlbl("&Width:",this),
+    heightlbl("&Height:",this),
+    whichsize("&Zoomed",this),
+    fontsize(this),
+    normal("times"),
+#ifdef WS_WIN
+    normalfixed("courier new"),
+#else
+    normalfixed("courier"),
+#endif
+    large("times"),
+    theglyphs(0)
+
+{
+    int default_fontsize;
+
+    widthlbl.setBuddy(&tilewidth);
+    tilewidth.setRange(TILEWMIN, 128);
+    heightlbl.setBuddy(&tileheight);
+    tileheight.setRange(TILEHMIN, 128);
+
+    default_fontsize=2;
+    tilewidth.setValue(16);
+    tileheight.setValue(16);
+
+    // Tile/font sizes read from .nethackrc
+    if (qt_tilewidth != NULL) {
+       tilewidth.setValue(atoi(qt_tilewidth));
+       delete[] qt_tilewidth;
+    }
+    if (qt_tileheight != NULL) {
+       tileheight.setValue(atoi(qt_tileheight));
+       delete[] qt_tileheight;
+    }
+    if (qt_fontsize != NULL) {
+       switch (tolower(qt_fontsize[0])) {
+         case 'h': default_fontsize = 0; break;
+         case 'l': default_fontsize = 1; break;
+         case 'm': default_fontsize = 2; break;
+         case 's': default_fontsize = 3; break;
+         case 't': default_fontsize = 4; break;
+       }
+       delete[] qt_fontsize;
+    }
+
+    theglyphs=new NetHackQtGlyphs();
+    resizeTiles();
+
+    connect(&tilewidth,SIGNAL(valueChanged(int)),this,SLOT(resizeTiles()));
+    connect(&tileheight,SIGNAL(valueChanged(int)),this,SLOT(resizeTiles()));
+    connect(&whichsize,SIGNAL(toggled(bool)),this,SLOT(setGlyphSize(bool)));
+
+    fontsize.addItem("Huge");
+    fontsize.addItem("Large");
+    fontsize.addItem("Medium");
+    fontsize.addItem("Small");
+    fontsize.addItem("Tiny");
+    fontsize.setCurrentIndex(default_fontsize);
+    connect(&fontsize,SIGNAL(activated(int)),this,SIGNAL(fontChanged()));
+
+    QGridLayout* grid = new QGridLayout(this);
+    grid->addWidget(&whichsize, 0, 0, 1, 2);
+    grid->addWidget(&tilewidth, 1, 1); grid->addWidget(&widthlbl, 1, 0);
+    grid->addWidget(&tileheight, 2, 1); grid->addWidget(&heightlbl, 2, 0);
+    QLabel* flabel=new QLabel("&Font:",this);
+    flabel->setBuddy(&fontsize);
+    grid->addWidget(flabel, 3, 0); grid->addWidget(&fontsize, 3, 1);
+    QPushButton* dismiss=new QPushButton("Dismiss",this);
+    dismiss->setDefault(true);
+    grid->addWidget(dismiss, 4, 0, 1, 2);
+    grid->setRowStretch(4,0);
+    grid->setColumnStretch(1,1);
+    grid->setColumnStretch(2,2);
+    grid->activate();
+
+    connect(dismiss,SIGNAL(clicked()),this,SLOT(accept()));
+    resize(150,140);
+}
+
+NetHackQtGlyphs& NetHackQtSettings::glyphs()
+{
+    return *theglyphs;
+}
+
+void NetHackQtSettings::resizeTiles()
+{
+    int w = tilewidth.value();
+    int h = tileheight.value();
+
+    theglyphs->setSize(w,h);
+    emit tilesChanged();
+}
+
+void NetHackQtSettings::toggleGlyphSize()
+{
+    whichsize.toggle();
+}
+
+void NetHackQtSettings::setGlyphSize(bool which)
+{
+    QSize n = QSize(tilewidth.value(),tileheight.value());
+    if ( othersize.isValid() ) {
+       tilewidth.blockSignals(true);
+       tileheight.blockSignals(true);
+       tilewidth.setValue(othersize.width());
+       tileheight.setValue(othersize.height());
+       tileheight.blockSignals(false);
+       tilewidth.blockSignals(false);
+       resizeTiles();
+    }
+    othersize = n;
+}
+
+const QFont& NetHackQtSettings::normalFont()
+{
+    static int size[]={ 18, 14, 12, 10, 8 };
+    normal.setPointSize(size[fontsize.currentIndex()]);
+    return normal;
+}
+
+const QFont& NetHackQtSettings::normalFixedFont()
+{
+    static int size[]={ 18, 14, 13, 10, 8 };
+    normalfixed.setPointSize(size[fontsize.currentIndex()]);
+    return normalfixed;
+}
+
+const QFont& NetHackQtSettings::largeFont()
+{
+    static int size[]={ 24, 18, 14, 12, 10 };
+    large.setPointSize(size[fontsize.currentIndex()]);
+    return large;
+}
+
+bool NetHackQtSettings::ynInMessages()
+{
+    return !qt_compact_mode && !iflags.wc_popup_dialog;
+}
+
+NetHackQtSettings* qt_settings;
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4set.h b/win/Qt4/qt4set.h
new file mode 100644 (file)
index 0000000..e2253a8
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4set.h -- the Qt settings
+
+#ifndef QT4SET_H
+#define QT4SET_H
+
+namespace nethack_qt4 {
+
+class NetHackQtGlyphs;
+
+class NetHackQtSettings : public QDialog {
+       Q_OBJECT
+public:
+       // Size of window - used to decide default sizes
+       NetHackQtSettings(int width, int height);
+
+       NetHackQtGlyphs& glyphs();
+       const QFont& normalFont();
+       const QFont& normalFixedFont();
+       const QFont& largeFont();
+
+       bool ynInMessages();
+
+signals:
+       void fontChanged();
+       void tilesChanged();
+
+public slots:
+       void toggleGlyphSize();
+       void setGlyphSize(bool);
+
+private:
+       QSpinBox tilewidth;
+       QSpinBox tileheight;
+       QLabel widthlbl;
+       QLabel heightlbl;
+       QCheckBox whichsize;
+       QSize othersize;
+
+       QComboBox fontsize;
+
+       QFont normal, normalfixed, large;
+
+       NetHackQtGlyphs* theglyphs;
+
+private slots:
+       void resizeTiles();
+};
+
+extern NetHackQtSettings* qt_settings;
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4stat.cpp b/win/Qt4/qt4stat.cpp
new file mode 100644 (file)
index 0000000..3a15604
--- /dev/null
@@ -0,0 +1,540 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4stat.cpp -- bindings between the Qt 4 interface and the main code
+
+extern "C" {
+#include "hack.h"
+}
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4stat.h"
+#include "qt4stat.moc"
+#include "qt4set.h"
+#include "qt4str.h"
+#include "qt_xpms.h"
+
+extern const char *enc_stat[]; /* from botl.c */
+extern const char *hu_stat[]; /* from eat.c */
+
+namespace nethack_qt4 {
+
+NetHackQtStatusWindow::NetHackQtStatusWindow() :
+    // Notes:
+    //  Alignment needs -2 init value, because -1 is an alignment.
+    //  Armor Class is an schar, so 256 is out of range.
+    //  Blank value is 0 and should never change.
+    name(this,"(name)"),
+    dlevel(this,"(dlevel)"),
+    str(this,"STR"),
+    dex(this,"DEX"),
+    con(this,"CON"),
+    intel(this,"INT"),
+    wis(this,"WIS"),
+    cha(this,"CHA"),
+    gold(this,"Gold"),
+    hp(this,"Hit Points"),
+    power(this,"Power"),
+    ac(this,"Armour Class"),
+    level(this,"Level"),
+    exp(this,"Experience"),
+    align(this,"Alignment"),
+    time(this,"Time"),
+    score(this,"Score"),
+    hunger(this,""),
+    confused(this,"Confused"),
+    sick_fp(this,"Sick"),
+    sick_il(this,"Ill"),
+    blind(this,""),
+    stunned(this,"Stunned"),
+    hallu(this,"Hallu"),
+    encumber(this,""),
+    hline1(this),
+    hline2(this),
+    hline3(this),
+    first_set(true)
+{
+    p_str = QPixmap(str_xpm);
+    p_str = QPixmap(str_xpm);
+    p_dex = QPixmap(dex_xpm);
+    p_con = QPixmap(cns_xpm);
+    p_int = QPixmap(int_xpm);
+    p_wis = QPixmap(wis_xpm);
+    p_cha = QPixmap(cha_xpm);
+
+    p_chaotic = QPixmap(chaotic_xpm);
+    p_neutral = QPixmap(neutral_xpm);
+    p_lawful = QPixmap(lawful_xpm);
+
+    p_satiated = QPixmap(satiated_xpm);
+    p_hungry = QPixmap(hungry_xpm);
+
+    p_confused = QPixmap(confused_xpm);
+    p_sick_fp = QPixmap(sick_fp_xpm);
+    p_sick_il = QPixmap(sick_il_xpm);
+    p_blind = QPixmap(blind_xpm);
+    p_stunned = QPixmap(stunned_xpm);
+    p_hallu = QPixmap(hallu_xpm);
+
+    p_encumber[0] = QPixmap(slt_enc_xpm);
+    p_encumber[1] = QPixmap(mod_enc_xpm);
+    p_encumber[2] = QPixmap(hvy_enc_xpm);
+    p_encumber[3] = QPixmap(ext_enc_xpm);
+    p_encumber[4] = QPixmap(ovr_enc_xpm);
+
+    str.setIcon(p_str);
+    dex.setIcon(p_dex);
+    con.setIcon(p_con);
+    intel.setIcon(p_int);
+    wis.setIcon(p_wis);
+    cha.setIcon(p_cha);
+
+    align.setIcon(p_neutral);
+    hunger.setIcon(p_hungry);
+
+    confused.setIcon(p_confused);
+    sick_fp.setIcon(p_sick_fp);
+    sick_il.setIcon(p_sick_il);
+    blind.setIcon(p_blind);
+    stunned.setIcon(p_stunned);
+    hallu.setIcon(p_hallu);
+
+    encumber.setIcon(p_encumber[0]);
+
+    hline1.setFrameStyle(QFrame::HLine|QFrame::Sunken);
+    hline2.setFrameStyle(QFrame::HLine|QFrame::Sunken);
+    hline3.setFrameStyle(QFrame::HLine|QFrame::Sunken);
+    hline1.setLineWidth(1);
+    hline2.setLineWidth(1);
+    hline3.setLineWidth(1);
+
+#if 1 //RLC
+    name.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+    dlevel.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+    QVBoxLayout *vbox = new QVBoxLayout();
+    vbox->setSpacing(0);
+    vbox->addWidget(&name);
+    vbox->addWidget(&dlevel);
+    vbox->addWidget(&hline1);
+    QHBoxLayout *atr1box = new QHBoxLayout();
+       atr1box->addWidget(&str);
+       atr1box->addWidget(&dex);
+       atr1box->addWidget(&con);
+       atr1box->addWidget(&intel);
+       atr1box->addWidget(&wis);
+       atr1box->addWidget(&cha);
+    vbox->addLayout(atr1box);
+    vbox->addWidget(&hline2);
+    QHBoxLayout *atr2box = new QHBoxLayout();
+       atr2box->addWidget(&gold);
+       atr2box->addWidget(&hp);
+       atr2box->addWidget(&power);
+       atr2box->addWidget(&ac);
+       atr2box->addWidget(&level);
+       atr2box->addWidget(&exp);
+    vbox->addLayout(atr2box);
+    vbox->addWidget(&hline3);
+    QHBoxLayout *timebox = new QHBoxLayout();
+       timebox->addWidget(&time);
+       timebox->addWidget(&score);
+    vbox->addLayout(timebox);
+    QHBoxLayout *statbox = new QHBoxLayout();
+       statbox->addWidget(&align);
+       statbox->addWidget(&hunger);
+       statbox->addWidget(&confused);
+       statbox->addWidget(&sick_fp);
+       statbox->addWidget(&sick_il);
+       statbox->addWidget(&blind);
+       statbox->addWidget(&stunned);
+       statbox->addWidget(&hallu);
+       statbox->addWidget(&encumber);
+    statbox->setAlignment(Qt::AlignLeft|Qt::AlignVCenter);
+    vbox->addLayout(statbox);
+    setLayout(vbox);
+#endif
+
+    connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(doUpdate()));
+    doUpdate();
+}
+
+void NetHackQtStatusWindow::doUpdate()
+{
+    const QFont& large=qt_settings->largeFont();
+    name.setFont(large);
+    dlevel.setFont(large);
+
+    const QFont& normal=qt_settings->normalFont();
+    str.setFont(normal);
+    dex.setFont(normal);
+    con.setFont(normal);
+    intel.setFont(normal);
+    wis.setFont(normal);
+    cha.setFont(normal);
+    gold.setFont(normal);
+    hp.setFont(normal);
+    power.setFont(normal);
+    ac.setFont(normal);
+    level.setFont(normal);
+    exp.setFont(normal);
+    align.setFont(normal);
+    time.setFont(normal);
+    score.setFont(normal);
+    hunger.setFont(normal);
+    confused.setFont(normal);
+    sick_fp.setFont(normal);
+    sick_il.setFont(normal);
+    blind.setFont(normal);
+    stunned.setFont(normal);
+    hallu.setFont(normal);
+    encumber.setFont(normal);
+
+    updateStats();
+}
+
+QWidget* NetHackQtStatusWindow::Widget() { return this; }
+
+void NetHackQtStatusWindow::Clear()
+{
+}
+void NetHackQtStatusWindow::Display(bool block)
+{
+}
+void NetHackQtStatusWindow::CursorTo(int,int y)
+{
+    cursy=y;
+}
+void NetHackQtStatusWindow::PutStr(int attr, const QString& text)
+{
+    // do a complete update when line 0 is done (as per X11 fancy status)
+    if (cursy==0) updateStats();
+}
+
+#if 0 // RLC
+void NetHackQtStatusWindow::resizeEvent(QResizeEvent*)
+{
+#if 0
+    const float SP_name=0.13; //     <Name> the <Class> (large)
+    const float SP_dlev=0.13; //   Level 3 in The Dungeons of Doom (large)
+    const float SP_atr1=0.25; //  STR   DEX   CON   INT   WIS   CHA
+    const float SP_hln1=0.02; // ---
+    const float SP_atr2=0.09; //  Au    HP    PW    AC    LVL   EXP
+    const float SP_hln2=0.02; // ---
+    const float SP_time=0.09; //      time    score
+    const float SP_hln3=0.02; // ---
+    const float SP_stat=0.25; // Alignment, Poisoned, Hungry, Sick, etc.
+
+    int h=height();
+    int x=0,y=0;
+
+    int iw; // Width of an item across line
+    int lh; // Height of a line of values
+
+    lh=int(h*SP_name);
+    name.setGeometry(0,0,width(),lh); y+=lh;
+    lh=int(h*SP_dlev);
+    dlevel.setGeometry(0,y,width(),lh); y+=lh;
+
+    lh=int(h*SP_hln1);
+    hline1.setGeometry(0,y,width(),lh); y+=lh;
+
+    lh=int(h*SP_atr1);
+    iw=width()/6;
+    str.setGeometry(x,y,iw,lh); x+=iw;
+    dex.setGeometry(x,y,iw,lh); x+=iw;
+    con.setGeometry(x,y,iw,lh); x+=iw;
+    intel.setGeometry(x,y,iw,lh); x+=iw;
+    wis.setGeometry(x,y,iw,lh); x+=iw;
+    cha.setGeometry(x,y,iw,lh); x+=iw;
+    x=0; y+=lh;
+
+    lh=int(h*SP_hln2);
+    hline2.setGeometry(0,y,width(),lh); y+=lh;
+
+    lh=int(h*SP_atr2);
+    iw=width()/6;
+    gold.setGeometry(x,y,iw,lh); x+=iw;
+    hp.setGeometry(x,y,iw,lh); x+=iw;
+    power.setGeometry(x,y,iw,lh); x+=iw;
+    ac.setGeometry(x,y,iw,lh); x+=iw;
+    level.setGeometry(x,y,iw,lh); x+=iw;
+    exp.setGeometry(x,y,iw,lh); x+=iw;
+    x=0; y+=lh;
+
+    lh=int(h*SP_hln3);
+    hline3.setGeometry(0,y,width(),lh); y+=lh;
+
+    lh=int(h*SP_time);
+    iw=width()/3; x+=iw/2;
+    time.setGeometry(x,y,iw,lh); x+=iw;
+    score.setGeometry(x,y,iw,lh); x+=iw;
+    x=0; y+=lh;
+
+    lh=int(h*SP_stat);
+    iw=width()/9;
+    align.setGeometry(x,y,iw,lh); x+=iw;
+    hunger.setGeometry(x,y,iw,lh); x+=iw;
+    confused.setGeometry(x,y,iw,lh); x+=iw;
+    sick_fp.setGeometry(x,y,iw,lh); x+=iw;
+    sick_il.setGeometry(x,y,iw,lh); x+=iw;
+    blind.setGeometry(x,y,iw,lh); x+=iw;
+    stunned.setGeometry(x,y,iw,lh); x+=iw;
+    hallu.setGeometry(x,y,iw,lh); x+=iw;
+    encumber.setGeometry(x,y,iw,lh); x+=iw;
+    x=0; y+=lh;
+#else
+    // This is clumsy.  But QLayout objects are proving balky.
+
+    int row[10];
+
+    row[0] = name.sizeHint().height();
+    row[1] = dlevel.sizeHint().height();
+    row[2] = h.sizeHint().height();
+#endif
+}
+#endif
+
+
+/*
+ * Set all widget values to a null string.  This is used after all spacings
+ * have been calculated so that when the window is popped up we don't get all
+ * kinds of funny values being displayed.
+ */
+void NetHackQtStatusWindow::nullOut()
+{
+}
+
+void NetHackQtStatusWindow::fadeHighlighting()
+{
+    name.dissipateHighlight();
+    dlevel.dissipateHighlight();
+
+    str.dissipateHighlight();
+    dex.dissipateHighlight();
+    con.dissipateHighlight();
+    intel.dissipateHighlight();
+    wis.dissipateHighlight();
+    cha.dissipateHighlight();
+
+    gold.dissipateHighlight();
+    hp.dissipateHighlight();
+    power.dissipateHighlight();
+    ac.dissipateHighlight();
+    level.dissipateHighlight();
+    exp.dissipateHighlight();
+    align.dissipateHighlight();
+
+    time.dissipateHighlight();
+    score.dissipateHighlight();
+
+    hunger.dissipateHighlight();
+    confused.dissipateHighlight();
+    sick_fp.dissipateHighlight();
+    sick_il.dissipateHighlight();
+    blind.dissipateHighlight();
+    stunned.dissipateHighlight();
+    hallu.dissipateHighlight();
+    encumber.dissipateHighlight();
+}
+
+/*
+ * Update the displayed status.  The current code in botl.c updates
+ * two lines of information.  Both lines are always updated one after
+ * the other.  So only do our update when we update the second line.
+ *
+ * Information on the first line:
+ *    name, attributes, alignment, score
+ *
+ * Information on the second line:
+ *    dlvl, gold, hp, power, ac, {level & exp or HD **}
+ *    status (hunger, conf, halu, stun, sick, blind), time, encumbrance
+ *
+ * [**] HD is shown instead of level and exp if mtimedone is non-zero.
+ */
+void NetHackQtStatusWindow::updateStats()
+{
+    if (!parentWidget()) return;
+
+    QString buf;
+    const char *text;
+
+    if (cursy != 0) return;    /* do a complete update when line 0 is done */
+
+    if (ACURR(A_STR) > 118) {
+       buf.sprintf("STR:%d",ACURR(A_STR)-100);
+    } else if (ACURR(A_STR)==118) {
+       buf.sprintf("STR:18/**");
+    } else if(ACURR(A_STR) > 18) {
+       buf.sprintf("STR:18/%02d",ACURR(A_STR)-18);
+    } else {
+       buf.sprintf("STR:%d",ACURR(A_STR));
+    }
+    str.setLabel(buf,NetHackQtLabelledIcon::NoNum,ACURR(A_STR));
+
+    dex.setLabel("DEX:",(long)ACURR(A_DEX));
+    con.setLabel("CON:",(long)ACURR(A_CON));
+    intel.setLabel("INT:",(long)ACURR(A_INT));
+    wis.setLabel("WIS:",(long)ACURR(A_WIS));
+    cha.setLabel("CHA:",(long)ACURR(A_CHA));
+    const char* hung=hu_stat[u.uhs];
+    if (hung[0]==' ') {
+       hunger.hide();
+    } else {
+       hunger.setIcon(u.uhs ? p_hungry : p_satiated);
+       hunger.setLabel(hung);
+       hunger.show();
+    }
+    if (Confusion) confused.show(); else confused.hide();
+    if (Sick) {
+       if (u.usick_type & SICK_VOMITABLE) {
+           sick_fp.show();
+       } else {
+           sick_fp.hide();
+       }
+       if (u.usick_type & SICK_NONVOMITABLE) {
+           sick_il.show();
+       } else {
+           sick_il.hide();
+       }
+    } else {
+       sick_fp.hide();
+       sick_il.hide();
+    }
+    if (Blind) {
+       blind.setLabel("Blind");
+       blind.show();
+    } else {
+       blind.hide();
+    }
+    if (Stunned) stunned.show(); else stunned.hide();
+    if (Hallucination) hallu.show(); else hallu.hide();
+    const char* enc=enc_stat[near_capacity()];
+    if (enc[0]==' ' || !enc[0]) {
+       encumber.hide();
+    } else {
+       encumber.setIcon(p_encumber[near_capacity()-1]);
+       encumber.setLabel(enc);
+       encumber.show();
+    }
+    if (u.mtimedone) {
+       buf = nh_capitalize_words(mons[u.umonnum].mname);
+    } else {
+       buf = rank_of(u.ulevel, pl_character[0], ::flags.female);
+    }
+    QString buf2;
+    buf2.sprintf("%s the %s", plname, buf.toLatin1().constData());
+    name.setLabel(buf2, NetHackQtLabelledIcon::NoNum, u.ulevel);
+
+    char buf3[BUFSZ];
+    if (describe_level(buf3)) {
+       dlevel.setLabel(buf3,true);
+    } else {
+       buf.sprintf("%s, level ", dungeons[u.uz.dnum].dname);
+       dlevel.setLabel(buf,(long)::depth(&u.uz));
+    }
+
+    gold.setLabel("Au:", money_cnt(invent));
+
+    if (u.mtimedone) {
+       // You're a monster!
+
+       buf.sprintf("/%d", u.mhmax);
+       hp.setLabel("HP:", u.mh  > 0 ? u.mh  : 0, buf);
+       level.setLabel("HD:",(long)mons[u.umonnum].mlevel);
+    } else {
+       // You're normal.
+
+       buf.sprintf("/%d", u.uhpmax);
+       hp.setLabel("HP:", u.uhp > 0 ? u.uhp : 0, buf);
+       level.setLabel("Level:",(long)u.ulevel);
+    }
+    buf.sprintf("/%d", u.uenmax);
+    power.setLabel("Pow:", u.uen, buf);
+    ac.setLabel("AC:",(long)u.uac);
+#ifdef EXP_ON_BOTL
+    if (::flags.showexp) {
+       exp.setLabel("Exp:",(long)u.uexp);
+    } else
+#endif
+    {
+       exp.setLabel("");
+    }
+    if (u.ualign.type==A_CHAOTIC) {
+       align.setIcon(p_chaotic);
+       text = "Chaotic";
+    } else if (u.ualign.type==A_NEUTRAL) {
+       align.setIcon(p_neutral);
+       text = "Neutral";
+    } else {
+       align.setIcon(p_lawful);
+       text = "Lawful";
+    }
+    align.setLabel(text);
+
+    if (::flags.time) time.setLabel("Time:",(long)moves);
+    else time.setLabel("");
+#ifdef SCORE_ON_BOTL
+    if (::flags.showscore) {
+       score.setLabel("Score:",(long)botl_score());
+    } else
+#endif
+    {
+       score.setLabel("");
+    }
+
+    if (first_set)
+    {
+       first_set=false;
+
+       name.highlightWhenChanging();
+       dlevel.highlightWhenChanging();
+
+       str.highlightWhenChanging();
+       dex.highlightWhenChanging();
+       con.highlightWhenChanging();
+       intel.highlightWhenChanging();
+       wis.highlightWhenChanging();
+       cha.highlightWhenChanging();
+
+       gold.highlightWhenChanging();
+       hp.highlightWhenChanging();
+       power.highlightWhenChanging();
+       ac.highlightWhenChanging(); ac.lowIsGood();
+       level.highlightWhenChanging();
+       exp.highlightWhenChanging();
+       align.highlightWhenChanging();
+
+       //time.highlightWhenChanging();
+       score.highlightWhenChanging();
+
+       hunger.highlightWhenChanging();
+       confused.highlightWhenChanging();
+       sick_fp.highlightWhenChanging();
+       sick_il.highlightWhenChanging();
+       blind.highlightWhenChanging();
+       stunned.highlightWhenChanging();
+       hallu.highlightWhenChanging();
+       encumber.highlightWhenChanging();
+    }
+}
+
+/*
+ * Turn off hilighted status values after a certain amount of turns.
+ */
+void NetHackQtStatusWindow::checkTurnEvents()
+{
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4stat.h b/win/Qt4/qt4stat.h
new file mode 100644 (file)
index 0000000..a0a00a4
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4stat.h -- bindings between the Qt 4 interface and the main code
+
+#ifndef QT4STAT_H
+#define QT4STAT_H
+
+#include "qt4win.h"
+#include "qt4icon.h"
+
+namespace nethack_qt4 {
+
+class NetHackQtStatusWindow : QWidget, public NetHackQtWindow {
+       Q_OBJECT
+public:
+       NetHackQtStatusWindow();
+
+       virtual QWidget* Widget();
+
+       virtual void Clear();
+       virtual void Display(bool block);
+       virtual void CursorTo(int x,int y);
+       virtual void PutStr(int attr, const QString& text);
+
+       void fadeHighlighting();
+
+protected:
+       //RLC void resizeEvent(QResizeEvent*);
+
+private slots:
+       void doUpdate();
+
+private:
+       enum { hilight_time=1 };
+
+       QPixmap p_str;
+       QPixmap p_dex;
+       QPixmap p_con;
+       QPixmap p_int;
+       QPixmap p_wis;
+       QPixmap p_cha;
+
+       QPixmap p_chaotic;
+       QPixmap p_neutral;
+       QPixmap p_lawful;
+
+       QPixmap p_satiated;
+       QPixmap p_hungry;
+
+       QPixmap p_confused;
+       QPixmap p_sick_fp;
+       QPixmap p_sick_il;
+       QPixmap p_blind;
+       QPixmap p_stunned;
+       QPixmap p_hallu;
+
+       QPixmap p_encumber[5];
+
+       NetHackQtLabelledIcon name;
+       NetHackQtLabelledIcon dlevel;
+
+       NetHackQtLabelledIcon str;
+       NetHackQtLabelledIcon dex;
+       NetHackQtLabelledIcon con;
+       NetHackQtLabelledIcon intel;
+       NetHackQtLabelledIcon wis;
+       NetHackQtLabelledIcon cha;
+
+       NetHackQtLabelledIcon gold;
+       NetHackQtLabelledIcon hp;
+       NetHackQtLabelledIcon power;
+       NetHackQtLabelledIcon ac;
+       NetHackQtLabelledIcon level;
+       NetHackQtLabelledIcon exp;
+       NetHackQtLabelledIcon align;
+
+       NetHackQtLabelledIcon time;
+       NetHackQtLabelledIcon score;
+
+       NetHackQtLabelledIcon hunger;
+       NetHackQtLabelledIcon confused;
+       NetHackQtLabelledIcon sick_fp;
+       NetHackQtLabelledIcon sick_il;
+       NetHackQtLabelledIcon blind;
+       NetHackQtLabelledIcon stunned;
+       NetHackQtLabelledIcon hallu;
+       NetHackQtLabelledIcon encumber;
+
+       QFrame hline1;
+       QFrame hline2;
+       QFrame hline3;
+
+       int cursy;
+
+       bool first_set;
+
+       void nullOut();
+       void updateStats();
+       void checkTurnEvents();
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4str.cpp b/win/Qt4/qt4str.cpp
new file mode 100644 (file)
index 0000000..b6b4440
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4str.cpp -- some string functions
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include "qt4str.h"
+
+namespace nethack_qt4 {
+
+// Bounded string copy
+size_t str_copy(char *dest, const char *src, size_t max)
+{
+    size_t len = strlen(src);
+    if (max != 0) {
+       size_t csize = len;
+       if (len > max - 1) {
+           len = max - 1;
+       }
+       memcpy(dest, src, csize);
+       dest[csize] = '\0';
+    }
+    return len;
+}
+
+QString str_titlecase(const QString& str)
+{
+    if (str == "") { return str; }
+
+    return str.left(1).toUpper() + str.mid(1).toLower();
+}
+
+QString nh_capitalize_words(const QString& str)
+{
+    QStringList words = str.split(" ");
+    for (size_t i = 0; i < words.size(); ++i) {
+       words[i] = str_titlecase(words[i]);
+    }
+    return words.join(" ");
+}
+
+int cp437(int ch)
+{
+    static const unsigned short cp437table[] = {
+        0x0000, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
+        0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
+        0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
+        0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
+        0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+        0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+        0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+        0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+        0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+        0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
+        0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+        0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+        0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+        0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+        0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+        0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x2302,
+        0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
+        0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
+        0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
+        0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
+        0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
+        0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
+        0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+        0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
+        0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+        0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
+        0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+        0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
+        0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
+        0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
+        0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
+        0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0,
+    };
+    return cp437table[(unsigned char)ch];
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4str.h b/win/Qt4/qt4str.h
new file mode 100644 (file)
index 0000000..05f25f4
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4str.h -- various string functions
+
+#ifndef QT4STR_H
+#define QT4STR_H
+
+namespace nethack_qt4 {
+
+// Bounded string copy
+extern size_t str_copy(char *dest, const char *src, size_t max);
+
+// Case mappings
+extern QString str_titlecase(const QString& str);
+extern QString nh_capitalize_words(const QString& str);
+
+// Map symbol conversion
+extern int cp437(int ch);
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4streq.cpp b/win/Qt4/qt4streq.cpp
new file mode 100644 (file)
index 0000000..abe910f
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4streq.cpp -- string requestor
+
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4streq.h"
+#include "qt4str.h"
+
+namespace nethack_qt4 {
+
+// temporary
+void centerOnMain(QWidget *);
+// end temporary
+
+NetHackQtStringRequestor::NetHackQtStringRequestor(QWidget *parent, const char* p, const char* cancelstr) :
+    QDialog(parent),
+    prompt(QString::fromLatin1(p),this),
+    input(this,"input")
+{
+    cancel=new QPushButton(cancelstr,this);
+    connect(cancel,SIGNAL(clicked()),this,SLOT(reject()));
+
+    okay=new QPushButton("Okay",this);
+    connect(okay,SIGNAL(clicked()),this,SLOT(accept()));
+    connect(&input,SIGNAL(returnPressed()),this,SLOT(accept()));
+    okay->setDefault(true);
+
+    setFocusPolicy(Qt::StrongFocus);
+}
+
+void NetHackQtStringRequestor::resizeEvent(QResizeEvent*)
+{
+    const int margin=5;
+    const int gutter=5;
+
+    int h=(height()-margin*2-gutter);
+
+    if (prompt.text().size() > 16) {
+       h/=3;
+       prompt.setGeometry(margin,margin,width()-margin*2,h);
+       input.setGeometry(width()*1/5,margin+h+gutter,
+           (width()-margin-2-gutter)*4/5,h);
+    } else {
+       h/=2;
+       prompt.setGeometry(margin,margin,(width()-margin*2-gutter)*2/5,h);
+       input.setGeometry(prompt.geometry().right()+gutter,margin,
+           (width()-margin-2-gutter)*3/5,h);
+    }
+
+    cancel->setGeometry(margin,input.geometry().bottom()+gutter,
+       (width()-margin*2-gutter)/2,h);
+    okay->setGeometry(cancel->geometry().right()+gutter,cancel->geometry().y(),
+       cancel->width(),h);
+}
+
+void NetHackQtStringRequestor::SetDefault(const char* d)
+{
+    input.setText(d);
+}
+
+bool NetHackQtStringRequestor::Get(char* buffer, int maxchar)
+{
+    input.setMaxLength(maxchar);
+    if (prompt.text().size() > 16) {
+       resize(fontMetrics().width(prompt.text())+50,fontMetrics().height()*6);
+    } else {
+       resize(fontMetrics().width(prompt.text())*2+50,fontMetrics().height()*4);
+    }
+
+#ifdef EDIT_GETLIN
+    input.setText(buffer);
+#endif
+    centerOnMain(this);
+    show();
+    input.setFocus();
+    exec();
+
+    if (result()) {
+       str_copy(buffer,input.text().toLatin1().constData(),maxchar);
+       return true;
+    } else {
+       return false;
+    }
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4streq.h b/win/Qt4/qt4streq.h
new file mode 100644 (file)
index 0000000..a5f05d7
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4streq.h -- string requestor
+
+#ifndef QT4STREQ_H
+#define QT4STREQ_H
+
+#include "qt4line.h"
+
+namespace nethack_qt4 {
+
+class NetHackQtStringRequestor : QDialog {
+private:
+       QLabel prompt;
+       NetHackQtLineEdit input;
+       QPushButton* okay;
+       QPushButton* cancel;
+
+public:
+       NetHackQtStringRequestor(QWidget *parent, const char* p,const char* cancelstr="Cancel");
+       void SetDefault(const char*);
+       bool Get(char* buffer, int maxchar=80);
+       virtual void resizeEvent(QResizeEvent*);
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4svsel.cpp b/win/Qt4/qt4svsel.cpp
new file mode 100644 (file)
index 0000000..0b52715
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4svsel.cpp -- saved game selector
+
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4svsel.h"
+#include "qt4bind.h"
+#include "qt4str.h"
+
+namespace nethack_qt4 {
+
+NetHackQtSavedGameSelector::NetHackQtSavedGameSelector(const char** saved) :
+    QDialog(NetHackQtBind::mainWidget())
+{
+    QVBoxLayout *vbl = new QVBoxLayout(this);
+    QHBoxLayout* hb;
+
+    QLabel* logo = new QLabel(this); vbl->addWidget(logo);
+    logo->setAlignment(Qt::AlignCenter);
+    logo->setPixmap(QPixmap("nhsplash.xpm"));
+    QLabel* attr = new QLabel("by the NetHack DevTeam",this);
+    attr->setAlignment(Qt::AlignCenter);
+    vbl->addWidget(attr);
+    vbl->addStretch(2);
+    /*
+    QLabel* logo = new QLabel(hb);
+    hb = new QHBox(this);
+    vbl->addWidget(hb, Qt::AlignCenter);
+    logo->setPixmap(QPixmap(nh_icon));
+    logo->setAlignment(AlignRight|Qt::AlignVCenter);
+    new QLabel(nh_attribution,hb);
+    */
+
+    hb = new QHBoxLayout(this);
+    vbl->addLayout(hb, Qt::AlignCenter);
+    QPushButton* q = new QPushButton("Quit",this);
+    hb->addWidget(q);
+    connect(q, SIGNAL(clicked()), this, SLOT(reject()));
+    QPushButton* c = new QPushButton("New Game",this);
+    hb->addWidget(c);
+    connect(c, SIGNAL(clicked()), this, SLOT(accept()));
+    c->setDefault(true);
+
+    QGroupBox* box = new QGroupBox("Saved Characters",this);
+    QButtonGroup *bg = new QButtonGroup(this);
+    vbl->addWidget(box);
+    QVBoxLayout *bgl = new QVBoxLayout(box);
+    connect(bg, SIGNAL(buttonPressed(int)), this, SLOT(done(int)));
+    for (int i=0; saved[i]; i++) {
+       QPushButton* b = new QPushButton(saved[i],box);
+       bg->addButton(b, i+2);
+    }
+}
+
+int NetHackQtSavedGameSelector::choose()
+{
+#if defined(QWS) // probably safe with Qt 3, too (where show!=exec in QDialog).
+    if ( qt_compact_mode )
+       showMaximized();
+#endif
+    return exec()-2;
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4svsel.h b/win/Qt4/qt4svsel.h
new file mode 100644 (file)
index 0000000..918e6f7
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4svsel.h -- saved game selector
+
+#ifndef QT4SVSEL_H
+#define QT4SVSEL_H
+
+namespace nethack_qt4 {
+
+class NetHackQtSavedGameSelector : public QDialog {
+public:
+       NetHackQtSavedGameSelector(const char** saved);
+
+       int choose();
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4win.cpp b/win/Qt4/qt4win.cpp
new file mode 100644 (file)
index 0000000..ca0abe5
--- /dev/null
@@ -0,0 +1,136 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// Qt Binding for NetHack 3.4
+//
+// Copyright (C) 1996-2001 by Warwick W. Allison (warwick@troll.no)
+// 
+// Contributors:
+//    Michael Hohmuth <hohmuth@inf.tu-dresden.de>
+//       - Userid control
+//    Svante Gerhard <svante@algonet.se>
+//       - .nethackrc tile and font size settings
+//    Dirk Schoenberger <schoenberger@signsoft.com>
+//       - KDE support
+//       - SlashEm support
+//    and many others for bug reports.
+// 
+// Unfortunately, this doesn't use Qt as well as I would like,
+// primarily because NetHack is fundamentally a getkey-type program
+// rather than being event driven (hence the ugly key and click buffer)
+// and also because this is my first major application of Qt.  
+// 
+// The problem of NetHack's getkey requirement is solved by intercepting
+// key events by overiding QApplicion::notify(...), and putting them in
+// a buffer.  Mouse clicks on the map window are treated with a similar
+// buffer.  When the NetHack engine calls for a key, one is taken from
+// the buffer, or if that is empty, QApplication::exec() is called.
+// Whenever keys or clicks go into the buffer, QApplication::exit()
+// is called.
+//
+// Another problem is that some NetHack players are decade-long players who
+// demand complete keyboard control (while Qt and X11 conspire to make this
+// difficult by having widget-based focus rather than application based -
+// a good thing in general).  This problem is solved by again using the key
+// event buffer.
+//
+// Out of all this hackery comes a silver lining however, as macros for
+// the super-expert and menus for the ultra-newbie are also made possible
+// by the key event buffer.
+//
+
+// This includes all the definitions we need from the NetHack main
+// engine.  We pretend MSC is a STDC compiler, because C++ is close
+// enough, and we undefine NetHack macros which conflict with Qt
+// identifiers.
+
+#define QT_DEPRECATED_WARNINGS
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4win.h"
+#include "qt4bind.h"
+#include "qt4click.h"
+#include "qt4glyph.h"
+#include "qt4inv.h"
+#include "qt4key.h"
+#include "qt4icon.h"
+#include "qt4map.h"
+#include "qt4menu.h"
+#include "qt4msg.h"
+#include "qt4set.h"
+
+#include <ctype.h>
+
+#include "qt4clust.h"
+
+#include <dirent.h>
+
+#ifdef _WS_X11_
+// For userid control
+#include <unistd.h>
+#endif
+
+#ifdef USER_SOUNDS
+#if QT_VERSION >= 0x050000
+#  include <QtMultimedia/QSound>
+# else
+#  include <QtGui/QSound>
+# endif
+#endif
+
+
+#ifdef USER_SOUNDS
+extern void play_sound_for_message(const std::string& str);
+#endif
+
+namespace nethack_qt4 {
+
+void
+centerOnMain( QWidget* w )
+{
+    QWidget* m = NetHackQtBind::mainWidget();
+    if (!m) m = qApp->desktop();
+    QPoint p = m->mapToGlobal(QPoint(0,0));
+    w->move( p.x() + m->width()/2  - w->width()/2,
+              p.y() + m->height()/2 - w->height()/2 );
+}
+
+NetHackQtWindow::NetHackQtWindow()
+{
+}
+NetHackQtWindow::~NetHackQtWindow()
+{
+}
+
+// XXX Use "expected ..." for now, abort or default later.
+//
+void NetHackQtWindow::Clear() { puts("unexpected Clear"); }
+void NetHackQtWindow::Display(bool block) { puts("unexpected Display"); }
+bool NetHackQtWindow::Destroy() { return true; }
+void NetHackQtWindow::CursorTo(int x,int y) { puts("unexpected CursorTo"); }
+void NetHackQtWindow::PutStr(int attr, const QString& text) { puts("unexpected PutStr"); }
+void NetHackQtWindow::StartMenu() { puts("unexpected StartMenu"); }
+void NetHackQtWindow::AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
+    const QString& str, bool presel) { puts("unexpected AddMenu"); }
+void NetHackQtWindow::EndMenu(const QString& prompt) { puts("unexpected EndMenu"); }
+int NetHackQtWindow::SelectMenu(int how, MENU_ITEM_P **menu_list) { puts("unexpected SelectMenu"); return 0; }
+void NetHackQtWindow::ClipAround(int x,int y) { puts("unexpected ClipAround"); }
+void NetHackQtWindow::PrintGlyph(int x,int y,int glyph) { puts("unexpected PrintGlyph"); }
+//void NetHackQtWindow::PrintGlyphCompose(int x,int y,int,int) { puts("unexpected PrintGlyphCompose"); }
+void NetHackQtWindow::UseRIP(int how, time_t when) { puts("unexpected UseRIP"); }
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4win.h b/win/Qt4/qt4win.h
new file mode 100644 (file)
index 0000000..02e96cd
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// Qt Binding for NetHack 3.4
+//
+// Unfortunately, this doesn't use Qt as well as I would like,
+// primarily because NetHack is fundamentally a getkey-type
+// program rather than being event driven (hence the ugly key
+// and click buffer rather), but also because this is my first
+// major application of Qt.
+//
+
+#ifndef qt4win_h
+#define qt4win_h
+
+namespace nethack_qt4 {
+
+class NetHackQtWindow {
+public:
+       NetHackQtWindow();
+       virtual ~NetHackQtWindow();
+
+       virtual QWidget* Widget() =0;
+
+       virtual void Clear();
+       virtual void Display(bool block);
+       virtual bool Destroy();
+       virtual void CursorTo(int x,int y);
+       virtual void PutStr(int attr, const QString& text);
+        void PutStr(int attr, const char *text)
+        {
+            PutStr(attr, QString::fromUtf8(text).replace(QChar(0x200B), ""));
+        }
+       virtual void StartMenu();
+       virtual void AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr,
+                       const QString& str, bool presel);
+       virtual void EndMenu(const QString& prompt);
+       virtual int SelectMenu(int how, MENU_ITEM_P **menu_list);
+       virtual void ClipAround(int x,int y);
+       virtual void PrintGlyph(int x,int y,int glyph);
+       virtual void UseRIP(int how, time_t when);
+
+       int nhid;
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4xcmd.cpp b/win/Qt4/qt4xcmd.cpp
new file mode 100644 (file)
index 0000000..3e8703e
--- /dev/null
@@ -0,0 +1,134 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4xcmd.cpp -- extended command widget
+
+#include "hack.h"
+#include "func_tab.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4xcmd.h"
+#include "qt4xcmd.moc"
+#include "qt4bind.h"
+#include "qt4set.h"
+#include "qt4str.h"
+
+namespace nethack_qt4 {
+
+// temporary
+void centerOnMain(QWidget *);
+// end temporary
+
+NetHackQtExtCmdRequestor::NetHackQtExtCmdRequestor(QWidget *parent) :
+    QDialog(parent)
+{
+    QVBoxLayout *l = new QVBoxLayout(this);
+
+    QPushButton* can = new QPushButton("Cancel", this);
+    can->setDefault(true);
+    can->setMinimumSize(can->sizeHint());
+    l->addWidget(can);
+
+    prompt = new QLabel("#", this);
+    l->addWidget(prompt);
+
+    QButtonGroup *group=new QButtonGroup(this);
+    QGroupBox *grid=new QGroupBox("Extended commands",this);
+    l->addWidget(grid);
+
+    int i;
+    int butw=50;
+    QFontMetrics fm = fontMetrics();
+    for (i=0; extcmdlist[i].ef_txt; i++) {
+       butw = std::max(butw,30+fm.width(extcmdlist[i].ef_txt));
+    }
+    int ncols=4;
+
+    QVBoxLayout* bl = new QVBoxLayout(grid);
+    bl->addSpacing(fm.height());
+    QGridLayout* gl = new QGridLayout();
+    bl->addLayout(gl);
+    for (i=0; extcmdlist[i].ef_txt; i++) {
+       QPushButton* pb=new QPushButton(extcmdlist[i].ef_txt, grid);
+       pb->setMinimumSize(butw,pb->sizeHint().height());
+       group->addButton(pb, i+1);
+       gl->addWidget(pb,i/ncols,i%ncols);
+    }
+    group->addButton(can, 0);
+    connect(group,SIGNAL(buttonPressed(int)),this,SLOT(done(int)));
+
+    bl->activate();
+    l->activate();
+    resize(1,1);
+}
+
+void NetHackQtExtCmdRequestor::cancel()
+{
+    reject();
+}
+
+void NetHackQtExtCmdRequestor::keyPressEvent(QKeyEvent *event)
+{
+    QString text = event->text();
+    if (text == "\r" || text == "\n" || text == " " || text == "\033")
+    {
+       reject();
+    }
+    else if (text == "\b")
+    {
+       QString promptstr = prompt->text();
+       if (promptstr != "#")
+           prompt->setText(promptstr.left(promptstr.size()-1));
+    }
+    else
+    {
+       QString promptstr = prompt->text() + text;
+       QString typedstr = promptstr.mid(1); // skip the '#'
+       unsigned matches = 0;
+       unsigned match = 0;
+       for (unsigned i=0; extcmdlist[i].ef_txt; i++) {
+           if (QString(extcmdlist[i].ef_txt).startsWith(typedstr)) {
+               ++matches;
+               if (matches >= 2)
+                   break;
+               match = i;
+           }
+       }
+       if (matches == 1)
+           done(match+1);
+       else if (matches >= 2)
+           prompt->setText(promptstr);
+    }
+}
+
+int NetHackQtExtCmdRequestor::get()
+{
+    const int none = -10;
+    resize(1,1); // pack
+    centerOnMain(this);
+    // Add any keys presently buffered to the prompt
+    setResult(none);
+    while (NetHackQtBind::qt_kbhit() && result() == none) {
+       int ch = NetHackQtBind::qt_nhgetch();
+       QKeyEvent event(QEvent::KeyPress, 0, Qt::NoModifier, QChar(ch));
+       keyPressEvent(&event);
+    }
+    if (result() == none)
+       exec();
+    return result()-1;
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4xcmd.h b/win/Qt4/qt4xcmd.h
new file mode 100644 (file)
index 0000000..29ba23f
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4xcmd.h -- extended command widget
+
+#ifndef QT4XCMD_H
+#define QT4XCMD_H
+
+namespace nethack_qt4 {
+
+class NetHackQtExtCmdRequestor : public QDialog {
+    Q_OBJECT
+
+protected:
+    virtual void keyPressEvent(QKeyEvent *event);
+
+public:
+    NetHackQtExtCmdRequestor(QWidget *parent);
+    int get();
+
+private:
+    QLabel *prompt;
+
+private slots:
+    void cancel();
+};
+
+} // namespace nethack_qt4
+
+#endif
diff --git a/win/Qt4/qt4yndlg.cpp b/win/Qt4/qt4yndlg.cpp
new file mode 100644 (file)
index 0000000..e315189
--- /dev/null
@@ -0,0 +1,244 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4yndlg.cpp -- yes/no dialog
+
+#include "hack.h"
+#undef Invisible
+#undef Warning
+#undef index
+#undef msleep
+#undef rindex
+#undef wizard
+#undef yn
+#undef min
+#undef max
+
+#include <QtGui/QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets/QtWidgets>
+#endif
+#include "qt4yndlg.h"
+#include "qt4yndlg.moc"
+#include "qt4str.h"
+
+// temporary
+extern int qt_compact_mode;
+// end temporary
+
+namespace nethack_qt4 {
+
+// temporary
+void centerOnMain(QWidget *);
+// end temporary
+
+NetHackQtYnDialog::NetHackQtYnDialog(QWidget *parent,const QString& q,const char* ch,char df) :
+    QDialog(parent),
+    question(q), choices(ch), def(df),
+    keypress('\033')
+{
+    setWindowTitle("NetHack: Question");
+}
+
+char NetHackQtYnDialog::Exec()
+{
+    QString ch(QString::fromLatin1(choices));
+    int ch_per_line=6;
+    QString qlabel;
+    QString enable;
+    if ( qt_compact_mode && !choices ) {
+        ch = "";
+       // expand choices from prompt
+       // ##### why isn't choices set properly???
+        int c = question.indexOf(QChar('['));
+       qlabel = QString(question).left(c);
+       if ( c >= 0 ) {
+           c++;
+           if ( question[c] == '-' )
+               ch.append(question[c++]);
+           unsigned from=0;
+           while ( c < question.size() && question[c] != ']' && question[c] != ' ' ) {
+               if ( question[c] == '-' ) {
+                   from = question[c-1].unicode();
+               } else if ( from != 0 ) {
+                   for (unsigned f=from+1; f<=question[c]; f++)
+                       ch.append(QChar(f));
+                   from = 0;
+               } else {
+                   ch.append(question[c]);
+                   from = 0;
+               }
+               c++;
+           }
+           if ( question[c] == ' ' ) {
+               while ( c < question.size() && question[c] != ']' ) {
+                   if ( question[c] == '*' || question[c] == '?' )
+                       ch.append(question[c]);
+                   c++;
+               }
+           }
+       }
+       if ( question.indexOf("what direction") >= 0 ) {
+           // We replace this regardless, since sometimes you get choices.
+           const char* d = Cmd.dirchars;
+           enable=ch;
+           ch="";
+           ch.append(d[1]);
+           ch.append(d[2]);
+           ch.append(d[3]);
+           ch.append(d[0]);
+           ch.append('.');
+           ch.append(d[4]);
+           ch.append(d[7]);
+           ch.append(d[6]);
+           ch.append(d[5]);
+           ch.append(d[8]);
+           ch.append(d[9]);
+           ch_per_line = 3;
+           def = ' ';
+       } else {
+           // Hmm... they'll have to use a virtual keyboard
+       }
+    } else {
+        ch = QString::fromLatin1(choices);
+       qlabel = question.replace(QChar(0x200B), QString(""));
+    }
+    if (!ch.isNull()) {
+       QVBoxLayout *vb = new QVBoxLayout;
+       bool bigq = qlabel.length()>40;
+       if ( bigq ) {
+           QLabel* q = new QLabel(qlabel,this);
+           q->setAlignment(Qt::AlignLeft);
+           q->setWordWrap(true);
+           q->setMargin(4);
+           vb->addWidget(q);
+       }
+       QGroupBox *group = new QGroupBox(bigq ? QString::null : qlabel, this);
+       vb->addWidget(group);
+       QHBoxLayout *groupbox = new QHBoxLayout();
+       group->setLayout(groupbox);
+       QButtonGroup *bgroup = new QButtonGroup(group);
+
+       int nchoices=ch.length();
+
+       bool allow_count=ch.contains('#');
+       QString yn = "yn", ynq = "ynq";
+       bool is_ynq = ch == yn || ch == ynq;
+
+       const int margin=8;
+       const int gutter=8;
+       const int extra=fontMetrics().height(); // Extra for group
+       int x=margin, y=extra+margin;
+       int butsize=fontMetrics().height()*2+5;
+
+       QPushButton* button;
+       for (int i=0; i<nchoices && ch[i]!='\033'; i++) {
+           QString button_name = QString(ch[i]);
+           if (is_ynq) {
+               if (button_name == ynq.mid(0, 1)) {
+                   button_name = "Yes";
+               } else if (button_name == ynq.mid(1, 1)) {
+                   button_name = "No";
+               } else if (button_name == ynq.mid(2, 1)) {
+                   button_name = "Cancel";
+               }
+           }
+           button=new QPushButton(button_name);
+           if ( !enable.isNull() ) {
+               if ( !enable.contains(ch[i]) )
+                   button->setEnabled(false);
+           }
+           button->setFixedSize(butsize,butsize); // Square
+           if (ch[i]==def) button->setDefault(true);
+           if (i%10==9) {
+               // last in row
+               x=margin;
+               y+=butsize+gutter;
+           } else {
+               x+=butsize+gutter;
+           }
+           groupbox->addWidget(button);
+           bgroup->addButton(button, i);
+       }
+
+       connect(bgroup,SIGNAL(buttonClicked(int)),this,SLOT(doneItem(int)));
+
+       QLabel* lb=0;
+       QLineEdit* le=0;
+
+       if (allow_count) {
+           QHBoxLayout *hb = new QHBoxLayout(this);
+           lb=new QLabel("Count: ");
+           hb->addWidget(lb);
+           le=new QLineEdit();
+           hb->addWidget(le);
+           vb->addLayout(hb);
+       }
+
+       setLayout(vb);
+       adjustSize();
+       centerOnMain(this);
+       show();
+       char choice=0;
+       char ch_esc=0;
+       for (uint i=0; i<ch.length(); i++) {
+           if (ch[i].unicode()=='q') ch_esc='q';
+           else if (!ch_esc && ch[i].unicode()=='n') ch_esc='n';
+       }
+       exec();
+       if ( result() == 0) {
+           choice = ch_esc ? ch_esc : def ? def : ' ';
+       } else if ( result() == 1 ) {
+           choice = def ? def : ch_esc ? ch_esc : ' ';
+       } else if ( result() >= 1000 ) {
+           choice = ch[result() - 1000].unicode();
+       }
+       if (allow_count && !le->text().isEmpty()) {
+           yn_number=le->text().toInt();
+           choice='#';
+       }
+       return choice;
+    } else {
+       QLabel label(qlabel,this);
+       QPushButton cancel("Dismiss",this);
+       label.setFrameStyle(QFrame::Box|QFrame::Sunken);
+       label.setAlignment(Qt::AlignCenter);
+       label.resize(fontMetrics().width(qlabel)+60,30+fontMetrics().height());
+       cancel.move(width()/2-cancel.width()/2,label.geometry().bottom()+8);
+       connect(&cancel,SIGNAL(clicked()),this,SLOT(reject()));
+       centerOnMain(this);
+       setResult(-1);
+       show();
+       keypress = '\033';
+       exec();
+       return keypress;
+    }
+}
+
+void NetHackQtYnDialog::keyPressEvent(QKeyEvent* event)
+{
+    // Don't want QDialog's Return/Esc behaviour
+    //RLC ...or do we?
+    QString text(event->text());
+    if (choices == NULL || choices[0] == 0) {
+       if (text != "") {
+           keypress = text.toUcs4()[0];
+           done(1);
+       }
+    } else {
+       int where = QString::fromLatin1(choices).indexOf(text);
+       if (where != -1 && text != "#") {
+           done(where+1000);
+       } else {
+           QDialog::keyPressEvent(event);
+       }
+    }
+}
+
+void NetHackQtYnDialog::doneItem(int i)
+{
+    done(i+1000);
+}
+
+} // namespace nethack_qt4
diff --git a/win/Qt4/qt4yndlg.h b/win/Qt4/qt4yndlg.h
new file mode 100644 (file)
index 0000000..d1474f5
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (c) Warwick Allison, 1999.
+// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
+// NetHack may be freely redistributed.  See license for details.
+
+// qt4yndlg.h -- yes/no dialog
+
+#ifndef QT4YNDLG_H
+#define QT4YNDLG_H
+
+namespace nethack_qt4 {
+
+class NetHackQtYnDialog : QDialog {
+       Q_OBJECT
+private:
+       QString question;
+       const char* choices;
+       char def;
+       char keypress;
+
+protected:
+       virtual void keyPressEvent(QKeyEvent*);
+
+private slots:
+       void doneItem(int);
+
+public:
+       NetHackQtYnDialog(QWidget *,const QString&,const char*,char);
+
+       char Exec();
+};
+
+} // namespace nethack_qt4
+
+#endif
index dff03f8..a3fe458 100644 (file)
@@ -1,4 +1,6 @@
-$NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+$NHDT-Date: 1524689294 2018/04/25 20:48:14 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.11 $
+# Copyright (c) 2003 by David Cohrs
+# NetHack may be freely redistributed.  See license for details.
 
 This document describes the installation of NetHack with an X11 interface.
 
index 19c9a17..f7ec106 100644 (file)
@@ -1,17 +1,31 @@
-! $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+! $NHDT-Date: 1524689294 2018/04/25 20:48:14 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $
+! Copyright (c) 2017 by Pasi Kallinen
+! NetHack may be freely redistributed.  See license for details.
+
+#define NETHACK_FONT       -*-fixed-medium-*-*-*-15-*-*-*-*-*-*-*
+#define NETHACK_CLR_FG     grey
+#define NETHACK_CLR_BG     black
+#define NETHACK_CLR_QUIT   red
+#define NETHACK_CLR_RANDOM yellow
+#define NETHACK_CLR_PLAY   green
+#define NETHACK_CLR_HELP   green
+#define NETHACK_BTN_SHAPE  roundedRectangle
+#define NETHACK_BTN_ROUND  20
+#define NETHACK_CMD_BORDER 0
 
 ! The display_file, tombstone, and menu windows are all formatted assuming
 ! a fixed width font.  Text windows may or may not be formatted as above.
 ! The rip window applies if the GRAPHIC_TOMBSTONE option is turned on, and
 ! requires a 12 pixel font for correct appearance.
 !
-NetHack*font:                          variable
-NetHack*display_file*font:             fixed
-NetHack*tombstone*font:                        fixed
-NetHack*text*rip*font:                 -*-times-medium-r-*-*-12-*-*-*-*-*-*-*
-NetHack*menu*font:                     fixed
-NetHack*text*font:                     fixed
-NetHack*map*font:                      nh10
+NetHack*font:              NETHACK_FONT
+NetHack*display_file*font: NETHACK_FONT
+NetHack*map*font:          NETHACK_FONT
+NetHack*text*font:         NETHACK_FONT
+NetHack*menu*font:         NETHACK_FONT
+NetHack*tombstone*font:    NETHACK_FONT
+NetHack*text*rip*font:     -*-times-medium-r-*-*-12-*-*-*-*-*-*-*
+NetHack*text*borderWidth:  0
 
 ! tile_file names a file containing full-color tiles for the map.
 ! If you use a 100dpi (or greater) monitor you may wish to double the
@@ -35,7 +49,7 @@ NetHack.tile_file: x11tiles
 ! The image file
 !NetHack.tombstone: rip.xpm
 ! Text starts at (tombtext_x, tombtext_y) and subsequent lines
-! are displaced by (tombtext_dx, tombtext_dy) pixels.  If you
+! are displaced by (tombtext_dx, tombtext_dy) pixels.
 !NetHack.tombtext_x: 155
 !NetHack.tombtext_y: 78
 !NetHack.tombtext_dx: 0
@@ -68,6 +82,13 @@ NetHack*message*translations:        <KeyPress>: input()
 ! questions is _not_ used.
 NetHack*slow: True
 
+! If 'slow' is True, setting 'highlight_prompt' to True will cause the line
+! between map and message display that's used for prompting to be "hidden"
+! as part of the map when no prompt is active, then invert foreground and
+! background to stand out when a prompt is issued and waiting for a response.
+! If 'slow' is False, 'highlight_prompt' will have no effect.
+NetHack*highlight_prompt: False
+
 ! The number of lines the message window will show without scrolling.
 !NetHack*message_lines: 12
 !
@@ -85,99 +106,213 @@ NetHack*slow: True
 !NetHack*map*rows:     21
 !NetHack*map*columns:  80
 
-! Parts of the fancy status display.
-!
-NetHack*status_condition.borderWidth:  0
-NetHack*status_info*borderWidth:       0
+NetHack*background: NETHACK_CLR_BG
+NetHack*foreground: NETHACK_CLR_FG
 
-! Sample color screen entries.
-!
-NetHack*nethack.background:    wheat
-NetHack*map*yellow:            gold
-NetHack*map*brown:             tan
-NetHack*map*gray:              grey85
-NetHack*map*foreground:                wheat
-NetHack*map*background:                grey40
-
-NetHack*fancy_status.skipAdjust:        True
-NetHack*fancy_status.background:       wheat
-NetHack*status_info*foreground:                Sienna
-NetHack*status_info*background:                wheat
-NetHack*status_info.background:                wheat
-NetHack*status_attributes*foreground:  black
-NetHack*status_attributes*background:  white
-NetHack*status_condition*foreground:   red
-NetHack*status_condition*background:   wheat
-NetHack*Scrollbar*foreground:          Sienna
-NetHack*Scrollbar*background:          wheat
-NetHack*status_info*showGrip:          False
-NetHack*status_attributes*showGrip:    False
-
-NetHack*player_selection*random.borderColor:   blue
-NetHack*player_selection*random.borderWidth:    2
-NetHack*player_selection*random.foreground:    blue
-NetHack*player_selection*random.accelerators: #override\n\
-                               <Key>Return:    set() notify() unset()
-NetHack*player_selection*quit.borderColor:     blue
-NetHack*player_selection*quit.foreground:      blue
-NetHack*player_selection*Command.borderColor:  red
-NetHack*player_selection*Command.foreground:   red
-NetHack*player_selection*quit.accelerators: #override\n\
-                               <Key>Escape:    set() notify() unset()
-
-NetHack*race_selection*random.borderColor:     blue
-NetHack*race_selection*random.borderWidth:     2
-NetHack*race_selection*random.foreground:      blue
-NetHack*race_selection*random.accelerators: #override\n\
-                               <Key>Return:    set() notify() unset()
-NetHack*race_selection*quit.borderColor:       blue
-NetHack*race_selection*quit.foreground:                blue
-NetHack*race_selection*Command.borderColor:    red
-NetHack*race_selection*Command.foreground:     red
-NetHack*race_selection*quit.accelerators: #override\n\
-                               <Key>Escape:    set() notify() unset()
-
-NetHack*gender_selection*random.borderColor:   blue
-NetHack*gender_selection*random.borderWidth:   2
-NetHack*gender_selection*random.foreground:    blue
-NetHack*gender_selection*random.accelerators: #override\n\
-                               <Key>Return:    set() notify() unset()
-NetHack*gender_selection*quit.borderColor:     blue
-NetHack*gender_selection*quit.foreground:      blue
-NetHack*gender_selection*Command.borderColor:  red
-NetHack*gender_selection*Command.foreground:   red
-NetHack*gender_selection*quit.accelerators: #override\n\
-                               <Key>Escape:    set() notify() unset()
-
-NetHack*alignment_selection*random.borderColor:        blue
-NetHack*alignment_selection*random.borderWidth:        2
-NetHack*alignment_selection*random.foreground: blue
-NetHack*alignment_selection*random.accelerators: #override\n\
-                               <Key>Return:    set() notify() unset()
-NetHack*alignment_selection*quit.borderColor:  blue
-NetHack*alignment_selection*quit.foreground:   blue
-NetHack*alignment_selection*Command.borderColor: red
-NetHack*alignment_selection*Command.foreground:        red
-NetHack*alignment_selection*quit.accelerators: #override\n\
-                               <Key>Escape:    set() notify() unset()
-
-NetHack*extended_commands*dismiss.borderColor: blue
-NetHack*extended_commands*dismiss.foreground:  blue
-NetHack*extended_commands*help.borderColor:    blue
-NetHack*extended_commands*help.foreground:     blue
-NetHack*extended_commands*Command.borderColor: red
-NetHack*extended_commands*Command.foreground:  red
-NetHack*extended_commands*help.accelerators: #override\n\
-                               :<Key>?:        set() notify() unset()
-NetHack*extended_commands*dismiss.accelerators: #override\n\
-                               <Key>Escape:    set() notify() unset()
-!
-!
-! The following are the default 15 colors that the nethack map uses.
-! If they don't look good on your screen, change them.
-!
+NetHack*yn_prompt*borderWidth: 0
+
+NetHack*Scrollbar*foreground: gray40
+NetHack*Scrollbar*background: gray10
+
+NetHack*fancy_status*background: NETHACK_CLR_BG
+NetHack*fancy_status*foreground: NETHACK_CLR_FG
+NetHack*fancy_status.skipAdjust: True
+
+NetHack*showGrip: False
+
+! text input prompt window
+NetHack*response*textSink*background: red
+NetHack*textSink*background: red
+
+NetHack*response*foreground:  NETHACK_CLR_FG
+NetHack*response*background:  NETHACK_CLR_BG
+NetHack*response*borderColor: NETHACK_CLR_FG
+NetHack*response*borderWidth: 1
+
+! player selection dialog (OPTIONS=player_selection:dialog)
+!NetHack*player_selection_dialog.height:   420
+!NetHack*player_selection_dialog.width:   403
+
+!NetHack*player_selection_dialog*foreground:   black
+!NetHack*player_selection_dialog*background:   white
+NetHack*player_selection_dialog*name_label.borderWidth:   0
+NetHack*player_selection_dialog*race_label.borderWidth:   0
+NetHack*player_selection_dialog*role_label.borderWidth:   0
+NetHack*player_selection_dialog*gender_label.borderWidth: 0
+NetHack*player_selection_dialog*align_label.borderWidth:  0
+NetHack*player_selection_dialog*button_vp.borderWidth:    0
+
+NetHack*player_selection_dialog*name_input.borderWidth:   1
+NetHack*player_selection_dialog*name_input.borderColor:   NETHACK_CLR_FG
+
+NetHack*player_selection_dialog*role_vp.borderColor:   NETHACK_CLR_FG
+NetHack*player_selection_dialog*race_vp.borderColor:   NETHACK_CLR_FG
+NetHack*player_selection_dialog*gender_vp.borderColor: NETHACK_CLR_FG
+NetHack*player_selection_dialog*align_vp.borderColor:  NETHACK_CLR_FG
+
+NetHack*player_selection_dialog*random.foreground:   NETHACK_CLR_RANDOM
+NetHack*player_selection_dialog*random.borderColor:  NETHACK_CLR_RANDOM
+NetHack*player_selection_dialog*random.borderWidth:  1
+NetHack*player_selection_dialog*random.shapeStyle:   NETHACK_BTN_SHAPE
+NetHack*player_selection_dialog*random.cornerRoundPercent: NETHACK_BTN_ROUND
+
+NetHack*player_selection_dialog*quit.foreground:     NETHACK_CLR_QUIT
+NetHack*player_selection_dialog*quit.borderColor:    NETHACK_CLR_QUIT
+NetHack*player_selection_dialog*quit.borderWidth:    1
+NetHack*player_selection_dialog*quit.shapeStyle:     NETHACK_BTN_SHAPE
+NetHack*player_selection_dialog*quit.cornerRoundPercent: NETHACK_BTN_ROUND
+
+NetHack*player_selection_dialog*play.foreground:     NETHACK_CLR_PLAY
+NetHack*player_selection_dialog*play.borderColor:    NETHACK_CLR_PLAY
+NetHack*player_selection_dialog*play.borderWidth:    1
+NetHack*player_selection_dialog*play.shapeStyle:     NETHACK_BTN_SHAPE
+NetHack*player_selection_dialog*play.cornerRoundPercent: NETHACK_BTN_ROUND
+
+
+! role selection window  (OPTIONS=player_selection:prompts)
+NetHack*player_selection*random.foreground:   NETHACK_CLR_RANDOM
+NetHack*player_selection*random.background:   black
+NetHack*player_selection*random.borderColor:  NETHACK_CLR_RANDOM
+NetHack*player_selection*random.borderWidth:  1
+NetHack*player_selection*random.shapeStyle: NETHACK_BTN_SHAPE
+NetHack*player_selection*random.cornerRoundPercent: NETHACK_BTN_ROUND
+NetHack*player_selection*quit.foreground:     NETHACK_CLR_QUIT
+NetHack*player_selection*quit.borderColor:    NETHACK_CLR_QUIT
+NetHack*player_selection*quit.borderWidth:    1
+NetHack*player_selection*quit.shapeStyle: NETHACK_BTN_SHAPE
+NetHack*player_selection*quit.cornerRoundPercent: NETHACK_BTN_ROUND
+NetHack*player_selection*Command.foreground:  NETHACK_CLR_FG
+NetHack*player_selection*Command.borderColor: NETHACK_CLR_FG
+NetHack*player_selection*Command.borderWidth: NETHACK_CMD_BORDER
+
+! race selection window
+NetHack*race_selection*random.foreground:   NETHACK_CLR_RANDOM
+NetHack*race_selection*random.background:   black
+NetHack*race_selection*random.borderColor:  NETHACK_CLR_RANDOM
+NetHack*race_selection*random.borderWidth:  1
+NetHack*race_selection*random.shapeStyle:   NETHACK_BTN_SHAPE
+NetHack*race_selection*random.cornerRoundPercent: NETHACK_BTN_ROUND
+NetHack*race_selection*quit.foreground:     NETHACK_CLR_QUIT
+NetHack*race_selection*quit.borderColor:    NETHACK_CLR_QUIT
+NetHack*race_selection*quit.borderWidth:    1
+NetHack*race_selection*quit.shapeStyle:     NETHACK_BTN_SHAPE
+NetHack*race_selection*quit.cornerRoundPercent: NETHACK_BTN_ROUND
+NetHack*race_selection*Command.foreground:  NETHACK_CLR_FG
+NetHack*race_selection*Command.borderColor: NETHACK_CLR_FG
+NetHack*race_selection*Command.borderWidth: NETHACK_CMD_BORDER
+
+! gender selection window
+NetHack*gender_selection*random.foreground:   NETHACK_CLR_RANDOM
+NetHack*gender_selection*random.background:   black
+NetHack*gender_selection*random.borderColor:  NETHACK_CLR_RANDOM
+NetHack*gender_selection*random.borderWidth:  1
+NetHack*gender_selection*random.shapeStyle:   NETHACK_BTN_SHAPE
+NetHack*gender_selection*random.cornerRoundPercent: NETHACK_BTN_ROUND
+NetHack*gender_selection*quit.foreground:     NETHACK_CLR_QUIT
+NetHack*gender_selection*quit.borderColor:    NETHACK_CLR_QUIT
+NetHack*gender_selection*quit.borderWidth:    1
+NetHack*gender_selection*quit.shapeStyle:     NETHACK_BTN_SHAPE
+NetHack*gender_selection*quit.cornerRoundPercent: NETHACK_BTN_ROUND
+NetHack*gender_selection*Command.foreground:  NETHACK_CLR_FG
+NetHack*gender_selection*Command.borderColor: NETHACK_CLR_FG
+NetHack*gender_selection*Command.borderWidth: NETHACK_CMD_BORDER
+
+! alignment selection window
+NetHack*alignment_selection*random.foreground:   NETHACK_CLR_RANDOM
+NetHack*alignment_selection*random.background:   black
+NetHack*alignment_selection*random.borderColor:  NETHACK_CLR_RANDOM
+NetHack*alignment_selection*random.borderWidth:  1
+NetHack*alignment_selection*random.shapeStyle:   NETHACK_BTN_SHAPE
+NetHack*alignment_selection*random.cornerRoundPercent: NETHACK_BTN_ROUND
+NetHack*alignment_selection*quit.foreground:     NETHACK_CLR_QUIT
+NetHack*alignment_selection*quit.borderColor:    NETHACK_CLR_QUIT
+NetHack*alignment_selection*quit.borderWidth:    1
+NetHack*alignment_selection*quit.shapeStyle:     NETHACK_BTN_SHAPE
+NetHack*alignment_selection*quit.cornerRoundPercent: NETHACK_BTN_ROUND
+NetHack*alignment_selection*Command.foreground:  NETHACK_CLR_FG
+NetHack*alignment_selection*Command.borderColor: NETHACK_CLR_FG
+NetHack*alignment_selection*Command.borderWidth: NETHACK_CMD_BORDER
+
+! extended commands window
+NetHack*extended_commands*dismiss.foreground:  NETHACK_CLR_QUIT
+NetHack*extended_commands*dismiss.borderColor: NETHACK_CLR_QUIT
+NetHack*extended_commands*dismiss.borderWidth: 1
+NetHack*extended_commands*dismiss.shapeStyle:  NETHACK_BTN_SHAPE
+NetHack*extended_commands*dismiss.cornerRoundPercent: NETHACK_BTN_ROUND
+NetHack*extended_commands*help.foreground:     NETHACK_CLR_HELP
+NetHack*extended_commands*help.borderColor:    NETHACK_CLR_HELP
+NetHack*extended_commands*help.borderWidth:    1
+NetHack*extended_commands*help.shapeStyle:     NETHACK_BTN_SHAPE
+NetHack*extended_commands*help.cornerRoundPercent: NETHACK_BTN_ROUND
+NetHack*extended_commands*Command.foreground:  NETHACK_CLR_FG
+NetHack*extended_commands*Command.borderColor: NETHACK_CLR_FG
+NetHack*extended_commands*Command.borderWidth: NETHACK_CMD_BORDER
+! The extended command menu may be too big to fit on the screen so need
+! a vertical scroll bar.  When truncated, its height will be as tall as
+! possible unless height_delta is non-zero, in which case there will be
+! that many pixels of margin left unused.  On OSX, this can be used to
+! avoid overlapping with the desktop docking tray to prevent that from
+! obscuring the bottom of the menu.
+NetHack*extcmd_height_delta: 75
+
+! menu buttons
+NetHack*OK.foreground:  green
+NetHack*OK.borderColor: green
+NetHack*OK.shapeStyle: NETHACK_BTN_SHAPE
+NetHack*OK.cornerRoundPercent: NETHACK_BTN_ROUND
+
+NetHack*okay.foreground:  green
+NetHack*okay.borderColor: green
+NetHack*okay.shapeStyle: NETHACK_BTN_SHAPE
+NetHack*okay.cornerRoundPercent: NETHACK_BTN_ROUND
+
+NetHack*cancel.foreground:  red
+NetHack*cancel.borderColor: red
+NetHack*cancel.shapeStyle: NETHACK_BTN_SHAPE
+NetHack*cancel.cornerRoundPercent: NETHACK_BTN_ROUND
+
+NetHack*all.foreground:  green
+NetHack*all.borderColor: green
+NetHack*all.shapeStyle: NETHACK_BTN_SHAPE
+NetHack*all.cornerRoundPercent: NETHACK_BTN_ROUND
+
+NetHack*none.foreground:  green
+NetHack*none.borderColor: green
+NetHack*none.shapeStyle: NETHACK_BTN_SHAPE
+NetHack*none.cornerRoundPercent: NETHACK_BTN_ROUND
+
+NetHack*invert.foreground:  green
+NetHack*invert.borderColor: green
+NetHack*invert.shapeStyle: NETHACK_BTN_SHAPE
+NetHack*invert.cornerRoundPercent: NETHACK_BTN_ROUND
+
+NetHack*search.foreground:  green
+NetHack*search.borderColor: green
+NetHack*search.shapeStyle: NETHACK_BTN_SHAPE
+NetHack*search.cornerRoundPercent: NETHACK_BTN_ROUND
+
+! map colors
 ! The foreground color is used as "no color".
+NetHack*map*foreground: NETHACK_CLR_FG
+NetHack*map*background: NETHACK_CLR_BG
+
+NetHack*map*black:          grey15
+NetHack*map*red:            red3
+NetHack*map*green:          green3
+NetHack*map*brown:          DarkOrange3
+NetHack*map*blue:           blue3
+NetHack*map*magenta:        magenta3
+NetHack*map*cyan:           cyan3
+NetHack*map*gray:           gray50
+NetHack*map*orange:         yellow
+NetHack*map*bright_green:   green
+NetHack*map*yellow:         yellow
+NetHack*map*bright_blue:    blue
+NetHack*map*bright_magenta: magenta
+NetHack*map*bright_cyan:    cyan
+NetHack*map*white:          white
 !
+! The following are the default 15 colors that the nethack map uses.
 !NetHack*map*black:            black
 !NetHack*map*red:              red
 !NetHack*map*green:            pale green
index 51fb091..76affff 100644 (file)
@@ -132,11 +132,7 @@ Region region; /* unused */
     nhUse(region);
 
     /* This isn't correct - we need to call the callback with region. */
-#if 0 /*JP*/
-    XtCallCallbacks(w, XtNexposeCallback, (caddr_t) event);
-#else
-    XtCallCallbacks(w, XtNexposeCallback, (XtPointer) event);
-#endif
+    XtCallCallbacks(w, XtNexposeCallback, (XtPointer)event);
 }
 
 /* ARGSUSED */
@@ -144,11 +140,7 @@ static void
 Resize(w)
 Widget w;
 {
-#if 0 /*JP*/
-    XtCallCallbacks(w, XtNresizeCallback, (caddr_t) 0);
-#else
     XtCallCallbacks(w, XtNresizeCallback, (XtPointer) 0);
-#endif
 }
 
 WindowClassRec windowClassRec = {
index 6ffe08a..b72ea9a 100644 (file)
@@ -1,25 +1,24 @@
 /*
  * Copyright 1991 University of Wisconsin-Madison
  *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
  * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of the University of Wisconsin-Madison not
- * be used in advertising or publicity pertaining to distribution of the
+ * documentation, and that the name of the University of Wisconsin-Madison
+ * not be used in advertising or publicity pertaining to distribution of the
  * software without specific, written prior permission.  The University of
  * Wisconsin-Madison makes no representations about the suitability of this
  * software for any purpose.  It is provided "as is" without express or
  * implied warranty.
  *
- * THE UNIVERSITY OF WISCONSIN-MADISON DISCLAIMS ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * THE UNIVERSITY OF WISCONSIN-MADISON DISCLAIMS ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF WISCONSIN-MADISON BE LIABLE
- *FOR
- * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  * Author:  Tim Theisen             Department of Computer Sciences
  *          tim@cs.wisc.edu         University of Wisconsin-Madison
  *
  *    + Make the cancel button optional.
  *    + Put an #ifdef SPECIAL_CMAP around code to fix a colormap bug.
- *     We don't need it here.
+ *      We don't need it here.
  *    + Add the function positionpopup() from another part of ghostview
- *     to this code.
+ *      to this code.
  *
  * Modified 2/93, Various.
  *    + Added workaround for SYSV include problem.
  *    + Changed the default width response text widget to be as wide as the
- *     window itself.  Suggestion from David E. Wexelblat, dwex@goblin.org.
+ *      window itself.  Suggestion from David E. Wexelblat, dwex@goblin.org.
  *
  * Modified 5/2015, anonymous.
  *    + Include nethack's lint.h to get nhStr() macro.
  *    + Use nhStr() on string literals (or macros from <X11/StringDefs.h>
- *     that hide string literals) to cast away implicit 'const' in order
- *     to suppress "warning: assignment discards qualifers from pointer
- *     target type" issued by 'gcc -Wwrite-strings' as used by nethack.
- *     (For this file, always the second parameter to XtSetArg().)
+ *      that hide string literals) to cast away implicit 'const' in order
+ *      to suppress "warning: assignment discards qualifers from pointer
+ *      target type" issued by 'gcc -Wwrite-strings' as used by nethack.
+ *      (For this file, always the second parameter to XtSetArg().)
  *
- * $NHDT-Date: 1432512808 2015/05/25 00:13:28 $  $NHDT-Branch: master $:$NHDT-Revision: 1.6 $
+ * Modified 1/2016, Pat Rankin.
+ *    + Added minimum width argument to SetDialogResponse() so that the
+ *      text entry widget can be forced to wider than the default response.
+ *    + Make 'okay' button same width as 'cancel', and both wider than
+ *      default by a small arbitrary amount.
+ *
+ * $NHDT-Date: 1455157470 2016/02/11 02:24:30 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.9 $
  */
 
 /*
@@ -100,10 +105,10 @@ static const char cancel_accelerators[] = "#override\n\
      :<Ctrl>[: set() notify() unset()\n"; /* for keyboards w/o an ESC */
 
 /* Create a dialog widget.  It is just a form widget with
- *     a label prompt
- *     a text response
- *     an okay button
- *     an optional cancel button
+ *      a label prompt
+ *      a text response
+ *      an okay button
+ *      an optional cancel button
  */
 Widget
 CreateDialog(parent, name, okay_callback, cancel_callback)
@@ -115,75 +120,54 @@ XtCallbackProc cancel_callback;
     Widget form, prompt, response, okay, cancel;
     Arg args[20];
     Cardinal num_args;
+    Dimension owidth, cwidth;
 
     num_args = 0;
 #ifdef SPECIAL_CMAP
     if (special_cmap) {
-        XtSetArg(args[num_args], nhStr(XtNbackground), white);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbackground), white); num_args++;
     }
 #endif
-    form =
-        XtCreateManagedWidget(name, formWidgetClass, parent, args, num_args);
+    form = XtCreateManagedWidget(name, formWidgetClass, parent,
+                                 args, num_args);
 
     num_args = 0;
 #ifdef SPECIAL_CMAP
     if (special_cmap) {
-        XtSetArg(args[num_args], nhStr(XtNforeground), black);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbackground), white);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNforeground), black); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbackground), white); num_args++;
     }
 #endif
-    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNresizable), True);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNborderWidth), 0);
-    num_args++;
+    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNresizable), True); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNborderWidth), 0); num_args++;
 #if defined(X11R6) && defined(XI18N)
-    XtSetArg(args[num_args], XtNinternational, True);
-    num_args++;
+    XtSetArg(args[num_args], XtNinternational, True); num_args++;
 #endif
-    prompt = XtCreateManagedWidget("prompt", labelWidgetClass, form, args,
-                                   num_args);
+    prompt = XtCreateManagedWidget("prompt", labelWidgetClass, form,
+                                   args, num_args);
 
     num_args = 0;
 #ifdef SPECIAL_CMAP
     if (special_cmap) {
-        XtSetArg(args[num_args], nhStr(XtNforeground), black);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbackground), white);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNforeground), black); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbackground), white); num_args++;
     }
 #endif
-    XtSetArg(args[num_args], nhStr(XtNfromVert), prompt);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNresizable), True);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNeditType), XawtextEdit);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNresize), XawtextResizeWidth);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNstring), "");
-    num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), prompt); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNresizable), True); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNeditType), XawtextEdit); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNresize), XawtextResizeWidth); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNstring), ""); num_args++;
 #if defined(X11R6) && defined(XI18N)
-    XtSetArg(args[num_args], XtNinternational, True);
-    num_args++;
+    XtSetArg(args[num_args], XtNinternational, True); num_args++;
 #endif
     response = XtCreateManagedWidget("response", asciiTextWidgetClass, form,
                                      args, num_args);
@@ -191,69 +175,50 @@ XtCallbackProc cancel_callback;
     num_args = 0;
 #ifdef SPECIAL_CMAP
     if (special_cmap) {
-        XtSetArg(args[num_args], nhStr(XtNforeground), black);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbackground), white);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNforeground), black); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbackground), white); num_args++;
     }
 #endif
-    XtSetArg(args[num_args], nhStr(XtNfromVert), response);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNresizable), True);
-    num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), response); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNresizable), True); num_args++;
     XtSetArg(args[num_args], nhStr(XtNaccelerators),
-             XtParseAcceleratorTable(okay_accelerators));
-    num_args++;
+             XtParseAcceleratorTable(okay_accelerators)); num_args++;
 #if defined(X11R6) && defined(XI18N)
-    XtSetArg(args[num_args], XtNinternational, True);
-    num_args++;
+    XtSetArg(args[num_args], XtNinternational, True); num_args++;
 #endif
 /*JP
-    okay = XtCreateManagedWidget("okay", commandWidgetClass, form, args,
+    okay = XtCreateManagedWidget("okay", commandWidgetClass, form,
 */
-    okay = XtCreateManagedWidget("OK", commandWidgetClass, form, args,
-                                 num_args);
+    okay = XtCreateManagedWidget("OK", commandWidgetClass, form,
+                                 args, num_args);
     XtAddCallback(okay, XtNcallback, okay_callback, form);
+    XtSetArg(args[0], XtNwidth, &owidth);
+    XtGetValues(okay, args, ONE);
 
     /* Only create cancel button if there is a callback for it. */
     if (cancel_callback) {
         num_args = 0;
 #ifdef SPECIAL_CMAP
         if (special_cmap) {
-            XtSetArg(args[num_args], nhStr(XtNforeground), black);
-            num_args++;
-            XtSetArg(args[num_args], nhStr(XtNbackground), white);
-            num_args++;
+            XtSetArg(args[num_args], nhStr(XtNforeground), black); num_args++;
+            XtSetArg(args[num_args], nhStr(XtNbackground), white); num_args++;
         }
 #endif
-        XtSetArg(args[num_args], nhStr(XtNfromVert), response);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), okay);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNresizable), True);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), response); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), okay); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNresizable), True); num_args++;
         XtSetArg(args[num_args], nhStr(XtNaccelerators),
-                 XtParseAcceleratorTable(cancel_accelerators));
-        num_args++;
+                 XtParseAcceleratorTable(cancel_accelerators)); num_args++;
 #if defined(X11R6) && defined(XI18N)
-        XtSetArg(args[num_args], XtNinternational, True);
-        num_args++;
+        XtSetArg(args[num_args], XtNinternational, True); num_args++;
 #endif
 /*JP
         cancel = XtCreateManagedWidget("cancel", commandWidgetClass, form,
@@ -262,7 +227,18 @@ XtCallbackProc cancel_callback;
                                        args, num_args);
         XtAddCallback(cancel, XtNcallback, cancel_callback, form);
         XtInstallAccelerators(response, cancel);
-    }
+        XtSetArg(args[0], XtNwidth, &cwidth);
+        XtGetValues(cancel, args, ONE);
+        /* widen the cancel button */
+        cwidth += 25;
+        XtSetArg(args[0], XtNwidth, cwidth);
+        XtSetValues(cancel, args, ONE);
+    } else
+        cwidth = owidth + 25;
+
+    /* make okay button same width as cancel, or widen it if no cancel */
+    XtSetArg(args[0], XtNwidth, cwidth);
+    XtSetValues(okay, args, ONE);
 
     XtInstallAccelerators(response, okay);
     XtSetKeyboardFocus(form, response);
@@ -317,12 +293,12 @@ Widget w;
     return XtNewString(s);
 }
 
-#define max(a, b) (((a) > (b)) ? (a) : (b))
 /* set the default reponse */
 void
-SetDialogResponse(w, s)
+SetDialogResponse(w, s, ln)
 Widget w;
 String s;
+unsigned ln;
 {
 #ifndef XI18N
     Arg args[4];
@@ -332,11 +308,14 @@ String s;
     Widget response;
     XFontStruct *font;
     Dimension width, nwidth, leftMargin, rightMargin;
+    unsigned s_len = strlen(s);
 #ifdef XI18N
     XFontSet fontset;
     XFontSetExtents *extent;
 #endif
 
+    if (s_len < ln)
+        s_len = ln;
     response = XtNameToWidget(w, "response");
     XtSetArg(args[0], nhStr(XtNfont), &font);
     XtSetArg(args[1], nhStr(XtNleftMargin), &leftMargin);
@@ -345,7 +324,7 @@ String s;
 #ifndef XI18N
     XtGetValues(response, args, FOUR);
     /* width includes margins as per Xaw documentation */
-    nwidth = (font->max_bounds.width * strlen(s)) + leftMargin + rightMargin;
+    nwidth = font->max_bounds.width * (s_len + 1) + leftMargin + rightMargin;
 #else
     XtSetArg(args[4], XtNfontSet, &fontset);
     XtGetValues(response, args, FIVE);
@@ -378,8 +357,7 @@ ClearDialogResponse(w)
 }
 #endif
 
-/* Not a part of the original dialogs.c from ghostview ---------------------
- */
+/* Not a part of the original dialogs.c from ghostview -------------------- */
 
 /* position popup window under the cursor */
 void
@@ -403,12 +381,9 @@ boolean bottom; /* position y on bottom? */
     XQueryPointer(XtDisplay(toplevel), XtWindow(toplevel), &root, &child, &x,
                   &y, &dummyx, &dummyy, &dummymask);
     num_args = 0;
-    XtSetArg(args[num_args], XtNwidth, &width);
-    num_args++;
-    XtSetArg(args[num_args], XtNheight, &height);
-    num_args++;
-    XtSetArg(args[num_args], XtNborderWidth, &b_width);
-    num_args++;
+    XtSetArg(args[num_args], XtNwidth, &width); num_args++;
+    XtSetArg(args[num_args], XtNheight, &height); num_args++;
+    XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
     XtGetValues(w, args, num_args);
 
     /* position so that the cursor is center,center or center,bottom */
@@ -416,7 +391,7 @@ boolean bottom; /* position y on bottom? */
     x -= ((Position) width / 2);
     if (x < 0)
         x = 0;
-    if (x > (max_x = (Position)(XtScreen(w)->width - width)))
+    if (x > (max_x = (Position) (XtScreen(w)->width - width)))
         x = max_x;
 
     if (bottom) {
@@ -428,19 +403,16 @@ boolean bottom; /* position y on bottom? */
     }
     if (y < 0)
         y = 0;
-    if (y > (max_y = (Position)(XtScreen(w)->height - height)))
+    if (y > (max_y = (Position) (XtScreen(w)->height - height)))
         y = max_y;
 
     num_args = 0;
-    XtSetArg(args[num_args], XtNx, x);
-    num_args++;
-    XtSetArg(args[num_args], XtNy, y);
-    num_args++;
+    XtSetArg(args[num_args], XtNx, x); num_args++;
+    XtSetArg(args[num_args], XtNy, y); num_args++;
     XtSetValues(w, args, num_args);
 
-    /* Some older window managers ignore XtN{x,y}; hint the same values */
-    /* The {x,y} are not used by newer window managers; older ones need them
-     */
+    /* Some older window managers ignore XtN{x,y}; hint the same values.
+       {x,y} are not used by newer window managers; older ones need them. */
     XtRealizeWidget(w);
     hints = XAllocSizeHints();
     hints->flags = USPosition;
@@ -449,3 +421,5 @@ boolean bottom; /* position y on bottom? */
     XSetWMNormalHints(XtDisplay(w), XtWindow(w), hints);
     XFree(hints);
 }
+
+/*dialogs.c*/
index f4c1269..cc6a882 100644 (file)
@@ -1,6 +1,9 @@
 #
 # Nethack configuration file.
-# $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# $NHDT-Date: 1524689294 2018/04/25 20:48:14 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.7 $
+# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
+# NetHack may be freely redistributed.  See license for details.
+
 #
 # Naming this file $(HOME)/.nethackrc (for UNIX) or setting the environment
 # variable NETHACKOPTIONS to point to its full path name elsewhere tells
index c9e410f..750f12a 100644 (file)
@@ -1,4 +1,6 @@
-/* $NHDT-Date: 1432512808 2015/05/25 00:13:28 $  $NHDT-Branch: master $:$NHDT-Revision: 1.6 $ */
+/* $NHDT-Date: 1524689304 2018/04/25 20:48:24 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.11 $ */
+/*      Copyright (c) 2017 by Pasi Kallinen                       */
+/* NetHack may be freely redistributed.  See license for details. */
 
 /*
  * Convert the given input files into an output file that is expected
@@ -91,7 +93,7 @@ merge_text_colormap()
 
         if (j == header.ncolors) { /* couldn't find it */
 #ifdef PRINT_COLORMAP
-            printf("color %2d: %3d %3d %3d\n", header.ncolors,
+            Fprintf(stdout, "color %2d: %3d %3d %3d\n", header.ncolors,
                    ColorMap[CM_RED][i], ColorMap[CM_GREEN][i],
                    ColorMap[CM_BLUE][i]);
 #endif
@@ -117,7 +119,7 @@ char *fname;
     }
     merge_text_colormap();
     count = convert_tiles(&curr_tb, header.ntiles);
-    Fprintf(stderr, "%s: %lu tiles\n", fname, count);
+    Fprintf(stdout, "%s: %lu tiles\n", fname, count);
     header.ntiles += count;
     fclose_text_file();
 }
@@ -177,7 +179,7 @@ char **argv;
     header.per_row = TILES_PER_ROW;
 
     if (argc == 1) {
-        Fprintf(stderr, "usage: %s txt_file1 [txt_file2 ...]\n", argv[0]);
+        Fprintf(stderr, "usage: %s txt_file1 [txt_file2 ...] [-grayscale txt_fileN]\n", argv[0]);
         exit(1);
     }
 
@@ -190,9 +192,16 @@ char **argv;
     /* don't leave garbage at end of partial row */
     (void) memset((genericptr_t) tile_bytes, 0, sizeof(tile_bytes));
 
-    for (i = 1; i < argc; i++)
+    for (i = 1; i < argc; i++) {
+        if (!strncmp(argv[i], "-grayscale", 10)) {
+            set_grayscale(TRUE);
+            if (i < (argc - 1)) i++;
+        } else {
+            set_grayscale(FALSE);
+        }
         process_file(argv[i]);
-    Fprintf(stderr, "Total tiles: %ld\n", header.ntiles);
+    }
+    Fprintf(stdout, "Total tiles: %ld\n", header.ntiles);
 
     /* round size up to the end of the row */
     if ((header.ntiles % header.per_row) != 0) {
index 72b2857..2387469 100644 (file)
@@ -1,5 +1,5 @@
-/* NetHack 3.6 winX.c  $NHDT-Date: 1432512808 2015/05/25 00:13:28 $  $NHDT-Branch: master $:$NHDT-Revision: 1.33 $ */
-/* Copyright (c) Dean Luick, 1992                                */
+/* NetHack 3.6 winX.c  $NHDT-Date: 1507846693 2017/10/12 22:18:13 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.44 $ */
+/* Copyright (c) Dean Luick, 1992                                 */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -104,7 +104,11 @@ extern NEARDATA winid WIN_STATUS;
 
 /* Interface definition, for windows.c */
 struct window_procs X11_procs = {
-    "X11", WC_COLOR | WC_HILITE_PET | WC_TILED_MAP, 0L, X11_init_nhwindows,
+    "X11",
+    (WC_COLOR | WC_HILITE_PET | WC_ASCII_MAP | WC_TILED_MAP
+     | WC_PLAYER_SELECTION | WC_PERM_INVENT | WC_MOUSE_SUPPORT),
+    0L, /* WC2 flag mask */
+    X11_init_nhwindows,
     X11_player_selection, X11_askname, X11_get_nh_event, X11_exit_nhwindows,
     X11_suspend_nhwindows, X11_resume_nhwindows, X11_create_nhwindow,
     X11_clear_nhwindow, X11_display_nhwindow, X11_destroy_nhwindow, X11_curs,
@@ -132,47 +136,53 @@ struct window_procs X11_procs = {
     genl_outrip,
 #endif
     X11_preference_update, genl_getmsghistory, genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init, genl_status_finish, genl_status_enablefield,
     genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_no, /* XXX may not always be correct */
 };
 
 /*
  * Local functions.
  */
-static void FDECL(dismiss_file, (Widget, XEvent *, String *, Cardinal *));
-static void FDECL(delete_file, (Widget, XEvent *, String *, Cardinal *));
-static void FDECL(yn_key, (Widget, XEvent *, String *, Cardinal *));
-static void FDECL(yn_delete, (Widget, XEvent *, String *, Cardinal *));
+static winid NDECL(find_free_window);
+static void FDECL(nhFreePixel, (XtAppContext, XrmValuePtr, XtPointer,
+                                XrmValuePtr, Cardinal *));
+static boolean FDECL(new_resource_macro, (String, unsigned));
+static void NDECL(load_default_resources);
+static void NDECL(release_default_resources);
+#ifdef X11_HANGUP_SIGNAL
+static void FDECL(X11_sig, (int));
+static void FDECL(X11_sig_cb, (XtPointer, XtSignalId *));
+#endif
+static void FDECL(d_timeout, (XtPointer, XtIntervalId *));
+static void FDECL(X11_hangup, (Widget, XEvent *, String *, Cardinal *));
 static void FDECL(askname_delete, (Widget, XEvent *, String *, Cardinal *));
+static void FDECL(askname_done, (Widget, XtPointer, XtPointer));
+static void FDECL(done_button, (Widget, XtPointer, XtPointer));
 static void FDECL(getline_delete, (Widget, XEvent *, String *, Cardinal *));
-static void FDECL(X11_hangup, (Widget, XEvent *, String *, Cardinal *));
+static void FDECL(abort_button, (Widget, XtPointer, XtPointer));
+static void NDECL(release_getline_widgets);
+static void FDECL(delete_file, (Widget, XEvent *, String *, Cardinal *));
+static void FDECL(dismiss_file, (Widget, XEvent *, String *, Cardinal *));
+static void FDECL(yn_delete, (Widget, XEvent *, String *, Cardinal *));
+static void FDECL(yn_key, (Widget, XEvent *, String *, Cardinal *));
+static void NDECL(release_yn_widgets);
 static int FDECL(input_event, (int));
 static void FDECL(win_visible, (Widget, XtPointer, XEvent *, Boolean *));
 static void NDECL(init_standard_windows);
-#ifdef X11_HANGUP_SIGNAL
-static void FDECL(X11_sig, (int));
-static void FDECL(X11_sig_cb, (XtPointer, XtSignalId *));
+
+#ifdef  INSTALLCOLORMAP
+Colormap     cmap;
 #endif
 
 /*
  * Local variables.
  */
-static boolean x_inited = FALSE;    /* TRUE if window system is set up. */
-static winid message_win = WIN_ERR, /* These are the winids of the          */
-    map_win = WIN_ERR,              /*   message, map, and status           */
-    status_win = WIN_ERR;           /*   windows, when they are created */
-                                    /*   in init_windows().                 */
-static Pixmap icon_pixmap = None;   /* Pixmap for icon.             */
-
-#ifdef  INSTALLCOLORMAP
-Colormap     cmap;
-#endif
+static boolean x_inited = FALSE;    /* TRUE if window system is set up.     */
+static winid message_win = WIN_ERR, /* These are the winids of the message, */
+             map_win = WIN_ERR,     /*   map, and status windows, when they */
+             status_win = WIN_ERR;  /*   are created in init_windows().     */
+static Pixmap icon_pixmap = None;   /* Pixmap for icon.                     */
 
 /*
  * Find the window structure that corresponds to the given widget.  Note
@@ -185,8 +195,10 @@ Widget w;
     int windex;
     struct xwindow *wp;
 
-    /* Search to find the corresponding window.  Look at the main widget, */
-    /* popup, the parent of the main widget, then parent of the widget. */
+    /*
+     * Search to find the corresponding window.  Look at the main widget,
+     * popup, the parent of the main widget, then parent of the widget.
+     */
     for (windex = 0, wp = window_list; windex < MAX_WINDOWS; windex++, wp++)
         if (wp->type != NHW_NONE && (wp->w == w || wp->popup == w
                                      || (wp->w && (XtParent(wp->w)) == w)
@@ -224,10 +236,12 @@ find_free_window()
  * This is an attempt to find some close readonly cell and use it.
  */
 XtConvertArgRec const nhcolorConvertArgs[] = {
-    { XtWidgetBaseOffset, (XtPointer) XtOffset(Widget, core.screen),
-      sizeof(Screen *) },
-    { XtWidgetBaseOffset, (XtPointer) XtOffset(Widget, core.colormap),
-      sizeof(Colormap) }
+    { XtWidgetBaseOffset,
+      (XtPointer) (ptrdiff_t) XtOffset(Widget, core.screen),
+      sizeof (Screen *) },
+    { XtWidgetBaseOffset,
+      (XtPointer) (ptrdiff_t) XtOffset(Widget, core.colormap),
+      sizeof (Colormap) }
 };
 
 #define done(type, value)                             \
@@ -248,9 +262,9 @@ XtConvertArgRec const nhcolorConvertArgs[] = {
     }
 
 /*
- * Find a color that approximates the color named in "str".  The "str" color
- * may be a color name ("red") or number ("#7f0000").  If str == NULL, then
- * "color" is assumed to contain the RGB color wanted.
+ * Find a color that approximates the color named in "str".
+ * The "str" color may be a color name ("red") or number ("#7f0000").
+ * If str is Null, then "color" is assumed to contain the RGB color wanted.
  * The approximate color found is returned in color as well.
  * Return True if something close was found.
  */
@@ -268,8 +282,8 @@ XColor *color;     /* the X color structure; changed only if successful */
     register int i, j;
     register long tdiff;
 
-    /* if the screen doesn't have a big colormap, don't waste our time */
-    /* or if it's huge, and _some_ match should have been possible */
+    /* if the screen doesn't have a big colormap, don't waste our time
+       or if it's huge, and _some_ match should have been possible */
     if ((ncells = CellsOfScreen(screen)) < 256 || ncells > 4096)
         return False;
 
@@ -288,9 +302,9 @@ XColor *color;     /* the X color structure; changed only if successful */
         XQueryColors(DisplayOfScreen(screen), colormap, table, ncells);
     }
 
-/* go thru cells and look for the one with smallest diff */
+/* go thru cells and look for the one with smallest diff        */
 /* diff is calculated abs(reddiff)+abs(greendiff)+abs(bluediff) */
-/* a more knowledgeable color person might improve this -dlc */
+/* a more knowledgeable color person might improve this -dlc    */
 try_again:
     for (i = 0; i < ncells; i++) {
         if (table[i].flags == tmp.flags) {
@@ -394,10 +408,10 @@ XtPointer *closure_ret;
     Cardinal num_params = 1;
 
     if (*num_args != 2) {
-        XtAppWarningMsg(
-            app, "wrongParameters", "cvtStringToPixel", "XtToolkitError",
-            "String to pixel conversion needs screen and colormap arguments",
-            (String *) 0, (Cardinal *) 0);
+        XtAppWarningMsg(app, "wrongParameters",
+                        "cvtStringToPixel", "XtToolkitError",
+             "String to pixel conversion needs screen and colormap arguments",
+                        (String *) 0, (Cardinal *) 0);
         return False;
     }
 
@@ -481,10 +495,9 @@ Cardinal *num_args;
     Colormap colormap;
 
     if (*num_args != 2) {
-        XtAppWarningMsg(
-            app, "wrongParameters", "freePixel", "XtToolkitError",
-            "Freeing a pixel requires screen and colormap arguments",
-            (String *) 0, (Cardinal *) 0);
+        XtAppWarningMsg(app, "wrongParameters", "freePixel", "XtToolkitError",
+                     "Freeing a pixel requires screen and colormap arguments",
+                        (String *) 0, (Cardinal *) 0);
         return;
     }
 
@@ -500,9 +513,11 @@ Cardinal *num_args;
 /* [ALI] Utility function to ask Xaw for font height, since the previous
  * assumption of ascent + descent is not always valid.
  */
-Dimension nhFontHeight(w) Widget w;
-#ifdef _XawTextSink_h
+Dimension
+nhFontHeight(w)
+Widget w;
 {
+#ifdef _XawTextSink_h
     Widget sink;
     XawTextPosition pos = 0;
     int resWidth, resHeight;
@@ -513,9 +528,7 @@ Dimension nhFontHeight(w) Widget w;
 
     XawTextSinkFindPosition(sink, pos, 0, 0, 0, &pos, &resWidth, &resHeight);
     return resHeight;
-}
 #else
-{
     XFontStruct *fs;
     Arg args[1];
 
@@ -524,11 +537,172 @@ Dimension nhFontHeight(w) Widget w;
 
     /* Assume font height is ascent + descent. */
     return = fs->ascent + fs->descent;
-}
 #endif
+}
 
-/* Global Functions ========================================================
- */
+static String *default_resource_data = 0, /* NULL-terminated arrays */
+              *def_rsrc_macr = 0, /* macro names */
+              *def_rsrc_valu = 0; /* macro values */
+
+/* caller found "#define"; parse into macro name and its expansion value */
+static boolean
+new_resource_macro(inbuf, numdefs)
+String inbuf; /* points past '#define' rather than to start of buffer */
+unsigned numdefs; /* array slot to fill */
+{
+    String p, q;
+
+    /* we expect inbuf to be terminated by newline; get rid of it */
+    q = eos(inbuf);
+    if (q > inbuf && q[-1] == '\n')
+        q[-1] = '\0';
+
+    /* figure out macro's name */
+    for (p = inbuf; *p == ' ' || *p == '\t'; ++p)
+        continue; /* skip whitespace */
+    for (q = p; *q && *q != ' ' && *q != '\t'; ++q)
+        continue; /* token consists of non-whitespace */
+    Strcat(q, " "); /* guarantee something beyond '#define FOO' */
+    *q++ = '\0'; /* p..(q-1) contains macro name */
+    if (!*p) /* invalid definition: '#define' followed by nothing */
+        return FALSE;
+    def_rsrc_macr[numdefs] = dupstr(p);
+
+    /* figure out macro's value; empty value is supported but not expected */
+    while (*q == ' ' || *q == '\t')
+        ++q; /* skip whitespace between name and value */
+    for (p = eos(q); --p > q && (*p == ' ' || *p == '\t'); )
+        continue; /* discard trailing whitespace */
+    *++p = '\0'; /* q..p containes macro value */
+    def_rsrc_valu[numdefs] = dupstr(q);
+    return TRUE;
+}
+
+/* read the template NetHack.ad into default_resource_data[] to supply
+   fallback resources to XtAppInitialize() */
+static void
+load_default_resources()
+{
+    FILE *fp;
+    String inbuf;
+    unsigned insiz, linelen, longlen, numlines, numdefs, midx;
+    boolean comment, isdef;
+
+    /*
+     * Running nethack via the shell script adds $HACKDIR to the path used
+     * by X to find resources, but running it directly doesn't.  So, if we
+     * can find the template file for NetHack.ad in the current directory,
+     * load its contents into memory so that the application startup call
+     * in X11_init_nhwindows() can use them as fallback resources.
+     *
+     * No attempt to support the 'include' directive has been made, nor
+     * backslash+newline continuation lines.  Macro expansion (at most
+     * one substitution per line) is supported.  '#define' to introduce
+     * a macro must be at start of line (no whitespace before or after
+     * the '#' character).
+     */
+    fp = fopen("./NetHack.ad", "r");
+    if (!fp)
+        return;
+
+    /* measure the file without retaining its contents */
+    insiz = BUFSIZ; /* stdio BUFSIZ, not nethack BUFSZ */
+    inbuf = (String) alloc(insiz);
+    linelen = longlen = 0;
+    numlines = numdefs = 0;
+    comment = isdef = FALSE; /* lint suppression */
+    while (fgets(inbuf, insiz, fp)) {
+        if (!linelen) {
+            /* !linelen: inbuf has start of record; treat empty as comment */
+            comment = (*inbuf == '!' || *inbuf == '\n');
+            isdef = !strncmp(inbuf, "#define", 7);
+            ++numdefs;
+        }
+        linelen += strlen(inbuf);
+        if (!index(inbuf, '\n'))
+            continue;
+        if (linelen > longlen)
+            longlen = linelen;
+        linelen = 0;
+        if (!comment && !isdef)
+            ++numlines;
+    }
+    insiz = longlen + 1;
+    if (numdefs) { /* don't alloc if 0; no need for any terminator */
+        def_rsrc_macr = (String *) alloc(numdefs * sizeof (String));
+        def_rsrc_valu = (String *) alloc(numdefs * sizeof (String));
+        insiz += BUFSIZ; /* include room for macro expansion within buffer */
+    }
+    if (insiz > BUFSIZ) {
+        free((genericptr_t) inbuf);
+        inbuf = (String) alloc(insiz);
+    }
+    ++numlines; /* room for terminator */
+    default_resource_data = (String *) alloc(numlines * sizeof (String));
+
+    /* now re-read the file, storing its contents into the allocated array
+       after performing macro substitutions */
+    (void) rewind(fp);
+    numlines = numdefs = 0;
+    while (fgets(inbuf, insiz, fp)) {
+        if (!strncmp(inbuf, "#define", 7)) {
+            if (new_resource_macro(&inbuf[7], numdefs))
+                ++numdefs;
+        } else if (*inbuf != '!' && *inbuf != '\n') {
+            if (numdefs) {
+                /*
+                 * Macro expansion:  we assume at most one substitution
+                 * per line.  That's all that our sample NetHack.ad uses.
+                 *
+                 * If we ever need more, this will have to become a lot
+                 * more sophisticated.  It will need to find the first
+                 * instance within inbuf[] rather than first macro which
+                 * appears, and to avoid finding names within substituted
+                 * expansion values.
+                 *
+                 * Any substitution which would exceed the buffer size is
+                 * skipped.  A sophisticated implementation would need to
+                 * be prepared to allocate a bigger buffer when needed.
+                 */
+                linelen = strlen(inbuf);
+                for (midx = 0; midx < numdefs; ++midx) {
+                    if ((linelen + strlen(def_rsrc_valu[midx])
+                         < insiz - strlen(def_rsrc_macr[midx]))
+                        && strNsubst(inbuf, def_rsrc_macr[midx],
+                                     def_rsrc_valu[midx], 1))
+                        break;
+                }
+            }
+            default_resource_data[numlines++] = dupstr(inbuf);
+        }
+    }
+    default_resource_data[numlines] = (String) 0;
+    (void) fclose(fp);
+    free((genericptr_t) inbuf);
+    if (def_rsrc_macr) { /* implies def_rsrc_valu is non-Null too */
+        for (midx = 0; midx < numdefs; ++midx) {
+            free((genericptr_t) def_rsrc_macr[midx]);
+            free((genericptr_t) def_rsrc_valu[midx]);
+        }
+        free((genericptr_t) def_rsrc_macr), def_rsrc_macr = 0;
+        free((genericptr_t) def_rsrc_valu), def_rsrc_valu = 0;
+    }
+}
+
+static void
+release_default_resources()
+{
+    if (default_resource_data) {
+        unsigned idx;
+
+        for (idx = 0; default_resource_data[idx]; idx++)
+            free((genericptr_t) default_resource_data[idx]);
+        free((genericptr_t) default_resource_data), default_resource_data = 0;
+    }
+    /* def_rsrc_macr[] and def_rsrc_valu[] have already been released */
+}
+
+/* Global Functions ======================================================= */
 void
 X11_raw_print(str)
 const char *str;
@@ -776,19 +950,20 @@ boolean blocking;
         if (wp->popup)
             nh_XtPopup(wp->popup, (int) XtGrabNone, wp->w);
         display_map_window(wp); /* flush map */
-                                /*
-                                 * We need to flush the message window here due to the way the tty
-                                 * port is set up.  To flush a window, you need to call this
-                                 * routine.  However, the tty port _pauses_ with a --more-- if we
-                                 * do a display_nhwindow(WIN_MESSAGE, FALSE).  Thus, we can't call
-                                 * display_nhwindow(WIN_MESSAGE,FALSE) in parse() because then we
-                                 * get a --more-- after every line.
-                                 *
-                                 * Perhaps the window document should mention that when the map
-                                 * is flushed, everything on the three main windows should be
-                                 * flushed.  Note: we don't need to flush the status window
-                                 * because we don't buffer changes.
-                                 */
+
+        /*
+         * We need to flush the message window here due to the way the tty
+         * port is set up.  To flush a window, you need to call this
+         * routine.  However, the tty port _pauses_ with a --more-- if we
+         * do a display_nhwindow(WIN_MESSAGE, FALSE).  Thus, we can't call
+         * display_nhwindow(WIN_MESSAGE,FALSE) in parse() because then we
+         * get a --more-- after every line.
+         *
+         * Perhaps the window document should mention that when the map
+         * is flushed, everything on the three main windows should be
+         * flushed.  Note: we don't need to flush the status window
+         * because we don't buffer changes.
+         */
         if (WIN_MESSAGE != WIN_ERR)
             display_message_window(&window_list[WIN_MESSAGE]);
         if (blocking)
@@ -943,7 +1118,8 @@ const char *str;
 
 /* Under X, we don't need to initialize the number pad. */
 /* ARGSUSED */
-void X11_number_pad(state) /* called from options.c */
+void
+X11_number_pad(state) /* called from options.c */
 int state;
 {
     nhUse(state);
@@ -951,16 +1127,19 @@ int state;
     return;
 }
 
+/* called from setftty() in unixtty.c */
 void
 X11_start_screen()
 {
     return;
-} /* called from setftty() in unixtty.c */
+}
+
+/* called from settty() in unixtty.c */
 void
 X11_end_screen()
 {
     return;
-} /* called from settty() in unixtty.c */
+}
 
 #ifdef GRAPHIC_TOMBSTONE
 void
@@ -984,8 +1163,7 @@ time_t when;
 }
 #endif
 
-/* init and exit nhwindows -------------------------------------------------
- */
+/* init and exit nhwindows ------------------------------------------------ */
 
 XtAppContext app_context;     /* context of application */
 Widget toplevel = (Widget) 0; /* toplevel widget */
@@ -996,8 +1174,7 @@ static XtActionsRec actions[] = {
     { nhStr("delete_file"), delete_file },   /* file delete-window */
     { nhStr("dismiss_text"), dismiss_text }, /* text widget button action */
     { nhStr("delete_text"), delete_text },   /* text widget delete action */
-    { nhStr("key_dismiss_text"),
-      key_dismiss_text }, /* text widget key action */
+    { nhStr("key_dismiss_text"), key_dismiss_text }, /* text key action   */
 #ifdef GRAPHIC_TOMBSTONE
     { nhStr("rip_dismiss_text"), rip_dismiss_text }, /* rip in text widget */
 #endif
@@ -1010,6 +1187,9 @@ static XtActionsRec actions[] = {
     { nhStr("ec_key"), ec_key },                 /* extended commands */
     { nhStr("ec_delete"), ec_delete },           /* ext-com menu delete */
     { nhStr("ps_key"), ps_key },                 /* player selection */
+    { nhStr("plsel_quit"), plsel_quit },   /* player selection dialog */
+    { nhStr("plsel_play"), plsel_play },   /* player selection dialog */
+    { nhStr("plsel_rnd"), plsel_randomize }, /* player selection dialog */
     { nhStr("race_key"), race_key },             /* race selection */
     { nhStr("gend_key"), gend_key },             /* gender selection */
     { nhStr("algn_key"), algn_key },             /* alignment selection */
@@ -1026,6 +1206,9 @@ static XtResource resources[] = {
     { nhStr("message_line"), nhStr("Message_line"), XtRBoolean,
       sizeof(Boolean), XtOffset(AppResources *, message_line), XtRString,
       nhStr("False") },
+    { nhStr("highlight_prompt"), nhStr("Highlight_prompt"), XtRBoolean,
+      sizeof(Boolean), XtOffset(AppResources *, highlight_prompt), XtRString,
+      nhStr("True") },
     { nhStr("double_tile_size"), nhStr("Double_tile_size"), XtRBoolean,
       sizeof(Boolean), XtOffset(AppResources *, double_tile_size), XtRString,
       nhStr("False") },
@@ -1041,6 +1224,9 @@ static XtResource resources[] = {
       XtOffset(AppResources *, icon), XtRString, nhStr("nh72") },
     { nhStr("message_lines"), nhStr("Message_lines"), XtRInt, sizeof(int),
       XtOffset(AppResources *, message_lines), XtRString, nhStr("12") },
+    { nhStr("extcmd_height_delta"), nhStr("Extcmd_height_delta"),
+      XtRInt, sizeof (int),
+      XtOffset(AppResources *, extcmd_height_delta), XtRString, nhStr("0") },
     { nhStr("pet_mark_bitmap"), nhStr("Pet_mark_bitmap"), XtRString,
       sizeof(String), XtOffset(AppResources *, pet_mark_bitmap), XtRString,
       nhStr("pet_mark.xbm") },
@@ -1084,6 +1270,8 @@ char **argv;
     /* add another option that can be set */
     set_wc_option_mod_status(WC_TILED_MAP, SET_IN_GAME);
 
+    load_default_resources(); /* create default_resource_data[] */
+
     /*
      * setuid hack: make sure that if nethack is setuid, to use real uid
      * when opening X11 connections, in case the user is using xauth, since
@@ -1107,23 +1295,22 @@ char **argv;
                        0, 0, XtCacheByDisplay, 0);
 #endif
     num_args = 0;
-    XtSetArg(args[num_args], XtNallowShellResize, True);
-    num_args++;
-    toplevel =
+    XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
+    XtSetArg(args[num_args], XtNtitle, "NetHack"); num_args++;
+
 #if 0 /*JP*/
-        XtAppInitialize(&app_context, "NetHack",  /* application class */
+    toplevel = XtAppInitialize(&app_context, "NetHack",     /* application  */
 #else
-        XtAppInitialize(&app_context, "JNetHack", /* application class */
+    toplevel = XtAppInitialize(&app_context, "JNetHack",    /* application  */
 #endif
-                        (XrmOptionDescList) 0, 0, /* options list */
-                        argcp, (String *) argv,   /* command line args */
-                        (String *) 0,             /* fallback resources */
-                        (ArgList) args, num_args);
-    XtOverrideTranslations(
-        toplevel,
-        XtParseTranslationTable("<Message>WM_PROTOCOLS: X11_hangup()"));
+                               (XrmOptionDescList) 0, 0,    /* options list */
+                               argcp, (String *) argv,      /* command line */
+                               default_resource_data, /* fallback resources */
+                               (ArgList) args, num_args);
+    XtOverrideTranslations(toplevel,
+              XtParseTranslationTable("<Message>WM_PROTOCOLS: X11_hangup()"));
 
-/* We don't need to realize the top level widget. */
+    /* We don't need to realize the top level widget. */
 
 #ifdef TEXTCOLOR
     /* add new color converter to deal with overused colormaps */
@@ -1169,6 +1356,9 @@ char **argv;
     (void) seteuid(savuid);
 
     x_inited = TRUE; /* X is now initialized */
+    plsel_ask_name = FALSE;
+
+    release_default_resources();
 
     /* Display the startup banner in the message window. */
     for (i = 1; i <= 4 + 2; ++i) /* (values beyond 4 yield blank lines) */
@@ -1204,10 +1394,14 @@ const char *dummy;
         X11_destroy_nhwindow(WIN_MAP);
     if (WIN_MESSAGE != WIN_ERR)
         X11_destroy_nhwindow(WIN_MESSAGE);
+
+    release_getline_widgets();
+    release_yn_widgets();
 }
 
 #ifdef X11_HANGUP_SIGNAL
-static void X11_sig(sig) /* Unix signal handler */
+static void
+X11_sig(sig) /* Unix signal handler */
 int sig;
 {
     XtNoticeSignal(X11_sig_id);
@@ -1237,8 +1431,7 @@ XtSignalId *id;
 }
 #endif
 
-/* delay_output ------------------------------------------------------------
- */
+/* delay_output ----------------------------------------------------------- */
 
 /*
  * Timeout callback for delay_output().  Send a fake message to the map
@@ -1284,8 +1477,7 @@ X11_delay_output()
     (void) x_event(EXIT_ON_SENT_EVENT);
 }
 
-/* X11_hangup --------------------------------------------------------------
- */
+/* X11_hangup ------------------------------------------------------------- */
 /* ARGSUSED */
 static void
 X11_hangup(w, event, params, num_params)
@@ -1303,8 +1495,7 @@ Cardinal *num_params;
     exit_x_event = TRUE;
 }
 
-/* askname -----------------------------------------------------------------
- */
+/* askname ---------------------------------------------------------------- */
 /* ARGSUSED */
 static void
 askname_delete(w, event, params, num_params)
@@ -1330,7 +1521,7 @@ Widget w;
 XtPointer client_data;
 XtPointer call_data;
 {
-    int len;
+    unsigned len;
     char *s;
     Widget dialog = (Widget) client_data;
 
@@ -1339,15 +1530,15 @@ XtPointer call_data;
 
     s = (char *) GetDialogResponse(dialog);
 
-    len = (int) strlen(s);
+    len = strlen(s);
     if (len == 0) {
         X11_nhbell();
         return;
     }
 
     /* Truncate name if necessary */
-    if (len >= (int) sizeof(plname) - 1)
-        len = (int) sizeof(plname) - 1;
+    if (len >= sizeof plname - 1)
+        len = sizeof plname - 1;
 
     (void) strncpy(plname, s, len);
     plname[len] = '\0';
@@ -1357,25 +1548,33 @@ XtPointer call_data;
     exit_x_event = TRUE;
 }
 
+/* ask player for character's name to replace generic name "player" (or other
+   values; see config.h) after 'nethack -u player' or OPTIONS=name:player */
 void
 X11_askname()
 {
     Widget popup, dialog;
     Arg args[1];
 
+    if (iflags.wc_player_selection == VIA_DIALOG) {
+        /* X11_player_selection_dialog() handles name query */
+        plsel_ask_name = TRUE;
+        iflags.defer_plname = TRUE;
+        return;
+    } /* else iflags.wc_player_selection == VIA_PROMPTS */
+
     XtSetArg(args[0], XtNallowShellResize, True);
 
     popup = XtCreatePopupShell("askname", transientShellWidgetClass, toplevel,
                                args, ONE);
-    XtOverrideTranslations(
-        popup,
-        XtParseTranslationTable("<Message>WM_PROTOCOLS: askname_delete()"));
+    XtOverrideTranslations(popup,
+          XtParseTranslationTable("<Message>WM_PROTOCOLS: askname_delete()"));
 
     dialog = CreateDialog(popup, nhStr("dialog"), askname_done,
                           (XtCallbackProc) 0);
 
     SetDialogPrompt(dialog, nhStr("What is your name?")); /* set prompt */
-    SetDialogResponse(dialog, nhStr("")); /* set default answer */
+    SetDialogResponse(dialog, plname, PL_NSIZ); /* set default answer */
 
     XtRealizeWidget(popup);
     positionpopup(popup, TRUE); /* center,bottom */
@@ -1384,10 +1583,12 @@ X11_askname()
 
     /* The callback will enable the event loop exit. */
     (void) x_event(EXIT_ON_EXIT);
+
+    XtDestroyWidget(dialog);
+    XtDestroyWidget(popup);
 }
 
-/* getline -----------------------------------------------------------------
- */
+/* getline ---------------------------------------------------------------- */
 /* This uses Tim Theisen's dialog widget set (from GhostView). */
 
 static Widget getline_popup, getline_dialog;
@@ -1460,28 +1661,34 @@ XtPointer call_data;
     exit_x_event = TRUE;
 }
 
+static void
+release_getline_widgets()
+{
+    if (getline_dialog)
+        XtDestroyWidget(getline_dialog), getline_dialog = (Widget) 0;
+    if (getline_popup)
+        XtDestroyWidget(getline_popup), getline_popup = (Widget) 0;
+}
+
 void
 X11_getlin(question, input)
 const char *question;
 char *input;
 {
-    static boolean need_to_init = True;
-
     getline_input = input;
 
     flush_screen(1);
-    if (need_to_init) {
+    if (!getline_popup) {
         Arg args[1];
 
-        need_to_init = False;
-
         XtSetArg(args[0], XtNallowShellResize, True);
 
-        getline_popup = XtCreatePopupShell(
-            "getline", transientShellWidgetClass, toplevel, args, ONE);
-        XtOverrideTranslations(
-            getline_popup, XtParseTranslationTable(
-                               "<Message>WM_PROTOCOLS: getline_delete()"));
+        getline_popup = XtCreatePopupShell("getline",
+                                           transientShellWidgetClass,
+                                           toplevel, args, ONE);
+        XtOverrideTranslations(getline_popup,
+                               XtParseTranslationTable(
+                                  "<Message>WM_PROTOCOLS: getline_delete()"));
 
         getline_dialog = CreateDialog(getline_popup, nhStr("dialog"),
                                       done_button, abort_button);
@@ -1491,7 +1698,17 @@ char *input;
                         &wm_delete_window, 1);
     }
     SetDialogPrompt(getline_dialog, (String) question); /* set prompt */
-    SetDialogResponse(getline_dialog, nhStr("")); /* set default answer */
+    /* 60:  make the answer widget be wide enough to hold 60 characters,
+       or the length of the prompt string, whichever is bigger.  User's
+       response can be longer--when limit is reached, value-so-far will
+       slide left hiding some chars at the beginning of the response but
+       making room to type more.  [Prior to 3.6.1, width wasn't specifiable
+       and answer box always got sized to match the width of the prompt.] */
+#ifdef EDIT_GETLIN
+    SetDialogResponse(getline_dialog, input, 60); /* set default answer */
+#else
+    SetDialogResponse(getline_dialog, nhStr(""), 60); /* set default answer */
+#endif
     positionpopup(getline_popup, TRUE);           /* center,bottom */
 
     nh_XtPopup(getline_popup, (int) XtGrabExclusive, getline_dialog);
@@ -1500,8 +1717,7 @@ char *input;
     (void) x_event(EXIT_ON_EXIT);
 }
 
-/* Display file ------------------------------------------------------------
- */
+/* Display file ----------------------------------------------------------- */
 static const char display_translations[] = "#override\n\
      <Key>q: dismiss_file()\n\
      <Key>Escape: dismiss_file()\n\
@@ -1560,7 +1776,7 @@ boolean complain;
 #define LLEN 128
     char line[LLEN];
     int num_lines;
-    char *textlines;
+    char *textlines, *bp;
     int charcount;
 #ifdef XI18N
     XFontSet fontset;
@@ -1573,7 +1789,6 @@ boolean complain;
     if (!fp) {
         if (complain)
             pline("Cannot open %s.  Sorry.", str);
-
         return; /* it doesn't exist, ignore */
     }
 
@@ -1606,65 +1821,52 @@ boolean complain;
 
     fp = dlb_fopen(str, RDTMODE);
 
+    bp = textlines;
     while (dlb_fgets(line, LLEN, fp)) {
-        (void) strcat(textlines, line);
+        Strcpy((bp = eos(bp)), line);
     }
 
     (void) dlb_fclose(fp);
 
     num_args = 0;
-    XtSetArg(args[num_args], nhStr(XtNtitle), str);
-    num_args++;
+    XtSetArg(args[num_args], nhStr(XtNtitle), str); num_args++;
 
     popup = XtCreatePopupShell("display_file", topLevelShellWidgetClass,
                                toplevel, args, num_args);
-    XtOverrideTranslations(
-        popup,
+    XtOverrideTranslations(popup,
         XtParseTranslationTable("<Message>WM_PROTOCOLS: delete_file()"));
 
     num_args = 0;
     XtSetArg(args[num_args], nhStr(XtNscrollHorizontal),
-             XawtextScrollWhenNeeded);
-    num_args++;
+             XawtextScrollWhenNeeded); num_args++;
     XtSetArg(args[num_args], nhStr(XtNscrollVertical), XawtextScrollAlways);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNtype), XawAsciiString);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNstring), textlines);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNdisplayCaret), False);
-    num_args++;
+                                                                   num_args++;
+    XtSetArg(args[num_args], nhStr(XtNtype), XawAsciiString); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNstring), textlines); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNdisplayCaret), False); num_args++;
     XtSetArg(args[num_args], nhStr(XtNtranslations),
-             XtParseTranslationTable(display_translations));
-    num_args++;
+             XtParseTranslationTable(display_translations)); num_args++;
 
-/*JP*/
 #if defined(X11R6) && defined(XI18N)
-    XtSetArg(args[num_args], XtNinternational, True);
-    num_args++;
+    XtSetArg(args[num_args], XtNinternational, True); num_args++;
 #endif
-    dispfile =
-        XtCreateManagedWidget("text",                      /* name */
-                              asciiTextWidgetClass, popup, /* parent widget */
-                              args,      /* set some values */
-                              num_args); /* number of values to set */
+    dispfile = XtCreateManagedWidget("text",                      /* name */
+                                     asciiTextWidgetClass, popup, /* parent */
+                                     args, num_args);
 
     /* Get font and border information. */
     num_args = 0;
-#ifndef XI18N
-    XtSetArg(args[num_args], nhStr(XtNfont), &fs);
+#if 0 /*JP*/
+    XtSetArg(args[num_args], nhStr(XtNfont), &fs); num_args++;
 #else
-    XtSetArg(args[num_args], XtNfontSet, &fontset);
+    XtSetArg(args[num_args], XtNfontSet, &fontset); num_args++;
 #endif
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNtopMargin), &top_margin);
-    num_args++;
+    XtSetArg(args[num_args], nhStr(XtNtopMargin), &top_margin); num_args++;
     XtSetArg(args[num_args], nhStr(XtNbottomMargin), &bottom_margin);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNleftMargin), &left_margin);
-    num_args++;
+                                                                   num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleftMargin), &left_margin); num_args++;
     XtSetArg(args[num_args], nhStr(XtNrightMargin), &right_margin);
-    num_args++;
+                                                                   num_args++;
     XtGetValues(dispfile, args, num_args);
 
     /*
@@ -1684,18 +1886,15 @@ boolean complain;
 
     /* Set the new width and height. */
     num_args = 0;
-    XtSetArg(args[num_args], XtNwidth, new_width);
-    num_args++;
-    XtSetArg(args[num_args], XtNheight, new_height);
-    num_args++;
+    XtSetArg(args[num_args], XtNwidth, new_width); num_args++;
+    XtSetArg(args[num_args], XtNheight, new_height); num_args++;
     XtSetValues(dispfile, args, num_args);
 
     nh_XtPopup(popup, (int) XtGrabNone, (Widget) 0);
     free(textlines);
 }
 
-/* yn_function -------------------------------------------------------------
- */
+/* yn_function ------------------------------------------------------------ */
 /* (not threaded) */
 
 static const char *yn_quitchars = " \n\r";
@@ -1833,21 +2032,32 @@ Cardinal *num_params;
     exit_x_event = TRUE; /* exit our event handler */
 }
 
+/* called at exit time */
+static void
+release_yn_widgets()
+{
+    if (yn_label)
+        XtDestroyWidget(yn_label), yn_label = (Widget) 0;
+    if (yn_popup)
+        XtDestroyWidget(yn_popup), yn_popup = (Widget) 0;
+}
+
+/* X11-specific edition of yn_function(), the routine called by the core
+   to show a prompt and get a single keystroke answer, often 'y' vs 'n' */
 char
 X11_yn_function(ques, choices, def)
 const char *ques;
-const char *choices;
-char def;
+const char *choices; /* string of possible response chars; any char if Null */
+char def;            /* default response if user hits <space> or <return> */
 {
-    static Boolean need_to_init = True;
     char buf[BUFSZ];
     Arg args[4];
     Cardinal num_args;
 
     yn_choices = choices; /* set up globals for callback to use */
     yn_def = def;
-    yn_preserve_case =
-        !choices; /* preserve when arbitrary response allowed */
+    yn_preserve_case = !choices; /* preserve case when an arbitrary
+                                    response is allowed */
 
     /*
      * This is sort of a kludge.  There are quite a few places in the main
@@ -1884,8 +2094,9 @@ char def;
         Strcat(buf, " ");
 
         /* escape maps to 'q' or 'n' or default, in that order */
-        yn_esc_map =
-            (index(choices, 'q') ? 'q' : (index(choices, 'n') ? 'n' : def));
+        yn_esc_map = (index(choices, 'q') ? 'q'
+                      : index(choices, 'n') ? 'n'
+                        : def);
     } else {
         if ((int) (1 + strlen(ques) + 1) >= BUFSZ)
             panic("X11_yn_function:  question too long");
@@ -1893,24 +2104,43 @@ char def;
         Strcat(buf, " ");
     }
 
-    if (!appResources.slow && need_to_init) {
-        need_to_init = False;
+    /*
+     * The 'slow' resource is misleadingly named.  When it is True, we
+     * re-use the same one-line widget above the map for all yn prompt
+     * responses instead of re-using a popup widget for each one.  It's
+     * crucial for client/server configs where the server is slow putting
+     * up a popup or requires click-to-focus to respond to the popup, but
+     * is also useful for players who just want to be able to look at the
+     * same location to read questions they're being asked to answer.
+     */
 
+    if (appResources.slow) {
+        /*
+         * 'slow':  the yn_label widget was created when the map and
+         * status widgets were, and is positioned between them.  It
+         * will persist until end of game.  All we need to do for
+         * yn_function is direct keystroke input to the yn response
+         * handler and reset its label to be the prompt text (below).
+         */
+        input_func = yn_key;
+        highlight_yn(FALSE); /* expose yn_label as separate from map */
+    } else if (!yn_label) {
+        /*
+         * Not 'slow'; create a persistent widget that will be popped up
+         * as needed, then down again, and last until end of game.  The
+         * associated yn_label widget is used to track whether it exists.
+         */
         XtSetArg(args[0], XtNallowShellResize, True);
         yn_popup = XtCreatePopupShell("query", transientShellWidgetClass,
                                       toplevel, args, ONE);
-        XtOverrideTranslations(
-            yn_popup,
-            XtParseTranslationTable("<Message>WM_PROTOCOLS: yn_delete()"));
+        XtOverrideTranslations(yn_popup,
+               XtParseTranslationTable("<Message>WM_PROTOCOLS: yn_delete()"));
 
         num_args = 0;
         XtSetArg(args[num_args], XtNtranslations,
-                 XtParseTranslationTable(yn_translations));
-        num_args++;
-/*JP*/
+                 XtParseTranslationTable(yn_translations)); num_args++;
 #if defined(X11R6) && defined(XI18N)
-        XtSetArg(args[num_args], XtNinternational, True);
-        num_args++;
+        XtSetArg(args[num_args], XtNinternational, True); num_args++;
 #endif
         yn_label = XtCreateManagedWidget("yn_label", labelWidgetClass,
                                          yn_popup, args, num_args);
@@ -1920,12 +2150,9 @@ char def;
                         &wm_delete_window, 1);
     }
 
-    if (appResources.slow)
-        input_func = yn_key;
-
+    /* set the label of the yn widget to be the prompt text */
     num_args = 0;
-    XtSetArg(args[num_args], XtNlabel, buf);
-    num_args++;
+    XtSetArg(args[num_args], XtNlabel, buf); num_args++;
     XtSetValues(yn_label, args, num_args);
 
     if (!appResources.slow) {
@@ -1934,8 +2161,7 @@ char def;
          * need to set the label twice to get the size to change.
          */
         num_args = 0;
-        XtSetArg(args[num_args], XtNlabel, buf);
-        num_args++;
+        XtSetArg(args[num_args], XtNlabel, buf); num_args++;
         XtSetValues(yn_label, args, num_args);
 
         positionpopup(yn_popup, TRUE);
@@ -1943,22 +2169,27 @@ char def;
     }
 
     yn_getting_num = FALSE;
-    (void) x_event(EXIT_ON_EXIT);
+    (void) x_event(EXIT_ON_EXIT); /* get keystroke(s) */
 
     if (appResources.slow) {
+        /* keystrokes now belong to the map */
         input_func = 0;
+        /* erase the prompt */
         num_args = 0;
-        XtSetArg(args[num_args], XtNlabel, " ");
-        num_args++;
+        XtSetArg(args[num_args], XtNlabel, " "); num_args++;
         XtSetValues(yn_label, args, num_args);
+        highlight_yn(FALSE); /* disguise yn_label as part of map */
     } else {
         nh_XtPopdown(yn_popup); /* this removes the event grab */
     }
 
+    pline("%s%c", buf, (yn_return != '\033') ? yn_return : '\0');
+
     return yn_return;
 }
 
-/*ARGSUSED*/
+/* used when processing window-capability-specific run-time options;
+   we support toggling tiles on and off via iflags.wc_tiled_map */
 void
 X11_preference_update(pref)
 const char *pref;
@@ -1969,8 +2200,7 @@ const char *pref;
     }
 }
 
-/* End global functions ====================================================
- */
+/* End global functions =================================================== */
 
 /*
  * Before we wait for input via nhgetch() and nh_poskey(), we need to
@@ -2005,8 +2235,10 @@ XEvent *event;
     map_input(window_list[WIN_MAP].w, event, (String *) 0, &num);
 }
 
+/* only called for autofocus */
 /*ARGSUSED*/
-static void win_visible(w, data, event, flag) /* only called for autofocus */
+static void
+win_visible(w, data, event, flag)
 Widget w;
 XtPointer data; /* client_data not used */
 XEvent *event;
@@ -2026,9 +2258,48 @@ Boolean *flag; /* continue_to_dispatch flag not used */
     }
 }
 
+/* if 'slow' and 'highlight_prompt', set the yn_label widget to look like
+   part of the map when idle or to invert background and foreground when
+   a prompt is active */
+void
+highlight_yn(init)
+boolean init;
+{
+    struct xwindow *xmap;
+
+    if (!appResources.slow || !appResources.highlight_prompt)
+        return;
+
+    /* first time through, WIN_MAP isn't fully initiialized yet */
+    xmap = ((map_win != WIN_ERR) ? &window_list[map_win]
+               : (WIN_MAP != WIN_ERR) ? &window_list[WIN_MAP] : 0);
+
+    if (init && xmap) {
+        Arg args[2];
+        XGCValues vals;
+        unsigned long fg_bg = (GCForeground | GCBackground);
+        GC gc = (xmap->map_information->is_tile
+                    ? xmap->map_information->tile_map.white_gc
+                    : xmap->map_information->text_map.copy_gc);
+
+        (void) memset((genericptr_t) &vals, 0, sizeof vals);
+        if (XGetGCValues(XtDisplay(xmap->w), gc, fg_bg, &vals)) {
+            XtSetArg(args[0], XtNforeground, vals.foreground);
+            XtSetArg(args[1], XtNbackground, vals.background);
+            XtSetValues(yn_label, args, TWO);
+        }
+    } else
+        swap_fg_bg(yn_label);
+}
+
 /*
  * Set up the playing console.  This has three major parts:  the
  * message window, the map, and the status window.
+ *
+ * For configs specifying the 'slow' resource, the yn_label widget
+ * is placed above the map and below the message window.  Prompts
+ * requiring a single character response are displayed there rather
+ * than using a popup.
  */
 static void
 init_standard_windows()
@@ -2041,8 +2312,7 @@ init_standard_windows()
     struct xwindow *wp;
 
     num_args = 0;
-    XtSetArg(args[num_args], XtNallowShellResize, True);
-    num_args++;
+    XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
 #if 0 /*JP*/
     form = XtCreateManagedWidget("nethack", panedWidgetClass, toplevel, args,
                                  num_args);
@@ -2070,20 +2340,15 @@ init_standard_windows()
 
     /* Tell the form that contains it that resizes are OK. */
     num_args = 0;
-    XtSetArg(args[num_args], nhStr(XtNresizable), True);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-    num_args++;
+    XtSetArg(args[num_args], nhStr(XtNresizable), True); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
     XtSetValues(message_viewport, args, num_args);
 
     if (appResources.slow) {
         num_args = 0;
         XtSetArg(args[num_args], XtNtranslations,
-                 XtParseTranslationTable(yn_translations));
-        num_args++;
-/*JP*/
+                 XtParseTranslationTable(yn_translations)); num_args++;
 #if defined(X11R6) && defined(XI18N)
         XtSetArg(args[num_args], XtNinternational, True);
         num_args++;
@@ -2092,13 +2357,11 @@ init_standard_windows()
                                          args, num_args);
         num_args = 0;
         XtSetArg(args[num_args], nhStr(XtNfromVert), message_viewport);
-        num_args++;
+                                                                   num_args++;
         XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNresizable), True);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNlabel), " ");
-        num_args++;
+                                                                  num_args++;
+        XtSetArg(args[num_args], nhStr(XtNresizable), True); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNlabel), " "); num_args++;
         XtSetValues(yn_label, args, num_args);
     }
 
@@ -2116,14 +2379,12 @@ init_standard_windows()
     /* Chain beneath message_viewport or yn window. */
     num_args = 0;
     if (appResources.slow) {
-        XtSetArg(args[num_args], nhStr(XtNfromVert), yn_label);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), yn_label); num_args++;
     } else {
         XtSetArg(args[num_args], nhStr(XtNfromVert), message_viewport);
-        num_args++;
+                                                                   num_args++;
     }
-    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom);
-    num_args++;
+    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom); num_args++;
     XtSetValues(map_viewport, args, num_args);
 
     /* Create the status window, with the form as it's parent. */
@@ -2142,16 +2403,11 @@ init_standard_windows()
      * will never expand or contract.
      */
     num_args = 0;
-    XtSetArg(args[num_args], nhStr(XtNfromVert), map_viewport);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNtop), XtChainBottom);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom);
-    num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), map_viewport); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNtop), XtChainBottom); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom); num_args++;
     XtSetValues(status, args, num_args);
 
     /*
@@ -2163,8 +2419,8 @@ init_standard_windows()
      */
     /* XtSetMappedWhenManaged(toplevel, False); */
     XtRealizeWidget(toplevel);
-    wm_delete_window =
-        XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", False);
+    wm_delete_window = XInternAtom(XtDisplay(toplevel),
+                                   "WM_DELETE_WINDOW", False);
     XSetWMProtocols(XtDisplay(toplevel), XtWindow(toplevel),
                     &wm_delete_window, 1);
 
@@ -2247,6 +2503,8 @@ init_standard_windows()
     /* attempt to catch fatal X11 errors before the program quits */
     (void) XtAppSetErrorHandler(app_context, (XtErrorHandler) hangup);
 
+    highlight_yn(TRUE); /* switch foreground and background */
+
     /* We can now print to the message window. */
     iflags.window_inited = 1;
 }
@@ -2287,8 +2545,7 @@ int dir;
      * libXmu.sa.4.0, but not in libXmu.so.4.0.  Rather than fiddle with
      * static linking, we do this.
      */
-    if (rn2(2) > 2) {
-        /* i.e., FALSE that an optimizer probably can't find */
+    if (rn2(2) > 2) { /* i.e., FALSE that an optimizer probably can't find */
         get_wmShellWidgetClass();
         get_applicationShellWidgetClass();
     }
@@ -2328,6 +2585,7 @@ Cardinal *num_params;
         /* Perhaps the widget enclosing this has scrollbars (could use while)
          */
         Widget parent = XtParent(viewport);
+
         if (parent) {
             horiz_sb = XtNameToWidget(parent, "horizontal");
             vert_sb = XtNameToWidget(parent, "vertical");
index 8edb874..7250ef7 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 winmap.c        $NHDT-Date: 1447844616 2015/11/18 11:03:36 $  $NHDT-Branch: master $:$NHDT-Revision: 1.25 $ */
+/* NetHack 3.6 winmap.c        $NHDT-Date: 1455389908 2016/02/13 18:58:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.29 $ */
 /* Copyright (c) Dean Luick, 1992                                 */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -115,6 +115,7 @@ int bkglyph UNUSED;
         int color, och;
         unsigned special;
 #ifdef TEXTCOLOR
+        int colordif;
         register unsigned char *co_ptr;
 #endif
 
@@ -129,24 +130,23 @@ int bkglyph UNUSED;
 
         /* Only update if we need to. */
         ch_ptr = &map_info->text_map.text[y][x];
-
-#ifdef TEXTCOLOR
-        co_ptr = &map_info->text_map.colors[y][x];
-        if (*ch_ptr != ch || *co_ptr != color)
-#else
-        if (*ch_ptr != ch)
-#endif
-        {
+        if (*ch_ptr != ch) {
             *ch_ptr = ch;
+            if (!map_info->is_tile)
+                update_bbox = TRUE;
+        }
 #ifdef TEXTCOLOR
-            if ((special & MG_PET) && iflags.hilite_pet)
-                color += CLR_MAX;
-            if ((special & MG_OBJPILE) && iflags.hilite_pile)
-            *co_ptr = color;
-#endif
+        co_ptr = &map_info->text_map.colors[y][x];
+        colordif = (((special & MG_PET) != 0 && iflags.hilite_pet)
+                    || ((special & MG_OBJPILE) != 0 && iflags.hilite_pile)
+                    || ((special & (MG_DETECT | MG_BW_LAVA)) != 0))
+                      ? CLR_MAX : 0;
+        if (*co_ptr != (uchar) (color + colordif)) {
+            *co_ptr = (uchar) (color + colordif);
             if (!map_info->is_tile)
                 update_bbox = TRUE;
         }
+#endif
     }
 
     if (update_bbox) { /* update row bbox */
@@ -165,8 +165,10 @@ int bkglyph UNUSED;
 /*ARGSUSED*/
 void
 X11_cliparound(x, y)
-int x, y;
+int x UNUSED;
+int y UNUSED;
 {
+    return;
 }
 #endif /* CLIPPING */
 
@@ -261,6 +263,11 @@ post_process_tiles()
               tile_image, 0, 0, 0, 0, /* src, dest top left */
               width, height);
 
+#ifdef MONITOR_HEAP
+    /* if we let XDestroyImage() handle it, our tracking will be off */
+    if (tile_image->data)
+        free((genericptr_t) tile_image->data), tile_image->data = 0;
+#endif
     XDestroyImage(tile_image); /* data bytes free'd also */
     tile_image = 0;
 #else
@@ -937,7 +944,8 @@ Font font;
     set_color_gc(CLR_BRIGHT_CYAN, XtNbright_cyan);
     set_color_gc(CLR_WHITE, XtNwhite);
 #else
-    set_gc(wp->w, font, XtNforeground, bgpixel, &map_info->text_map.copy_gc,
+    set_gc(wp->w, font, XtNforeground, bgpixel,
+           &map_info->text_map.copy_gc,
            &map_info->text_map.inv_copy_gc);
 #endif
 }
@@ -976,6 +984,7 @@ struct xwindow *wp;
         XClearWindow(XtDisplay(wp->w), XtWindow(wp->w));
         set_map_size(wp, COLNO, ROWNO);
         check_cursor_visibility(wp);
+        highlight_yn(TRUE); /* change fg/bg to match map */
     } else if (wp->prevx != wp->cursx || wp->prevy != wp->cursy) {
         register unsigned int x = wp->prevx, y = wp->prevy;
 
@@ -1035,17 +1044,17 @@ struct xwindow *wp;
 
     map_all_stone(map_info);
     (void) memset((genericptr_t) map_info->text_map.text, ' ',
-                  sizeof(map_info->text_map.text));
+                  sizeof map_info->text_map.text);
 #ifdef TEXTCOLOR
     (void) memset((genericptr_t) map_info->text_map.colors, NO_COLOR,
-                  sizeof(map_info->text_map.colors));
+                  sizeof map_info->text_map.colors);
 #endif
 
     /* force a full update */
     (void) memset((genericptr_t) map_info->t_start, (char) 0,
-                  sizeof(map_info->t_start));
+                  sizeof map_info->t_start);
     (void) memset((genericptr_t) map_info->t_stop, (char) COLNO - 1,
-                  sizeof(map_info->t_stop));
+                  sizeof map_info->t_stop);
     display_map_window(wp);
 }
 
@@ -1070,8 +1079,8 @@ struct xwindow *wp;
 #ifdef VERBOSE
     printf("Font information:\n");
     printf("fid = %ld, direction = %d\n", fs->fid, fs->direction);
-    printf("first = %d, last = %d\n", fs->min_char_or_byte2,
-           fs->max_char_or_byte2);
+    printf("first = %d, last = %d\n",
+           fs->min_char_or_byte2, fs->max_char_or_byte2);
     printf("all chars exist? %s\n", fs->all_chars_exist ? "yes" : "no");
     printf("min_bounds:lb=%d rb=%d width=%d asc=%d des=%d attr=%d\n",
            fs->min_bounds.lbearing, fs->min_bounds.rbearing,
@@ -1082,8 +1091,8 @@ struct xwindow *wp;
            fs->max_bounds.width, fs->max_bounds.ascent,
            fs->max_bounds.descent, fs->max_bounds.attributes);
     printf("per_char = 0x%lx\n", (unsigned long) fs->per_char);
-    printf("Text: (max) width = %d, height = %d\n", text_map->square_width,
-           text_map->square_height);
+    printf("Text: (max) width = %d, height = %d\n",
+           text_map->square_width, text_map->square_height);
 #endif
 
     if (fs->min_bounds.width != fs->max_bounds.width)
@@ -1094,9 +1103,9 @@ struct xwindow *wp;
  * keyhit buffer
  */
 #define INBUF_SIZE 64
-int inbuf[INBUF_SIZE];
-int incount = 0;
-int inptr = 0; /* points to valid data */
+static int inbuf[INBUF_SIZE];
+static int incount = 0;
+static int inptr = 0; /* points to valid data */
 
 /*
  * Keyboard and button event handler for map window.
@@ -1364,7 +1373,7 @@ XtPointer widget_data; /* expose event from Window widget */
 /*
  * Do the actual work of the putting characters onto our X window.  This
  * is called from the expose event routine, the display window (flush)
- * routine, and the display cursor routine.  The later involves inverting
+ * routine, and the display cursor routine.  The last involves inverting
  * the foreground and background colors, which are also inverted when the
  * position's color is above CLR_MAX.
  *
@@ -1392,8 +1401,8 @@ boolean inverted;
     }
 
 #ifdef VERBOSE_UPDATE
-    printf("update: [0x%x] %d %d %d %d\n", (int) wp->w, start_row, stop_row,
-           start_col, stop_col);
+    printf("update: [0x%x] %d %d %d %d\n",
+           (int) wp->w, start_row, stop_row, start_col, stop_col);
 #endif
     win_start_row = start_row;
     win_start_col = start_col;
@@ -1426,8 +1435,8 @@ boolean inverted;
                 src_y = (tile / TILES_PER_ROW) * tile_height;
                 XCopyArea(dpy, tile_pixmap, XtWindow(wp->w),
                           tile_map->black_gc, /* no grapics_expose */
-                          src_x, src_y, tile_width, tile_height, dest_x,
-                          dest_y);
+                          src_x, src_y, tile_width, tile_height,
+                          dest_x, dest_y);
 #else
                 struct rm *lev = &levl[cur_col][row];
                 int glyph = tile_map->glyphs[row][cur_col].glyph;
@@ -1566,7 +1575,7 @@ boolean inverted;
         struct text_map_info_t *text_map = &map_info->text_map;
 
 #ifdef TEXTCOLOR
-        if (iflags.use_color) {
+        {
             register char *c_ptr;
             char *t_ptr;
             int cur_col, color, win_ystart;
@@ -1593,8 +1602,13 @@ boolean inverted;
                     }
 
                     XDrawImageString(XtDisplay(wp->w), XtWindow(wp->w),
-                                     cur_inv ? text_map->inv_color_gcs[color]
-                                             : text_map->color_gcs[color],
+                                     iflags.use_color
+                                        ? (cur_inv
+                                           ? text_map->inv_color_gcs[color]
+                                           : text_map->color_gcs[color])
+                                        : (cur_inv
+                                           ? text_map->inv_copy_gc
+                                           : text_map->copy_gc),
                                      text_map->square_lbearing
                                          + (text_map->square_width * cur_col),
                                      win_ystart, t_ptr, count);
@@ -1604,8 +1618,8 @@ boolean inverted;
                     cur_col += count;
                 } /* col loop */
             }     /* row loop */
-        } else
-#endif /* TEXTCOLOR */
+        }
+#else   /* !TEXTCOLOR */
         {
             int win_row, win_xstart;
 
@@ -1627,6 +1641,7 @@ boolean inverted;
                                  count);
             }
         }
+#endif  /* ?TEXTCOLOR */
     }
 }
 
@@ -1648,10 +1663,8 @@ Dimension cols, rows;
     }
 
     num_args = 0;
-    XtSetArg(args[num_args], XtNwidth, wp->pixel_width);
-    num_args++;
-    XtSetArg(args[num_args], XtNheight, wp->pixel_height);
-    num_args++;
+    XtSetArg(args[num_args], XtNwidth, wp->pixel_width); num_args++;
+    XtSetArg(args[num_args], XtNheight, wp->pixel_height); num_args++;
     XtSetValues(wp->w, args, num_args);
 }
 
@@ -1662,10 +1675,10 @@ struct xwindow *wp;
     struct map_info_t *map_info = wp->map_information;
     struct text_map_info_t *text_map = &map_info->text_map;
 
-    (void) memset((genericptr_t) text_map->text, ' ', sizeof(text_map->text));
+    (void) memset((genericptr_t) text_map->text, ' ', sizeof text_map->text);
 #ifdef TEXTCOLOR
     (void) memset((genericptr_t) text_map->colors, NO_COLOR,
-                  sizeof(text_map->colors));
+                  sizeof text_map->colors);
 #endif
 
     get_char_info(wp);
@@ -1856,6 +1869,11 @@ struct xwindow *wp;
                          (XtPointer) 0);
     else
         wp->type = NHW_NONE; /* allow re-use */
+
+    /* when map goes away, presumably we're exiting, so get rid of the
+       cached extended commands menu (if we aren't actually exiting, it
+       will get recreated if needed again) */
+    release_extended_cmds();
 }
 
 boolean exit_x_event; /* exit condition for the event loop */
index 61fff2d..9b237fe 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 winmenu.c       $NHDT-Date: 1432512809 2015/05/25 00:13:29 $  $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
+/* NetHack 3.6 winmenu.c       $NHDT-Date: 1453448854 2016/01/22 07:47:34 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.13 $ */
 /* Copyright (c) Dean Luick, 1992                                */
 /* NetHack may be freely redistributed.  See license for details. */
 
 
 #include "hack.h"
 #include "winX.h"
-#include <ctype.h>
 
 static void FDECL(menu_select, (Widget, XtPointer, XtPointer));
-static void FDECL(invert_line,
-                  (struct xwindow *, x11_menu_item *, int, long));
+static void FDECL(invert_line, (struct xwindow *, x11_menu_item *, int, long));
 static void FDECL(menu_ok, (Widget, XtPointer, XtPointer));
 static void FDECL(menu_cancel, (Widget, XtPointer, XtPointer));
 static void FDECL(menu_all, (Widget, XtPointer, XtPointer));
@@ -130,7 +128,9 @@ XtPointer client_data, call_data;
     }
 
     /* if we've reached here, we've found our selected item */
-    curr->selected = !curr->selected;
+    if (menu_info->how != PICK_ONE || !curr->preselected)
+        curr->selected = !curr->selected;
+    curr->preselected = FALSE;
     if (curr->selected) {
         curr->str[2] = (how_many != -1L) ? '#' : '+';
         curr->pick_count = how_many;
@@ -178,7 +178,11 @@ long how_many;
     nhUse(which);
 #endif
     reset_menu_count(wp->menu_information);
-    curr->selected = !curr->selected;
+    /* invert selection unless explicitly choosing the preselected
+       entry of a PICK_ONE menu */
+    if (wp->menu_information->how != PICK_ONE || !curr->preselected)
+        curr->selected = !curr->selected;
+    curr->preselected = FALSE;
     if (curr->selected) {
 #ifdef USE_FWF
         XfwfMultiListHighlightItem((XfwfMultiListWidget) wp->w, which);
@@ -246,7 +250,7 @@ Cardinal *num_params;
             select_none(wp);
         } else if (ch == '\n' || ch == '\r') {
             ; /* accept */
-        } else if (isdigit(ch)) {
+        } else if (digit(ch)) {
             /* special case: '0' is also the default ball class */
             if (ch == '0' && !menu_info->counting
                 && index(menu_info->curr_menu.gacc, ch))
@@ -326,9 +330,8 @@ Cardinal *num_params;
                     break;
 
             if (curr) {
-                invert_line(wp, curr, count, menu_info->counting
-                                                 ? menu_info->menu_count
-                                                 : -1L);
+                invert_line(wp, curr, count,
+                            menu_info->counting ? menu_info->menu_count : -1L);
 #ifndef USE_FWF
                 XawListChange(wp->w, menu_info->curr_menu.list_pointer, 0, 0,
                               True);
@@ -468,8 +471,8 @@ struct xwindow *wp;
 
 #ifndef USE_FWF
     if (changed)
-        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer, 0,
-                      0, True);
+        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer,
+                      0, 0, True);
 #endif
 }
 
@@ -492,8 +495,8 @@ struct xwindow *wp;
 
 #ifndef USE_FWF
     if (changed)
-        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer, 0,
-                      0, True);
+        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer,
+                      0, 0, True);
 #endif
 }
 
@@ -511,8 +514,8 @@ struct xwindow *wp;
             invert_line(wp, curr, count, -1L);
 
 #ifndef USE_FWF
-    XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer, 0, 0,
-                  True);
+    XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer,
+                  0, 0, True);
 #endif
 }
 
@@ -528,15 +531,18 @@ char *match; /* wildcard pattern for pmatch() */
     reset_menu_count(wp->menu_information);
     for (count = 0, curr = wp->menu_information->curr_menu.base; curr;
          curr = curr->next, count++)
-        if (curr->identifier.a_void != 0 && pmatchi(match, curr->str)) {
-            invert_line(wp, curr, count, -1L);
-            changed = TRUE;
+        if (curr->identifier.a_void != 0) {
+            if (pmatchi(match, curr->str)) {
+                invert_line(wp, curr, count, -1L);
+                changed = TRUE;
+            }
+            curr->preselected = FALSE;
         }
 
 #ifndef USE_FWF
     if (changed)
-        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer, 0,
-                      0, True);
+        XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer,
+                      0, 0, True);
 #endif
 }
 
@@ -545,26 +551,30 @@ select_match(wp, match)
 struct xwindow *wp;
 char *match; /* wildcard pattern for pmatch() */
 {
-    x11_menu_item *curr;
+    x11_menu_item *curr, *found = 0;
     int count;
 
     reset_menu_count(wp->menu_information);
     for (count = 0, curr = wp->menu_information->curr_menu.base; curr;
          curr = curr->next, count++)
-        if (curr->identifier.a_void != 0 && pmatchi(match, curr->str)) {
-            if (!curr->selected) {
-                invert_line(wp, curr, count, -1L);
+        if (curr->identifier.a_void != 0) {
+            if (!found && pmatchi(match, curr->str))
+                found = curr;
+            curr->preselected = FALSE;
+        }
+
+    if (found) {
+        if (!found->selected) {
+            invert_line(wp, found, count, -1L);
 #ifndef USE_FWF
-                XawListChange(wp->w,
-                              wp->menu_information->curr_menu.list_pointer, 0,
-                              0, True);
+            XawListChange(wp->w, wp->menu_information->curr_menu.list_pointer,
+                          0, 0, True);
 #endif
-            }
-            return;
         }
-
-    /* no match */
-    X11_nhbell();
+    } else {
+        /* no match */
+        X11_nhbell();
+    }
 }
 
 static void
@@ -604,12 +614,14 @@ int *items;
                 break;
             }
 #if 0
-        if (curr->selected && !found)
-            printf("sync: deselecting %s\n", curr->str);
-        else if (!curr->selected && found)
-            printf("sync: selecting %s\n", curr->str);
+       if (curr->selected && !found)
+           printf("sync: deselecting %s\n", curr->str);
+       else if (!curr->selected && found)
+           printf("sync: selecting %s\n", curr->str);
 #endif
         curr->selected = found ? TRUE : FALSE;
+        /* once active selection takes place, preselection becomes history */
+        curr->preselected = FALSE;
     }
 }
 #endif /* USE_FWF */
@@ -650,7 +662,6 @@ boolean preselected;
     struct menu_info_t *menu_info;
 
     nhUse(glyph);
-    nhUse(preselected); /*FIXME*/
 
     check_winid(window);
     menu_info = window_list[window].menu_information;
@@ -663,8 +674,7 @@ boolean preselected;
     item->next = (x11_menu_item *) 0;
     item->identifier = *identifier;
     item->attr = attr;
-    /*    item->selected = preselected; */
-    item->selected = FALSE;
+    item->selected = item->preselected = preselected;
     item->pick_count = -1L;
 
     if (identifier->a_void) {
@@ -688,7 +698,7 @@ boolean preselected;
             impossible("Menu item too long (%d).", len);
             len = BUFSZ - 1;
         }
-        Sprintf(buf, "%c - ", ch ? ch : ' ');
+        Sprintf(buf, "%c %c ", ch ? ch : ' ', preselected ? '+' : '-');
         (void) strncpy(buf + 4, str, len);
         buf[4 + len] = '\0';
         item->str = copy_of(buf);
@@ -739,10 +749,10 @@ menu_item **menu_list;
     Cardinal num_args;
     String *ptr;
     int retval;
-    Dimension v_pixel_width, v_pixel_height;
+    Dimension v_pixel_width, v_pixel_height, lblwidth[6], maxlblwidth;
     boolean labeled;
-    Widget viewport_widget, form, label, ok, cancel, all, none, invert,
-        search;
+    Widget viewport_widget, form, label,
+           ok, cancel, all, none, invert, search, lblwidget[6];
     Boolean sens;
 #ifdef USE_FWF
     Boolean *boolp;
@@ -832,193 +842,173 @@ menu_item **menu_list;
         num_args = 0;
         XtSetArg(args[num_args], XtNallowShellResize, True);
         num_args++;
-        wp->popup =
-            XtCreatePopupShell(window == WIN_INVEN ? "inventory" : "menu",
-                               how == PICK_NONE ? topLevelShellWidgetClass
-                                                : transientShellWidgetClass,
-                               toplevel, args, num_args);
-        XtOverrideTranslations(
-            wp->popup,
-            XtParseTranslationTable("<Message>WM_PROTOCOLS: menu_delete()"));
+        wp->popup = XtCreatePopupShell((window == WIN_INVEN)
+                                           ? "inventory" : "menu",
+                                       (how == PICK_NONE)
+                                           ? topLevelShellWidgetClass
+                                           : transientShellWidgetClass,
+                                       toplevel, args, num_args);
+        XtOverrideTranslations(wp->popup,
+                               XtParseTranslationTable(
+                                     "<Message>WM_PROTOCOLS: menu_delete()"));
 
         num_args = 0;
         XtSetArg(args[num_args], XtNtranslations,
-                 XtParseTranslationTable(menu_translations));
-        num_args++;
+                 XtParseTranslationTable(menu_translations)); num_args++;
         form = XtCreateManagedWidget("mform", formWidgetClass, wp->popup,
                                      args, num_args);
 
         num_args = 0;
-        XtSetArg(args[num_args], XtNborderWidth, 0);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
+        XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
 
-        if (labeled)
-            label =
-                XtCreateManagedWidget(menu_info->new_menu.query,
-                                      labelWidgetClass, form, args, num_args);
-        else
-            label = NULL;
+        label = labeled ? XtCreateManagedWidget(menu_info->new_menu.query,
+                                                labelWidgetClass, form,
+                                                args, num_args)
+                        : (Widget) 0;
 
         /*
          * Create ok, cancel, all, none, invert, and search buttons..
          */
+        maxlblwidth = 0;
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
-        ok = XtCreateManagedWidget("OK", commandWidgetClass, form, args,
-                                   num_args);
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+        ok = XtCreateManagedWidget("OK", commandWidgetClass, form,
+                                   args, num_args);
         XtAddCallback(ok, XtNcallback, menu_ok, (XtPointer) wp);
+        XtSetArg(args[0], XtNwidth, &lblwidth[0]);
+        XtGetValues(lblwidget[0] = ok, args, ONE);
+        if (lblwidth[0] > maxlblwidth)
+            maxlblwidth = lblwidth[0];
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), ok);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), ok); num_args++;
         XtSetArg(args[num_args], nhStr(XtNsensitive), how != PICK_NONE);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
+                                                                   num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
 /*JP
         cancel = XtCreateManagedWidget("cancel", commandWidgetClass, form,
 */
         cancel = XtCreateManagedWidget("\83L\83\83\83\93\83Z\83\8b", commandWidgetClass, form,
                                        args, num_args);
         XtAddCallback(cancel, XtNcallback, menu_cancel, (XtPointer) wp);
+        XtSetArg(args[0], XtNwidth, &lblwidth[1]);
+        XtGetValues(lblwidget[1] = cancel, args, ONE);
+        if (lblwidth[1] > maxlblwidth)
+            maxlblwidth = lblwidth[1];
 
         sens = (how == PICK_ANY);
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), cancel);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNsensitive), sens);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), cancel); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNsensitive), sens); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
 /*JP
-        all = XtCreateManagedWidget("all", commandWidgetClass, form, args,
+        all = XtCreateManagedWidget("all", commandWidgetClass, form,
 */
-        all = XtCreateManagedWidget("\82·\82×\82Ä\91I\91ð", commandWidgetClass, form, args,
-                                    num_args);
+        all = XtCreateManagedWidget("\82·\82×\82Ä\91I\91ð", commandWidgetClass, form,
+                                    args, num_args);
         XtAddCallback(all, XtNcallback, menu_all, (XtPointer) wp);
+        XtSetArg(args[0], XtNwidth, &lblwidth[2]);
+        XtGetValues(lblwidget[2] = all, args, ONE);
+        if (lblwidth[2] > maxlblwidth)
+            maxlblwidth = lblwidth[2];
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), all);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNsensitive), sens);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), all); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNsensitive), sens); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
 /*JP
-        none = XtCreateManagedWidget("none", commandWidgetClass, form, args,
+        none = XtCreateManagedWidget("none", commandWidgetClass, form,
 */
-        none = XtCreateManagedWidget("\82·\82×\82Ä\89ð\8f\9c", commandWidgetClass, form, args,
-                                     num_args);
+        none = XtCreateManagedWidget("\82·\82×\82Ä\89ð\8f\9c", commandWidgetClass, form,
+                                     args, num_args);
         XtAddCallback(none, XtNcallback, menu_none, (XtPointer) wp);
+        XtSetArg(args[0], XtNwidth, &lblwidth[3]);
+        XtGetValues(lblwidget[3] = none, args, ONE);
+        if (lblwidth[3] > maxlblwidth)
+            maxlblwidth = lblwidth[3];
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), none);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNsensitive), sens);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), none); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNsensitive), sens); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
 /*JP
         invert = XtCreateManagedWidget("invert", commandWidgetClass, form,
 */
         invert = XtCreateManagedWidget("\94½\93]", commandWidgetClass, form,
                                        args, num_args);
         XtAddCallback(invert, XtNcallback, menu_invert, (XtPointer) wp);
+        XtSetArg(args[0], XtNwidth, &lblwidth[4]);
+        XtGetValues(lblwidget[4] = invert, args, ONE);
+        if (lblwidth[4] > maxlblwidth)
+            maxlblwidth = lblwidth[4];
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNfromHoriz), invert);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromHoriz), invert); num_args++;
         XtSetArg(args[num_args], nhStr(XtNsensitive), how != PICK_NONE);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft);
-        num_args++;
+                                                                   num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
 /*JP
         search = XtCreateManagedWidget("search", commandWidgetClass, form,
 */
         search = XtCreateManagedWidget("\8c\9f\8dõ", commandWidgetClass, form,
                                        args, num_args);
         XtAddCallback(search, XtNcallback, menu_search, (XtPointer) wp);
+        XtSetArg(args[0], XtNwidth, &lblwidth[5]);
+        XtGetValues(lblwidget[5] = search, args, ONE);
+        if (lblwidth[5] > maxlblwidth)
+            maxlblwidth = lblwidth[5];
+
+        /* make all buttons be the same width */
+        {
+            int i;
+
+            XtSetArg(args[0], XtNwidth, maxlblwidth);
+            for (i = 0; i < 6; ++i)
+                if (lblwidth[i] < maxlblwidth)
+                    XtSetValues(lblwidget[i], args, ONE);
+        }
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNallowVert), True);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNallowHoriz), False);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNuseBottom), True);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNuseRight), True);
-        num_args++;
-        /*
-                XtSetArg(args[num_args], nhStr(XtNforceBars), True);
-           num_args++;
-        */
-        XtSetArg(args[num_args], nhStr(XtNfromVert), all);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNright), XtChainRight);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNallowVert), True); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNallowHoriz), False); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNuseBottom), True); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNuseRight), True); num_args++;
+#if 0
+        XtSetArg(args[num_args], nhStr(XtNforceBars), True); num_args++;
+#endif
+        XtSetArg(args[num_args], nhStr(XtNfromVert), all); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
         viewport_widget = XtCreateManagedWidget(
             "menu_viewport",           /* name */
             viewportWidgetClass, form, /* parent widget */
@@ -1028,22 +1018,16 @@ menu_item **menu_list;
         move_menu(&menu_info->new_menu, &menu_info->curr_menu);
 
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNforceColumns), True);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNcolumnSpacing), 1);
-        num_args++;
-        XtSetArg(args[num_args], nhStr(XtNdefaultColumns), 1);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNforceColumns), True); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNcolumnSpacing), 1); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNdefaultColumns), 1); num_args++;
         XtSetArg(args[num_args], nhStr(XtNlist),
-                 menu_info->curr_menu.list_pointer);
-        num_args++;
+                 menu_info->curr_menu.list_pointer); num_args++;
 #ifdef USE_FWF
         XtSetArg(args[num_args], nhStr(XtNsensitiveArray),
-                 menu_info->curr_menu.sensitive);
-        num_args++;
+                 menu_info->curr_menu.sensitive); num_args++;
         XtSetArg(args[num_args], nhStr(XtNmaxSelectable),
-                 menu_info->curr_menu.count);
-        num_args++;
+                 menu_info->curr_menu.count); num_args++;
 #endif
 #if defined(X11R6) && defined(XI18N)
         XtSetArg(args[num_args], XtNinternational, True);
@@ -1064,19 +1048,16 @@ menu_item **menu_list;
         /* Get the font and margin information. */
         num_args = 0;
 #ifndef XI18N
-        XtSetArg(args[num_args], XtNfont, &menu_info->fs);
+        XtSetArg(args[num_args], XtNfont, &menu_info->fs); num_args++;
 #else
-        XtSetArg(args[num_args], XtNfontSet, &menu_info->fontset);
+        XtSetArg(args[num_args], XtNfontSet, &menu_info->fontset); num_args++;
 #endif
-        num_args++;
         XtSetArg(args[num_args], XtNinternalHeight,
-                 &menu_info->internal_height);
-        num_args++;
+                 &menu_info->internal_height); num_args++;
         XtSetArg(args[num_args], XtNinternalWidth,
-                 &menu_info->internal_width);
-        num_args++;
+                 &menu_info->internal_width); num_args++;
         XtSetArg(args[num_args], nhStr(XtNrowSpacing), &row_spacing);
-        num_args++;
+                                                                   num_args++;
         XtGetValues(wp->w, args, num_args);
 
         /* font height is ascent + descent */
@@ -1093,10 +1074,8 @@ menu_item **menu_list;
         menu_info->valid_widgets = TRUE;
 
         num_args = 0;
-        XtSetArg(args[num_args], XtNwidth, &v_pixel_width);
-        num_args++;
-        XtSetArg(args[num_args], XtNheight, &v_pixel_height);
-        num_args++;
+        XtSetArg(args[num_args], XtNwidth, &v_pixel_width); num_args++;
+        XtSetArg(args[num_args], XtNheight, &v_pixel_height); num_args++;
         XtGetValues(wp->w, args, num_args);
     } else {
         Dimension len;
@@ -1117,9 +1096,8 @@ menu_item **menu_list;
 
         /* add viewport internal border */
         v_pixel_width += 2 * menu_info->internal_width;
-        v_pixel_height =
-            (2 * menu_info->internal_height)
-            + (menu_info->new_menu.count * menu_info->line_height);
+        v_pixel_height = (2 * menu_info->internal_height)
+                       + (menu_info->new_menu.count * menu_info->line_height);
 
         /* make new menu the current menu */
         move_menu(&menu_info->new_menu, &menu_info->curr_menu);
@@ -1134,10 +1112,8 @@ menu_item **menu_list;
 
     /* if viewport will be bigger than the screen, limit its height */
     num_args = 0;
-    XtSetArg(args[num_args], XtNwidth, &v_pixel_width);
-    num_args++;
-    XtSetArg(args[num_args], XtNheight, &v_pixel_height);
-    num_args++;
+    XtSetArg(args[num_args], XtNwidth, &v_pixel_width); num_args++;
+    XtSetArg(args[num_args], XtNheight, &v_pixel_height); num_args++;
     XtGetValues(wp->w, args, num_args);
     if ((Dimension) XtScreen(wp->w)->height * 5 / 6 < v_pixel_height) {
         /* scrollbar is 14 pixels wide.  Widen the form to accommodate it. */
@@ -1147,10 +1123,8 @@ menu_item **menu_list;
         v_pixel_height = XtScreen(wp->w)->height * 5 / 6;
 
         num_args = 0;
-        XtSetArg(args[num_args], XtNwidth, v_pixel_width);
-        num_args++;
-        XtSetArg(args[num_args], XtNheight, v_pixel_height);
-        num_args++;
+        XtSetArg(args[num_args], XtNwidth, v_pixel_width); num_args++;
+        XtSetArg(args[num_args], XtNheight, v_pixel_height); num_args++;
         XtSetValues(wp->w, args, num_args);
     }
     XtRealizeWidget(wp->popup); /* need to realize before we position */
@@ -1184,16 +1158,22 @@ menu_item **menu_list;
 
         if (retval) {
             menu_item *mi;
+            boolean toomany = (how == PICK_ONE && retval > 1);
 
+            if (toomany)
+                retval = 1;
             *menu_list = mi = (menu_item *) alloc(retval * sizeof(menu_item));
             for (curr = menu_info->curr_menu.base; curr; curr = curr->next)
                 if (curr->selected) {
                     mi->item = curr->identifier;
                     mi->count = curr->pick_count;
-                    mi++;
+                    if (!toomany)
+                        mi++;
+                    if (how == PICK_ONE && !curr->preselected)
+                        break;
                 }
         }
-    }
+    } /* ?(WIN_INVEN && PICK_NONE) */
 
     return retval;
 }
@@ -1204,8 +1184,6 @@ menu_item **menu_list;
 /*
  * Allocate a copy of the given string.  If null, return a string of
  * zero length.
- *
- * This is an exact duplicate of copy_of() in tty/wintty.c.
  */
 static char *
 copy_of(s)
@@ -1213,7 +1191,7 @@ const char *s;
 {
     if (!s)
         s = "";
-    return strcpy((char *) alloc((unsigned) (strlen(s) + 1)), s);
+    return dupstr(s);
 }
 
 static void
index 037459d..146ac6d 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 winmesg.c       $NHDT-Date: 1432512808 2015/05/25 00:13:28 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
+/* NetHack 3.6 winmesg.c       $NHDT-Date: 1454811935 2016/02/07 02:25:35 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $ */
 /* Copyright (c) Dean Luick, 1992                                */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -48,8 +48,11 @@ static void FDECL(get_gc, (Widget, struct mesg_info_t *));
 static void FDECL(mesg_resized, (Widget, XtPointer, XtPointer));
 
 static char mesg_translations[] = "#override\n\
- <Key>:         input() \
-";
+ <Key>Left:     scroll(4)\n\
+ <Key>Right:    scroll(6)\n\
+ <Key>Up:       scroll(8)\n\
+ <Key>Down:     scroll(2)\n\
+ <Key>:         input()";
 
 /* Move the message window's vertical scrollbar's slider to the bottom. */
 void
@@ -84,7 +87,7 @@ Widget parent;
     wp->type = NHW_MESSAGE;
 
     wp->mesg_information = mesg_info =
-        (struct mesg_info_t *) alloc(sizeof(struct mesg_info_t));
+        (struct mesg_info_t *) alloc(sizeof (struct mesg_info_t));
 
     mesg_info->fs = 0;
     mesg_info->num_lines = 0;
@@ -247,6 +250,7 @@ void
 display_message_window(wp)
 struct xwindow *wp;
 {
+    set_message_slider(wp);
     if (wp->mesg_information->dirty)
         redraw_message_window(wp);
 }
index 4eca6db..09419d1 100644 (file)
@@ -1,11 +1,11 @@
-/* NetHack 3.6 winmisc.c       $NHDT-Date: 1432512807 2015/05/25 00:13:27 $  $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
-/* Copyright (c) Dean Luick, 1992                                */
+/* NetHack 3.6 winmisc.c       $NHDT-Date: 1457079197 2016/03/04 08:13:17 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.25 $ */
+/* Copyright (c) Dean Luick, 1992                                 */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
  * Misc. popup windows: player selection and extended commands.
  *
- *     + Global functions: player_selection() and get_ext_cmd().
+ *      + Global functions: player_selection() and get_ext_cmd().
  */
 
 /*
 #include <X11/Xaw/Command.h>
 #include <X11/Xaw/Form.h>
 #include <X11/Xaw/Label.h>
+#include <X11/Xaw/AsciiText.h>
+#include <X11/Xaw/Scrollbar.h>
+#include <X11/Xaw/Toggle.h>
+#include <X11/Xaw/Viewport.h>
 #include <X11/Xaw/Cardinals.h>
+#include <X11/Xaw/List.h>
 #include <X11/Xos.h> /* for index() */
 #include <X11/Xatom.h>
 
 static Widget extended_command_popup = 0;
 static Widget extended_command_form;
 static Widget *extended_commands = 0;
-static int extended_command_selected; /* index of the selected command; */
+static int extended_cmd_selected; /* index of the selected command; */
 static int ps_selected;               /* index of selected role */
 #define PS_RANDOM (-50)
 #define PS_QUIT (-75)
-static const char ps_randchars[] = "*@";
+/* 'r' for random won't work for role but will for race, gender, alignment */
+static const char ps_randchars[] = "*@\n\rrR";
 static const char ps_quitchars[] = "\033qQ";
 
 #define EC_NCHARS 32
@@ -56,7 +62,22 @@ static int ec_nchars = 0;
 static char ec_chars[EC_NCHARS];
 static Time ec_time;
 
+boolean plsel_ask_name;
+
+static const char plsel_dialog_translations[] = "#override\n\
+     <Key>Escape: plsel_quit()\n\
+     <Key>Return: plsel_play()";
+
+static const char plsel_input_accelerators[] = "#override\n\
+     <Key>Escape: plsel_quit()\n\
+     <Key>Return: plsel_play()\n\
+     <Key>Tab: \n";
+
 static const char extended_command_translations[] = "#override\n\
+     <Key>Left: scroll(4)\n\
+     <Key>Right: scroll(6)\n\
+     <Key>Up: scroll(8)\n\
+     <Key>Down: scroll(2)\n\
      <Key>: ec_key()";
 
 static const char player_select_translations[] = "#override\n\
@@ -68,16 +89,37 @@ static const char gend_select_translations[] = "#override\n\
 static const char algn_select_translations[] = "#override\n\
      <Key>: algn_key()";
 
-static void FDECL(popup_delete, (Widget, XEvent *, String *, Cardinal *));
-static void NDECL(ec_dismiss);
-static Widget FDECL(make_menu,
-                    (const char *, const char *, const char *, const char *,
-                     XtCallbackProc, const char *, XtCallbackProc, int,
-                     const char **, Widget **, XtCallbackProc, Widget *));
-static void NDECL(init_extended_commands_popup);
 static void FDECL(ps_quit, (Widget, XtPointer, XtPointer));
 static void FDECL(ps_random, (Widget, XtPointer, XtPointer));
 static void FDECL(ps_select, (Widget, XtPointer, XtPointer));
+static void FDECL(extend_select, (Widget, XtPointer, XtPointer));
+static void FDECL(extend_dismiss, (Widget, XtPointer, XtPointer));
+static void FDECL(extend_help, (Widget, XtPointer, XtPointer));
+static void FDECL(popup_delete, (Widget, XEvent *, String *, Cardinal *));
+static void NDECL(ec_dismiss);
+static void FDECL(ec_scroll_to_view, (int));
+static void NDECL(init_extended_commands_popup);
+static Widget FDECL(make_menu, (const char *, const char *, const char *,
+                                const char *, XtCallbackProc, const char *,
+                                XtCallbackProc, int, const char **,
+                                Widget **, XtCallbackProc, Widget *));
+
+void NDECL(X11_player_selection_setupOthers);
+void NDECL(X11_player_selection_randomize);
+
+/* Bad Hack alert. Using integers instead of XtPointers */
+XtPointer
+i2xtp(i)
+int i;
+{
+    return (XtPointer)(long)i;
+}
+int
+xtp2i(x)
+XtPointer x;
+{
+    return (long)x;
+}
 
 /* Player Selection --------------------------------------------------------
  */
@@ -118,7 +160,7 @@ XtPointer client_data, call_data;
     nhUse(w);
     nhUse(call_data);
 
-    ps_selected = (int) client_data;
+    ps_selected = (int) (ptrdiff_t) client_data;
     exit_x_event = TRUE; /* leave event loop */
 }
 
@@ -294,10 +336,947 @@ Cardinal *num_params;
     exit_x_event = TRUE;
 }
 
+int plsel_n_races, plsel_n_roles;
+Widget *plsel_race_radios = (Widget *) 0;
+Widget *plsel_role_radios = (Widget *) 0;
+Widget *plsel_gend_radios = (Widget *) 0;
+Widget *plsel_align_radios = (Widget *) 0;
+
+Widget plsel_name_input;
+
+Widget plsel_btn_play;
+
+void
+plsel_dialog_acceptvalues()
+{
+    Arg args[2];
+    String s;
+
+    flags.initrace = xtp2i(XawToggleGetCurrent(plsel_race_radios[0])) - 1;
+    flags.initrole = xtp2i(XawToggleGetCurrent(plsel_role_radios[0])) - 1;
+    flags.initgend = xtp2i(XawToggleGetCurrent(plsel_gend_radios[0])) - 1;
+    flags.initalign = xtp2i(XawToggleGetCurrent(plsel_align_radios[0])) - 1;
+
+    XtSetArg(args[0], nhStr(XtNstring), &s);
+    XtGetValues(plsel_name_input, args, ONE);
+
+    (void) strncpy(plname, (char *) s, sizeof plname - 1);
+    plname[sizeof plname - 1] = '\0';
+    (void) mungspaces(plname);
+    if (strlen(plname) < 1)
+        (void) strcpy(plname, "Mumbles");
+    iflags.renameinprogress = FALSE;
+}
+
+/* ARGSUSED */
+void
+plsel_quit(w, event, params, num_params)
+Widget w;
+XEvent *event;
+String *params;
+Cardinal *num_params;
+{
+    nhUse(w);
+    nhUse(event);
+    nhUse(params);
+    nhUse(num_params);
+
+    ps_selected = PS_QUIT;
+    exit_x_event = TRUE; /* leave event loop */
+}
+
+/* ARGSUSED */
+void
+plsel_play(w, event, params, num_params)
+Widget w;
+XEvent *event;
+String *params;
+Cardinal *num_params;
+{
+    Arg args[2];
+    Boolean state;
+
+    nhUse(w);
+    nhUse(event);
+    nhUse(params);
+    nhUse(num_params);
+
+    XtSetArg(args[0], nhStr(XtNsensitive), &state);
+    XtGetValues(plsel_btn_play, args, ONE);
+
+    if (state) {
+        plsel_dialog_acceptvalues();
+        exit_x_event = TRUE; /* leave event loop */
+    } else {
+        X11_nhbell();
+    }
+}
+
+/* ARGSUSED */
+void
+plsel_randomize(w, event, params, num_params)
+Widget w;
+XEvent *event;
+String *params;
+Cardinal *num_params;
+{
+    nhUse(w);
+    nhUse(event);
+    nhUse(params);
+    nhUse(num_params);
+
+    X11_player_selection_randomize();
+}
+
+/* enable or disable the Play button */
+void
+plsel_set_play_button(state)
+boolean state;
+{
+    Arg args[2];
+
+    XtSetArg(args[0], nhStr(XtNsensitive), !state);
+    XtSetValues(plsel_btn_play, args, ONE);
+}
+
+void
+plsel_set_sensitivities(setcurr)
+boolean setcurr;
+{
+    Arg args[2];
+    int j, valid;
+    int c = 0;
+    int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0]))-1;
+    int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0]))-1;
+
+    plsel_set_play_button(ra < 0 || ro < 0);
+
+    if (ra < 0 || ro < 0)
+        return;
+
+    valid = -1;
+
+    for (j = 0; roles[j].name.m; j++) {
+        boolean v = validrace(j, ra);
+
+        if (j == ro)
+            c = j;
+        XtSetArg(args[0], nhStr(XtNsensitive), v);
+        XtSetValues(plsel_role_radios[j], args, ONE);
+        if (valid < 0 && v)
+            valid = j;
+    }
+    if (!validrace(ro, c))
+        c = valid;
+
+    if (setcurr)
+        XawToggleSetCurrent(plsel_role_radios[0], i2xtp(c + 1));
+
+    valid = -1;
+
+    for (j = 0; races[j].noun; j++) {
+        boolean v = validrace(ro, j);
+
+        if (j == ra)
+            c = j;
+        XtSetArg(args[0], nhStr(XtNsensitive), v);
+        XtSetValues(plsel_race_radios[j], args, ONE);
+        if (valid < 0 && v)
+            valid = j;
+    }
+    if (!validrace(ro, c))
+        c = valid;
+
+    if (setcurr)
+        XawToggleSetCurrent(plsel_race_radios[0], i2xtp(c + 1));
+
+    X11_player_selection_setupOthers();
+}
+
+void
+X11_player_selection_randomize()
+{
+    int nrole = plsel_n_roles;
+    int nrace = plsel_n_races;
+    int ro, ra, a, g;
+    boolean fully_specified_role, choose_race_first;
+    boolean picksomething = (flags.initrole == ROLE_NONE
+                             || flags.initrace == ROLE_NONE
+                             || flags.initgend == ROLE_NONE
+                             || flags.initalign == ROLE_NONE);
+
+    if (flags.randomall && picksomething) {
+        if (flags.initrole == ROLE_NONE)
+            flags.initrole = ROLE_RANDOM;
+        if (flags.initrace == ROLE_NONE)
+            flags.initrace = ROLE_RANDOM;
+        if (flags.initgend == ROLE_NONE)
+            flags.initgend = ROLE_RANDOM;
+        if (flags.initalign == ROLE_NONE)
+            flags.initalign = ROLE_RANDOM;
+    }
+
+    rigid_role_checks();
+
+    /* Randomize race and role, unless specified in config */
+    ro = flags.initrole;
+    if (ro == ROLE_NONE || ro == ROLE_RANDOM) {
+        ro = rn2(nrole);
+        if (flags.initrole != ROLE_RANDOM) {
+            fully_specified_role = FALSE;
+        }
+    }
+    ra = flags.initrace;
+    if (ra == ROLE_NONE || ra == ROLE_RANDOM) {
+        ra = rn2(nrace);
+        if (flags.initrace != ROLE_RANDOM) {
+            fully_specified_role = FALSE;
+        }
+    }
+
+    /* make sure we have a valid combination, honoring
+       the users request if possible. */
+    choose_race_first = FALSE;
+    if (flags.initrace >= 0 && flags.initrole < 0) {
+        choose_race_first = TRUE;
+    }
+
+    while (!validrace(ro,ra)) {
+        if (choose_race_first) {
+            ro = rn2(nrole);
+            if (flags.initrole != ROLE_RANDOM) {
+                fully_specified_role = FALSE;
+            }
+        } else {
+            ra = rn2(nrace);
+            if (flags.initrace != ROLE_RANDOM) {
+                fully_specified_role = FALSE;
+            }
+        }
+    }
+
+    g = flags.initgend;
+    if (g == ROLE_NONE) {
+        g = rn2(ROLE_GENDERS);
+        fully_specified_role = FALSE;
+    }
+    while (!validgend(ro,ra,g)) {
+        g = rn2(ROLE_GENDERS);
+    }
+
+    a = flags.initalign;
+    if (a == ROLE_NONE) {
+        a = rn2(ROLE_ALIGNS);
+        fully_specified_role = FALSE;
+    }
+    while (!validalign(ro,ra,a)) {
+        a = rn2(ROLE_ALIGNS);
+    }
+
+    XawToggleSetCurrent(plsel_gend_radios[0], i2xtp(g + 1));
+    XawToggleSetCurrent(plsel_align_radios[0], i2xtp(a + 1));
+    XawToggleSetCurrent(plsel_race_radios[0], i2xtp(ra + 1));
+    XawToggleSetCurrent(plsel_role_radios[0], i2xtp(ro + 1));
+    plsel_set_sensitivities(FALSE);
+}
+
+void
+X11_player_selection_setupOthers()
+{
+    Arg args[2];
+    int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0])) - 1;
+    int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0])) - 1;
+    int valid = -1, c = 0, j;
+    int gchecked = xtp2i(XawToggleGetCurrent(plsel_gend_radios[0])) - 1;
+    int achecked = xtp2i(XawToggleGetCurrent(plsel_align_radios[0])) - 1;
+
+    if (ro < 0 || ra < 0)
+        return;
+
+    for (j = 0; j < ROLE_GENDERS; j++) {
+        boolean v = validgend(ro, ra, j);
+
+        if (j == gchecked)
+            c = j;
+        XtSetArg(args[0], nhStr(XtNsensitive), v);
+        XtSetValues(plsel_gend_radios[j], args, ONE);
+        if (valid < 0 && v)
+            valid = j;
+    }
+    if (!validgend(ro, ra, c))
+        c = valid;
+
+    XawToggleSetCurrent(plsel_gend_radios[0], i2xtp(c + 1));
+
+    valid = -1;
+
+    for (j = 0; j < ROLE_ALIGNS; j++) {
+        boolean v = validalign(ro, ra, j);
+
+        if (j == achecked)
+            c = j;
+        XtSetArg(args[0], nhStr(XtNsensitive), v);
+        XtSetValues(plsel_align_radios[j], args, ONE);
+        if (valid < 0 && v)
+            valid = j;
+    }
+    if (!validalign(ro, ra, c))
+        c = valid;
+
+    XawToggleSetCurrent(plsel_align_radios[0], i2xtp(c + 1));
+}
+
+static void
+racetoggleCallback(w, client, call)
+Widget w;
+XtPointer client, call;
+{
+    Arg args[2];
+    int j, valid;
+    int c = 0;
+    int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0])) - 1;
+    int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0])) - 1;
+
+    nhUse(w);
+    nhUse(client);
+    nhUse(call);
+
+    plsel_set_play_button(ra < 0 || ro < 0);
+
+    if (ra < 0 || ro < 0)
+        return;
+
+    valid = -1;
+
+    for (j = 0; roles[j].name.m; j++) {
+        boolean v = validrace(j, ra);
+
+        if (j == ro)
+            c = j;
+        XtSetArg(args[0], nhStr(XtNsensitive), v);
+        XtSetValues(plsel_role_radios[j], args, ONE);
+        if (valid < 0 && v)
+            valid = j;
+    }
+    if (!validrace(c, ra))
+        c = valid;
+
+    j = c + 1;
+    XawToggleSetCurrent(plsel_role_radios[0], i2xtp(j));
+
+    X11_player_selection_setupOthers();
+}
+
+static void
+roletoggleCallback(w, client, call)
+Widget w;
+XtPointer client, call;
+{
+    Arg args[2];
+    int j, valid;
+    int c = 0;
+    int ra = xtp2i(XawToggleGetCurrent(plsel_race_radios[0])) - 1;
+    int ro = xtp2i(XawToggleGetCurrent(plsel_role_radios[0])) - 1;
+
+    nhUse(w);
+    nhUse(client);
+    nhUse(call);
+
+    plsel_set_play_button(ra < 0 || ro < 0);
+
+    if (ra < 0 || ro < 0)
+        return;
+
+    valid = -1;
+
+    for (j = 0; races[j].noun; j++) {
+        boolean v = validrace(ro, j);
+
+        if (j == ra)
+            c = j;
+        XtSetArg(args[0], nhStr(XtNsensitive), v);
+        XtSetValues(plsel_race_radios[j], args, ONE);
+        if (valid < 0 && v)
+            valid = j;
+    }
+    if (!validrace(ro, c))
+        c = valid;
+
+    j = c + 1;
+    XawToggleSetCurrent(plsel_race_radios[0], i2xtp(j));
+
+    X11_player_selection_setupOthers();
+}
+
+static void
+gendertoggleCallback(w, client, call)
+Widget w;
+XtPointer client, call;
+{
+    int i, r = xtp2i(XawToggleGetCurrent(plsel_gend_radios[0])) - 1;
+
+    nhUse(w);
+    nhUse(client);
+    nhUse(call);
+
+    plsel_set_play_button(r < 0);
+
+    for (i = 0; roles[i].name.m; i++) {
+        if (roles[i].name.f) {
+            Arg args[2];
+
+            XtSetArg(args[0], XtNlabel,
+                     (r < 1) ? roles[i].name.m : roles[i].name.f);
+            XtSetValues(plsel_role_radios[i], args, ONE);
+        }
+    }
+}
+
+static void
+aligntoggleCallback(w, client, call)
+Widget w;
+XtPointer client, call;
+{
+    int r = xtp2i(XawToggleGetCurrent(plsel_align_radios[0])) - 1;
+
+    nhUse(w);
+    nhUse(client);
+    nhUse(call);
+
+    plsel_set_play_button(r < 0);
+}
+
+static void
+plsel_random_btn_callback(w, client, call)
+Widget w;
+XtPointer client;
+XtPointer call;
+{
+    nhUse(w);
+    nhUse(client);
+    nhUse(call);
+
+    X11_player_selection_randomize();
+}
+
+static void
+plsel_play_btn_callback(w, client, call)
+Widget w;
+XtPointer client;
+XtPointer call;
+{
+    nhUse(w);
+    nhUse(client);
+    nhUse(call);
+
+    plsel_dialog_acceptvalues();
+    exit_x_event = TRUE; /* leave event loop */
+}
+
+static void
+plsel_quit_btn_callback(w, client, call)
+Widget w;
+XtPointer client;
+XtPointer call;
+{
+    nhUse(w);
+    nhUse(client);
+    nhUse(call);
+
+    ps_selected = PS_QUIT;
+    exit_x_event = TRUE; /* leave event loop */
+}
+
+Widget
+X11_create_player_selection_name(form)
+Widget form;
+{
+    Widget namelabel, name_vp, name_form;
+    Arg args[10];
+    Cardinal num_args;
+
+    /* name viewport */
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
+    XtSetArg(args[num_args], XtNforceBars, False); num_args++;
+    XtSetArg(args[num_args], XtNallowVert, False); num_args++;
+    XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
+    name_vp = XtCreateManagedWidget("name_vp", viewportWidgetClass, form,
+                                    args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
+    name_form = XtCreateManagedWidget("name_form", formWidgetClass, name_vp,
+                                      args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNlabel), "Name"); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
+
+    namelabel = XtCreateManagedWidget("name_label",
+                                      labelWidgetClass, name_form,
+                                      args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), namelabel); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNresizable), True); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNeditType),
+             !plsel_ask_name ? XawtextRead : XawtextEdit); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNresize), XawtextResizeWidth); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNstring), plname); num_args++;
+    XtSetArg(args[num_args], XtNinsertPosition, strlen(plname)); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNaccelerators),
+             XtParseAcceleratorTable(plsel_input_accelerators)); num_args++;
+    plsel_name_input = XtCreateManagedWidget("name_input",
+                                             asciiTextWidgetClass, name_form,
+                                             args, num_args);
+
+    XtInstallAccelerators(plsel_name_input, plsel_name_input);
+    if (plsel_ask_name) {
+        XtSetKeyboardFocus(form, plsel_name_input);
+    } else {
+        XtSetArg(args[0], nhStr(XtNdisplayCaret), False);
+        XtSetValues(plsel_name_input, args, ONE);
+    }
+
+    return name_vp;
+}
+
+void
+X11_player_selection_dialog()
+{
+    Widget popup, popup_vp;
+    Widget form;
+    Widget name_vp;
+    Widget racelabel, race_form, race_vp, race_form2;
+    Widget rolelabel, role_form, role_vp, role_form2;
+    Widget gendlabel, gend_form,
+           gend_radio_m, gend_radio_f, gend_vp, gend_form2;
+    Widget alignlabel, align_form,
+           align_radio_l, align_radio_n, align_radio_c, align_vp, align_form2;
+    Widget btn_vp, btn_form, random_btn, play_btn, quit_btn;
+    Widget tmpwidget;
+    Arg args[10];
+    Cardinal num_args;
+    int i;
+    int winwid = 400;
+    int cwid = (winwid / 3) - 14;
+
+    num_args = 0;
+    XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
+    XtSetArg(args[num_args], XtNtitle, "Player Selection"); num_args++;
+    popup = XtCreatePopupShell("player_selection_dialog",
+                               transientShellWidgetClass,
+                               toplevel, args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], XtNtranslations,
+             XtParseTranslationTable(plsel_dialog_translations)); num_args++;
+    popup_vp = XtCreateManagedWidget("plsel_vp", viewportWidgetClass,
+                                     popup, args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], XtNtranslations,
+             XtParseTranslationTable(plsel_dialog_translations)); num_args++;
+    form = XtCreateManagedWidget("plsel_form", formWidgetClass, popup_vp,
+                                 args, num_args);
+
+    name_vp = X11_create_player_selection_name(form);
+
+    num_args = 0;
+    XtSetArg(args[num_args], XtNwidth, winwid); num_args++;
+    XtSetValues(name_vp, args, num_args);
+
+    /*
+     * Layout; role is centered rather than first:
+     *
+     *   +------------------------------------+
+     *   | name                               |
+     *   +------------------------------------+
+     *   +--------+   +------------+   +---------+
+     *   | human  |   |archeologist|   |  male   |
+     *   |  elf   |   | barbarian  |   | female  |
+     *   | dwarf  |   |  caveman   |   +---------+
+     *   | gnome  |   |   healer   |   +---------+
+     *   |  orc   |   |   knight   |   | lawful  |
+     *   +--------+   |    monk    |   | neutral |
+     *                |   priest   |   | chaotic |
+     *                |   rogue    |   +---------+
+     *                |   ranger   |   +--------+
+     *                |  samurai   |   + Random +
+     *                |  tourist   |   +  Play  +
+     *                |  valkyrie  |   +  Quit  +
+     *                |   wizard   |   +--------+
+     *                +------------+
+     *
+     * TODO:
+     *  make name box same width as race+gap+role+gap+gender/alignment
+     *  (resize it after the other boxes have been placed);
+     *  make Random/Play/Quit buttons same width as gender/alignment and
+     *  align bottom of them with bottom of role (they already specify
+     *  the same width for the label text but different decorations--
+     *  room for radio button box--of the other widgets results in the
+     *  total width being different);
+     *  add 'random' to each of the four boxes and Choose to the Random/
+     *  Play/Quit buttons; if none of the four 'random's are currently
+     *  selected, gray-out Choose; conversely, when Choose or Play is
+     *  clicked on, make the random assignments for any/all of the four
+     *  boxes which have 'random' selected.
+     *  Maybe:  move gender box underneath race, bottom aligned with role
+     *  and move alignment up to where gender currently is.  If that's
+     *  done, move role column first and race+gender to middle.
+     */
+
+    /********************************************/
+
+    /* Race */
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), name_vp); num_args++;
+    race_form = XtCreateManagedWidget("race_form", formWidgetClass, form,
+                                      args, num_args);
+
+    /* race label */
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNlabel), "Race"); num_args++;
+    racelabel = XtCreateManagedWidget("race_label",
+                                      labelWidgetClass, race_form,
+                                      args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), racelabel); num_args++;
+    XtSetArg(args[num_args], XtNforceBars, False); num_args++;
+    XtSetArg(args[num_args], XtNallowVert, True); num_args++;
+    XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
+    race_vp = XtCreateManagedWidget("race_vp", viewportWidgetClass, race_form,
+                                    args, num_args);
+
+    num_args = 0;
+    race_form2 = XtCreateManagedWidget("race_form2", formWidgetClass, race_vp,
+                                      args, num_args);
+
+    for (i = 0; races[i].noun; i++)
+        continue;
+    plsel_n_races = i;
+
+    plsel_race_radios = (Widget *) alloc(sizeof (Widget) * plsel_n_races);
+
+    /* race radio buttons */
+    for (i = 0; races[i].noun; i++) {
+        Widget racewidget;
+
+        num_args = 0;
+        if (i > 0)
+            XtSetArg(args[num_args], nhStr(XtNfromVert),
+                     tmpwidget); num_args++;
+        XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
+        if (i > 0)
+            XtSetArg(args[num_args], nhStr(XtNradioGroup),
+                     plsel_race_radios[0]); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNradioData), (i + 1)); num_args++;
+
+        racewidget = XtCreateManagedWidget(races[i].noun,
+                                           toggleWidgetClass,
+                                           race_form2,
+                                           args, num_args);
+        XtAddCallback(racewidget, XtNcallback, racetoggleCallback, i2xtp(i));
+        tmpwidget = racewidget;
+        plsel_race_radios[i] = racewidget;
+    }
+
+    XawToggleUnsetCurrent(plsel_race_radios[0]);
+
+    /********************************************/
+
+    /* Role */
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), name_vp); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromHoriz), race_form); num_args++;
+    role_form = XtCreateManagedWidget("role_form", formWidgetClass, form,
+                                      args, num_args);
+
+    /* role label */
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNlabel), "Role"); num_args++;
+    rolelabel = XtCreateManagedWidget("role_label", labelWidgetClass,
+                                      role_form, args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), rolelabel); num_args++;
+    XtSetArg(args[num_args], XtNforceBars, False); num_args++;
+    XtSetArg(args[num_args], XtNallowVert, True); num_args++;
+    XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
+    role_vp = XtCreateManagedWidget("role_vp", viewportWidgetClass, role_form,
+                                    args, num_args);
+
+    num_args = 0;
+    role_form2 = XtCreateManagedWidget("role_form2", formWidgetClass, role_vp,
+                                      args, num_args);
+
+    for (i = 0; roles[i].name.m; i++)
+        continue;
+    plsel_n_roles = i;
+
+    plsel_role_radios = (Widget *) alloc(sizeof (Widget) * plsel_n_roles);
+
+    /* role radio buttons */
+    for (i = 0; roles[i].name.m; i++) {
+        Widget rolewidget;
+
+        num_args = 0;
+        if (i > 0)
+            XtSetArg(args[num_args], nhStr(XtNfromVert),
+                     tmpwidget); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNwidth), cwid); num_args++;
+        if (i > 0)
+            XtSetArg(args[num_args], nhStr(XtNradioGroup),
+                     plsel_role_radios[0]); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNradioData), (i + 1)); num_args++;
+
+        rolewidget = XtCreateManagedWidget(roles[i].name.m, toggleWidgetClass,
+                                           role_form2, args, num_args);
+        XtAddCallback(rolewidget, XtNcallback, roletoggleCallback, i2xtp(i));
+        tmpwidget = rolewidget;
+        plsel_role_radios[i] = rolewidget;
+    }
+    XawToggleUnsetCurrent(plsel_role_radios[0]);
+
+    /********************************************/
+
+    /* Gender*/
+
+    plsel_gend_radios = (Widget *) alloc(sizeof (Widget) * ROLE_GENDERS);
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), name_vp); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromHoriz), role_form); num_args++;
+    gend_form = XtCreateManagedWidget("gender_form", formWidgetClass, form,
+                                      args, num_args);
+
+    /* gender label */
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNlabel), "Gender"); num_args++;
+    gendlabel = XtCreateManagedWidget("gender_label", labelWidgetClass,
+                                      gend_form, args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), gendlabel); num_args++;
+    XtSetArg(args[num_args], XtNforceBars, False); num_args++;
+    XtSetArg(args[num_args], XtNallowVert, True); num_args++;
+    XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
+    gend_vp = XtCreateManagedWidget("gender_vp", viewportWidgetClass,
+                                    gend_form, args, num_args);
+
+    num_args = 0;
+    gend_form2 = XtCreateManagedWidget("gender_form2", formWidgetClass,
+                                       gend_vp, args, num_args);
+
+    /* gender radio buttons */
+    num_args = 0;
+    XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNradioData), 1); num_args++;
+    plsel_gend_radios[0] = gend_radio_m
+        =  XtCreateManagedWidget("Male", toggleWidgetClass,
+                                 gend_form2, args, num_args);
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), gend_radio_m); num_args++;
+    XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNradioGroup),
+             plsel_gend_radios[0]); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNradioData), 2); num_args++;
+    plsel_gend_radios[1] = gend_radio_f
+        =  XtCreateManagedWidget("Female", toggleWidgetClass,
+                                 gend_form2, args, num_args);
+
+    XawToggleUnsetCurrent(plsel_gend_radios[0]);
+
+    XtAddCallback(gend_radio_m, XtNcallback,
+                  gendertoggleCallback, (XtPointer) (1));
+    XtAddCallback(gend_radio_f, XtNcallback,
+                  gendertoggleCallback, (XtPointer) (2));
+
+    /********************************************/
+
+    /* Alignment */
+
+    plsel_align_radios = (Widget *) alloc(sizeof (Widget) * ROLE_ALIGNS);
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), gend_form); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNvertDistance), 30); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromHoriz), role_form); num_args++;
+    align_form = XtCreateManagedWidget("align_form", formWidgetClass, form,
+                                       args, num_args);
+
+    /* align label */
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNjustify), XtJustifyLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNlabel), "Alignment"); num_args++;
+    alignlabel = XtCreateManagedWidget("align_label", labelWidgetClass,
+                                       align_form, args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNtopMargin), 0); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), alignlabel); num_args++;
+    XtSetArg(args[num_args], XtNforceBars, False); num_args++;
+    XtSetArg(args[num_args], XtNallowVert, True); num_args++;
+    XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
+    align_vp = XtCreateManagedWidget("align_vp", viewportWidgetClass,
+                                     align_form, args, num_args);
+
+    num_args = 0;
+    align_form2 = XtCreateManagedWidget("align_form2", formWidgetClass,
+                                        align_vp, args, num_args);
+
+    num_args = 0;
+    XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNradioData), 1); num_args++;
+    plsel_align_radios[0] = align_radio_l
+        =  XtCreateManagedWidget("Lawful", toggleWidgetClass,
+                                 align_form2, args, num_args);
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), align_radio_l); num_args++;
+    XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNradioGroup),
+             plsel_align_radios[0]); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNradioData), 2); num_args++;
+    plsel_align_radios[1] = align_radio_n
+        = XtCreateManagedWidget("Neutral", toggleWidgetClass,
+                                align_form2, args, num_args);
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), align_radio_n); num_args++;
+    XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNradioGroup),
+             plsel_align_radios[0]); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNradioData), 3); num_args++;
+    plsel_align_radios[2] = align_radio_c
+        =  XtCreateManagedWidget("Chaotic", toggleWidgetClass,
+                                 align_form2, args, num_args);
+
+    XawToggleUnsetCurrent(plsel_align_radios[0]);
+
+    XtAddCallback(align_radio_l, XtNcallback,
+                  aligntoggleCallback, (XtPointer) (1));
+    XtAddCallback(align_radio_n, XtNcallback,
+                  aligntoggleCallback, (XtPointer) (2));
+    XtAddCallback(align_radio_c, XtNcallback,
+                  aligntoggleCallback, (XtPointer) (3));
+
+    /********************************************/
+
+    /* Buttons! */
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), align_form); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNvertDistance), 30); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNrightMargin), 0); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromHoriz), role_form); num_args++;
+    XtSetArg(args[num_args], XtNforceBars, False); num_args++;
+    XtSetArg(args[num_args], XtNallowVert, False); num_args++;
+    XtSetArg(args[num_args], XtNallowHoriz, False); num_args++;
+    btn_vp = XtCreateManagedWidget("btn_vp", viewportWidgetClass, form,
+                                   args, num_args);
+
+    num_args = 0;
+    btn_form = XtCreateManagedWidget("btn_form", formWidgetClass, btn_vp,
+                                     args, num_args);
+
+    /* "Random" button */
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNtop), XtChainTop); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
+    XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNlabel), "Random"); num_args++;
+    random_btn = XtCreateManagedWidget("random", commandWidgetClass, btn_form,
+                                       args, num_args);
+    XtAddCallback(random_btn, XtNcallback, plsel_random_btn_callback, form);
+
+    /* "Play" button */
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), random_btn); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
+    XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNlabel), "Play"); num_args++;
+    plsel_btn_play = play_btn
+        = XtCreateManagedWidget("play", commandWidgetClass, btn_form,
+                                args, num_args);
+    XtAddCallback(play_btn, XtNcallback, plsel_play_btn_callback, form);
+
+    /* "Quit" button */
+
+    num_args = 0;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), play_btn); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNbottom), XtChainBottom); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNleft), XtChainLeft); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNright), XtChainRight); num_args++;
+    XtSetArg(args[num_args], XtNwidth, cwid); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNlabel), "Quit"); num_args++;
+    quit_btn = XtCreateManagedWidget("quit", commandWidgetClass, btn_form,
+                                     args, num_args);
+    XtAddCallback(quit_btn, XtNcallback, plsel_quit_btn_callback, form);
+
+    /********************************************/
+
+    XtRealizeWidget(popup);
+    X11_player_selection_randomize();
+
+    ps_selected = -1;
+
+    nh_XtPopup(popup, (int) XtGrabExclusive, form);
+
+    /* The callback will enable the event loop exit. */
+    (void) x_event(EXIT_ON_EXIT);
+
+    nh_XtPopdown(popup);
+    XtDestroyWidget(popup);
+
+    if (plsel_race_radios)
+        free(plsel_race_radios);
+
+    if (plsel_role_radios)
+        free(plsel_role_radios);
+
+    if (plsel_gend_radios)
+        free(plsel_gend_radios);
+
+    if (plsel_align_radios)
+        free(plsel_align_radios);
+
+    if (ps_selected == PS_QUIT || program_state.done_hup) {
+        clearlocks();
+        X11_exit_nhwindows((char *) 0);
+        nh_terminate(0);
+    }
+}
+
 /* Global functions =========================================================
  */
 void
-X11_player_selection()
+X11_player_selection_prompts()
 {
     int num_roles, num_races, num_gends, num_algns, i, availcount, availindex;
     Widget popup, player_form;
@@ -326,7 +1305,7 @@ X11_player_selection()
         /* select a role */
         for (num_roles = 0; roles[num_roles].name.m; ++num_roles)
             continue;
-        choices = (const char **) alloc(sizeof(char *) * num_roles);
+        choices = (const char **) alloc(sizeof (char *) * num_roles);
         for (;;) {
             availcount = 0;
             for (i = 0; i < num_roles; i++) {
@@ -381,7 +1360,7 @@ X11_player_selection()
         if (ps_selected == PS_QUIT || program_state.done_hup) {
             clearlocks();
             X11_exit_nhwindows((char *) 0);
-            terminate(0);
+            nh_terminate(0);
         } else if (ps_selected == PS_RANDOM) {
             flags.initrole = ROLE_RANDOM;
         } else if (ps_selected < 0 || ps_selected >= num_roles) {
@@ -461,7 +1440,7 @@ X11_player_selection()
             if (ps_selected == PS_QUIT || program_state.done_hup) {
                 clearlocks();
                 X11_exit_nhwindows((char *) 0);
-                terminate(0);
+                nh_terminate(0);
             } else if (ps_selected == PS_RANDOM) {
                 flags.initrace = ROLE_RANDOM;
             } else if (ps_selected < 0 || ps_selected >= num_races) {
@@ -539,7 +1518,7 @@ X11_player_selection()
             if (ps_selected == PS_QUIT || program_state.done_hup) {
                 clearlocks();
                 X11_exit_nhwindows((char *) 0);
-                terminate(0);
+                nh_terminate(0);
             } else if (ps_selected == PS_RANDOM) {
                 flags.initgend = ROLE_RANDOM;
             } else if (ps_selected < 0 || ps_selected >= num_gends) {
@@ -615,7 +1594,7 @@ X11_player_selection()
             if (ps_selected == PS_QUIT || program_state.done_hup) {
                 clearlocks();
                 X11_exit_nhwindows((char *) 0);
-                terminate(0);
+                nh_terminate(0);
             } else if (ps_selected == PS_RANDOM) {
                 flags.initalign = ROLE_RANDOM;
             } else if (ps_selected < 0 || ps_selected >= num_algns) {
@@ -628,17 +1607,35 @@ X11_player_selection()
     }
 }
 
+void
+X11_player_selection()
+{
+    if (iflags.wc_player_selection == VIA_DIALOG) {
+        if (!*plname) {
+#ifdef UNIX
+            char *defplname = get_login_name();
+#else
+            char *defplname = (char *)0;
+#endif
+            (void) strncpy(plname, defplname ? defplname : "Mumbles",
+                           sizeof plname - 1);
+            plname[sizeof plname - 1] = '\0';
+            iflags.renameinprogress = TRUE;
+        }
+        X11_player_selection_dialog();
+    } else { /* iflags.wc_player_selection == VIA_PROMPTS */
+        X11_player_selection_prompts();
+    }
+}
+
 int
 X11_get_ext_cmd()
 {
-    static Boolean initialized = False;
-
-    if (!initialized) {
+    if (!extended_commands)
         init_extended_commands_popup();
-        initialized = True;
-    }
 
-    extended_command_selected = -1; /* reset selected value */
+    extended_cmd_selected = -1; /* reset selected value */
+    ec_scroll_to_view(-1); /* force scroll bar to top */
 
     positionpopup(extended_command_popup, FALSE); /* center on cursor */
     nh_XtPopup(extended_command_popup, (int) XtGrabExclusive,
@@ -647,7 +1644,16 @@ X11_get_ext_cmd()
     /* The callbacks will enable the event loop exit. */
     (void) x_event(EXIT_ON_EXIT);
 
-    return extended_command_selected;
+    return extended_cmd_selected;
+}
+
+void
+release_extended_cmds()
+{
+    if (extended_commands) {
+        XtDestroyWidget(extended_command_popup);
+        free((genericptr_t) extended_commands), extended_commands = 0;
+    }
 }
 
 /* End global functions =====================================================
@@ -661,24 +1667,24 @@ extend_select(w, client_data, call_data)
 Widget w;
 XtPointer client_data, call_data;
 {
-    int selected = (int) client_data;
+    int selected = (int) (ptrdiff_t) client_data;
 
     nhUse(w);
     nhUse(call_data);
 
-    if (extended_command_selected != selected) {
+    if (extended_cmd_selected != selected) {
         /* visibly deselect old one */
-        if (extended_command_selected >= 0)
-            swap_fg_bg(extended_commands[extended_command_selected]);
+        if (extended_cmd_selected >= 0)
+            swap_fg_bg(extended_commands[extended_cmd_selected]);
 
         /* select new one */
         swap_fg_bg(extended_commands[selected]);
-        extended_command_selected = selected;
+        extended_cmd_selected = selected;
     }
 
     nh_XtPopdown(extended_command_popup);
     /* reset colors while popped down */
-    swap_fg_bg(extended_commands[extended_command_selected]);
+    swap_fg_bg(extended_commands[extended_cmd_selected]);
     ec_active = FALSE;
     exit_x_event = TRUE; /* leave event loop */
 }
@@ -746,14 +1752,119 @@ static void
 ec_dismiss()
 {
     /* unselect while still visible */
-    if (extended_command_selected >= 0)
-        swap_fg_bg(extended_commands[extended_command_selected]);
-    extended_command_selected = -1; /* dismiss */
+    if (extended_cmd_selected >= 0)
+        swap_fg_bg(extended_commands[extended_cmd_selected]);
+    extended_cmd_selected = -1; /* dismiss */
     nh_XtPopdown(extended_command_popup);
     ec_active = FALSE;
     exit_x_event = TRUE; /* leave event loop */
 }
 
+/* scroll the extended command menu if necessary
+   so that choices extended_cmd_selected through ec_indx will be visible */
+static void
+ec_scroll_to_view(ec_indx)
+int ec_indx; /* might be greater than extended_cmd_selected */
+{
+    Widget viewport, scrollbar, tmpw;
+    Arg args[5];
+    Cardinal num_args;
+    Position lo_y, hi_y; /* ext cmd label y */
+    float s_shown, s_top; /* scrollbar pos */
+    float s_min, s_max;
+    Dimension h, hh, wh, vh; /* widget and viewport heights */
+    Dimension border_width;
+    int distance = 0;
+    boolean force_top = (ec_indx < 0);
+
+    /*
+     * If the extended command menu needs to be scrolled in order to move
+     * either the highlighted entry (extended_cmd_selected) or the target
+     * entry (ec_indx) into view, we want to make both end up visible.
+     * [Highligthed one is the first matching entry when the user types
+     * something, such as "adjust" after typing 'a', and will be chosen
+     * by pressing <return>.  Target entry is one past the last matching
+     * entry (or last matching entry itself if at end of command list),
+     * showing the user the other potential matches so far.]
+     *
+     * If that's not possible (maybe menu has been resized so that it's
+     * too small), the highlighted entry takes precedence and the target
+     * will be decremented until close enough to fit.
+     */
+
+    if (force_top)
+        ec_indx = 0;
+
+    /* get viewport and scrollbar widgets */
+    tmpw = extended_commands[ec_indx];
+    viewport = XtParent(tmpw);
+    do {
+        scrollbar = XtNameToWidget(tmpw, "*vertical");
+        if (scrollbar)
+            break;
+        tmpw = XtParent(tmpw);
+    } while (tmpw);
+
+    if (scrollbar && viewport) {
+        /* get selected ext command label y position and height */
+        num_args = 0;
+        XtSetArg(args[num_args], XtNy, &hi_y); num_args++;
+        XtSetArg(args[num_args], XtNheight, &h); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNborderWidth), &border_width);
+                                                                   num_args++;
+        XtSetArg(args[num_args], nhStr(XtNdefaultDistance), &distance);
+                                                                   num_args++;
+        XtGetValues(extended_commands[ec_indx], args, num_args);
+        if (distance < 1 || distance > 32766) /* defaultDistance is weird */
+            distance = 4;
+        /* vertical distance between top of one command widget and the next */
+        hh = h + distance + 2 * border_width;
+        /* location of the highlighted entry, if any */
+        if (extended_cmd_selected >= 0) {
+            XtSetArg(args[0], XtNy, &lo_y);
+            XtGetValues(extended_commands[extended_cmd_selected], args, ONE);
+        } else
+            lo_y = hi_y;
+
+        /* get menu widget and viewport heights */
+        XtSetArg(args[0], XtNheight, &wh);
+        XtGetValues(tmpw, args, ONE);
+        XtSetArg(args[0], XtNheight, &vh);
+        XtGetValues(viewport, args, ONE);
+
+        /* widget might be too small if it has been resized or
+           there are a very large number of ambiguous choices */
+        if (hi_y - lo_y > wh) {
+            ec_indx = extended_cmd_selected;
+            if (wh > hh)
+                ec_indx += (wh / hh);
+            XtSetArg(args[0], XtNy, &hi_y);
+            XtGetValues(extended_commands[ec_indx], args, num_args);
+        }
+
+        /* get scrollbar "height" and "top" position; floats between 0-1 */
+        num_args = 0;
+        XtSetArg(args[num_args], XtNshown, &s_shown); num_args++;
+        XtSetArg(args[num_args], nhStr(XtNtopOfThumb), &s_top); num_args++;
+        XtGetValues(scrollbar, args, num_args);
+
+        s_min = s_top * vh;
+        s_max = (s_top + s_shown) * vh;
+
+        /* scroll if outside the view */
+        if (force_top) {
+            s_min = 0.0;
+            XtCallCallbacks(scrollbar, XtNjumpProc, &s_min);
+        } else if ((int) lo_y <= (int) s_min) {
+            s_min = (float) (lo_y / (float) vh);
+            XtCallCallbacks(scrollbar, XtNjumpProc, &s_min);
+        } else if ((int) (hi_y + h) >= (int) s_max) {
+            s_min = (float) ((hi_y + h) / (float) vh) - s_shown;
+            XtCallCallbacks(scrollbar, XtNjumpProc, &s_min);
+        }
+    }
+}
+
 /* ARGSUSED */
 void
 ec_key(w, event, params, num_params)
@@ -764,6 +1875,7 @@ Cardinal *num_params;
 {
     char ch;
     int i;
+    int pass;
     XKeyEvent *xkey = (XKeyEvent *) event;
 
     nhUse(w);
@@ -775,26 +1887,35 @@ Cardinal *num_params;
     if (ch == '\0') { /* don't accept nul char/modifier event */
         /* don't beep */
         return;
+    } else if (ch == '?') {
+        extend_help((Widget) 0, (XtPointer) 0, (XtPointer) 0);
+        return;
     } else if (index("\033\n\r", ch)) {
         if (ch == '\033') {
             /* unselect while still visible */
-            if (extended_command_selected >= 0)
-                swap_fg_bg(extended_commands[extended_command_selected]);
-            extended_command_selected = -1; /* dismiss */
+            if (extended_cmd_selected >= 0)
+                swap_fg_bg(extended_commands[extended_cmd_selected]);
+            extended_cmd_selected = -1; /* dismiss */
         }
 
         nh_XtPopdown(extended_command_popup);
         /* unselect while invisible */
-        if (extended_command_selected >= 0)
-            swap_fg_bg(extended_commands[extended_command_selected]);
+        if (extended_cmd_selected >= 0)
+            swap_fg_bg(extended_commands[extended_cmd_selected]);
 
         exit_x_event = TRUE; /* leave event loop */
         ec_active = FALSE;
         return;
     }
 
-    /* too much time has elapsed */
-    if ((xkey->time - ec_time) > 500)
+    /*
+     * If too much time has elapsed, treat current key as starting a new
+     * choice, otherwise it is a continuation of the choice in progress.
+     * Extra letters might be needed to disambiguate between choices
+     * ("ride" vs "rub", for instance), or player may just be typing in
+     * the whole word.
+     */
+    if (ec_active && (xkey->time - ec_time) > 2500) /* 2.5 seconds */
         ec_active = FALSE;
 
     if (!ec_active) {
@@ -807,20 +1928,42 @@ Cardinal *num_params;
     if (ec_nchars >= EC_NCHARS)
         ec_nchars = EC_NCHARS - 1; /* don't overflow */
 
-    for (i = 0; extcmdlist[i].ef_txt; i++) {
-        if (extcmdlist[i].ef_txt[0] == '?')
-            continue;
-
-        if (!strncmp(ec_chars, extcmdlist[i].ef_txt, ec_nchars)) {
-            if (extended_command_selected != i) {
-                /* I should use set() and unset() actions, but how do */
-                /* I send the an action to the widget? */
-                if (extended_command_selected >= 0)
-                    swap_fg_bg(extended_commands[extended_command_selected]);
-                extended_command_selected = i;
-                swap_fg_bg(extended_commands[extended_command_selected]);
+    for (pass = 0; pass < 2; pass++) {
+        if (pass == 1) {
+            /* first pass finished, but no matching command was found */
+            /* start a new one with the last char entered */
+            if (extended_cmd_selected >= 0)
+                swap_fg_bg(extended_commands[extended_cmd_selected]);
+            extended_cmd_selected = -1; /* dismiss */
+            ec_chars[0] = ec_chars[ec_nchars-1];
+            ec_nchars = 1;
+        }
+        for (i = 0; extcmdlist[i].ef_txt; i++) {
+            if (extcmdlist[i].ef_txt[0] == '?')
+                continue;
+
+            if (!strncmp(ec_chars, extcmdlist[i].ef_txt, ec_nchars)) {
+                if (extended_cmd_selected != i) {
+                    /* I should use set() and unset() actions, but how do */
+                    /* I send the an action to the widget? */
+                    if (extended_cmd_selected >= 0)
+                        swap_fg_bg(extended_commands[extended_cmd_selected]);
+                    extended_cmd_selected = i;
+                    swap_fg_bg(extended_commands[extended_cmd_selected]);
+                }
+                /* advance to one past last matching entry, so that all
+                   ambiguous choices, plus one to show thare aren't any
+                   more such, will scroll into view */
+                do {
+                    if (!extcmdlist[i + 1].ef_txt
+                        || *extcmdlist[i + 1].ef_txt == '?')
+                        break; /* end of list */
+                    ++i;
+                } while (!strncmp(ec_chars, extcmdlist[i].ef_txt, ec_nchars));
+
+                ec_scroll_to_view(i);
+                return;
             }
-            break;
         }
     }
 }
@@ -872,21 +2015,21 @@ init_extended_commands_popup()
 /*
  * Create a popup widget of the following form:
  *
- *                   popup_label
- *             ----------- ------------
- *             |left_name| |right_name|
- *             ----------- ------------
- *             ------------------------
- *             |       name1          |
- *             ------------------------
- *             ------------------------
- *             |       name2          |
- *             ------------------------
- *                       .
- *                       .
- *             ------------------------
- *             |       nameN          |
- *             ------------------------
+ *                    popup_label
+ *              ----------- ------------
+ *              |left_name| |right_name|
+ *              ----------- ------------
+ *              ------------------------
+ *              |       name1          |
+ *              ------------------------
+ *              ------------------------
+ *              |       name2          |
+ *              ------------------------
+ *                        .
+ *                        .
+ *              ------------------------
+ *              |       nameN          |
+ *              ------------------------
  */
 static Widget
 make_menu(popup_name, popup_label, popup_translations, left_name,
@@ -905,83 +2048,99 @@ Widget **command_widgets;
 XtCallbackProc name_callback;
 Widget *formp; /* return */
 {
-    Widget popup, form, label, above, left, right;
+    Widget popup, form, label, above, left, right, view;
     Widget *commands, *curr;
     int i;
     Arg args[8];
     Cardinal num_args;
-    Dimension width, max_width;
+    Dimension width, other_width, max_width, border_width,
+              height, cumulative_height, screen_height;
     int distance, skip;
 
-    commands = (Widget *) alloc((unsigned) num_names * sizeof(Widget));
+    commands = (Widget *) alloc((unsigned) num_names * sizeof (Widget));
 
     num_args = 0;
-    XtSetArg(args[num_args], XtNallowShellResize, True);
-    num_args++;
-
+    XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
     popup = XtCreatePopupShell(popup_name, transientShellWidgetClass,
                                toplevel, args, num_args);
     XtOverrideTranslations(
         popup, XtParseTranslationTable("<Message>WM_PROTOCOLS: ec_delete()"));
 
     num_args = 0;
+    XtSetArg(args[num_args], XtNforceBars, False); num_args++;
+    XtSetArg(args[num_args], XtNallowVert, True); num_args++;
+    XtSetArg(args[num_args], XtNtranslations,
+             XtParseTranslationTable(popup_translations)); num_args++;
+    view = XtCreateManagedWidget("menuformview", viewportWidgetClass, popup,
+                                 args, num_args);
+
+    num_args = 0;
     XtSetArg(args[num_args], XtNtranslations,
-             XtParseTranslationTable(popup_translations));
-    num_args++;
-    *formp = form = XtCreateManagedWidget("menuform", formWidgetClass, popup,
+             XtParseTranslationTable(popup_translations)); num_args++;
+    *formp = form = XtCreateManagedWidget("menuform", formWidgetClass, view,
                                           args, num_args);
 
-    /* Get the default distance between objects in the form widget. */
+    /*
+     * Get the default distance between objects in the viewport widget.
+     * (Something is fishy here:  'distance' ends up being 0 but there
+     * is a non-zero gap between the borders of the internal widgets.
+     * It matches exactly the default value of 4 for defaultDistance.)
+     */
     num_args = 0;
-    XtSetArg(args[num_args], nhStr(XtNdefaultDistance), &distance);
-    num_args++;
-    XtGetValues(form, args, num_args);
+    XtSetArg(args[num_args], nhStr(XtNdefaultDistance), &distance); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNborderWidth), &border_width); num_args++;
+    XtGetValues(view, args, num_args);
+    if (distance < 1 || distance > 32766)
+        distance = 4;
 
     /*
      * Create the label.
      */
     num_args = 0;
 #if defined(X11R6) && defined(XI18N)
-    XtSetArg(args[num_args], XtNinternational, True);
-    num_args++;
+    XtSetArg(args[num_args], XtNinternational, True); num_args++;
 #endif
-    XtSetArg(args[num_args], XtNborderWidth, 0);
-    num_args++;
+    XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
     label = XtCreateManagedWidget(popup_label, labelWidgetClass, form, args,
                                   num_args);
 
+    cumulative_height = 0;
+    XtSetArg(args[0], XtNheight, &height);
+    XtGetValues(label, args, ONE);
+    cumulative_height += distance + height; /* no border for label */
+
     /*
      * Create the left button.
      */
     num_args = 0;
-    XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-    num_args++;
-    /*
-        XtSetArg(args[num_args], nhStr(XtNshapeStyle),
-                                    XmuShapeRoundedRectangle); num_args++;
-    */
+    XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+#if 0
+    XtSetArg(args[num_args], nhStr(XtNshapeStyle),
+                              XmuShapeRoundedRectangle); num_args++;
+#endif
     left = XtCreateManagedWidget(left_name, commandWidgetClass, form, args,
                                  num_args);
     XtAddCallback(left, XtNcallback, left_callback, (XtPointer) 0);
-    skip = 3 * distance; /* triple the spacing */
-    if (!skip)
-        skip = 3;
+    skip = (distance < 4) ? 8 : 2 * distance;
+
+    num_args = 0;
+    XtSetArg(args[0], XtNheight, &height);
+    XtGetValues(left, args, ONE);
+    cumulative_height += distance + height + 2 * border_width;
 
     /*
      * Create right button.
      */
     num_args = 0;
-    XtSetArg(args[num_args], nhStr(XtNfromHoriz), left);
-    num_args++;
-    XtSetArg(args[num_args], nhStr(XtNfromVert), label);
-    num_args++;
-    /*
-        XtSetArg(args[num_args], nhStr(XtNshapeStyle),
-                                    XmuShapeRoundedRectangle); num_args++;
-    */
+    XtSetArg(args[num_args], nhStr(XtNfromHoriz), left); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNhorizDistance), skip); num_args++;
+    XtSetArg(args[num_args], nhStr(XtNfromVert), label); num_args++;
+#if 0
+    XtSetArg(args[num_args], nhStr(XtNshapeStyle),
+                              XmuShapeRoundedRectangle); num_args++;
+#endif
 #if defined(X11R6) && defined(XI18N)
-    XtSetArg(args[num_args], XtNinternational, True);
-    num_args++;
+    XtSetArg(args[num_args], XtNinternational, True); num_args++;
 #endif
     right = XtCreateManagedWidget(right_name, commandWidgetClass, form, args,
                                   num_args);
@@ -997,13 +2156,14 @@ Widget *formp; /* return */
         if (!widget_names[i])
             continue;
         num_args = 0;
-        XtSetArg(args[num_args], nhStr(XtNfromVert), above);
-        num_args++;
+        XtSetArg(args[num_args], nhStr(XtNfromVert), above); num_args++;
         if (above == left) {
             /* if first, we are farther apart */
-            XtSetArg(args[num_args], nhStr(XtNvertDistance), skip);
-            num_args++;
-        }
+            XtSetArg(args[num_args], nhStr(XtNvertDistance), skip); num_args++;
+            cumulative_height += skip;
+        } else
+            cumulative_height += distance;
+        cumulative_height += height + 2 * border_width;
 
 #if defined(X11R6) && defined(XI18N)
         XtSetArg(args[num_args], XtNinternational, True);
@@ -1011,19 +2171,23 @@ Widget *formp; /* return */
 #endif
         *curr = XtCreateManagedWidget(widget_names[i], commandWidgetClass,
                                       form, args, num_args);
-        XtAddCallback(*curr, XtNcallback, name_callback, (XtPointer) i);
+        XtAddCallback(*curr, XtNcallback, name_callback,
+                      (XtPointer) (ptrdiff_t) i);
         above = *curr++;
     }
+    cumulative_height += distance; /* space at bottom of form */
 
     /*
-     * Now find the largest width.  Start with the width dismiss + help
-     * buttons, since they are adjacent.
+     * Now find the largest width.  Start with width of left + right buttons
+     * ('dismiss' + 'help' or 'quit' + 'random'), since they are adjacent.
      */
     XtSetArg(args[0], XtNwidth, &max_width);
     XtGetValues(left, args, ONE);
     XtSetArg(args[0], XtNwidth, &width);
     XtGetValues(right, args, ONE);
-    max_width = max_width + width + distance;
+    /* doesn't count leftmost 'distance + border_width' and
+       rightmost 'border_width + distance' since all entries have those */
+    max_width = max_width + border_width + skip + border_width + width;
 
     /* Next, the title. */
     XtSetArg(args[0], XtNwidth, &width);
@@ -1043,6 +2207,40 @@ Widget *formp; /* return */
     }
 
     /*
+     * Re-do the two side-by-side widgets to take up half the width each.
+     *
+     * With max_width and skip both having even values, we never have to
+     * tweak left or right to maybe be one pixel wider than the other.
+     */
+    if (max_width % 2)
+        ++max_width;
+    XtSetArg(args[0], XtNwidth, &width);
+    XtGetValues(left, args, ONE);
+    XtSetArg(args[0], XtNwidth, &other_width);
+    XtGetValues(right, args, ONE);
+    if (width + border_width + skip / 2 < max_width / 2
+        && other_width + border_width + skip / 2 < max_width / 2) {
+        /* both are narrower than half */
+        width = other_width = max_width / 2 - border_width - skip / 2;
+        XtSetArg(args[0], XtNwidth, width);
+        XtSetValues(left, args, ONE);
+        XtSetArg(args[0], XtNwidth, other_width);
+        XtSetValues(right, args, ONE);
+    } else if (width + border_width + skip / 2 < max_width / 2) {
+        /* 'other_width' (right) is half or more */
+        width = max_width - other_width - 2 * border_width - skip;
+        XtSetArg(args[0], XtNwidth, width);
+        XtSetValues(left, args, ONE);
+    } else if (other_width + border_width + skip / 2 < max_width / 2) {
+        /* 'width' (left) is half or more */
+        other_width = max_width - width - 2 * border_width - skip;
+        XtSetArg(args[0], XtNwidth, other_width);
+        XtSetValues(right, args, ONE);
+    } else {
+        ; /* both are exactly half... */
+    }
+
+    /*
      * Finally, set all of the single line widgets to the largest width.
      */
     XtSetArg(args[0], XtNwidth, max_width);
@@ -1061,8 +2259,30 @@ Widget *formp; /* return */
     else
         free((char *) commands);
 
+    /*
+     * If the menu's complete height is too big for the display,
+     * forcing the height to be smaller will cause the vertical
+     * scroll bar (enabled but not forced above) to be included.
+     */
+    screen_height = XHeightOfScreen(XtScreen(popup));
+    screen_height -= appResources.extcmd_height_delta; /* NetHack.ad */
+    if (cumulative_height >= screen_height) {
+        /* 25 is a guesstimate for scrollbar width;
+           window manager might override the request for y==1 */
+        num_args = 0;
+        XtSetArg(args[num_args], XtNy, 1); num_args++;
+        XtSetArg(args[num_args], XtNwidth, max_width + 25); num_args++;
+        XtSetArg(args[num_args], XtNheight, screen_height - 1); num_args++;
+        XtSetValues(popup, args, num_args);
+    }
     XtRealizeWidget(popup);
     XSetWMProtocols(XtDisplay(popup), XtWindow(popup), &wm_delete_window, 1);
 
+    /* during role selection, highlight "random" as pre-selected choice */
+    if (right_callback == ps_random && index(ps_randchars, '\n'))
+        swap_fg_bg(right);
+
     return popup;
 }
+
+/*winmisc.c*/
index 8862f59..bd91010 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 winstat.c       $NHDT-Date: 1432512808 2015/05/25 00:13:28 $  $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
+/* NetHack 3.6 winstat.c       $NHDT-Date: 1452920162 2016/01/16 04:56:02 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
 /* Copyright (c) Dean Luick, 1992                                */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -183,9 +183,9 @@ struct xwindow *wp;
 
 /*
  * This assumes several things:
- *      + Status has only 2 lines
- *      + That both lines are updated in succession in line order.
- *      + We didn't set stringInPlace on the widget.
+ *     + Status has only 2 lines
+ *     + That both lines are updated in succession in line order.
+ *     + We didn't set stringInPlace on the widget.
  */
 void
 adjust_status(wp, str)
@@ -225,8 +225,8 @@ struct X_status_value {
     Widget w;           /* widget of name/value pair */
     long last_value;    /* value displayed */
     int turn_count;     /* last time the value changed */
-    boolean set;        /* if hilighed */
-    boolean after_init; /* don't hilight on first change (init) */
+    boolean set;        /* if highlighted */
+    boolean after_init; /* don't highlight on first change (init) */
 };
 
 /* valid type values */
@@ -240,43 +240,56 @@ static const char *FDECL(width_string, (int));
 static void FDECL(create_widget, (Widget, struct X_status_value *, int));
 static void FDECL(get_widths, (struct X_status_value *, int *, int *));
 static void FDECL(set_widths, (struct X_status_value *, int, int));
-static Widget FDECL(init_column,
-                    (const char *, Widget, Widget, Widget, int *));
+static Widget FDECL(init_column, (const char *, Widget, Widget, Widget,
+                                  int *));
+static void NDECL(fixup_cond_widths);
 static Widget FDECL(init_info_form, (Widget, Widget, Widget));
 
 /*
  * Form entry storage indices.
  */
-#define F_STR 0
-#define F_DEX 1
-#define F_CON 2
-#define F_INT 3
-#define F_WIS 4
-#define F_CHA 5
-
-#define F_NAME 6
-#define F_DLEVEL 7
-#define F_GOLD 8
-#define F_HP 9
-#define F_MAXHP 10
-#define F_POWER 11
-#define F_MAXPOWER 12
-#define F_AC 13
-#define F_LEVEL 14
-#define F_EXP 15
-#define F_ALIGN 16
-#define F_TIME 17
-#define F_SCORE 18
-
-#define F_HUNGER 19
-#define F_CONFUSED 20
-#define F_SICK 21
-#define F_BLIND 22
-#define F_STUNNED 23
-#define F_HALLU 24
-#define F_ENCUMBER 25
-
-#define NUM_STATS 26
+#define F_DUMMY     0
+#define F_STR       1
+#define F_DEX       2
+#define F_CON       3
+#define F_INT       4
+#define F_WIS       5
+#define F_CHA       6
+
+#define F_NAME      7
+#define F_DLEVEL    8
+#define F_GOLD      9
+#define F_HP       10
+#define F_MAXHP    11
+#define F_POWER    12
+#define F_MAXPOWER 13
+#define F_AC       14
+#define F_LEVEL    15
+#define F_EXP      16
+#define F_ALIGN    17
+#define F_TIME     18
+#define F_SCORE    19
+
+/* status conditions grouped by columns; tty orders these differently */
+#define F_STONE    20
+#define F_SLIME    21
+#define F_STRNGL   22
+#define F_FOODPOIS 23
+#define F_TERMILL  24
+
+#define F_HUNGER   25
+#define F_ENCUMBER 26
+#define F_LEV      27
+#define F_FLY      28
+#define F_RIDE     29
+
+#define F_BLIND    30
+#define F_DEAF     31
+#define F_STUN     32
+#define F_CONF     33
+#define F_HALLU    34
+
+#define NUM_STATS 35
 
 /*
  * Notes:
@@ -285,45 +298,39 @@ static Widget FDECL(init_info_form, (Widget, Widget, Widget));
  * + Blank value is 0 and should never change.
  */
 static struct X_status_value shown_stats[NUM_STATS] = {
+    { "", SV_NAME, (Widget) 0, -1, 0, FALSE, FALSE }, /* 0*/
+
 #if 0 /*JP*/
-    { "Strength", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /* 0*/
+    { "Strength", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "Dexterity", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "Constitution", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "Intelligence", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
-    { "Wisdom", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
-    { "Charisma", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /* 5*/
+    { "Wisdom", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /* 5*/
+    { "Charisma", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
+#else /*JP*/
+    { "\8b­\82³",   SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },    /* 0*/
+    { "\91f\91\81\82³", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
+    { "\91Ï\8bv\97Í", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
+    { "\92m\97Í",   SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
+    { "\8c«\82³",   SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
+    { "\96£\97Í",   SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },    /* 5*/
+#endif
 
     { "", SV_LABEL, (Widget) 0, -1, 0, FALSE, FALSE }, /* name */
     { "", SV_LABEL, (Widget) 0, -1, 0, FALSE, FALSE }, /* dlvl */
+#if 0 /*JP*/
     { "Gold", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
-    { "Hit Points", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
-    { "Max HP", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /*10*/
+    { "Hit Points", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /*10*/
+    { "Max HP", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "Power", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "Max Power", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "Armor Class", SV_VALUE, (Widget) 0, 256, 0, FALSE, FALSE },
-    { "Level", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
-    { "Experience", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /*15*/
+    { "Level", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE }, /*15*/
+    { "Experience", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "Alignment", SV_VALUE, (Widget) 0, -2, 0, FALSE, FALSE },
     { "Time", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "Score", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
-
-    { "", SV_NAME, (Widget) 0, -1, 0, FALSE, TRUE },        /* hunger*/
-    { "Confused", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*20*/
-    { "", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },         /* sick */
-    { "Blind", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
-    { "Stunned", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
-    { "Hallucinating", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
-    { "", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*encumbr*/
 #else /*JP*/
-    { "\8b­\82³",   SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },    /* 0*/
-    { "\91f\91\81\82³", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
-    { "\91Ï\8bv\97Í", SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
-    { "\92m\97Í",   SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
-    { "\8c«\82³",   SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
-    { "\96£\97Í",   SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },    /* 5*/
-
-    { "",               SV_LABEL, (Widget) 0, -1, 0, FALSE, FALSE }, /* name */
-    { "",               SV_LABEL, (Widget) 0, -1, 0, FALSE, FALSE }, /* dlvl */
     { "\8bà",             SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "\91Ì\97Í",           SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "\8dÅ\91å\91Ì\97Í",       SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },    /*10*/
@@ -335,15 +342,47 @@ static struct X_status_value shown_stats[NUM_STATS] = {
     { "\91®\90«",           SV_VALUE, (Widget) 0, -2, 0, FALSE, FALSE },
     { "\8e\9e\8aÔ",           SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
     { "\83X\83R\83A",         SV_VALUE, (Widget) 0, -1, 0, FALSE, FALSE },
+#endif
 
-    { "",               SV_NAME,  (Widget) 0, -1, 0, FALSE, TRUE }, /* hunger*/
-    { "\81@\8d¬\97\90\81@",       SV_NAME,  (Widget) 0,  0, 0, FALSE, TRUE },     /*20*/
-    { "\81@\95a\8bC\81@",       SV_NAME,  (Widget) 0,  0, 0, FALSE, TRUE },
-    { "\81@\96Ó\96Ú\81@",       SV_NAME,  (Widget) 0,  0, 0, FALSE, TRUE },
-    { "  á¿\9dò  ",       SV_NAME,  (Widget) 0,  0, 0, FALSE, TRUE },
-    { "\81@\8c\8ao\81@",       SV_NAME,  (Widget) 0,  0, 0, FALSE, TRUE },
-    { "",               SV_NAME,  (Widget) 0,  0, 0, FALSE, TRUE }, /*encumbr*/
-#endif /*JP*/
+#if 0 /*JP*/
+    { "Petrifying", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*20*/
+    { "Slimed", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "Strangled", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "Food Pois", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "Term Ill", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+#else
+    { "\90Î\89»", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*20*/
+    { "\83X\83\89\83C\83\80", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "\92\82\91§", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "\90H\93Å", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "\95a\8bC", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+#endif
+
+    { "", SV_NAME, (Widget) 0, -1, 0, FALSE, TRUE }, /*25*/     /* hunger */
+    { "", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },             /*encumbr */
+#if 0 /*JP*/
+    { "Levitating", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "Flying", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "Riding", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+#else
+    { "\95\82\97V", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "\94ò\8ds", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "\8bR\8fæ", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+#endif
+
+#if 0 /*JP*/
+    { "Blind", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*30*/
+    { "Deaf", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "Stunned", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "Confused", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "Hallucinating", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+#else
+    { "\96Ó\96Ú", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE }, /*30*/
+    { "\8e¨\98W", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "á¿\9dò", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "\8d¬\97\90", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+    { "\8c\8ao", SV_NAME, (Widget) 0, 0, 0, FALSE, TRUE },
+#endif
 };
 
 /*
@@ -405,25 +444,21 @@ long new_value;
     if (attr_rec->type == SV_LABEL) {
         if (attr_rec == &shown_stats[F_NAME]) {
             Strcpy(buf, plname);
-            if ('a' <= buf[0] && buf[0] <= 'z')
-                buf[0] += 'A' - 'a';
-/*JP
+            buf[0] = highc(buf[0]);
+#if 0 /*JP*/
             Strcat(buf, " the ");
-*/
+#else
             Strcat(buf, " ");
-            if (u.mtimedone) {
-                char mname[BUFSZ];
-#if 0 /*JP*/
-                int k = 0;
 #endif
+            if (Upolyd) {
+                char mname[BUFSZ];
+                int k;
 
                 Strcpy(mname, mons[u.umonnum].mname);
-#if 0 /*JP*/
-                while (mname[k] != 0) {
-                    if ((k == 0 || (k > 0 && mname[k - 1] == ' '))
-                        && 'a' <= mname[k] && mname[k] <= 'z')
-                        mname[k] += 'A' - 'a';
-                    k++;
+#if 0 /*JP*//*\83L\83\83\83s\83^\83\89\83C\83Y\95s\97v*/
+                for (k = 0; mname[k] != '\0'; k++) {
+                    if (k == 0 || mname[k - 1] == ' ')
+                        mname[k] = highc(mname[k]);
                 }
 #endif
                 Strcat(buf, mname);
@@ -464,24 +499,6 @@ long new_value;
             XtSetArg(args[0], XtNlabel, hu_stat[new_value]);
         } else if (attr_rec == &shown_stats[F_ENCUMBER]) {
             XtSetArg(args[0], XtNlabel, enc_stat[new_value]);
-        } else if (attr_rec == &shown_stats[F_SICK]) {
-            buf[0] = 0;
-            if (Sick) {
-                if (u.usick_type & SICK_VOMITABLE)
-/*JP
-                    Strcat(buf, "FoodPois");
-*/
-                    Strcat(buf, "\90H\93Å");
-                if (u.usick_type & SICK_NONVOMITABLE) {
-                    if (u.usick_type & SICK_VOMITABLE)
-                        Strcat(buf, " ");
-/*JP
-                    Strcat(buf, "Ill");
-*/
-                    Strcat(buf, "\95a\8bC");
-                }
-            }
-            XtSetArg(args[0], XtNlabel, buf);
         } else if (new_value) {
             XtSetArg(args[0], XtNlabel, attr_rec->name);
         } else {
@@ -556,11 +573,11 @@ long new_value;
         else if (attr_rec == &shown_stats[F_LEVEL]) {
             static boolean lev_was_poly = FALSE;
 
-            if (u.mtimedone && !lev_was_poly) {
+            if (Upolyd && !lev_was_poly) {
                 force_update = TRUE;
                 set_name(attr_rec->w, "HD");
                 lev_was_poly = TRUE;
-            } else if (!u.mtimedone && lev_was_poly) {
+            } else if (Upolyd && lev_was_poly) {
                 force_update = TRUE;
                 set_name(attr_rec->w, shown_stats[F_LEVEL].name);
                 lev_was_poly = FALSE;
@@ -568,17 +585,17 @@ long new_value;
         } else if (attr_rec == &shown_stats[F_EXP]) {
             static boolean exp_was_poly = FALSE;
 
-            if (u.mtimedone && !exp_was_poly) {
+            if (Upolyd && !exp_was_poly) {
                 force_update = TRUE;
                 set_name(attr_rec->w, "");
                 set_value(attr_rec->w, "");
                 exp_was_poly = TRUE;
-            } else if (!u.mtimedone && exp_was_poly) {
+            } else if (Upolyd && exp_was_poly) {
                 force_update = TRUE;
                 set_name(attr_rec->w, shown_stats[F_EXP].name);
                 exp_was_poly = FALSE;
             }
-            if (u.mtimedone)
+            if (Upolyd)
                 return; /* no display for exp when poly */
         }
 
@@ -645,13 +662,16 @@ long new_value;
  * the other.  So only do our update when we update the second line.
  *
  * Information on the first line:
- *      name, attributes, alignment, score
+ *     name, attributes, alignment, score
  *
  * Information on the second line:
- *      dlvl, gold, hp, power, ac, {level & exp or HD **}
- *      status (hunger, conf, halu, stun, sick, blind), time, encumbrance
+ *     dlvl, gold, hp, power, ac, {level & exp or HD **}, time,
+ *     status * (stone, slime, strngl, foodpois, termill,
+ *                hunger, encumbrance, lev, fly, ride,
+ *                blind, deaf, stun, conf, hallu)
  *
- * [**] HD is shown instead of level and exp if mtimedone is non-zero.
+ *  [*] order of status fields is different on tty.
+ * [**] HD is shown instead of level and exp if Upolyd.
  */
 static void
 update_fancy_status(wp)
@@ -666,6 +686,9 @@ struct xwindow *wp;
 
     for (i = 0, sv = shown_stats; i < NUM_STATS; i++, sv++) {
         switch (i) {
+        case F_DUMMY:
+            val = 0L;
+            break;
         case F_STR:
             val = (long) ACURR(A_STR);
             break;
@@ -692,23 +715,49 @@ struct xwindow *wp;
         case F_HUNGER:
             val = (long) u.uhs;
             break;
-        case F_CONFUSED:
-            val = (long) Confusion ? 1L : 0L;
+        case F_ENCUMBER:
+            val = (long) near_capacity();
+            break;
+        case F_LEV:
+            val = Levitation ? 1L : 0L;
             break;
-        case F_SICK:
-            val = (long) Sick ? (long) u.usick_type : 0L;
+        case F_FLY:
+            val = Flying ? 1L : 0L;
             break;
+        case F_RIDE:
+            val = u.usteed ? 1L : 0L;
+            break;
+        /* fatal status conditions */
+        case F_STONE:
+            val = Stoned ? 1L : 0L;
+            break;
+        case F_SLIME:
+            val = Slimed ? 1L : 0L;
+            break;
+        case F_STRNGL:
+            val = Strangled ? 1L : 0L;
+            break;
+        case F_FOODPOIS:
+            val = (Sick && (u.usick_type & SICK_VOMITABLE)) ? 1L : 0L;
+            break;
+        case F_TERMILL:
+            val = (Sick && (u.usick_type & SICK_NONVOMITABLE)) ? 1L : 0L;
+            break;
+        /* non-fatal status conditions */
         case F_BLIND:
-            val = (long) Blind ? 1L : 0L;
+            val = Blind ? 1L : 0L;
             break;
-        case F_STUNNED:
-            val = (long) Stunned ? 1L : 0L;
+        case F_DEAF:
+            val = Deaf ? 1L : 0L;
             break;
-        case F_HALLU:
-            val = (long) Hallucination ? 1L : 0L;
+        case F_STUN:
+            val = Stunned ? 1L : 0L;
             break;
-        case F_ENCUMBER:
-            val = (long) near_capacity();
+        case F_CONF:
+            val = Confusion ? 1L : 0L;
+            break;
+        case F_HALLU:
+            val = Hallucination ? 1L : 0L;
             break;
 
         case F_NAME:
@@ -719,13 +768,15 @@ struct xwindow *wp;
             break; /* special */
         case F_GOLD:
             val = money_cnt(invent);
+            if (val < 0L)
+                val = 0L; /* ought to issue impossible() and discard gold */
             break;
         case F_HP:
-            val = (long) (u.mtimedone ? (u.mh > 0 ? u.mh : 0)
-                                      : (u.uhp > 0 ? u.uhp : 0));
+            val = (long) (Upolyd ? (u.mh > 0 ? u.mh : 0)
+                                 : (u.uhp > 0 ? u.uhp : 0));
             break;
         case F_MAXHP:
-            val = (long) (u.mtimedone ? u.mhmax : u.uhpmax);
+            val = (long) (Upolyd ? u.mhmax : u.uhpmax);
             break;
         case F_POWER:
             val = (long) u.uen;
@@ -737,7 +788,7 @@ struct xwindow *wp;
             val = (long) u.uac;
             break;
         case F_LEVEL:
-            val = (long) (u.mtimedone ? mons[u.umonnum].mlevel : u.ulevel);
+            val = (long) (Upolyd ? mons[u.umonnum].mlevel : u.ulevel);
             break;
         case F_EXP:
             val = flags.showexp ? u.uexp : 0L;
@@ -748,34 +799,33 @@ struct xwindow *wp;
         case F_TIME:
             val = flags.time ? (long) moves : 0L;
             break;
-#ifdef SCORE_ON_BOTL
         case F_SCORE:
+#ifdef SCORE_ON_BOTL
             val = flags.showscore ? botl_score() : 0L;
-            break;
 #else
-        case F_SCORE:
             val = 0L;
-            break;
 #endif
+            break;
         default: {
             /*
              * There is a possible infinite loop that occurs with:
              *
-             *  impossible->pline->flush_screen->bot->bot{1,2}->
-             *  putstr->adjust_status->update_other->impossible
+             *         impossible->pline->flush_screen->bot->bot{1,2}->
+             *         putstr->adjust_status->update_other->impossible
              *
              * Break out with this.
              */
             static boolean active = FALSE;
+
             if (!active) {
                 active = TRUE;
                 impossible("update_other: unknown shown value");
                 active = FALSE;
             }
-            val = 0;
+            val = 0L;
             break;
-        }
-        }
+        } /* default */
+        } /* switch */
         update_val(sv, val);
     }
 }
@@ -812,6 +862,9 @@ width_string(sv_index)
 int sv_index;
 {
     switch (sv_index) {
+    case F_DUMMY:
+        return " ";
+
     case F_STR:
         return "018/**";
     case F_DEX:
@@ -822,19 +875,24 @@ int sv_index;
         return "088"; /* all but str never get bigger */
 
     case F_HUNGER:
-        return shown_stats[F_HUNGER].name;
-    case F_CONFUSED:
-        return shown_stats[F_CONFUSED].name;
-    case F_SICK:
-        return shown_stats[F_SICK].name;
+        return "Satiated";
+    case F_ENCUMBER:
+        return "Overloaded";
+
+    case F_LEV:
+    case F_FLY:
+    case F_RIDE:
+    case F_STONE:
+    case F_SLIME:
+    case F_STRNGL:
+    case F_FOODPOIS:
+    case F_TERMILL:
     case F_BLIND:
-        return shown_stats[F_BLIND].name;
-    case F_STUNNED:
-        return shown_stats[F_STUNNED].name;
+    case F_DEAF:
+    case F_STUN:
+    case F_CONF:
     case F_HALLU:
-        return shown_stats[F_HALLU].name;
-    case F_ENCUMBER:
-        return shown_stats[F_ENCUMBER].name;
+        return shown_stats[sv_index].name;
 
     case F_NAME:
     case F_DLEVEL:
@@ -844,20 +902,20 @@ int sv_index;
         return "9999";
     case F_POWER:
     case F_MAXPOWER:
-        return "999";
+        return "9999";
     case F_AC:
-        return "-99";
+        return "-127";
     case F_LEVEL:
         return "99";
     case F_GOLD:
+        /* strongest hero can pick up roughly 30% of this much */
+        return "999999"; /* same limit as tty */
     case F_EXP:
-        return "4294967295"; /* max ulong */
-    case F_ALIGN:
-        return "Neutral";
     case F_TIME:
-        return "4294967295"; /* max ulong */
     case F_SCORE:
-        return "4294967295"; /* max ulong */
+        return "123456789"; /* a tenth digit will still fit legibly */
+    case F_ALIGN:
+        return "Neutral";
     }
     impossible("width_string: unknown index %d\n", sv_index);
     return "";
@@ -888,25 +946,23 @@ int sv_index;
         num_args++;
         XtSetArg(args[num_args], XtNinternalHeight, 0);
         num_args++;
-/*JP*/
 #if defined(X11R6) && defined(XI18N)
         XtSetArg(args[num_args], XtNinternational, True);
         num_args++;
 #endif
-        sv->w =
-            XtCreateManagedWidget(sv_index == F_NAME ? "name" : "dlevel",
-                                  labelWidgetClass, parent, args, num_args);
+        sv->w = XtCreateManagedWidget((sv_index == F_NAME)
+                                         ? "name"
+                                         : "dlevel",
+                                      labelWidgetClass, parent,
+                                      args, num_args);
         break;
     case SV_NAME:
         num_args = 0;
-        XtSetArg(args[num_args], XtNborderWidth, 0);
-        num_args++;
-        XtSetArg(args[num_args], XtNinternalHeight, 0);
-        num_args++;
-/*JP*/
+        XtSetArg(args[0], XtNlabel, width_string(sv_index)); num_args++;
+        XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
+        XtSetArg(args[num_args], XtNinternalHeight, 0); num_args++;
 #if defined(X11R6) && defined(XI18N)
-        XtSetArg(args[num_args], XtNinternational, True);
-        num_args++;
+        XtSetArg(args[num_args], XtNinternational, True); num_args++;
 #endif
         sv->w = XtCreateManagedWidget(sv->name, labelWidgetClass, parent,
                                       args, num_args);
@@ -917,7 +973,7 @@ int sv_index;
 }
 
 /*
- * Get current width of value.  width2p is only valid for SV_LABEL types.
+ * Get current width of value.  width2p is only valid for SV_VALUE types.
  */
 static void
 get_widths(sv, width1p, width2p)
@@ -990,8 +1046,8 @@ int *col_indices;
     }
     XtSetArg(args[num_args], nhStr(XtNdefaultDistance), 0);
     num_args++;
-    form =
-        XtCreateManagedWidget(name, formWidgetClass, parent, args, num_args);
+    form = XtCreateManagedWidget(name, formWidgetClass, parent,
+                                 args, num_args);
 
     max_width1 = max_width2 = 0;
     for (ip = col_indices; *ip >= 0; ip++) {
@@ -1026,27 +1082,41 @@ int *col_indices;
  * indicates the end of the column.  The two numbers after that are used
  * to store widths that are calculated at run-time.
  */
-static int attrib_indices[] = { F_STR, F_DEX, F_CON, F_INT, F_WIS,
-                                F_CHA, -1,    0,     0 };
-static int status_indices[] = { F_HUNGER,  F_CONFUSED, F_SICK,     F_BLIND,
-                                F_STUNNED, F_HALLU,    F_ENCUMBER, -1,
-                                0,         0 };
-
-static int col2_indices[] = { F_MAXHP,    F_ALIGN, F_TIME, F_EXP,
-                              F_MAXPOWER, -1,      0,      0 };
-static int col1_indices[] = { F_HP,    F_AC, F_GOLD, F_LEVEL, F_POWER,
-                              F_SCORE, -1,   0,      0 };
-
+static int attrib_indices[] = { F_STR, F_DEX, F_CON, F_INT, F_WIS, F_CHA,
+                                -1, 0, 0 };
+/* including F_DUMMY makes the three status condition columns evenly
+   spaced with regard to the adjacent characteristics (Str,Dex,&c) column;
+   we lose track of the Widget pointer for them, each use clobbering the
+   one before, leaving the one from leftover_indices[]; since they're never
+   updated, that shouldn't matter */
+static int status_indices[3][9] = { { F_STONE, F_SLIME, F_STRNGL,
+                                      F_FOODPOIS, F_TERMILL, F_DUMMY,
+                                      -1, 0, 0 },
+                                    { F_HUNGER, F_ENCUMBER,
+                                      F_LEV, F_FLY, F_RIDE, F_DUMMY,
+                                      -1, 0, 0 },
+                                    { F_BLIND, F_DEAF, F_STUN,
+                                      F_CONF, F_HALLU, F_DUMMY,
+                                      -1, 0, 0 } };
+/* used to fill up the empty space to right of 3rd status condition column */
+static int leftover_indices[] = { F_DUMMY, -1, 0, 0 };
+
+static int col1_indices[] = { F_HP,    F_POWER,    F_AC,    F_LEVEL, F_GOLD,
+                              F_SCORE, -1, 0, 0 };
+static int col2_indices[] = { F_MAXHP, F_MAXPOWER, F_ALIGN, F_EXP,   F_TIME,
+                              -1, 0, 0 };
 /*
  * Produce a form that looks like the following:
  *
- *                 name
- *                dlevel
- * col1_indices[0]      col2_indices[0]
- * col1_indices[1]      col2_indices[1]
- *    .             .
- *    .             .
- * col1_indices[n]      col2_indices[n]
+ *                name
+ *               dlevel
+ * col1_indices[0]     col2_indices[0]
+ * col1_indices[1]     col2_indices[1]
+ *    .                    .
+ *    .                    .
+ * col1_indices[n]     col2_indices[n]
+ *
+ * TODO:  increase the space between the two columns.
  */
 static Widget
 init_info_form(parent, top, left)
@@ -1108,6 +1178,40 @@ Widget parent, top, left;
     return form;
 }
 
+/* give the three status condition columns the same width */
+static void
+fixup_cond_widths()
+{
+    int pass, i, *ip, w1, w2;
+
+    w1 = w2 = 0;
+    for (pass = 1; pass <= 2; ++pass) { /* two passes... */
+        for (i = 0; i < 3; i++) { /* three columns */
+            for (ip = status_indices[i]; *ip != -1; ++ip) { /* X fields */
+                /* pass 1: find -1;  pass 2: update field widths, find -1 */
+                if (pass == 2)
+                    set_widths(&shown_stats[*ip], w1, w2);
+            }
+            /* found -1; the two slots beyond it contain column widths */
+            if (pass == 1) { /* pass 1: collect maxima */
+                if (ip[1] > w1)
+                    w1 = ip[1];
+                if (ip[2] > w2)
+                    w2 = ip[2];
+            } else { /* pass 2: update column widths with maxima */
+                ip[1] = w1;
+                ip[2] = w2;
+            }
+        }
+        /* ascetics:  expand the maximum width to make cond columns wider */
+        if (pass == 1) {
+            w1 += 20;
+            if (w2 > 0)
+                w2 += 20;
+        }
+    }
+}
+
 /*
  * Create the layout for the fancy status.  Return a form widget that
  * contains everything.
@@ -1120,6 +1224,8 @@ Widget parent, top;
     Widget w;
     Arg args[8];
     Cardinal num_args;
+    char buf[32];
+    int i;
 
     num_args = 0;
     if (top != (Widget) 0) {
@@ -1137,8 +1243,13 @@ Widget parent, top;
 
     w = init_info_form(form, (Widget) 0, (Widget) 0);
     w = init_column("status_attributes", form, (Widget) 0, w, attrib_indices);
-    (void) init_column("status_condition", form, (Widget) 0, w,
-                       status_indices);
+    for (i = 0; i < 3; i++) {
+        Sprintf(buf, "status_condition%d", i + 1);
+        w = init_column(buf, form, (Widget) 0, w, status_indices[i]);
+    }
+    fixup_cond_widths(); /* make all 3 status_conditionN columns same width */
+    w = init_column("status_leftover", form, (Widget) 0, w, leftover_indices);
+    nhUse(w);
     return form;
 }
 
index 7d8b0bf..61f4834 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 wintext.c       $NHDT-Date: 1432512807 2015/05/25 00:13:27 $  $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */
+/* NetHack 3.6 wintext.c       $NHDT-Date: 1450453309 2015/12/18 15:41:49 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $ */
 /* Copyright (c) Dean Luick, 1992                                */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -247,7 +247,7 @@ boolean blocking;
     if (width
         > (Dimension) XtScreen(wp->w)->width) { /* too wide for screen */
         /* Back off some amount - we really need to back off the scrollbar */
-        /* width plus some extra.                                          */
+        /* width plus some extra.                                         */
         width = XtScreen(wp->w)->width - 20;
     }
     XtSetArg(args[num_args], XtNstring, text_info->text.text);
@@ -546,7 +546,7 @@ calculate_rip_text(int how, time_t when)
     /* Put $ on stone */
     Sprintf(rip_line[GOLD_LINE], "%ld Au", done_money);
     /* Put together death description */
-    formatkiller(buf, sizeof buf, how);
+    formatkiller(buf, sizeof buf, how, FALSE);
 
     /* Put death type on stone */
     for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; line++) {
index efa26b5..c3cdfe2 100644 (file)
@@ -169,7 +169,7 @@ Widget w;
 }
 
 /* Swap foreground and background colors (this is the best I can do with */
-/* a label widget, unless I can get some init hook in there).            */
+/* a label widget, unless I can get some init hook in there).           */
 void
 hilight_value(w)
 Widget w;
index 66362bd..bd0a118 100644 (file)
@@ -462,7 +462,6 @@ boolean is_restoring;
     (*cibase->nprocs->win_putmsghistory)(cibase->ndata, msg, is_restoring);
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
 void
 chainin_status_init()
 {
@@ -487,29 +486,15 @@ boolean enable;
 }
 
 void
-chainin_status_update(idx, ptr, chg, percent)
-int idx, chg, percent;
+chainin_status_update(idx, ptr, chg, percent, color, colormasks)
+int idx, chg, percent, color;
 genericptr_t ptr;
+unsigned long *colormasks;
 {
     (*cibase->nprocs->win_status_update)(cibase->ndata, idx, ptr, chg,
-                                         percent);
+                                         percent, color, colormasks);
 }
 
-#ifdef STATUS_HILITES
-void
-chainin_status_threshold(fldidx, thresholdtype, threshold, behavior, under,
-                         over)
-int fldidx, thresholdtype;
-int behavior, under, over;
-anything threshold;
-{
-    (*cibase->nprocs->win_status_threshold)(cibase->ndata, fldidx,
-                                            thresholdtype, threshold,
-                                            behavior, under, over);
-}
-#endif
-#endif
-
 boolean
 chainin_can_suspend()
 {
@@ -561,12 +546,7 @@ struct window_procs chainin_procs = {
 
     chainin_outrip, chainin_preference_update, chainin_getmsghistory,
     chainin_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     chainin_status_init, chainin_status_finish, chainin_status_enablefield,
     chainin_status_update,
-#ifdef STATUS_HILITES
-    chainin_status_threshold,
-#endif
-#endif
     chainin_can_suspend,
 };
index 85b2651..af96443 100644 (file)
@@ -586,7 +586,6 @@ boolean is_restoring;
     (*tdp->nprocs->win_putmsghistory)(msg, is_restoring);
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
 void
 chainout_status_init(vp)
 void *vp;
@@ -619,33 +618,17 @@ boolean enable;
 }
 
 void
-chainout_status_update(vp, idx, ptr, chg, percent)
+chainout_status_update(vp, idx, ptr, chg, percent, color, colormasks)
 void *vp;
-int idx, chg, percent;
+int idx, chg, percent, color;
 genericptr_t ptr;
+unsigned long *colormasks;
 {
     struct chainout_data *tdp = vp;
 
-    (*tdp->nprocs->win_status_update)(idx, ptr, chg, percent);
+    (*tdp->nprocs->win_status_update)(idx, ptr, chg, percent, color, colormasks);
 }
 
-#ifdef STATUS_HILITES
-void
-chainout_status_threshold(vp, fldidx, thresholdtype, threshold, behavior,
-                          under, over)
-void *vp;
-int fldidx, thresholdtype;
-int behavior, under, over;
-anything threshold;
-{
-    struct chainout_data *tdp = vp;
-
-    (*tdp->nprocs->win_status_threshold)(fldidx, thresholdtype, threshold,
-                                         behavior, under, over);
-}
-#endif
-#endif
-
 boolean
 chainout_can_suspend(vp)
 void *vp;
@@ -700,12 +683,7 @@ struct chain_procs chainout_procs = {
 
     chainout_outrip, chainout_preference_update, chainout_getmsghistory,
     chainout_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     chainout_status_init, chainout_status_finish, chainout_status_enablefield,
     chainout_status_update,
-#ifdef STATUS_HILITES
-    chainout_status_threshold,
-#endif
-#endif
     chainout_can_suspend,
 };
index 9073e06..ec81f0a 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 wc_trace.c      $NHDT-Date: 1433806611 2015/06/08 23:36:51 $  $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */
+/* NetHack 3.6 wc_trace.c      $NHDT-Date: 1501464799 2017/07/31 01:33:19 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.8 $ */
 /* Copyright (c) Kenneth Lorber, 2012                            */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -10,7 +10,7 @@
 #include <errno.h>
 
 FILE *wc_tracelogf; /* Should be static, but it's just too useful to have
-             * access to this logfile from arbitrary other files. */
+                     * access to this logfile from arbitrary other files. */
 static unsigned int indent_level; /* Some winfuncs call other winfuncs, so
                                    * we need to support nesting. */
 
@@ -560,7 +560,7 @@ char *posbar;
         fprintf(wc_tracelogf, "%supdate_positionbar('%s'(%d))\n", INDENT,
                 posbar, (int) strlen(posbar));
     } else {
-        fprintf(wc_tracelogf, "%supdate_positionbar(NULL)\n");
+        fprintf(wc_tracelogf, "%supdate_positionbar(NULL)\n", INDENT);
     }
     PRE;
     (*tdp->nprocs->win_update_positionbar)(tdp->ndata, posbar);
@@ -901,7 +901,7 @@ void *vp;
     struct trace_data *tdp = vp;
     char *rv;
 
-    fprintf(wc_tracelogf, "%sget_color_string()\n");
+    fprintf(wc_tracelogf, "%sget_color_string()\n", INDENT);
 
     PRE;
     rv = (*tdp->nprocs->win_get_color_string)(tdp->ndata);
@@ -911,7 +911,7 @@ void *vp;
         fprintf(wc_tracelogf, "%s=> '%s'(%d)\n", INDENT, rv,
                 (int) strlen(rv));
     } else {
-        fprintf(wc_tracelogf, "%s=> NULL\n");
+        fprintf(wc_tracelogf, "%s=> NULL\n", INDENT);
     }
 
     return rv;
@@ -1027,7 +1027,6 @@ boolean is_restoring;
     POST;
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
 void
 trace_status_init(vp)
 void *vp;
@@ -1084,10 +1083,11 @@ boolean enable;
 }
 
 void
-trace_status_update(vp, idx, ptr, chg, percent)
+trace_status_update(vp, idx, ptr, chg, percent, color, colormasks)
 void *vp;
-int idx, chg, percent;
+int idx, chg, percent, color;
 genericptr_t ptr;
+unsigned long *colormasks;
 {
     struct trace_data *tdp = vp;
 
@@ -1095,33 +1095,10 @@ genericptr_t ptr;
             ptr, chg, percent);
 
     PRE;
-    (*tdp->nprocs->win_status_update)(tdp->ndata, idx, ptr, chg, percent);
+    (*tdp->nprocs->win_status_update)(tdp->ndata, idx, ptr, chg, percent, color, colormasks);
     POST;
 }
 
-#ifdef STATUS_HILITES
-void
-trace_status_threshold(vp, fldidx, thresholdtype, threshold, behavior, under,
-                       over)
-void *vp;
-int fldidx, thresholdtype;
-int behavior, under, over;
-anything threshold;
-{
-    struct trace_data *tdp = vp;
-
-    /* XXX how do we print an anything?  We don't. */
-    fprintf(wc_tracelogf, "%sstatus_threshold(%d, %d, -, %d, %d, %d)\n",
-            INDENT, fldidx, thresholdtype, behavior, under, over);
-
-    PRE;
-    (*tdp->nprocs->win_status_threshold)(tdp->ndata, fldidx, thresholdtype,
-                                         threshold, behavior, under, over);
-    POST;
-}
-#endif
-#endif
-
 boolean
 trace_can_suspend(vp)
 void *vp;
@@ -1179,12 +1156,7 @@ struct chain_procs trace_procs = {
 
     trace_outrip, trace_preference_update, trace_getmsghistory,
     trace_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     trace_status_init, trace_status_finish, trace_status_enablefield,
     trace_status_update,
-#ifdef STATUS_HILITES
-    trace_status_threshold,
-#endif
-#endif
     trace_can_suspend,
 };
index 33b3702..8cd33ca 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 wingem.c        $NHDT-Date: 1433806613 2015/06/08 23:36:53 $  $NHDT-Branch: master $:$NHDT-Revision: 1.25 $ */
+/* NetHack 3.6 wingem.c        $NHDT-Date: 1450453304 2015/12/18 15:41:44 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.26 $ */
 /* Copyright (c) Christian Bressler, 1999 */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -70,13 +70,8 @@ struct window_procs Gem_procs = {
     /* other defs that really should go away (they're tty specific) */
     Gem_start_screen, Gem_end_screen, Gem_outrip, Gem_preference_update,
     genl_getmsghistory, genl_putmsghistory
-#ifdef STATUS_VIA_WINDOWPORT
                             genl_status_init,
     genl_status_finish, genl_status_enablefield, genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_no,
 };
 
@@ -129,7 +124,7 @@ const char *mesg;
 {
     clearlocks();
     Gem_exit_nhwindows(mesg);
-    terminate(EXIT_SUCCESS);
+    nh_terminate(EXIT_SUCCESS);
     /*NOTREACHED*/
 }
 
@@ -1083,7 +1078,7 @@ time_t when;
     /* Put $ on stone */
     Sprintf(rip_line[GOLD_LINE], "%ld Au", done_money);
     /* Put together death description */
-    formatkiller(buf, sizeof buf, how);
+    formatkiller(buf, sizeof buf, how, FALSE);
 
     /* Put death type on stone */
     for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; line++) {
index cc40bb1..bc35214 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 gnbind.c        $NHDT-Date: 1433806614 2015/06/08 23:36:54 $  $NHDT-Branch: master $:$NHDT-Revision: 1.32 $ */
+/* NetHack 3.6 gnbind.c        $NHDT-Date: 1450453305 2015/12/18 15:41:45 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.33 $ */
 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -48,13 +48,8 @@ struct window_procs Gnome_procs = {
     /* other defs that really should go away (they're tty specific) */
     gnome_start_screen, gnome_end_screen, gnome_outrip,
     genl_preference_update, genl_getmsghistory, genl_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     genl_status_init, genl_status_finish, genl_status_enablefield,
     genl_status_update,
-#ifdef STATUS_HILITES
-    genl_status_threshold,
-#endif
-#endif
     genl_can_suspend_yes,
 };
 
@@ -1182,7 +1177,7 @@ gnome_outrip(winid wid, int how, time_t when)
     Strcat(ripString, buf);
 
     /* Put together death description */
-    formatkiller(buf, sizeof buf, how);
+    formatkiller(buf, sizeof buf, how, FALSE);
 
     /* Put death type on stone */
     Strcat(ripString, buf);
index 04260d9..28879c0 100644 (file)
@@ -1,5 +1,5 @@
 #!/usr/bin/osascript
-# NetHack 3.6.0  NetHackGuidebook.applescript $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# NetHack 3.6.1  NetHackGuidebook.applescript $NHDT-Date: 1524684596 2018/04/25 19:29:56 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.8 $
 # Copyright (c) Kenneth Lorber, Kensington, Maryland, 2011
 # NetHack may be freely redistributed.  See license for details.
 
index 31c518e..c1db101 100644 (file)
@@ -1,5 +1,5 @@
 #!/usr/bin/osascript
-# NetHack 3.6  NetHackRecover.applescript $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# NetHack 3.6  NetHackRecover.applescript $NHDT-Date: 1524684596 2018/04/25 19:29:56 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.9 $
 # Copyright (c) Kenneth Lorber, Kensington, Maryland, 2009
 # NetHack may be freely redistributed.  See license for details. 
 
index 127b2c2..f1d1eb1 100644 (file)
@@ -1,5 +1,5 @@
 #!/usr/bin/osascript
-# NetHack 3.6.0  NetHackTerm.applescript $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# NetHack 3.6.1  NetHackTerm.applescript $NHDT-Date: 1524684597 2018/04/25 19:29:57 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.8 $
 # Copyright (c) Kenneth Lorber, Kensington, Maryland, 2011
 # NetHack may be freely redistributed.  See license for details.
 
index e14aafb..bb66c8d 100644 (file)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 
-# NetHack 3.6  recover.pl $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# NetHack 3.6  recover.pl $NHDT-Date: 1524684612 2018/04/25 19:30:12 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.12 $
 # Copyright (c) Kenneth Lorber, Kensington, Maryland, 2009
 # NetHack may be freely redistributed.  See license for details.
 
diff --git a/win/share/bmptiles.c b/win/share/bmptiles.c
new file mode 100644 (file)
index 0000000..6414159
--- /dev/null
@@ -0,0 +1,622 @@
+/* NetHack 3.6    bmptiles.c    $NHDT-Date: 1457207054 2016/03/05 19:44:14 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.0 $ */
+/* Copyright (c) Ray Chason, 2016. */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#include "config.h"
+#include "integer.h"
+#include "tileset.h"
+
+/* First BMP file header */
+struct BitmapHeader {
+    char magic[2];
+    uint32 bmp_size;
+    uint32 img_offset;
+};
+
+/* Color model information for larger BMP headers */
+struct CIE_XYZ {
+    uint32 ciexyzX;
+    uint32 ciexyzY;
+    uint32 ciexyzZ;
+};
+
+struct CIE_XYZTriple {
+    struct CIE_XYZ ciexyzRed;
+    struct CIE_XYZ ciexyzGreen;
+    struct CIE_XYZ ciexyzBlue;
+};
+
+/* Second BMP file header */
+/* This one can vary in size; contents can vary according to the size */
+struct BitmapInfoHeader {
+    uint32 Size;                    /* 12 40 52 56 108 124 64 */
+    int32  Width;                   /* 12 40 52 56 108 124 64 */
+    int32  Height;                  /* 12 40 52 56 108 124 64 */
+    uint16 NumPlanes;               /* 12 40 52 56 108 124 64 */
+    uint16 BitsPerPixel;            /* 12 40 52 56 108 124 64 */
+    uint32 Compression;             /*    40 52 56 108 124 64 */
+    uint32 ImageDataSize;           /*    40 52 56 108 124 64 */
+    int32  XResolution;             /*    40 52 56 108 124 64 */
+    int32  YResolution;             /*    40 52 56 108 124 64 */
+    uint32 ColorsUsed;              /*    40 52 56 108 124 64 */
+    uint32 ColorsImportant;         /*    40 52 56 108 124 64 */
+    uint32 RedMask;                 /*       52 56 108 124 */
+    uint32 GreenMask;               /*       52 56 108 124 */
+    uint32 BlueMask;                /*       52 56 108 124 */
+    uint32 AlphaMask;               /*          56 108 124 */
+    uint32 CSType;                  /*             108 124 */
+    struct CIE_XYZTriple Endpoints; /*             108 124 */
+    uint32 GammaRed;                /*             108 124 */
+    uint32 GammaGreen;              /*             108 124 */
+    uint32 GammaBlue;               /*             108 124 */
+    uint32 Intent;                  /*                 124 */
+    uint32 ProfileData;             /*                 124 */
+    uint32 ProfileSize;             /*                 124 */
+};
+/* Compression */
+#define BI_RGB           0
+#define BI_RLE8          1
+#define BI_RLE4          2
+#define BI_BITFIELDS     3
+#define BI_JPEG          4
+#define BI_PNG           5
+
+static uint16 FDECL(read_u16, (const unsigned char buf[2]));
+static uint32 FDECL(read_u32, (const unsigned char buf[4]));
+static int32 FDECL(read_s32, (const unsigned char buf[4]));
+static struct Pixel FDECL(build_pixel, (const struct BitmapInfoHeader *, uint32));
+static unsigned char FDECL(pixel_element, (uint32, uint32));
+static boolean FDECL(read_header, (FILE *, struct BitmapHeader *));
+static boolean FDECL(read_info_header, (FILE *, struct BitmapInfoHeader *));
+static boolean FDECL(check_info_header, (const struct BitmapInfoHeader *));
+static unsigned FDECL(get_palette_size, (const struct BitmapInfoHeader *));
+static boolean FDECL(read_palette, (FILE *, struct Pixel *, unsigned));
+
+/* Read a .BMP file into the image structure */
+/* Return TRUE if successful, FALSE on any error */
+boolean
+read_bmp_tiles(filename, image)
+const char *filename;
+struct TileSetImage *image;
+{
+    struct BitmapHeader header1;
+    struct BitmapInfoHeader header2;
+    unsigned palette_size;
+    size_t num_pixels, size;
+    unsigned x, y, y_start, y_end, y_inc;
+    unsigned bytes_per_row;
+
+    FILE *fp = NULL; /* custodial */
+    unsigned char *row_bytes = NULL; /* custodial */
+
+    image->width = 0;
+    image->height = 0;
+    image->pixels = NULL;       /* custodial, returned */
+    image->indexes = NULL;      /* custodial, returned */
+    image->image_desc = NULL;   /* custodial, returned */
+    image->tile_width = 0;
+    image->tile_height = 0;
+
+    fp = fopen(filename, "rb");
+    if (fp == NULL) goto error;
+
+    /* Read the headers */
+    if (!read_header(fp, &header1)) goto error;
+    if (memcmp(header1.magic, "BM", 2) != 0) goto error;
+
+    if (!read_info_header(fp, &header2)) goto error;
+    if (!check_info_header(&header2)) goto error;
+
+#if 0 /* TODO */
+    if (header2.Compression == BI_PNG) {
+        /* Image data is an embedded PNG bit stream */
+        boolean ok = do_read_png_tiles(fp, image));
+        fclose(fp);
+        return ok;
+    }
+#endif
+
+    /* header2.Height < 0 means the Y coordinate is reversed; the origin is
+     * top left rather than bottom left */
+    image->width = header2.Width;
+    image->height = labs(header2.Height);
+
+    /* Allocate pixel area; watch out for overflow */
+    num_pixels = (size_t) image->width * (size_t) image->height;
+    if (num_pixels / image->width != image->height) goto error; /* overflow */
+    size = num_pixels * sizeof(image->pixels[0]);
+    if (size / sizeof(image->pixels[0]) != num_pixels) goto error; /* overflow */
+    image->pixels = (struct Pixel *) alloc(size);
+    if (header2.BitsPerPixel <= 8) {
+        image->indexes = (unsigned char *) alloc(num_pixels);
+    }
+
+    /* Read the palette */
+    palette_size = get_palette_size(&header2);
+    if (!read_palette(fp, image->palette, palette_size)) goto error;
+
+    /* Read the pixels */
+    fseek(fp, header1.img_offset, SEEK_SET);
+    if (header2.Height < 0) {
+        y_start = 0;
+        y_end = image->height;
+        y_inc = 1;
+    } else {
+        y_start = image->height - 1;
+        y_end = (unsigned) -1;
+        y_inc = -1;
+    }
+    if (header2.Compression == BI_RLE4 || header2.Compression == BI_RLE8) {
+        unsigned char *p;
+        p = image->indexes;
+        memset(p, 0, num_pixels);
+        x = 0;
+        y = image->height - 1;
+        while (TRUE) {
+            int b1, b2;
+            b1 = fgetc(fp);
+            if (b1 == EOF) goto error;
+            b2 = fgetc(fp);
+            if (b2 == EOF) goto error;
+            /*
+             * b1  b2
+             *  0   0   end of line
+             *  0   1   end of bitmap
+             *  0   2   next two bytes are x and y offset
+             *  0  >2   b2 is a count of bytes
+             * >0  any  repeat b2, b1 times
+             */
+            if (b1 == 0) {
+                if (b2 == 0) {
+                    /* end of line */
+                    --y;
+                    x = 0;
+                } else if (b2 == 1) {
+                    /* end of bitmap */
+                    break;
+                } else if (b2 == 2) {
+                    /* next two bytes are x and y offset */
+                    b1 = fgetc(fp);
+                    if (b1 == EOF) break;
+                    b2 = fgetc(fp);
+                    if (b2 == EOF) break;
+                    x += b1;
+                    y += b2;
+                } else {
+                    /* get bytes */
+                    int i;
+                    if (y < image->height) {
+                        p = image->indexes + y * image->width;
+                        for (i = 0; i < b2; ++i) {
+                            b1 = fgetc(fp);
+                            if (b1 == EOF) break;
+                            if (header2.BitsPerPixel == 8) {
+                                if (x < image->width) {
+                                    p[x] = b1;
+                                }
+                                ++x;
+                            } else {
+                                if (x < image->width) {
+                                    p[x] = b1 >> 4;
+                                }
+                                ++x;
+                                if (x < image->width) {
+                                    p[x] = b1 & 0xF;
+                                }
+                                ++x;
+                            }
+                        }
+                        if (b2 & 1) {
+                            b1 = fgetc(fp);
+                            if (b1 == EOF) break;
+                        }
+                    }
+                }
+            } else {
+                /* repeat b2, b1 times */
+                int i;
+                if (y < image->height) {
+                    p = image->indexes + y * image->width;
+                    for (i = 0; i < b1; ++i) {
+                        if (header2.BitsPerPixel == 8) {
+                            if (x < image->width) {
+                                p[x] = b2;
+                            }
+                            ++x;
+                        } else {
+                            if (x < image->width) {
+                                p[x] = b2 >> 4;
+                            }
+                            ++x;
+                            if (x < image->width) {
+                                p[x] = b2 & 0xF;
+                            }
+                            ++x;
+                        }
+                    }
+                }
+            }
+        }
+    } else {
+        bytes_per_row = (image->width * header2.BitsPerPixel + 31) / 32 * 4;
+        row_bytes = (unsigned char *) alloc(bytes_per_row);
+        if (header2.Compression == BI_RGB) {
+            switch (header2.BitsPerPixel) {
+            case 16:
+                header2.RedMask   = 0x001F;
+                header2.GreenMask = 0x07E0;
+                header2.BlueMask  = 0xF800;
+                header2.AlphaMask = 0x0000;
+                break;
+
+            case 32:
+                header2.RedMask   = 0x000000FF;
+                header2.GreenMask = 0x0000FF00;
+                header2.BlueMask  = 0x00FF0000;
+                header2.AlphaMask = 0xFF000000;
+                break;
+            }
+        }
+        for (y = y_start; y != y_end; y += y_inc) {
+            struct Pixel *row = image->pixels + y * image->width;
+            unsigned char *ind = image->indexes + y * image->width;
+            size = fread(row_bytes, 1, bytes_per_row, fp);
+            if (size < bytes_per_row) goto error;
+            switch (header2.BitsPerPixel) {
+            case 1:
+                for (x = 0; x < image->width; ++x) {
+                    unsigned byte = x / 8;
+                    unsigned shift = x % 8;
+                    unsigned color = (row_bytes[byte] >> shift) & 1;
+                    ind[x] = color;
+                }
+                break;
+            case 4:
+                for (x = 0; x < image->width; ++x) {
+                    unsigned byte = x / 2;
+                    unsigned shift = (x % 2) * 4;
+                    unsigned color = (row_bytes[byte] >> shift) & 1;
+                    ind[x] = color;
+                }
+                break;
+            case 8:
+                for (x = 0; x < image->width; ++x) {
+                    ind[x] = row_bytes[x];
+                }
+                break;
+            case 16:
+                for (x = 0; x < image->width; ++x) {
+                    uint16 color = read_u16(row_bytes + x * 2);
+                    row[x] = build_pixel(&header2, color);
+                }
+                break;
+            case 24:
+                for (x = 0; x < image->width; ++x) {
+                    row[x].r = row_bytes[x * 3 + 2];
+                    row[x].g = row_bytes[x * 3 + 1];
+                    row[x].b = row_bytes[x * 3 + 0];
+                    row[x].a = 255;
+                }
+                break;
+            case 32:
+                for (x = 0; x < image->width; ++x) {
+                    uint32 color = read_u32(row_bytes + x * 2);
+                    row[x] = build_pixel(&header2, color);
+                }
+                break;
+            }
+        }
+        free(row_bytes);
+        row_bytes = NULL;
+    }
+
+    if (image->indexes != NULL) {
+        size_t i;
+        for (i = 0; i < num_pixels; ++i) {
+            image->pixels[i] = image->palette[image->indexes[i]];
+        }
+    }
+
+    fclose(fp);
+    return TRUE;
+
+error:
+    if (fp) fclose(fp);
+    free(row_bytes);
+    free(image->pixels);
+    image->pixels = NULL;
+    free(image->indexes);
+    image->indexes = NULL;
+    free(image->image_desc);
+    image->image_desc = NULL;
+    return FALSE;
+}
+
+/* Read and decode the first header */
+static boolean
+read_header(fp, header)
+FILE *fp;
+struct BitmapHeader *header;
+{
+    unsigned char buf[14];
+    size_t size;
+
+    size = fread(buf, 1, sizeof(buf), fp);
+    if (size < sizeof(buf)) return FALSE;
+
+    memcpy(header->magic, buf + 0, 2);
+    header->bmp_size = read_u32(buf + 2);
+    /* 6 and 8 are 16 bit integers giving the hotspot of a cursor */
+    header->img_offset = read_u32(buf + 10);
+    return TRUE;
+}
+
+/* Read and decode the second header */
+static boolean
+read_info_header(fp, header)
+FILE *fp;
+struct BitmapInfoHeader *header;
+{
+    unsigned char buf[124]; /* maximum size */
+    size_t size;
+    boolean have_color_mask;
+
+    memset(header, 0, sizeof(*header));
+
+    /* Get the header size */
+    size = fread(buf, 1, 4, fp);
+    if (size < 4) return FALSE;
+    header->Size = read_u32(buf + 0);
+    if (header->Size > sizeof(buf)) return FALSE;
+
+    /* Get the rest of the header */
+    size = fread(buf + 4, 1, header->Size - 4, fp);
+    if (size < header->Size - 4) return FALSE;
+
+    have_color_mask = FALSE;
+    switch (header->Size) {
+    case 124: /* BITMAPV5INFOHEADER */
+        /* 120 is reserved */
+        header->ProfileSize = read_u32(buf + 116);
+        header->ProfileData = read_u32(buf + 112);
+        header->Intent = read_u32(buf + 108);
+        /* fall through */
+
+    case 108: /* BITMAPV4INFOHEADER */
+        header->GammaBlue = read_u32(buf + 104);
+        header->GammaGreen = read_u32(buf + 100);
+        header->GammaRed = read_u32(buf + 96);
+        header->Endpoints.ciexyzBlue.ciexyzZ = read_u32(buf + 92);
+        header->Endpoints.ciexyzBlue.ciexyzY = read_u32(buf + 88);
+        header->Endpoints.ciexyzBlue.ciexyzX = read_u32(buf + 84);
+        header->Endpoints.ciexyzGreen.ciexyzZ = read_u32(buf + 80);
+        header->Endpoints.ciexyzGreen.ciexyzY = read_u32(buf + 76);
+        header->Endpoints.ciexyzGreen.ciexyzX = read_u32(buf + 72);
+        header->Endpoints.ciexyzRed.ciexyzZ = read_u32(buf + 68);
+        header->Endpoints.ciexyzRed.ciexyzY = read_u32(buf + 64);
+        header->Endpoints.ciexyzRed.ciexyzX = read_u32(buf + 60);
+        header->CSType = read_u32(buf + 56);
+        /* fall through */
+
+    case 56: /* BITMAPV3INFOHEADER */
+        header->AlphaMask = read_u32(buf + 52);
+        /* fall through */
+
+    case 52: /* BITMAPV2INFOHEADER */
+        header->BlueMask = read_u32(buf + 48);
+        header->GreenMask = read_u32(buf + 44);
+        header->RedMask = read_u32(buf + 40);
+        have_color_mask = TRUE;
+        /* fall through */
+
+    case 40: /* BITMAPINFOHEADER */
+    case 64: /* OS22XBITMAPHEADER */
+        /* The last 24 bytes in OS22XBITMAPHEADER are incompatible with the
+         * later Microsoft versions of the header */
+        header->ColorsImportant = read_u32(buf + 36);
+        header->ColorsUsed = read_u32(buf + 32);
+        header->YResolution = read_s32(buf + 28);
+        header->XResolution = read_s32(buf + 24);
+        header->ImageDataSize = read_u32(buf + 20);
+        header->Compression = read_u32(buf + 16);
+        header->BitsPerPixel = read_u16(buf + 14);
+        header->NumPlanes = read_u16(buf + 12);
+        header->Height = read_s32(buf + 8);
+        header->Width = read_s32(buf + 4);
+        break;
+
+    case 12: /* BITMAPCOREHEADER */
+        header->BitsPerPixel = read_u16(buf + 10);
+        header->NumPlanes = read_u16(buf + 8);
+        header->Height = read_u16(buf + 6);
+        header->Width = read_u16(buf + 4);
+        break;
+
+    default:
+        return FALSE;
+    }
+
+    /* For BI_BITFIELDS, the next three 32 bit words are the color masks */
+    if (header->Compression == BI_BITFIELDS && !have_color_mask) {
+        size = fread(buf, 1, 12, fp);
+        if (size < 12) return FALSE;
+        header->RedMask = read_u32(buf + 0);
+        header->GreenMask = read_u32(buf + 4);
+        header->BlueMask = read_u32(buf + 8);
+    }
+
+    return TRUE;
+}
+
+/* Check the second header for consistency and unsupported features */
+static boolean
+check_info_header(header)
+const struct BitmapInfoHeader *header;
+{
+    if (header->NumPlanes != 1) return FALSE;
+    switch (header->BitsPerPixel) {
+#if 0 /* TODO */
+    case 0:
+        if (header->Compression != BI_PNG) return FALSE;
+        /* JPEG not supported */
+        break;
+#endif
+
+    case 1:
+    case 24:
+        if (header->Compression != BI_RGB) return FALSE;
+        break;
+
+    case 4:
+        if (header->Compression != BI_RGB
+        &&  header->Compression != BI_RLE4) return FALSE;
+        break;
+
+    case 8:
+        if (header->Compression != BI_RGB
+        &&  header->Compression != BI_RLE8) return FALSE;
+        break;
+
+    case 16:
+    case 32:
+        if (header->Compression != BI_RGB
+        &&  header->Compression != BI_BITFIELDS) return FALSE;
+        /* Any of the color masks could conceivably be zero; the bitmap, though
+         * limited, would still be meaningful */
+        if (header->Compression == BI_BITFIELDS
+        &&  header->RedMask == 0
+        &&  header->GreenMask == 0
+        &&  header->BlueMask == 0) return FALSE;
+        break;
+
+    default:
+        return FALSE;
+    }
+
+    if (header->Height < 0 && header->Compression != BI_RGB
+            && header->Compression != BI_BITFIELDS) return FALSE;
+
+    return TRUE;
+}
+
+/* Return the number of palette entries to read from the file */
+static unsigned
+get_palette_size(header)
+const struct BitmapInfoHeader *header;
+{
+    switch (header->BitsPerPixel) {
+    case 1:
+        return 2;
+
+    case 4:
+        return header->ColorsUsed ? header->ColorsUsed : 16;
+
+    case 8:
+        return header->ColorsUsed ? header->ColorsUsed : 256;
+
+    default:
+        return 0;
+    }
+}
+
+/*
+ * Read the palette from the file
+ * palette_size is the number of entries to read, but no more than 256 will
+ * be written into the palette array
+ * Return TRUE if successful, FALSE on any error
+ */
+static boolean
+read_palette(fp, palette, palette_size)
+FILE *fp;
+struct Pixel *palette;
+unsigned palette_size;
+{
+    unsigned i;
+    unsigned char buf[4];
+    unsigned read_size;
+
+    read_size = (palette_size < 256) ? palette_size : 256;
+    for (i = 0; i < read_size; ++i) {
+        size_t size = fread(buf, 1, sizeof(buf), fp);
+        if (size < sizeof(buf)) return FALSE;
+        palette[i].b = buf[0];
+        palette[i].g = buf[1];
+        palette[i].r = buf[2];
+        palette[i].a = 255;
+    }
+    for (; i < 256; ++i) {
+        palette[i].b = 0;
+        palette[i].g = 0;
+        palette[i].r = 0;
+        palette[i].a = 255;
+    }
+    fseek(fp, 4 * (palette_size - read_size), SEEK_CUR);
+    return TRUE;
+}
+
+/* Decode an unsigned 16 bit quantity */
+static uint16
+read_u16(buf)
+const unsigned char buf[2];
+{
+    return ((uint16)buf[0] << 0)
+         | ((uint16)buf[1] << 8);
+}
+
+/* Decode an unsigned 32 bit quantity */
+static uint32
+read_u32(buf)
+const unsigned char buf[4];
+{
+    return ((uint32)buf[0] <<  0)
+         | ((uint32)buf[1] <<  8)
+         | ((uint32)buf[2] << 16)
+         | ((uint32)buf[3] << 24);
+}
+
+/* Decode a signed 32 bit quantity */
+static int32
+read_s32(buf)
+const unsigned char buf[4];
+{
+    return (int32)((read_u32(buf) ^ 0x80000000) - 0x80000000);
+}
+
+/* Build a pixel structure, given the mask words in the second header and
+ * a packed 16 or 32 bit pixel */
+static struct Pixel
+build_pixel(header, color)
+const struct BitmapInfoHeader *header;
+uint32 color;
+{
+    struct Pixel pixel;
+
+    pixel.r = pixel_element(header->RedMask, color);
+    pixel.g = pixel_element(header->GreenMask, color);
+    pixel.b = pixel_element(header->BlueMask, color);
+    pixel.a = header->AlphaMask ? pixel_element(header->AlphaMask, color) : 255;
+    return pixel;
+}
+
+/* Extract one element (red, green, blue or alpha) from a pixel */
+static unsigned char
+pixel_element(mask, color)
+uint32 mask;
+uint32 color;
+{
+    uint32 bits, shift;
+
+    if (mask == 0) return 0;
+    bits = 0xFFFF; /* 0xFF, 0xF, 0x3, 0x1 */
+    shift = 16;    /*    8,   4,   2,   1 */
+    while (bits != 0) {
+        if ((mask & bits) == 0) {
+            mask >>= shift;
+            color >>= shift;
+        }
+        shift /= 2;
+        bits >>= shift;
+    }
+    color &= mask;
+    return color * 255 / mask;
+}
diff --git a/win/share/giftiles.c b/win/share/giftiles.c
new file mode 100644 (file)
index 0000000..911ea3c
--- /dev/null
@@ -0,0 +1,512 @@
+/* NetHack 3.6    giftiles.c    $NHDT-Date: 1457358406 2016/03/07 13:46:46 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.0 $ */
+/* Copyright (c) Ray Chason, 2016. */
+/* NetHack may be freely redistributed.  See license for details. */
+
+/* giftiles.c -- read a tile map in GIF format */
+/* Reference: GIF specification,, retrieved from
+ * http://www.w3.org/Graphics/GIF/spec-gif89a.txt */
+
+#include "config.h"
+#include "tileset.h"
+
+#define MIN_LZW_BITS 3
+#define MAX_LZW_BITS 12
+#define END_OF_DATA 0x7FFF
+
+/* For use when reading the GIF as a bitstream */
+struct Bitstream {
+    /* The file */
+    FILE *fp;
+
+    /* For unpacking LZW codes */
+    unsigned long bits;
+    unsigned char num_bits;
+    unsigned char bit_width;
+    unsigned char initial_bit_width;
+    unsigned char block_size;
+
+    /* The dictionary */
+    struct {
+        unsigned char byte;
+        unsigned short next;
+    } dictionary[1 << MAX_LZW_BITS];
+    unsigned short dict_size;
+
+    /* The string currently being decoded */
+    unsigned char string[1 << MAX_LZW_BITS];
+    unsigned short str_size;
+
+    unsigned short last_code;
+};
+
+struct DataBlock {
+    size_t size;
+    size_t index;
+    unsigned char *data;
+};
+
+static boolean FDECL(read_data_block, (struct Bitstream *gif, struct DataBlock *block));
+static void FDECL(free_data_block, (struct DataBlock *block));
+static unsigned short FDECL(read_u16, (const unsigned char buf[2]));
+static void FDECL(init_decoder, (struct Bitstream *gif, unsigned bit_width));
+static void FDECL(reset_decoder, (struct Bitstream *gif));
+static int FDECL(decode, (struct Bitstream *gif, struct DataBlock *block));
+static int FDECL(get_code, (struct Bitstream *gif, struct DataBlock *block));
+static unsigned FDECL(interlace_incr, (unsigned y, unsigned height));
+
+/*
+ * GIF specifies a canvas, which may have a palette (the "global color table")
+ * of up to 256 colors, of which one is a background color, and zero or more
+ * images, each of which may have its own palette (a "local color table")
+ * independently of the canvas. We will join all palettes found into a single
+ * palette, and indicate that the image uses a palette if, and only if, the
+ * various palettes do not total more than 256 colors.
+ */
+
+boolean
+read_gif_tiles(filename, image)
+const char *filename;
+struct TileSetImage *image;
+{
+    struct Bitstream gif;
+    struct DataBlock block;
+
+    unsigned char buf[1024];
+    size_t size, num_pixels, i;
+
+    /* Image data not returned to the caller */
+    boolean have_gct;   /* global color table is present */
+    unsigned gct_size;  /* global color table size */
+    unsigned back_color; /* index for background color */
+    unsigned trans_color = 0xFFFF; /* index for transparent palette entry */
+
+    block.data = NULL;      /* custodial */
+    gif.fp = NULL;          /* custodial */
+
+    image->width = 0;
+    image->height = 0;
+    image->pixels = NULL;       /* custodial, returned */
+    image->indexes = NULL;      /* custodial, returned */
+    image->image_desc = NULL;   /* custodial, returned */
+    image->tile_width = 0;
+    image->tile_height = 0;
+
+    gif.fp = fopen(filename, "rb");
+    if (gif.fp == NULL) goto error;
+
+    /* 17. Header */
+    size = fread(buf, 1, 6, gif.fp);
+    if (size < 6) goto error;
+    if (memcmp(buf, "GIF87a", 6) != 0 && memcmp(buf, "GIF89a", 6) != 0)
+        goto error;
+
+    /* 18. Logical screen descriptor */
+    size = fread(buf, 1, 7, gif.fp);
+    if (size < 7) goto error;
+    image->width = read_u16(buf + 0);
+    image->height = read_u16(buf + 2);
+    have_gct = (buf[4] & 0x80) != 0;
+    gct_size = 1 << ((buf[4] & 0x07) + 1);
+    back_color = buf[5];
+    if (image->width == 0 || image->height == 0) goto error;
+
+    /* 19. Global Color Table */
+    for (i = 0; i < SIZE(image->palette); ++i) {
+        image->palette[i].r = 0;
+        image->palette[i].g = 0;
+        image->palette[i].b = 0;
+        image->palette[i].a = 255;
+    }
+    if (have_gct) {
+        size = fread(buf, 3, gct_size, gif.fp);
+        if (size < gct_size) goto error;
+        for (i = 0; i < gct_size; ++i) {
+            image->palette[i].r = buf[i * 3 + 0];
+            image->palette[i].g = buf[i * 3 + 1];
+            image->palette[i].b = buf[i * 3 + 2];
+            image->palette[i].a = 255;
+        }
+    }
+
+    /* Allocate pixel area; watch out for overflow */
+    num_pixels = (size_t) image->width * (size_t) image->height;
+    if (num_pixels / image->width != image->height) goto error; /* overflow */
+    size = num_pixels * sizeof(image->pixels[0]);
+    if (size / sizeof(image->pixels[0]) != num_pixels) goto error; /* overflow */
+    image->pixels = (struct Pixel *) alloc(size);
+    image->indexes = (unsigned char *) alloc(num_pixels);
+
+    /* Fill with the background color */
+    for (i = 0; i < num_pixels; ++i) {
+        image->pixels[i] = image->palette[back_color];
+        image->indexes[i] = back_color;
+    }
+
+    /* Read the image data */
+    while (TRUE) {
+        int b = fgetc(gif.fp);
+        if (b == EOF) goto error;
+
+        /* 27. Trailer (0x3B) */
+        if (b == 0x3B) break;
+
+        switch (b) {
+        case 0x2C:
+            /* 20. Image descriptor (0x2C) */
+            {
+                unsigned img_left, img_top, img_width, img_height;
+                boolean have_lct, interlace;
+                unsigned lct_start, lct_size;
+                struct Pixel lct[256];
+                int b;
+                unsigned x, y, x2, y2;
+
+                size = fread(buf, 1, 9, gif.fp);
+                if (size < 9) goto error;
+                img_left = read_u16(buf + 0);
+                img_top = read_u16(buf + 2);
+                img_width = read_u16(buf + 4);
+                img_height = read_u16(buf + 6);
+                have_lct = (buf[8] & 0x80) != 0;
+                interlace = (buf[8] & 0x40) != 0;
+                lct_size = 1 << ((buf[8] & 0x07) + 1);
+
+                /* 21. Local color table */
+                lct_start = 0;
+                memcpy(lct, image->palette, sizeof(lct));
+                if (have_lct) {
+                    size = fread(buf, 3, lct_size, gif.fp);
+                    if (size < lct_size) goto error;
+                    for (i = 0; i < lct_size; ++i) {
+                        lct[i].r = buf[i * 3 + 0];
+                        lct[i].g = buf[i * 3 + 1];
+                        lct[i].b = buf[i * 3 + 2];
+                        lct[i].a = 255;
+                    }
+                    /*
+                     * The combined palette may exceed 256 colors, in which
+                     * case the indexes array will be discarded, indicating a
+                     * full-color image.
+                     */
+                    if (lct_size + gct_size <= 256) {
+                        memcpy(image->palette, lct, sizeof(lct[0]) * lct_size);
+                    }
+                    lct_start = gct_size;
+                    gct_size += lct_start;
+                }
+                if (trans_color != 0xFFFF) {
+                    lct[trans_color].a = 0;
+                    if (!have_lct) {
+                        /* FIXME: this will affect all images using the global
+                         * color table, not just the current one */
+                        image->palette[trans_color].a = 0;
+                    }
+                }
+                /* 22. Table based image data */
+                b = fgetc(gif.fp);
+                if (b == EOF) goto error;
+                if (b < MIN_LZW_BITS - 1 || MAX_LZW_BITS - 1 < b) goto error;
+                init_decoder(&gif, b);
+                x = 0;
+                y = 0;
+                if (!read_data_block(&gif, &block)) goto error;
+                while (TRUE) {
+                    b = decode(&gif, &block);
+                    if (b == EOF) goto error;
+                    if (b == END_OF_DATA) break;
+                    if (y >= img_height) goto error;
+                    x2 = img_left + x;
+                    y2 = img_top + y;
+                    if (x2 < image->width && y2 < image->height) {
+                        image->pixels[y2 * image->width + x2] = lct[b];
+                        image->indexes[y2 * image->width + x2] = b + lct_start;
+                    }
+                    ++x;
+                    if (x >= img_width) {
+                        x = 0;
+                        if (interlace) {
+                            y = interlace_incr(y, img_height);
+                        } else {
+                            ++y;
+                        }
+                    }
+                }
+                free_data_block(&block);
+                trans_color = 0xFFFF;
+            }
+            break;
+
+        case 0x21:
+            /* Extension blocks */
+            {
+                int label;
+
+                label = fgetc(gif.fp);
+                if (label == EOF) goto error;
+                if (!read_data_block(&gif, &block)) goto error;
+                switch (label) {
+                case 0xF9:
+                    /* 23. Graphic control extension (0xF9) */
+                    if (block.size >= 4 && (block.data[0] & 0x01) != 0) {
+                        /* image has a transparent index */
+                        trans_color = block.data[3];
+                    }
+                    break;
+
+#if 0
+                case 0xFE:
+                    /* 24. Comment extension (0xFE) */
+                    break;
+
+                case 0x01:
+                    /* 25. Plain text extension (0x01) */
+                    break;
+#endif
+
+                case 0xFF:
+                    /* 26. Application extension (0xFF) */
+                    if (block.size > 11
+                    &&  memcmp(block.data, "NETHACK3GIF", 11) == 0
+                    &&  image->image_desc == NULL) {
+                        memmove(block.data, block.data + 11, block.size - 11);
+                        block.data[block.size - 11] = '\0';
+                        image->image_desc = (char *) block.data;
+                        block.data = NULL;
+                    }
+                    break;
+
+                default:
+                    /* Unknown extension type */
+                    break;
+                }
+                free_data_block(&block);
+            }
+            break;
+
+        default:
+            goto error;
+        }
+    }
+
+    fclose(gif.fp);
+    free_data_block(&block);
+    if (gct_size > 256) {
+        /* Max palette size exceeded; indexes array is not meaningful */
+        free(image->indexes);
+        image->indexes = NULL;
+    }
+    return TRUE;
+
+error:
+    if (gif.fp) fclose(gif.fp);
+    free_data_block(&block);
+    free(image->pixels);
+    image->pixels = NULL;
+    free(image->indexes);
+    image->indexes = NULL;
+    free(image->image_desc);
+    image->image_desc = NULL;
+    return FALSE;
+}
+
+static void
+init_decoder(gif, bit_width)
+struct Bitstream *gif;
+unsigned bit_width;
+{
+    unsigned i;
+    unsigned clear;
+
+    gif->bits = 0;
+    gif->num_bits = 0;
+    gif->initial_bit_width = bit_width;
+    gif->block_size = 0;
+
+    clear = 1 << bit_width;
+    gif->dict_size = clear + 2;
+    for (i = 0; i < clear; ++i) {
+        gif->dictionary[i].byte = i;
+        gif->dictionary[i].next = 0xFFFF;
+    }
+
+    gif->str_size = 0;
+
+    reset_decoder(gif);
+}
+
+static void
+reset_decoder(gif)
+struct Bitstream *gif;
+{
+    /* Set the bit width */
+    gif->bit_width = gif->initial_bit_width + 1;
+
+    /* Reset the dictionary */
+    gif->dict_size = (1 << gif->initial_bit_width) + 2;
+
+    /* No last code */
+    gif->last_code = 0xFFFF;
+}
+
+static int
+decode(gif, block)
+struct Bitstream *gif;
+struct DataBlock *block;
+{
+    int code;
+    unsigned clear = 1 << gif->initial_bit_width;
+
+    /* If a string is being decoded, return the next byte */
+    if (gif->str_size != 0) {
+        return gif->string[--gif->str_size];
+    }
+
+    /* Get the next code, until code other than clear */
+    while (TRUE) {
+        code = get_code(gif, block);
+        if (code != clear) break;
+        reset_decoder(gif);
+    }
+
+    if (code == EOF) return EOF;
+    if (code == clear + 1) return END_OF_DATA;
+    if (code > gif->dict_size) return EOF;
+
+    /* Add a new string to the dictionary */
+    if (gif->last_code != 0xFFFF && gif->dict_size < SIZE(gif->dictionary)) {
+        unsigned next_code;
+        if (code < gif->dict_size) {
+            next_code = code;
+        } else {
+            next_code = gif->last_code;
+        }
+        while (next_code >= clear) {
+            next_code = gif->dictionary[next_code].next;
+        }
+        gif->dictionary[gif->dict_size].next = gif->last_code;
+        gif->dictionary[gif->dict_size].byte = next_code;
+        ++gif->dict_size;
+        if (gif->dict_size >= 1 << gif->bit_width
+        &&  gif->bit_width < MAX_LZW_BITS) {
+            ++gif->bit_width;
+        }
+    }
+    gif->last_code = code;
+
+    /* code is less than gif->dict_size and not equal to clear or clear + 1 */
+    /* Prepare the decoded string for return; note that it is stored in
+     * reverse order */
+    while (code >= clear) {
+        gif->string[gif->str_size++] = gif->dictionary[code].byte;
+        code = gif->dictionary[code].next;
+    }
+
+    return code;
+}
+
+static int
+get_code(gif, block)
+struct Bitstream *gif;
+struct DataBlock *block;
+{
+    int code;
+
+    while (gif->num_bits < gif->bit_width) {
+        unsigned char b;
+        if (block->index >= block->size) return EOF;
+        b = block->data[block->index++];
+        gif->bits |= (unsigned long)b << gif->num_bits;
+        gif->num_bits += 8;
+    }
+
+    code = (int) (gif->bits & ((1UL << gif->bit_width) - 1));
+    gif->bits >>= gif->bit_width;
+    gif->num_bits -= gif->bit_width;
+    return code;
+}
+
+static unsigned
+interlace_incr(y, height)
+unsigned y;
+unsigned height;
+{
+    static const unsigned char incr[] = { 8, 2, 4, 2 };
+
+    /* The lower three bits indicate the current pass */
+
+    /* Advance to the next row of the current pass */
+    y += incr[y & 0x3];
+
+    /* Go to the next pass if y exceeds height */
+    /* Might not be the immediately following pass if height is small */
+    if (y >= height && (y & 0x7) == 0) {
+        /* Pass 1 -> Pass 2 */
+        y = 4;
+    }
+    if (y >= height && (y & 0x7) == 4) {
+        /* Pass 2 -> Pass 3 */
+        y = 2;
+    }
+    if (y >= height && (y & 0x3) == 2) {
+        /* Pass 3 -> Pass 4 */
+        y = 1;
+    }
+
+    return y;
+}
+
+/* Decode an unsigned 16 bit quantity */
+static unsigned short
+read_u16(buf)
+const unsigned char buf[2];
+{
+    return ((unsigned short)buf[0] << 0)
+         | ((unsigned short)buf[1] << 8);
+}
+
+static boolean
+read_data_block(gif, block)
+struct Bitstream *gif;
+struct DataBlock *block;
+{
+    long pos = ftell(gif->fp);
+    int b;
+    size_t i;
+
+    free_data_block(block);
+
+    /* Get the length of the data block */
+    while (TRUE) {
+        b = fgetc(gif->fp);
+        if (b == EOF) return FALSE;
+        if (b == 0) break;
+        block->size += b;
+        fseek(gif->fp, b, SEEK_CUR);
+    }
+    fseek(gif->fp, pos, SEEK_SET);
+
+    /* Allocate memory */
+    block->data = (unsigned char *) alloc(block->size);
+
+    /* Read the data from the file */
+    i = 0;
+    while (TRUE) {
+        b = fgetc(gif->fp);
+        if (b == EOF) return FALSE;
+        if (b == 0) break;
+        if (fread(block->data + i, 1, b, gif->fp) != b) return FALSE;
+        i += b;
+    }
+
+    block->index = 0;
+    return TRUE;
+}
+
+static void
+free_data_block(block)
+struct DataBlock *block;
+{
+    free(block->data);
+    block->size = 0;
+    block->data = NULL;
+}
index 996c591..15c6181 100644 (file)
@@ -7108,7 +7108,7 @@ Z = (195, 195, 195)
   ..KKAKKAAKKKOAA.
   .JKKKAAAKKKOKA..
   .KKKKKKKKKLOAA..
-  .KOOLKKKKKOKA..K
+  .KOOLKKKKKOKA...
   ..JKOOKKKKOAA...
   ....JKLOOOKA....
   ......JJKKAA....
index e63a35f..3ff7899 100644 (file)
@@ -46,7 +46,7 @@ Z = (195, 195, 195)
   AAAAAAAAAAAAAAAA
   AAAAAAAAAAAAAAAA
 }
-# tile 1 (\95Ç)
+# tile 1 (\8fc\82Ì\95Ç)
 {
   ANNOA1PPPPP1NNOA
   AOOOA1P1PP11OOOA
@@ -65,7 +65,7 @@ Z = (195, 195, 195)
   A111A11PPPP1111A
   AOPPA11PPPP1OP1A
 }
-# tile 2 (\95Ç)
+# tile 2 (\89¡\82Ì\95Ç)
 {
   AAANOOAAAAANOOAA
   OOONOOA1OOONOOA1
@@ -84,7 +84,7 @@ Z = (195, 195, 195)
   1111111111111111
   AAAAAAAAAAAAAAAA
 }
-# tile 3 (\95Ç)
+# tile 3 (\8d\8fã\8ap\82Ì\95Ç)
 {
   AAANNNNOOOOOOAAA
   NNNNAA11PPPPO111
@@ -103,7 +103,7 @@ Z = (195, 195, 195)
   A111A11PPPP1111A
   AOPPA11PPPP1OP1A
 }
-# tile 4 (\95Ç)
+# tile 4 (\89E\8fã\8ap\82Ì\95Ç)
 {
   AAANNNNOOOOOOAAA
   NNNNAA11PPPPO111
@@ -122,7 +122,7 @@ Z = (195, 195, 195)
   A111A11PPPP1111A
   AOPPA11PPPP1OP1A
 }
-# tile 5 (\95Ç)
+# tile 5 (\8d\89º\8ap\82Ì\95Ç)
 {
   AAANNNNOOOOOOAAA
   NNNNAA11PPPPO111
@@ -141,7 +141,7 @@ Z = (195, 195, 195)
   1111111111111111
   AAAAAAAAAAAAAAAA
 }
-# tile 6 (\95Ç)
+# tile 6 (\89E\89º\8ap\82Ì\95Ç)
 {
   AAANNNNOOOOOOAAA
   NNNNAA11PPPPO111
@@ -160,7 +160,7 @@ Z = (195, 195, 195)
   1111111111111111
   AAAAAAAAAAAAAAAA
 }
-# tile 7 (\95Ç)
+# tile 7 (\8cð\8d·\82µ\82½\95Ç)
 {
   AAANNNNOOOOOOAAA
   NNNNAA11PPPPO111
@@ -179,7 +179,7 @@ Z = (195, 195, 195)
   A111A11PPPP1111A
   AOPPA11PPPP1OP1A
 }
-# tile 8 (\95Ç)
+# tile 8 (tuwall)
 {
   AAANNNNOOOOOOAAA
   NNNNAA11PPPPO111
@@ -198,7 +198,7 @@ Z = (195, 195, 195)
   1111111111111111
   AAAAAAAAAAAAAAAA
 }
-# tile 9 (\95Ç)
+# tile 9 (tdwall)
 {
   AAANNNNOOOOOOAAA
   NNNNAA11PPPPO111
@@ -217,7 +217,7 @@ Z = (195, 195, 195)
   A111A11PPPP1111A
   AOPPA11PPPP1OP1A
 }
-# tile 10 (\95Ç)
+# tile 10 (tlwall)
 {
   AAANNNNOOOOOOAAA
   NNNNAA11PPPPO111
@@ -236,7 +236,7 @@ Z = (195, 195, 195)
   A111A11PPPP1111A
   AOPPA11PPPP1OP1A
 }
-# tile 11 (\95Ç)
+# tile 11 (trwall)
 {
   AAANNNNOOOOOOAAA
   NNNNAA11PPPPO111
@@ -255,7 +255,7 @@ Z = (195, 195, 195)
   A111A11PPPP1111A
   AOPPA11PPPP1OP1A
 }
-# tile 12 (\8fo\93ü\8cû)
+# tile 12 (\94à\82È\82µ)
 {
   AAAAAAAAAAAAAAAA
   AA............AA
@@ -274,7 +274,7 @@ Z = (195, 195, 195)
   AA............AA
   AAAAAAAAAAAAAAAA
 }
-# tile 13 (\8aJ\82¢\82½\94à)
+# tile 13 (\8fc\82Ì\8aJ\82¢\82½\94à)
 {
   AAAAAAAAAAAAAAAA
   AAAAAAAAAAAAAAAA
@@ -293,7 +293,7 @@ Z = (195, 195, 195)
   A..............A
   AAAAAAAAAAAAAAAA
 }
-# tile 14 (\8aJ\82¢\82½\94à)
+# tile 14 (\89¡\82Ì\8aJ\82¢\82½\94à)
 {
   AAAAAAAAAAAAAAAA
   AAAAAAAAAAAAAAAA
@@ -312,7 +312,7 @@ Z = (195, 195, 195)
   AAAAAAAAAAAAAAAA
   AAAAAAAAAAAAAAAA
 }
-# tile 15 (\95Â\82\82½\94à)
+# tile 15 (\8fc\82Ì\95Â\82\82½\94à)
 {
   AAAAAAAAAAAAAAAA
   AAAAAAAAAAAAAAAA
@@ -331,7 +331,7 @@ Z = (195, 195, 195)
   AAAAAAAAAAAAAAAA
   AAAAAAAAAAAAAAAA
 }
-# tile 16 (\95Â\82\82½\94à)
+# tile 16 (\89¡\82Ì\95Â\82\82½\94à)
 {
   AAAAAAAAAAAAAAAA
   AAAAAAAAAAAAAAAA
@@ -578,7 +578,7 @@ Z = (195, 195, 195)
   FFFFFFFFFFFFFFF.
   ................
 }
-# tile 29 (\89Ø\82â\82©\82È\8bÊ\8dÀ)
+# tile 29 (\8bÊ\8dÀ)
 {
   ................
   .....HHHHH......
@@ -692,7 +692,7 @@ Z = (195, 195, 195)
   DDDDKKDDDDCDDDDD
   DDDDDDDDDDDKDDDD
 }
-# tile 35 (\8d~\82è\82Ä\82¢\82é\92µ\82Ë\8b´)
+# tile 35 (\8fc\82Ì\8aJ\82¢\82½\92µ\82Ë\8b´)
 {
   EKKAKKKKKKKAKKAE
   EJKKKKKKKKKKKJAA
@@ -711,7 +711,7 @@ Z = (195, 195, 195)
   EEJJJJJJJJJJJAAA
   EJKKKKKKKKKKKJAA
 }
-# tile 36 (\8d~\82è\82Ä\82¢\82é\92µ\82Ë\8b´)
+# tile 36 (\89¡\82Ì\8aJ\82¢\82½\92µ\82Ë\8b´)
 {
   EEEEEEEEEEEEEEEE
   JEJKJEJKJEJKJEJK
@@ -730,7 +730,7 @@ Z = (195, 195, 195)
   AAAAAAAAAAAAAAAA
   AAAEAAAEAAAEAAAE
 }
-# tile 37 (\8fã\82Á\82Ä\82¢\82é\92µ\82Ë\8b´)
+# tile 37 (\8fc\82Ì\95Â\82\82½\92µ\82Ë\8b´)
 {
   ................
   ..JKJ.JKJ.JKJ...
@@ -749,7 +749,7 @@ Z = (195, 195, 195)
   ...AAA.AAA.AAA..
   ................
 }
-# tile 38 (\8fã\82Á\82Ä\82¢\82é\92µ\82Ë\8b´)
+# tile 38 (\89¡\82Ì\95Â\82\82½\92µ\82Ë\8b´)
 {
   ................
   ..JJJJJJJJJJJ...
@@ -1262,7 +1262,7 @@ Z = (195, 195, 195)
   ................
   ................
 }
-# tile 65 (\95Ç)
+# tile 65 (\8fc\82Ì\83r\81[\83\80)
 {
   .......NN.......
   ......NN........
@@ -1281,7 +1281,7 @@ Z = (195, 195, 195)
   .........NN.....
   ........NN......
 }
-# tile 66 (\95Ç)
+# tile 66 (\89¡\82Ì\83r\81[\83\80)
 {
   ................
   ................
@@ -1300,7 +1300,7 @@ Z = (195, 195, 195)
   ................
   ................
 }
-# tile 67 (\95Ç)
+# tile 67 (\8d\8eÎ\82ß\82Ì\83r\81[\83\80)
 {
   NNNNN...........
   ....N...........
@@ -1319,7 +1319,7 @@ Z = (195, 195, 195)
   ............N...
   ............NNNN
 }
-# tile 68 (\95Ç)
+# tile 68 (\89E\8eÎ\82ß\82Ì\83r\81[\83\80)
 {
   ............NNNN
   ............N...
@@ -1338,7 +1338,7 @@ Z = (195, 195, 195)
   ....N...........
   NNNNN...........
 }
-# tile 69 (cmap 69)
+# tile 69 (dig beam)
 {
   ....AAAA........
   ..A....AA..AA...
@@ -1357,7 +1357,7 @@ Z = (195, 195, 195)
   ....AA....AAA...
   ................
 }
-# tile 70 (cmap 70)
+# tile 70 (flash beam)
 {
   ................
   .....NNNNNN.....
@@ -1376,7 +1376,7 @@ Z = (195, 195, 195)
   .....NNNNNN.....
   ................
 }
-# tile 71 (cmap 71)
+# tile 71 (boom left)
 {
   ................
   ................
@@ -1395,7 +1395,7 @@ Z = (195, 195, 195)
   ................
   ................
 }
-# tile 72 (cmap 72)
+# tile 72 (boom right)
 {
   ................
   ................
@@ -1414,7 +1414,7 @@ Z = (195, 195, 195)
   ................
   ................
 }
-# tile 73 (cmap 73)
+# tile 73 (shield1)
 {
   ................
   .....I....I.....
@@ -1433,7 +1433,7 @@ Z = (195, 195, 195)
   .....I....I.....
   ................
 }
-# tile 74 (cmap 74)
+# tile 74 (shield2)
 {
   ................
   .CCCCCCCCCCCCCCC
@@ -1452,7 +1452,7 @@ Z = (195, 195, 195)
   .CCCCCCCCCCCCCC.
   ................
 }
-# tile 75 (cmap 75)
+# tile 75 (shield3)
 {
   .......HH.......
   .......HH.......
@@ -1471,7 +1471,7 @@ Z = (195, 195, 195)
   .......HH.......
   .......HH.......
 }
-# tile 76 (cmap 76)
+# tile 76 (shield4)
 {
   ................
   ......NNNNN.....
@@ -1528,7 +1528,7 @@ Z = (195, 195, 195)
   .......FF.......
   ................
 }
-# tile 79 (cmap 79)
+# tile 79 (swallow top left)
 {
   AAAAAAADDDDDDAAA
   AAAAADDDDDDDDDDD
@@ -1547,7 +1547,7 @@ Z = (195, 195, 195)
   AAAADDDDDD......
   AAAADDDDDD......
 }
-# tile 80 (cmap 80)
+# tile 80 (swallow top center)
 {
   AAAAAAAAAAAAAAAA
   DDAAAAAAAAAAAAAA
@@ -1566,7 +1566,7 @@ Z = (195, 195, 195)
   ................
   ................
 }
-# tile 81 (cmap 81)
+# tile 81 (swallow top right)
 {
   AAAAAAAAAAAAAAAA
   AAADDDDDAAAAAAAA
@@ -1585,7 +1585,7 @@ Z = (195, 195, 195)
   ....DDDDDDDDDDDD
   ....DDDDDDDDDDDA
 }
-# tile 82 (cmap 82)
+# tile 82 (swallow middle left)
 {
   AAAADDDDDD......
   AAAADDDDDDD.....
@@ -1604,7 +1604,7 @@ Z = (195, 195, 195)
   DDDDDDD.........
   DDCCDDD.........
 }
-# tile 83 (cmap 83)
+# tile 83 (swallow middle right)
 {
   ....DDDDDDDDDDDA
   ....DDDDDDDDDDDA
@@ -1623,7 +1623,7 @@ Z = (195, 195, 195)
   ......DDDDDDDDAA
   .......DDDDDDDAA
 }
-# tile 84 (cmap 84)
+# tile 84 (swallow bottom left )
 {
   DDDCDDD.........
   DDDCDDD.........
@@ -1642,7 +1642,7 @@ Z = (195, 195, 195)
   AAAAAAAAAAAADDDD
   AAAAAAAAAAAAAADD
 }
-# tile 85 (cmap 85)
+# tile 85 (swallow bottom center)
 {
   ................
   ................
@@ -1661,7 +1661,7 @@ Z = (195, 195, 195)
   DDDDDDDDDDDDDDDD
   DDDDDDDDDDDDDDAA
 }
-# tile 86 (cmap 86)
+# tile 86 (swallow bottom right)
 {
   ......DDDDDDDDAA
   ......DDDDDDDDDA
@@ -1680,7 +1680,7 @@ Z = (195, 195, 195)
   DDAAAAAAAAAAAAAA
   AAAAAAAAAAAAAAAA
 }
-# tile 87 (explosion dark 0)
+# tile 87 (explosion top left)
 {
   ................
   ................
@@ -1699,7 +1699,7 @@ Z = (195, 195, 195)
   ..AAAA..AAAA....
   ..AAA..AAAAA....
 }
-# tile 88 (explosion dark 1)
+# tile 88 (explosion top centre)
 {
   ................
   ................
@@ -1718,7 +1718,7 @@ Z = (195, 195, 195)
   ........A.A.APAA
   .PA...APAAAAAAAA
 }
-# tile 89 (explosion dark 2)
+# tile 89 (explosion top right)
 {
   ................
   ................
@@ -1737,7 +1737,7 @@ Z = (195, 195, 195)
   AA.A..A.AAAA....
   A.AA..A.AAAAA...
 }
-# tile 90 (explosion dark 3)
+# tile 90 (explosion middle left)
 {
   ..AAA.A.AAA.....
   ..AAA.AAAAA.AP..
@@ -1756,7 +1756,7 @@ Z = (195, 195, 195)
   ..A.A...AAP...PA
   ....A.........PA
 }
-# tile 91 (explosion dark 4)
+# tile 91 (explosion middle center)
 {
   APAAA..PPAPAAAAA
   .APA..A.AAAPAAA.
@@ -1775,7 +1775,7 @@ Z = (195, 195, 195)
   AAAAAAAAAAAAA.AA
   AAAAAAAAAAA.HH..
 }
-# tile 92 (explosion dark 5)
+# tile 92 (explosion middle right)
 {
   ..AAA.A.A.AAAA..
   ..AAAAA.A.AAAA..
@@ -1794,7 +1794,7 @@ Z = (195, 195, 195)
   AAA...AAAAAAA...
   ....PPAAAAAAAA..
 }
-# tile 93 (explosion dark 6)
+# tile 93 (explosion bottom left)
 {
   ....A.......A..P
   ....A.......AA..
@@ -1813,7 +1813,7 @@ Z = (195, 195, 195)
   ................
   ................
 }
-# tile 94 (explosion dark 7)
+# tile 94 (explosion bottom center)
 {
   PPPAAAAAPAAA.A..
   AAPPAAPPPPA.A...
@@ -1832,7 +1832,7 @@ Z = (195, 195, 195)
   ................
   ................
 }
-# tile 95 (explosion dark 8)
+# tile 95 (explosion bottom right)
 {
   ....P..AAAAAAA..
   ..A..A.AA.A.AA..
index 1e7fa46..766e721 100644 (file)
@@ -1,6 +1,8 @@
 #!/bin/perl
 #
-#  $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+#  $NHDT-Date: 1524689313 2018/04/25 20:48:33 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.5 $
+# Copyright (c) 2015 by Derek S. Ray
+# NetHack may be freely redistributed.  See license for details.
 #
 
 sub bail($);
index 6980623..4d6793c 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 thintile.c      $NHDT-Date: 1432512803 2015/05/25 00:13:23 $  $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
+/* NetHack 3.6 thintile.c      $NHDT-Date: 1457207049 2016/03/05 19:44:09 $  $NHDT-Branch: chasonr $:$NHDT-Revision: 1.10 $ */
 /*   Copyright (c) NetHack Development Team 1995                    */
 /*   NetHack may be freely redistributed.  See license for details. */
 
@@ -32,7 +32,7 @@ copy_colormap()
     int r, g, b;
     char c[2];
 
-    while (fscanf(infile, "%[A-Za-z0-9] = (%d, %d, %d) ", c, &r, &g, &b)
+    while (fscanf(infile, "%[A-Za-z0-9.] = (%d, %d, %d) ", c, &r, &g, &b)
            == 4) {
         Fprintf(outfile, "%c = (%d, %d, %d)\n", c[0], r, g, b);
     }
index 8137f0f..baa7bd2 100644 (file)
@@ -1,4 +1,4 @@
-NetHack 3.6  tile.doc  $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+NetHack 3.6  tile.doc  $NHDT-Date: 1524684654 2018/04/25 19:30:54 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.7 $
 
 Window ports can optionally make use of the tiles (pictures for NetHack
 symbols) found in this directory.  They are distributed in a text format
@@ -57,8 +57,10 @@ boolean read_text_tile(pixel[TILE_Y][TILE_X]);
 boolean write_text_tile(pixel[TILE_Y][TILE_X]);
        writes tile
 
-There are two additional shared routines provided for writers:
+There are some additional shared routines provided for writers:
 
+void set_grayscale(boolean g);
+       do grayscale color substitutions when reading the tile text file
 void init_colormap();
        initialize the output colormap from the input one
        must be called before opening output file as colormap is part of header
index 566cc38..0313ac0 100644 (file)
@@ -1,4 +1,7 @@
-/* NetHack 3.6  tile.h       $NHDT-Date: 1432512803 2015/05/25 00:13:23 $  $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
+/* NetHack 3.6  tile.h       $NHDT-Date: 1524689272 2018/04/25 20:47:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.13 $ */
+/*      Copyright (c) 2016 by Michael Allison             */
+/* NetHack may be freely redistributed.  See license for details. */
+
 typedef unsigned char pixval;
 
 typedef struct pixel_s {
@@ -35,6 +38,7 @@ extern boolean FDECL(read_text_tile, (pixel(*) [TILE_X]));
 extern boolean FDECL(write_text_tile, (pixel(*) [TILE_X]));
 extern int NDECL(fclose_text_file);
 
+extern void FDECL(set_grayscale, (int));
 extern void NDECL(init_colormap);
 extern void NDECL(merge_colormap);
 
index 00bc76a..d0fb363 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 tile2bmp.c      $NHDT-Date: 1431192770 2015/05/09 17:32:50 $  $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */
+/* NetHack 3.6 tile2bmp.c      $NHDT-Date: 1451442061 2015/12/30 02:21:01 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $ */
 /*   Copyright (c) NetHack PC Development Team 1995                 */
 /*   NetHack may be freely redistributed.  See license for details. */
 
 #include "win32api.h"
 #endif
 
+#include <stdint.h>
+#if defined(UINT32_MAX) && defined(INT32_MAX) && defined(UINT16_MAX)
+#define UINT8 uint8_t
+#define UINT16 uint16_t
+#define UINT32 uint32_t
+#define INT32 int32_t
+#else
+# ifdef _MSC_VER
+#define UINT8 unsigned char
+#define UINT16 unsigned short
+#define UINT32 unsigned long
+#define INT32 long
+# endif
+#endif
+
 #if (TILE_X == 32)
 #define COLORS_IN_USE 256
 #else
@@ -61,8 +76,8 @@ leshort(short x)
 #endif
 }
 
-static long
-lelong(long x)
+static INT32
+lelong(INT32 x)
 {
 #ifdef __BIG_ENDIAN__
     return ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00)
@@ -74,37 +89,35 @@ lelong(long x)
 
 #ifdef __GNUC__
 typedef struct tagBMIH {
-    unsigned long biSize;
-    long biWidth;
-    long biHeight;
-    unsigned short biPlanes;
-    unsigned short biBitCount;
-    unsigned long biCompression;
-    unsigned long biSizeImage;
-    long biXPelsPerMeter;
-    long biYPelsPerMeter;
-    unsigned long biClrUsed;
-    unsigned long biClrImportant;
+    UINT32 biSize;
+    INT32 biWidth;
+    INT32 biHeight;
+    UINT16 biPlanes;
+    UINT16 biBitCount;
+    UINT32 biCompression;
+    UINT32 biSizeImage;
+    INT32 biXPelsPerMeter;
+    INT32 biYPelsPerMeter;
+    UINT32 biClrUsed;
+    UINT32 biClrImportant;
 } PACK BITMAPINFOHEADER;
 
 typedef struct tagBMFH {
-    unsigned short bfType;
-    unsigned long bfSize;
-    unsigned short bfReserved1;
-    unsigned short bfReserved2;
-    unsigned long bfOffBits;
+    UINT16 bfType;
+    UINT32 bfSize;
+    UINT16 bfReserved1;
+    UINT16 bfReserved2;
+    UINT32 bfOffBits;
 } PACK BITMAPFILEHEADER;
 
 typedef struct tagRGBQ {
-    unsigned char rgbBlue;
-    unsigned char rgbGreen;
-    unsigned char rgbRed;
-    unsigned char rgbReserved;
+    UINT8 rgbBlue;
+    UINT8 rgbGreen;
+    UINT8 rgbRed;
+    UINT8 rgbReserved;
 } PACK RGBQUAD;
-#define UINT unsigned int
-#define DWORD unsigned long
-#define LONG long
-#define WORD unsigned short
+#define DWORD UINT32
+#define WORD UINT16
 #define BI_RGB 0L
 #define BI_RLE8 1L
 #define BI_RLE4 2L
@@ -224,6 +237,7 @@ char *argv[];
             }
             initflag = 1;
         }
+        set_grayscale(pass == 3);
         /*             printf("Colormap initialized\n"); */
         while (read_text_tile(tilepixels)) {
             build_bmptile(tilepixels);
@@ -256,8 +270,8 @@ BITMAPFILEHEADER *pbmfh;
 {
     pbmfh->bfType = leshort(0x4D42);
     pbmfh->bfSize = lelong(BMPFILESIZE);
-    pbmfh->bfReserved1 = (UINT) 0;
-    pbmfh->bfReserved2 = (UINT) 0;
+    pbmfh->bfReserved1 = (UINT32) 0;
+    pbmfh->bfReserved2 = (UINT32) 0;
     pbmfh->bfOffBits = lelong(sizeof(bmp.bmfh) + sizeof(bmp.bmih)
                               + (RGBQUAD_COUNT * sizeof(RGBQUAD)));
 }
@@ -314,11 +328,6 @@ BITMAPINFOHEADER *pbmih;
     pbmih->biClrImportant = (DWORD) 0;
 }
 
-static int graymappings[] = {
-    /* .  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  */
-    0, 1, 17, 18, 19, 20, 27, 22, 23, 24, 25, 26, 21, 15, 13, 14, 14
-};
-
 static void
 build_bmptile(pixels)
 pixel (*pixels)[TILE_X];
@@ -338,14 +347,6 @@ pixel (*pixels)[TILE_X];
                 Fprintf(stderr, "color not in colormap!\n");
             y = (MAX_Y - 1) - (cur_y + yoffset);
             apply_color = cur_color;
-            if (pass == 3) {
-                /* map to shades of gray */
-                if (cur_color > (SIZE(graymappings) - 1))
-                    Fprintf(stderr, "Gray mapping issue %d %d.\n", cur_color,
-                            SIZE(graymappings) - 1);
-                else
-                    apply_color = graymappings[cur_color];
-            }
 #if BITCOUNT == 4
             x = (cur_x / 2) + xoffset;
             bmp.packtile[y][x] = cur_x % 2
index e41d618..46b1056 100644 (file)
@@ -1,4 +1,5 @@
-/* NetHack 3.6 tilemap.c       $NHDT-Date: 1447306925 2015/11/12 05:42:05 $  $NHDT-Branch: master $:$NHDT-Revision: 1.25 $ */
+/* NetHack 3.6 tilemap.c       $NHDT-Date: 1524689272 2018/04/25 20:47:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.33 $ */
+/*      Copyright (c) 2016 by Michael Allison                     */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -12,6 +13,7 @@
 const char *FDECL(tilename, (int, int));
 void NDECL(init_tilemap);
 void FDECL(process_substitutions, (FILE *));
+boolean FDECL(acceptable_tilename, (int, const char *, const char *));
 
 #if defined(MICRO) || defined(WIN32)
 #undef exit
@@ -20,7 +22,7 @@ extern void FDECL(exit, (int));
 #endif
 #endif
 
-#if defined(WIN32)
+#if defined(MSDOS) || defined(WIN32) || defined(X11_GRAPHICS)
 #define STATUES_LOOK_LIKE_MONSTERS
 #endif
 
@@ -463,8 +465,11 @@ FILE *ofp;
         fprintf(ofp, "%s\n", epilog[i]);
     }
 
-    fprintf(ofp, "\nint total_tiles_used = %d;\n", start);
     lastothtile = start - 1;
+#ifdef STATUES_LOOK_LIKE_MONSTERS
+    start = laststatuetile + 1;
+#endif
+    fprintf(ofp, "\nint total_tiles_used = %d;\n", start);
 }
 
 int
@@ -499,7 +504,9 @@ main()
     fprintf(ofp, "\n#define MAXMONTILE %d\n", lastmontile);
     fprintf(ofp, "#define MAXOBJTILE %d\n", lastobjtile);
     fprintf(ofp, "#define MAXOTHTILE %d\n", lastothtile);
-
+#ifdef STATUES_LOOK_LIKE_MONSTERS
+    fprintf(ofp, "/* #define MAXSTATUETILE %d */\n", laststatuetile);
+#endif
     fprintf(ofp, "\n/*tile.c*/\n");
 
     fclose(ofp);
@@ -509,3 +516,121 @@ main()
 }
 
 #endif /* TILETEXT */
+
+struct {
+    int idx;
+    const char *betterlabel;
+    const char *expectedlabel;
+} altlabels[] = {
+{S_stone,    "dark part of a room", "dark part of a room"},
+{S_vwall,    "vertical wall", "wall"},
+{S_hwall,    "horizontal wall", "wall"},
+{S_tlcorn,   "top left corner wall", "wall"},
+{S_trcorn,   "top right corner wall", "wall"},
+{S_blcorn,   "bottom left corner wall", "wall"},
+{S_brcorn,   "bottom right corner wall", "wall"},
+{S_crwall,   "cross wall", "wall"},
+{S_tuwall,   "tuwall", "wall"},
+{S_tdwall,   "tdwall", "wall"},
+{S_tlwall,   "tlwall", "wall"},
+{S_trwall,   "trwall", "wall"},
+{S_ndoor,    "no door", "doorway"},
+{S_vodoor,   "vertical open door", "open door"},
+{S_hodoor,   "horizontal open door", "open door"},
+{S_vcdoor,   "vertical closed door", "closed door"},
+{S_hcdoor,   "horizontal closed door", "closed door"},
+{S_bars,     "iron bars", "iron bars"},
+{S_tree,     "tree", "tree"},
+{S_room,     "room", "floor of a room"},
+{S_darkroom, "darkroom", "dark part of a room"},
+{S_corr,     "corridor", "corridor"},
+{S_litcorr,  "lit corridor", "lit corridor"},
+{S_upstair,  "up stairs", "staircase up"},
+{S_dnstair,  "down stairs", "staircase down"},
+{S_upladder, "up ladder", "ladder up"},
+{S_dnladder, "down ladder", "ladder down"},
+{S_altar,    "altar", "altar"},
+{S_grave,    "grave", "grave"},
+{S_throne,   "throne", "opulent throne"},
+{S_sink,     "sink", "sink"},
+{S_fountain, "fountain", "fountain"},
+{S_pool,     "pool", "water"},
+{S_ice,      "ice", "ice"},
+{S_lava,     "lava", "molten lava"},
+{S_vodbridge, "vertical open drawbridge", "lowered drawbridge"},
+{S_hodbridge, "horizontal open drawbridge", "lowered drawbridge"},
+{S_vcdbridge, "vertical closed drawbridge", "raised drawbridge"},
+{S_hcdbridge, "horizontal closed drawbridge", "raised drawbridge"},
+{S_air,      "air", "air"},
+{S_cloud,    "cloud", "cloud"},
+{S_water,    "water", "water"},
+{S_arrow_trap,           "arrow trap", "arrow trap"},
+{S_dart_trap,            "dart trap", "dart trap"},
+{S_falling_rock_trap,    "falling rock trap", "falling rock trap"},
+{S_squeaky_board,        "squeaky board", "squeaky board"},
+{S_bear_trap,            "bear trap", "bear trap"},
+{S_land_mine,            "land mine", "land mine"},
+{S_rolling_boulder_trap, "rolling boulder trap", "rolling boulder trap"},
+{S_sleeping_gas_trap,    "sleeping gas trap", "sleeping gas trap"},
+{S_rust_trap,            "rust trap", "rust trap"},
+{S_fire_trap,            "fire trap", "fire trap"},
+{S_pit,                  "pit", "pit"},
+{S_spiked_pit,           "spiked pit", "spiked pit"},
+{S_hole,                 "hole", "hole"},
+{S_trap_door,            "trap door", "trap door"},
+{S_teleportation_trap,   "teleportation trap", "teleportation trap"},
+{S_level_teleporter,     "level teleporter", "level teleporter"},
+{S_magic_portal,         "magic portal", "magic portal"},
+{S_web,                  "web", "web"},
+{S_statue_trap,          "statue trap", "statue trap"},
+{S_magic_trap,           "magic trap", "magic trap"},
+{S_anti_magic_trap,      "anti magic trap", "anti-magic field"},
+{S_polymorph_trap,       "polymorph trap", "polymorph trap"},
+{S_vibrating_square,     "vibrating square", "vibrating square"},
+{S_vbeam,    "vertical beam", "cmap 65"},
+{S_hbeam,    "horizontal beam", "cmap 66"},
+{S_lslant,   "left slant beam", "cmap 67"},
+{S_rslant,   "right slant beam", "cmap 68"},
+{S_digbeam,  "dig beam", "cmap 69"},
+{S_flashbeam, "flash beam", "cmap 70"},
+{S_boomleft, "boom left", "cmap 71"},
+{S_boomright, "boom right", "cmap 72"},
+{S_ss1,      "shield1", "cmap 73"},
+{S_ss2,      "shield2", "cmap 74"},
+{S_ss3,      "shield3", "cmap 75"},
+{S_ss4,      "shield4", "cmap 76"},
+{S_poisoncloud, "poison cloud", "poison cloud"},
+{S_goodpos,  "valid position", "valid position"},
+{S_sw_tl,    "swallow top left", "cmap 79"},
+{S_sw_tc,    "swallow top center", "cmap 80"},
+{S_sw_tr,    "swallow top right", "cmap 81"},
+{S_sw_ml,    "swallow middle left", "cmap 82"},
+{S_sw_mr,    "swallow middle right", "cmap 83"},
+{S_sw_bl,    "swallow bottom left ", "cmap 84"},
+{S_sw_bc,    "swallow bottom center", "cmap 85"},
+{S_sw_br,    "swallow bottom right", "cmap 86"},
+{S_explode1, "explosion top left", "explosion dark 0"},
+{S_explode2, "explosion top centre", "explosion dark 1"},
+{S_explode3, "explosion top right", "explosion dark 2"},
+{S_explode4, "explosion middle left", "explosion dark 3"},
+{S_explode5, "explosion middle center", "explosion dark 4"},
+{S_explode6, "explosion middle right", "explosion dark 5"},
+{S_explode7, "explosion bottom left", "explosion dark 6"},
+{S_explode8, "explosion bottom center", "explosion dark 7"},
+{S_explode9, "explosion bottom right", "explosion dark 8"},
+};
+
+boolean
+acceptable_tilename(idx, encountered, expected)
+int idx;
+const char *encountered, *expected;
+{
+    if (idx >= 0 && idx < SIZE(altlabels)) {
+        if (!strcmp(altlabels[idx].expectedlabel, expected)) {
+            if (!strcmp(altlabels[idx].betterlabel, encountered))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
diff --git a/win/share/tileset.c b/win/share/tileset.c
new file mode 100644 (file)
index 0000000..d37b912
--- /dev/null
@@ -0,0 +1,228 @@
+/* NetHack 3.6    tileset.c    $NHDT-Date: 1501463811 2017/07/31 01:16:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.0 $ */
+/* Copyright (c) Ray Chason, 2016. */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#include "hack.h"
+#include "tileset.h"
+
+static void FDECL(get_tile_map, (const char *));
+static void FDECL(split_tiles, (const struct TileSetImage *));
+static void FDECL(free_image, (struct TileSetImage *));
+
+static struct TileImage *tiles;
+static unsigned num_tiles;
+static struct TileImage blank_tile; /* for graceful undefined tile handling */
+
+static boolean have_palette;
+static struct Pixel palette[256];
+
+boolean
+read_tiles(filename, true_color)
+const char *filename;
+boolean true_color;
+{
+    static const unsigned char png_sig[] = {
+        0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A
+    };
+    struct TileSetImage image;
+    FILE *fp;
+    char header[16];
+    boolean ok;
+
+    /* Fill the image structure with known values */
+    image.width = 0;
+    image.height = 0;
+    image.pixels = NULL;        /* custodial */
+    image.indexes = NULL;       /* custodial */
+    image.image_desc = NULL;    /* custodial */
+    image.tile_width = 0;
+    image.tile_height = 0;
+
+    /* Identify the image type */
+    fp = fopen(filename, "rb");
+    if (!fp)
+        goto error;
+    memset(header, 0, sizeof(header));
+    fread(header, 1, sizeof(header), fp);
+    fclose(fp), fp = (FILE *) 0;
+
+    /* Call the loader appropriate for the image */
+    if (memcmp(header, "BM", 2) == 0) {
+        ok = read_bmp_tiles(filename, &image);
+    } else if (memcmp(header, "GIF87a", 6) == 0
+           ||  memcmp(header, "GIF89a", 6) == 0) {
+        ok = read_gif_tiles(filename, &image);
+    } else if (memcmp(header, png_sig, sizeof(png_sig)) == 0) {
+        ok = read_png_tiles(filename, &image);
+    } else {
+        ok = FALSE;
+    }
+    if (!ok)
+        goto error;
+
+    /* Reject if the interface cannot handle direct color and the image does
+       not use a palette */
+    if (!true_color && image.indexes == NULL)
+        goto error;
+
+    /* Save the palette if present */
+    have_palette = image.indexes != NULL;
+    memcpy(palette, image.palette, sizeof(palette));
+
+    /* Set defaults for tile metadata */
+    if (image.tile_width == 0) {
+        image.tile_width = image.width / 40;
+    }
+    if (image.tile_height == 0) {
+        image.tile_height = image.tile_width;
+    }
+    /* Set the tile dimensions if the user has not done so */
+    if (iflags.wc_tile_width == 0) {
+        iflags.wc_tile_width = image.tile_width;
+    }
+    if (iflags.wc_tile_height == 0) {
+        iflags.wc_tile_height = image.tile_height;
+    }
+
+    /* Parse the tile map */
+    get_tile_map(image.image_desc);
+
+    /* Split the image into tiles */
+    split_tiles(&image);
+
+    free_image(&image);
+    return TRUE;
+
+error:
+    if (fp)
+        fclose(fp);
+    free_image(&image);
+    return FALSE;
+}
+
+const struct Pixel *
+get_palette()
+{
+    return have_palette ? palette : NULL;
+}
+
+/* TODO: derive tile_map from image_desc */
+static void
+get_tile_map(image_desc)
+const char *image_desc;
+{
+    return;
+}
+
+void
+free_tiles()
+{
+    unsigned i;
+
+    if (tiles) {
+        for (i = 0; i < num_tiles; ++i) {
+            free((genericptr_t) tiles[i].pixels);
+            free((genericptr_t) tiles[i].indexes);
+        }
+        free((genericptr_t) tiles), tiles = NULL;
+    }
+    num_tiles = 0;
+
+    if (blank_tile.pixels)
+        free((genericptr_t) blank_tile.pixels), blank_tile.pixels = NULL;
+    if (blank_tile.indexes)
+        free((genericptr_t) blank_tile.indexes), blank_tile.indexes = NULL;
+}
+
+static void
+free_image(image)
+struct TileSetImage *image;
+{
+    if (image->pixels)
+        free((genericptr_t) image->pixels), image->pixels = NULL;
+    if (image->indexes)
+        free((genericptr_t) image->indexes), image->indexes = NULL;
+    if (image->image_desc)
+        free((genericptr_t) image->image_desc), image->image_desc = NULL;
+}
+
+const struct TileImage *
+get_tile(tile_index)
+unsigned tile_index;
+{
+    if (tile_index >= num_tiles)
+        return &blank_tile;
+    return &tiles[tile_index];
+}
+
+static void
+split_tiles(image)
+const struct TileSetImage *image;
+{
+    unsigned tile_rows, tile_cols;
+    size_t tile_size, i, j;
+    unsigned x1, y1, x2, y2;
+
+    /* Get the number of tiles */
+    tile_rows = image->height / iflags.wc_tile_height;
+    tile_cols = image->width / iflags.wc_tile_width;
+    num_tiles = tile_rows * tile_cols;
+    tile_size = (size_t) iflags.wc_tile_height * (size_t) iflags.wc_tile_width;
+
+    /* Allocate the tile array */
+    tiles = (struct TileImage *) alloc(num_tiles * sizeof(tiles[0]));
+    memset(tiles, 0, num_tiles * sizeof(tiles[0]));
+
+    /* Copy the pixels into the tile structures */
+    for (y1 = 0; y1 < tile_rows; ++y1) {
+        for (x1 = 0; x1 < tile_cols; ++x1) {
+            struct TileImage *tile = &tiles[y1 * tile_cols + x1];
+
+            tile->width = iflags.wc_tile_width;
+            tile->height = iflags.wc_tile_height;
+            tile->pixels = (struct Pixel *)
+                    alloc(tile_size * sizeof (struct Pixel));
+            if (image->indexes != NULL) {
+                tile->indexes = (unsigned char *) alloc(tile_size);
+            }
+            for (y2 = 0; y2 < iflags.wc_tile_height; ++y2) {
+                for (x2 = 0; x2 < iflags.wc_tile_width; ++x2) {
+                    unsigned x = x1 * iflags.wc_tile_width + x2;
+                    unsigned y = y1 * iflags.wc_tile_height + y2;
+
+                    i = y * image->width + x;
+                    j = y2 * tile->width + x2;
+                    tile->pixels[j] = image->pixels[i];
+                    if (image->indexes != NULL) {
+                        tile->indexes[j] = image->indexes[i];
+                    }
+                }
+            }
+        }
+    }
+
+    /* Create a blank tile for use when the tile index is invalid */
+    blank_tile.width = iflags.wc_tile_width;
+    blank_tile.height = iflags.wc_tile_height;
+    blank_tile.pixels = (struct Pixel *)
+            alloc(tile_size * sizeof (struct Pixel));
+    for (i = 0; i < tile_size; ++i) {
+        blank_tile.pixels[i].r = 0;
+        blank_tile.pixels[i].g = 0;
+        blank_tile.pixels[i].b = 0;
+        blank_tile.pixels[i].a = 255;
+    }
+    if (image->indexes) {
+        blank_tile.indexes = (unsigned char *) alloc(tile_size);
+        memset(blank_tile.indexes, 0, tile_size);
+    }
+}
+
+boolean
+read_png_tiles(filename, image)
+const char *filename;
+struct TileSetImage *image;
+{
+    /* stub */
+    return FALSE;
+}
index fdd40c0..480698c 100644 (file)
@@ -1,4 +1,5 @@
-/* NetHack 3.6 tiletext.c      $NHDT-Date: 1432512803 2015/05/25 00:13:23 $  $NHDT-Branch: master $:$NHDT-Revision: 1.11 $ */
+/* NetHack 3.6 tiletext.c      $NHDT-Date: 1524689272 2018/04/25 20:47:52 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $ */
+/*      Copyright (c) 2016 by Pasi Kallinen                       */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "config.h"
@@ -26,6 +27,7 @@ static const char *text_sets[] = { "monsters.txt", "objects.txt",
 #endif
 
 extern const char *FDECL(tilename, (int, int));
+extern boolean FDECL(acceptable_tilename, (int, const char *, const char *));
 static void FDECL(read_text_colormap, (FILE *));
 static boolean FDECL(write_text_colormap, (FILE *));
 static boolean FDECL(read_txttile, (FILE *, pixel (*)[TILE_X]));
@@ -36,6 +38,20 @@ static void FDECL(write_txttile, (FILE *, pixel (*)[TILE_X]));
     "%[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.] = " \
     "(%d, %d, %d) "
 
+static int grayscale = 0;
+/* grayscale color mapping */
+static const int graymappings[] = {
+ /* .  A  B   C   D   E   F   G   H   I   J   K   L   M   N   O   P */
+    0, 1, 17, 18, 19, 20, 27, 22, 23, 24, 25, 26, 21, 15, 13, 14, 14
+};
+
+void
+set_grayscale(g)
+int g;
+{
+    grayscale = g;
+}
+
 static void
 read_text_colormap(txtfile)
 FILE *txtfile;
@@ -110,7 +126,7 @@ pixel (*pixels)[TILE_X];
          * change when tiles are added
          */
         p = tilename(tile_set, tile_set_indx);
-        if (p && strcmp(p, buf)) {
+        if (p && strcmp(p, buf) && !acceptable_tilename(tile_set_indx,buf,p)) {
             Fprintf(stderr, "warning: for tile %d (numbered %d) of %s,\n",
                     tile_set_indx, i, text_sets[tile_set - 1]);
             Fprintf(stderr, "\tfound '%s' while expecting '%s'\n", buf, p);
@@ -134,6 +150,13 @@ pixel (*pixels)[TILE_X];
                 return FALSE;
             }
             k = color_index[(int) c[0]];
+            if (grayscale) {
+                if (k > (SIZE(graymappings) - 1))
+                    Fprintf(stderr, "Gray mapping issue %d > %d.\n", k,
+                            SIZE(graymappings) - 1);
+                else
+                    k = graymappings[k];
+            }
             if (k == -1)
                 Fprintf(stderr, "color %c not in colormap!\n", c[0]);
             else {
@@ -159,7 +182,7 @@ pixel (*pixels)[TILE_X];
     /* DICE again... it doesn't seem to eat whitespace after the } like
      * it should, so we have to do so manually.
      */
-    while ((*c = fgetc(txtfile)) != EOF && isspace(*c))
+    while ((*c = fgetc(txtfile)) != EOF && isspace((uchar) *c))
         ;
     ungetc(*c, txtfile);
 #endif
index 0147b00..3fc4487 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 getline.c       $NHDT-Date: 1432512813 2015/05/25 00:13:33 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */
+/* NetHack 3.6 getline.c       $NHDT-Date: 1523619111 2018/04/13 11:31:51 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.35 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2006. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
@@ -20,6 +21,7 @@
 #include "func_tab.h"
 
 char morc = 0; /* tell the outside world what char you chose */
+STATIC_VAR boolean suppress_history;
 STATIC_DCL boolean FDECL(ext_cmd_getlin_hook, (char *));
 
 typedef boolean FDECL((*getlin_hook_proc), (char *));
@@ -41,6 +43,7 @@ tty_getlin(query, bufp)
 const char *query;
 register char *bufp;
 {
+    suppress_history = FALSE;
     hooked_tty_getlin(query, bufp, (getlin_hook_proc) 0);
 }
 
@@ -76,8 +79,19 @@ getlin_hook_proc hook;
     cw->flags &= ~WIN_STOP;
     ttyDisplay->toplin = 3; /* special prompt state */
     ttyDisplay->inread++;
-    pline("%s ", query);
-    *obufp = 0;
+
+    /* issue the prompt */
+    custompline(OVERRIDE_MSGTYPE | SUPPRESS_HISTORY, "%s ", query);
+#ifdef EDIT_GETLIN
+    /* bufp is input/output; treat current contents (presumed to be from
+       previous getlin()) as default input */
+    addtopl(obufp);
+    bufp = eos(obufp);
+#else
+    /* !EDIT_GETLIN: bufp is output only; init it to empty */
+    *bufp = '\0';
+#endif
+
     for (;;) {
         (void) fflush(stdout);
         Strcat(strcat(strcpy(toplines, query), " "), obufp);
@@ -108,6 +122,7 @@ getlin_hook_proc hook;
         if (c == '\020') { /* ctrl-P */
             if (iflags.prevmsg_window != 's') {
                 int sav = ttyDisplay->inread;
+
                 ttyDisplay->inread = 0;
                 (void) tty_doprev_message();
                 ttyDisplay->inread = sav;
@@ -166,11 +181,7 @@ getlin_hook_proc hook;
                 }
             }
 #endif
-#if defined(apollo)
         } else if (c == '\n' || c == '\r') {
-#else
-        } else if (c == '\n') {
-#endif
 #ifndef NEWAUTOCOMP
             *bufp = 0;
 #endif /* not NEWAUTOCOMP */
@@ -178,11 +189,11 @@ getlin_hook_proc hook;
 #if 0 /*JP*/
         } else if (' ' <= (unsigned char) c && c != '\177'
 #else
-       } else if(' ' <= uc && uc < '\377'
+        } else if (' ' <= uc && uc < '\377'
 #endif
+                   /* avoid isprint() - some people don't have it
+                      ' ' is not always a printing char */
                    && (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO)) {
-/* avoid isprint() - some people don't have it
-   ' ' is not always a printing char */
 #ifdef NEWAUTOCOMP
             char *i = eos(bufp);
 
@@ -218,7 +229,7 @@ getlin_hook_proc hook;
 #endif /* NEWAUTOCOMP */
             }
         } else if (c == kill_char || c == '\177') { /* Robert Viduya */
-/* this test last - @ might be the kill_char */
+            /* this test last - @ might be the kill_char */
 #ifndef NEWAUTOCOMP
             while (bufp != obufp) {
                 bufp--;
@@ -240,6 +251,17 @@ getlin_hook_proc hook;
 #if 1 /*JP*/
     Strcpy(bfp, str2ic(tmp));
 #endif
+
+    if (suppress_history) {
+        /* prevent next message from pushing current query+answer into
+           tty message history */
+        *toplines = '\0';
+#ifdef DUMPLOG
+    } else {
+        /* needed because we've bypassed pline() */
+        dumplogmsg(toplines);
+#endif
+    }
 }
 
 void
@@ -254,7 +276,7 @@ register const char *s; /* chars allowed besides return */
         !program_state.done_hup &&
 #endif
         (c = tty_nhgetch()) != EOF) {
-        if (c == '\n')
+        if (c == '\n' || c == '\r')
             break;
 
         if (iflags.cbreak) {
@@ -264,7 +286,7 @@ register const char *s; /* chars allowed besides return */
                 morc = '\033';
                 break;
             }
-            if ((s && index(s, c)) || c == x) {
+            if ((s && index(s, c)) || c == x || (x == '\n' && c == '\r')) {
                 morc = (char) c;
                 break;
             }
@@ -293,7 +315,9 @@ char *base;
 
     com_index = -1;
     for (oindex = 0; extcmdlist[oindex].ef_txt != (char *) 0; oindex++) {
-        if (!strncmpi(base, extcmdlist[oindex].ef_txt, strlen(base))) {
+        if ((extcmdlist[oindex].flags & AUTOCOMPLETE)
+            && !(!wizard && (extcmdlist[oindex].flags & WIZMODECMD))
+            && !strncmpi(base, extcmdlist[oindex].ef_txt, strlen(base))) {
             if (com_index == -1) /* no matches yet */
                 com_index = oindex;
             else /* more than 1 match */
@@ -320,9 +344,15 @@ tty_get_ext_cmd()
 
     if (iflags.extmenu)
         return extcmd_via_menu();
-    /* maybe a runtime option? */
-    /* hooked_tty_getlin("#", buf, flags.cmd_comp ? ext_cmd_getlin_hook :
-     * (getlin_hook_proc) 0); */
+
+    suppress_history = TRUE;
+    /* maybe a runtime option?
+     * hooked_tty_getlin("#", buf,
+     *                   (flags.cmd_comp && !in_doagain)
+     *                      ? ext_cmd_getlin_hook
+     *                      : (getlin_hook_proc) 0);
+     */
+    buf[0] = '\0';
     hooked_tty_getlin("#", buf, in_doagain ? (getlin_hook_proc) 0
                                            : ext_cmd_getlin_hook);
     (void) mungspaces(buf);
index fd4d018..06da063 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 termcap.c       $NHDT-Date: 1447234979 2015/11/11 09:42:59 $  $NHDT-Branch: master $:$NHDT-Revision: 1.23 $ */
+/* NetHack 3.6 termcap.c       $NHDT-Date: 1456907853 2016/03/02 08:37:33 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.24 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Pasi Kallinen, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
@@ -1188,6 +1189,7 @@ int n;
     case ATR_ULINE:
         if (nh_US)
             return nh_US;
+        /*FALLTHRU*/
     case ATR_BOLD:
     case ATR_BLINK:
 #if defined(TERMLIB) && defined(TEXTCOLOR)
@@ -1209,6 +1211,7 @@ int n;
     case ATR_ULINE:
         if (nh_UE)
             return nh_UE;
+        /*FALLTHRU*/
     case ATR_BOLD:
     case ATR_BLINK:
         return nh_HE;
@@ -1263,6 +1266,7 @@ int color;
     xputs(hilites[color]);
 }
 
+/* not to be confused with has_colors() in unixtty.c */
 int
 has_color(color)
 int color;
@@ -1270,23 +1274,24 @@ int color;
 #ifdef X11_GRAPHICS
     /* XXX has_color() should be added to windowprocs */
     if (windowprocs.name != NULL && !strcmpi(windowprocs.name, "X11"))
-        return TRUE;
+        return 1;
 #endif
 #ifdef GEM_GRAPHICS
     /* XXX has_color() should be added to windowprocs */
     if (windowprocs.name != NULL && !strcmpi(windowprocs.name, "Gem"))
-        return TRUE;
+        return 1;
 #endif
 #ifdef QT_GRAPHICS
     /* XXX has_color() should be added to windowprocs */
     if (windowprocs.name != NULL && !strcmpi(windowprocs.name, "Qt"))
-        return TRUE;
+        return 1;
 #endif
 #ifdef AMII_GRAPHICS
     /* hilites[] not used */
-    return iflags.use_color;
-#endif
+    return iflags.use_color ? 1 : 0;
+#else
     return hilites[color] != (char *) 0;
+#endif
 }
 
 #endif /* TEXTCOLOR */
index 59149fb..85d44b9 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 topl.c  $NHDT-Date: 1431192777 2015/05/09 17:32:57 $  $NHDT-Branch: master $:$NHDT-Revision: 1.32 $ */
+/* NetHack 3.6 topl.c  $NHDT-Date: 1490908468 2017/03/30 21:14:28 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.36 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Michael Allison, 2009. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
@@ -8,7 +9,6 @@
 
 #include "tcap.h"
 #include "wintty.h"
-#include <ctype.h>
 
 #ifndef C /* this matches src/cmd.c */
 #define C(c) (0x1f & (c))
@@ -48,8 +48,7 @@ tty_doprev_message()
             do {
                 morc = 0;
                 if (cw->maxcol == cw->maxrow) {
-                    ttyDisplay->dismiss_more =
-                        C('p'); /* <ctrl/P> allowed at --More-- */
+                    ttyDisplay->dismiss_more = C('p'); /* ^P ok at --More-- */
                     redotoplin(toplines);
                     cw->maxcol--;
                     if (cw->maxcol < 0)
@@ -57,8 +56,7 @@ tty_doprev_message()
                     if (!cw->data[cw->maxcol])
                         cw->maxcol = cw->maxrow;
                 } else if (cw->maxcol == (cw->maxrow - 1)) {
-                    ttyDisplay->dismiss_more =
-                        C('p'); /* <ctrl/P> allowed at --More-- */
+                    ttyDisplay->dismiss_more = C('p'); /* ^P ok at --More-- */
                     redotoplin(cw->data[cw->maxcol]);
                     cw->maxcol--;
                     if (cw->maxcol < 0)
@@ -130,6 +128,7 @@ redotoplin(str)
 const char *str;
 {
     int otoplin = ttyDisplay->toplin;
+
     home();
 #if 0 /*JP*/
     if (*str & 0x80) {
@@ -258,8 +257,8 @@ register const char *bp;
     /* But messages like "You die..." deserve their own line */
     n0 = strlen(bp);
     if ((ttyDisplay->toplin == 1 || (cw->flags & WIN_STOP)) && cw->cury == 0
-        && n0 + (int) strlen(toplines) + 3 < CO - 8 && /* room for --More-- */
-        (notdied = strncmp(bp, "You die", 7))) {
+        && n0 + (int) strlen(toplines) + 3 < CO - 8 /* room for --More-- */
+        && (notdied = strncmp(bp, "You die", 7)) != 0) {
         Strcat(toplines, "  ");
         Strcat(toplines, bp);
         cw->curx += 2;
@@ -267,9 +266,9 @@ register const char *bp;
             addtopl(bp);
         return;
     } else if (!(cw->flags & WIN_STOP)) {
-        if (ttyDisplay->toplin == 1)
+        if (ttyDisplay->toplin == 1) {
             more();
-        else if (cw->cury) { /* for when flags.toplin == 2 && cury > 1 */
+        else if (cw->cury) { /* for when flags.toplin == 2 && cury > 1 */
             docorner(1, cw->cury + 1); /* reset cury = 0 if redraw screen */
             cw->curx = cw->cury = 0;   /* from home--cls() & docorner(1,n) */
         }
@@ -284,10 +283,11 @@ register const char *bp;
     (void) strncpy(toplines, bp, TBUFSZ);
     toplines[TBUFSZ - 1] = 0;
 
-    for (tl = toplines; n0 >= CO;) {
+    for (tl = toplines; n0 >= CO; ) {
         otl = tl;
-        for (tl += CO - 1; tl != otl && !isspace(*tl); --tl)
-            ;
+        for (tl += CO - 1; tl != otl; --tl)
+            if (*tl == ' ')
+                break;
         if (tl == otl) {
             /* Eek!  A huge token.  Try splitting after it. */
             tl = index(otl, ' ');
@@ -328,8 +328,8 @@ char c;
     case '\n':
         cl_end();
 #if 1 /*JP*/
-       (void) jputchar('\r'); /* raw mode \82Å\95K\97v? */
-       (void) jputchar('\n');
+        (void) jputchar('\r'); /* raw mode \82Å\95K\97v? */
+        (void) jputchar('\n');
 #endif
         ttyDisplay->curx = 0;
         ttyDisplay->cury++;
@@ -342,17 +342,17 @@ char c;
         break;
     default:
         if (ttyDisplay->curx == CO - 1)
-            topl_putsym('\n'); /* 1 <= curx <= CO; avoid CO */
+            topl_putsym('\n'); /* 1 <= curx < CO; avoid CO */
 #if 0 /*JP*/
 #ifdef WIN32CON
         (void) putchar(c);
 #endif
 #endif
 #if 1 /*JP*/
-       cw->curx = ttyDisplay->curx;
-       if(cw->curx == 0) cl_end();
-       (void) jputchar((unsigned char)uc);
-       cw->curx++;
+        cw->curx = ttyDisplay->curx;
+        if(cw->curx == 0) cl_end();
+        (void) jputchar((unsigned char)uc);
+        cw->curx++;
 #endif
         ttyDisplay->curx++;
     }
@@ -440,6 +440,7 @@ register int n;
 
 extern char erase_char; /* from xxxtty.c; don't need kill_char */
 
+/* returns a single keystroke; also sets 'yn_number' */
 char
 tty_yn_function(query, resp, def)
 const char *query, *resp;
@@ -463,6 +464,7 @@ char def;
     boolean doprev = 0;
     char prompt[BUFSZ];
 
+    yn_number = 0L;
     if (ttyDisplay->toplin == 1 && !(cw->flags & WIN_STOP))
         more();
     cw->flags &= ~WIN_STOP;
@@ -492,11 +494,12 @@ char def;
         /* not pline("%s ", prompt);
            trailing space is wanted here in case of reprompt */
         Strcat(prompt, " ");
-        pline("%s", prompt);
+        custompline(OVERRIDE_MSGTYPE | SUPPRESS_HISTORY, "%s", prompt);
     } else {
         /* no restriction on allowed response, so always preserve case */
         /* preserve_case = TRUE; -- moot since we're jumping to the end */
-        pline("%s ", query);
+        Sprintf(prompt, "%s ", query);
+        custompline(OVERRIDE_MSGTYPE | SUPPRESS_HISTORY, "%s", prompt);
         q = readchar();
         goto clean_up;
     }
@@ -553,6 +556,7 @@ char def;
             char z, digit_string[2];
             int n_len = 0;
             long value = 0;
+
             addtopl("#"), n_len++;
             digit_string[1] = '\0';
             if (q != '#') {
@@ -600,11 +604,16 @@ char def;
         }
     } while (!q);
 
-    if (q != '#') {
-        Sprintf(rtmp, "%c", q);
-        addtopl(rtmp);
-    }
-clean_up:
+ clean_up:
+    if (yn_number)
+        Sprintf(rtmp, "#%ld", yn_number);
+    else
+        (void) key2txt(q, rtmp);
+    /* addtopl(rtmp); -- rewrite toplines instead */
+    Sprintf(toplines, "%s%s", prompt, rtmp);
+#ifdef DUMPLOG
+    dumplogmsg(toplines);
+#endif
     ttyDisplay->inread--;
     ttyDisplay->toplin = 2;
     if (ttyDisplay->intr)
@@ -745,6 +754,9 @@ boolean restoring_msghist;
 {
     static boolean initd = FALSE;
     int idx;
+#ifdef DUMPLOG
+    extern unsigned saved_pline_index; /* pline.c */
+#endif
 
     if (restoring_msghist && !initd) {
         /* we're restoring history from the previous session, but new
@@ -754,18 +766,27 @@ boolean restoring_msghist;
            restored ones are being put into place */
         msghistory_snapshot(TRUE);
         initd = TRUE;
+#ifdef DUMPLOG
+        /* this suffices; there's no need to scrub saved_pline[] pointers */
+        saved_pline_index = 0;
+#endif
     }
 
     if (msg) {
-        /* move most recent message to history, make this become most recent
-         */
+        /* move most recent message to history, make this become most recent */
         remember_topl();
         Strcpy(toplines, msg);
+#ifdef DUMPLOG
+        dumplogmsg(toplines);
+#endif
     } else if (snapshot_mesgs) {
         /* done putting arbitrary messages in; put the snapshot ones back */
         for (idx = 0; snapshot_mesgs[idx]; ++idx) {
             remember_topl();
             Strcpy(toplines, snapshot_mesgs[idx]);
+#ifdef DUMPLOG
+            dumplogmsg(toplines);
+#endif
         }
         /* now release the snapshot */
         free_msghistory_snapshot(TRUE);
index d94a0db..fe5f9f8 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 wintty.c        $NHDT-Date: 1449052583 2015/12/02 10:36:23 $  $NHDT-Branch: master $:$NHDT-Revision: 1.116 $ */
+/* NetHack 3.6 wintty.c        $NHDT-Date: 1520825319 2018/03/12 03:28:39 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.142 $ */
 /* Copyright (c) David Cohrs, 1991                                */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -37,12 +37,20 @@ extern void msmsg(const char *, ...);
 #include "wintty.h"
 
 #ifdef CLIPPING /* might want SIGWINCH */
-#if defined(BSD) || defined(ULTRIX) || defined(AIX_31) \
-    || defined(_BULL_SOURCE)
+#if defined(BSD) || defined(ULTRIX) || defined(AIX_31) || defined(_BULL_SOURCE)
 #include <signal.h>
 #endif
 #endif
 
+#ifdef TTY_TILES_ESCCODES
+extern short glyph2tile[];
+#define TILE_ANSI_COMMAND 'z'
+#define AVTC_GLYPH_START   0
+#define AVTC_GLYPH_END     1
+#define AVTC_SELECT_WINDOW 2
+#define AVTC_INLINE_SYNC   3
+#endif
+
 extern char mapped_menu_cmds[]; /* from options.c */
 
 /* this is only needed until tty_status_* routines are written */
@@ -51,17 +59,22 @@ extern NEARDATA winid WIN_STATUS;
 /* Interface definition, for windows.c */
 struct window_procs tty_procs = {
     "tty",
+    (0
 #ifdef MSDOS
-    WC_TILED_MAP | WC_ASCII_MAP |
+     | WC_TILED_MAP | WC_ASCII_MAP
 #endif
 #if defined(WIN32CON)
-        WC_MOUSE_SUPPORT |
+     | WC_MOUSE_SUPPORT
 #endif
-        WC_COLOR | WC_HILITE_PET | WC_INVERSE | WC_EIGHT_BIT_IN,
+     | WC_COLOR | WC_HILITE_PET | WC_INVERSE | WC_EIGHT_BIT_IN),
+    (0
 #if defined(SELECTSAVED)
-    WC2_SELECTSAVED |
+     | WC2_SELECTSAVED
 #endif
-        WC2_DARKGRAY,
+#if defined(STATUS_HILITES)
+     | WC2_HILITE_STATUS | WC2_HITPOINTBAR | WC2_FLUSH_STATUS
+#endif
+     | WC2_DARKGRAY),
     tty_init_nhwindows, tty_player_selection, tty_askname, tty_get_nh_event,
     tty_exit_nhwindows, tty_suspend_nhwindows, tty_resume_nhwindows,
     tty_create_nhwindow, tty_clear_nhwindow, tty_display_nhwindow,
@@ -94,13 +107,12 @@ struct window_procs tty_procs = {
     genl_preference_update,
 #endif
     tty_getmsghistory, tty_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     tty_status_init,
     genl_status_finish, genl_status_enablefield,
-    tty_status_update,
 #ifdef STATUS_HILITES
-    tty_status_threshold,
-#endif
+    tty_status_update,
+#else
+    genl_status_update,
 #endif
     genl_can_suspend_yes,
 };
@@ -150,14 +162,15 @@ STATIC_DCL void FDECL(erase_menu_or_text,
 STATIC_DCL void FDECL(free_window_info, (struct WinDesc *, BOOLEAN_P));
 STATIC_DCL void FDECL(dmore, (struct WinDesc *, const char *));
 STATIC_DCL void FDECL(set_item_state, (winid, int, tty_menu_item *));
-STATIC_DCL void FDECL(set_all_on_page,
-                      (winid, tty_menu_item *, tty_menu_item *));
-STATIC_DCL void FDECL(unset_all_on_page,
-                      (winid, tty_menu_item *, tty_menu_item *));
-STATIC_DCL void FDECL(invert_all_on_page,
-                      (winid, tty_menu_item *, tty_menu_item *, CHAR_P));
-STATIC_DCL void FDECL(invert_all,
-                      (winid, tty_menu_item *, tty_menu_item *, CHAR_P));
+STATIC_DCL void FDECL(set_all_on_page, (winid, tty_menu_item *,
+                                        tty_menu_item *));
+STATIC_DCL void FDECL(unset_all_on_page, (winid, tty_menu_item *,
+                                          tty_menu_item *));
+STATIC_DCL void FDECL(invert_all_on_page, (winid, tty_menu_item *,
+                                           tty_menu_item *, CHAR_P));
+STATIC_DCL void FDECL(invert_all, (winid, tty_menu_item *,
+                                   tty_menu_item *, CHAR_P));
+STATIC_DCL void FDECL(toggle_menu_attr, (BOOLEAN_P, int, int));
 STATIC_DCL void FDECL(process_menu_window, (winid, struct WinDesc *));
 STATIC_DCL void FDECL(process_text_window, (winid, struct WinDesc *));
 STATIC_DCL tty_menu_item *FDECL(reverse, (tty_menu_item *));
@@ -181,6 +194,36 @@ static const char default_menu_cmds[] = {
     MENU_INVERT_PAGE,   MENU_SEARCH,      0 /* null terminator */
 };
 
+#ifdef TTY_TILES_ESCCODES
+static int vt_tile_current_window = -2;
+
+void
+print_vt_code(i, c, d)
+int i, c, d;
+{
+    if (iflags.vt_tiledata) {
+        if (c >= 0) {
+            if (i == AVTC_SELECT_WINDOW) {
+                if (c == vt_tile_current_window) return;
+                vt_tile_current_window = c;
+            }
+            if (d >= 0)
+                printf("\033[1;%d;%d;%d%c", i, c, d, TILE_ANSI_COMMAND);
+            else
+                printf("\033[1;%d;%d%c", i, c, TILE_ANSI_COMMAND);
+        } else {
+            printf("\033[1;%d%c", i, TILE_ANSI_COMMAND);
+        }
+    }
+}
+#else
+# define print_vt_code(i, c, d) ;
+#endif /* !TTY_TILES_ESCCODES */
+#define print_vt_code1(i)     print_vt_code((i), -1, -1)
+#define print_vt_code2(i,c)   print_vt_code((i), (c), -1)
+#define print_vt_code3(i,c,d) print_vt_code((i), (c), (d))
+
+
 /* clean up and quit */
 STATIC_OVL void
 bail(mesg)
@@ -188,13 +231,26 @@ const char *mesg;
 {
     clearlocks();
     tty_exit_nhwindows(mesg);
-    terminate(EXIT_SUCCESS);
+    nh_terminate(EXIT_SUCCESS);
     /*NOTREACHED*/
 }
 
 #if defined(SIGWINCH) && defined(CLIPPING)
+STATIC_DCL void FDECL(winch_handler, (int));
+
+    /*
+     * This really ought to just set a flag like the hangup handler does,
+     * then check the flag at "safe" times, in case the signal arrives
+     * while something fragile is executing.  Better to have a brief period
+     * where display updates don't fit the new size than for tty internals
+     * to become corrupted.
+     *
+     * 'winch_seen' has been "notyet" for a long time....
+     */
+/*ARGUSED*/
 STATIC_OVL void
-winch()
+winch_handler(sig_unused) /* signal handler is called with at least 1 arg */
+int sig_unused UNUSED;
 {
     int oldLI = LI, oldCO = CO, i;
     register struct WinDesc *cw;
@@ -312,12 +368,9 @@ char **argv UNUSED;
     ttyDisplay->lastwin = WIN_ERR;
 
 #if defined(SIGWINCH) && defined(CLIPPING) && !defined(NO_SIGNAL)
-    (void) signal(SIGWINCH, winch);
+    (void) signal(SIGWINCH, (SIG_RET_TYPE) winch_handler);
 #endif
 
-    /* add one a space forward menu command alias */
-    add_menu_cmd_alias(' ', MENU_NEXT_PAGE);
-
     tty_clear_nhwindow(BASE_WINDOW);
 
     tty_putstr(BASE_WINDOW, 0, "");
@@ -344,14 +397,25 @@ void
 tty_player_selection()
 {
     int i, k, n, choice, nextpick;
-    boolean getconfirmation;
+    boolean getconfirmation, picksomething;
     char pick4u = 'n';
     char pbuf[QBUFSZ], plbuf[QBUFSZ];
     winid win;
     anything any;
     menu_item *selected = 0;
 
-    if (flags.randomall) {
+    /* Used to avoid "Is this ok?" if player has already specified all
+     * four facets of role.
+     * Note that rigid_role_checks might force any unspecified facets to
+     * have a specific value, but that will still require confirmation;
+     * player can specify the forced ones if avoiding that is demanded.
+     */
+    picksomething = (ROLE == ROLE_NONE || RACE == ROLE_NONE
+                     || GEND == ROLE_NONE || ALGN == ROLE_NONE);
+    /* Used for '-@';
+     * choose randomly without asking for all unspecified facets.
+     */
+    if (flags.randomall && picksomething) {
         if (ROLE == ROLE_NONE)
             ROLE = ROLE_RANDOM;
         if (RACE == ROLE_NONE)
@@ -362,7 +426,8 @@ tty_player_selection()
             ALGN = ROLE_RANDOM;
     }
 
-    /* prevent an unnecessary prompt */
+    /* prevent unnecessary prompting if role forces race (samurai) or gender
+       (valkyrie) or alignment (rogue), or race forces alignment (orc), &c */
     rigid_role_checks();
 
     /* Should we randomly pick for the player? */
@@ -429,23 +494,38 @@ makepicks:
                     /* populate the menu with role choices */
                     setup_rolemenu(win, TRUE, RACE, GEND, ALGN);
                     /* add miscellaneous menu entries */
-                    role_menu_extra(ROLE_RANDOM, win);
-                    any.a_int = 0; /* separator, not a choice */
-                    add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
+                    role_menu_extra(ROLE_RANDOM, win, TRUE);
+                    any = zeroany; /* separator, not a choice */
+                    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
                              MENU_UNSELECTED);
-                    role_menu_extra(RS_RACE, win);
-                    role_menu_extra(RS_GENDER, win);
-                    role_menu_extra(RS_ALGNMNT, win);
+                    role_menu_extra(RS_RACE, win, FALSE);
+                    role_menu_extra(RS_GENDER, win, FALSE);
+                    role_menu_extra(RS_ALGNMNT, win, FALSE);
                     if (gotrolefilter())
-                        role_menu_extra(RS_filter, win);
-                    role_menu_extra(ROLE_NONE, win); /* quit */
+                        role_menu_extra(RS_filter, win, FALSE);
+                    role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
 /*JP
                     Strcpy(pbuf, "Pick a role or profession");
 */
                     Strcpy(pbuf, "\90E\8bÆ\82ð\91I\82ñ\82Å\82­\82¾\82³\82¢");
                     end_menu(win, pbuf);
                     n = select_menu(win, PICK_ONE, &selected);
-                    choice = (n == 1) ? selected[0].item.a_int : ROLE_NONE;
+                    /*
+                     * PICK_ONE with preselected choice behaves strangely:
+                     *  n == -1 -- <escape>, so use quit choice;
+                     *  n ==  0 -- explicitly chose preselected entry,
+                     *             toggling it off, so use it;
+                     *  n ==  1 -- implicitly chose preselected entry
+                     *             with <space> or <return>;
+                     *  n ==  2 -- explicitly chose a different entry, so
+                     *             both it and preselected one are in list.
+                     */
+                    if (n > 0) {
+                        choice = selected[0].item.a_int;
+                        if (n > 1 && choice == ROLE_RANDOM)
+                            choice = selected[1].item.a_int;
+                    } else
+                        choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
                     if (selected)
                         free((genericptr_t) selected), selected = 0;
                     destroy_nhwindow(win);
@@ -516,24 +596,28 @@ makepicks:
                         /* populate the menu with role choices */
                         setup_racemenu(win, TRUE, ROLE, GEND, ALGN);
                         /* add miscellaneous menu entries */
-                        role_menu_extra(ROLE_RANDOM, win);
+                        role_menu_extra(ROLE_RANDOM, win, TRUE);
                         any.a_int = 0; /* separator, not a choice */
-                        add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
+                        add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
                                  MENU_UNSELECTED);
-                        role_menu_extra(RS_ROLE, win);
-                        role_menu_extra(RS_GENDER, win);
-                        role_menu_extra(RS_ALGNMNT, win);
+                        role_menu_extra(RS_ROLE, win, FALSE);
+                        role_menu_extra(RS_GENDER, win, FALSE);
+                        role_menu_extra(RS_ALGNMNT, win, FALSE);
                         if (gotrolefilter())
-                            role_menu_extra(RS_filter, win);
-                        role_menu_extra(ROLE_NONE, win); /* quit */
+                            role_menu_extra(RS_filter, win, FALSE);
+                        role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
 /*JP
                         Strcpy(pbuf, "Pick a race or species");
 */
                         Strcpy(pbuf, "\8eí\91°\82ð\91I\82ñ\82Å\82­\82¾\82³\82¢");
                         end_menu(win, pbuf);
                         n = select_menu(win, PICK_ONE, &selected);
-                        choice = (n == 1) ? selected[0].item.a_int
-                                          : ROLE_NONE;
+                        if (n > 0) {
+                            choice = selected[0].item.a_int;
+                            if (n > 1 && choice == ROLE_RANDOM)
+                                choice = selected[1].item.a_int;
+                        } else
+                            choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
                         if (selected)
                             free((genericptr_t) selected), selected = 0;
                         destroy_nhwindow(win);
@@ -608,24 +692,28 @@ makepicks:
                         /* populate the menu with gender choices */
                         setup_gendmenu(win, TRUE, ROLE, RACE, ALGN);
                         /* add miscellaneous menu entries */
-                        role_menu_extra(ROLE_RANDOM, win);
+                        role_menu_extra(ROLE_RANDOM, win, TRUE);
                         any.a_int = 0; /* separator, not a choice */
-                        add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
+                        add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
                                  MENU_UNSELECTED);
-                        role_menu_extra(RS_ROLE, win);
-                        role_menu_extra(RS_RACE, win);
-                        role_menu_extra(RS_ALGNMNT, win);
+                        role_menu_extra(RS_ROLE, win, FALSE);
+                        role_menu_extra(RS_RACE, win, FALSE);
+                        role_menu_extra(RS_ALGNMNT, win, FALSE);
                         if (gotrolefilter())
-                            role_menu_extra(RS_filter, win);
-                        role_menu_extra(ROLE_NONE, win); /* quit */
+                            role_menu_extra(RS_filter, win, FALSE);
+                        role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
 /*JP
                         Strcpy(pbuf, "Pick a gender or sex");
 */
                         Strcpy(pbuf, "\90«\95Ê\82ð\91I\82ñ\82Å\82­\82¾\82³\82¢");
                         end_menu(win, pbuf);
                         n = select_menu(win, PICK_ONE, &selected);
-                        choice = (n == 1) ? selected[0].item.a_int
-                                          : ROLE_NONE;
+                        if (n > 0) {
+                            choice = selected[0].item.a_int;
+                            if (n > 1 && choice == ROLE_RANDOM)
+                                choice = selected[1].item.a_int;
+                        } else
+                            choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
                         if (selected)
                             free((genericptr_t) selected), selected = 0;
                         destroy_nhwindow(win);
@@ -696,24 +784,28 @@ makepicks:
                         start_menu(win);
                         any = zeroany; /* zero out all bits */
                         setup_algnmenu(win, TRUE, ROLE, RACE, GEND);
-                        role_menu_extra(ROLE_RANDOM, win);
+                        role_menu_extra(ROLE_RANDOM, win, TRUE);
                         any.a_int = 0; /* separator, not a choice */
-                        add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "",
+                        add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "",
                                  MENU_UNSELECTED);
-                        role_menu_extra(RS_ROLE, win);
-                        role_menu_extra(RS_RACE, win);
-                        role_menu_extra(RS_GENDER, win);
+                        role_menu_extra(RS_ROLE, win, FALSE);
+                        role_menu_extra(RS_RACE, win, FALSE);
+                        role_menu_extra(RS_GENDER, win, FALSE);
                         if (gotrolefilter())
-                            role_menu_extra(RS_filter, win);
-                        role_menu_extra(ROLE_NONE, win); /* quit */
+                            role_menu_extra(RS_filter, win, FALSE);
+                        role_menu_extra(ROLE_NONE, win, FALSE); /* quit */
 /*JP
                         Strcpy(pbuf, "Pick an alignment or creed");
 */
                         Strcpy(pbuf, "\91®\90«\82ð\91I\82ñ\82Å\82­\82¾\82³\82¢");
                         end_menu(win, pbuf);
                         n = select_menu(win, PICK_ONE, &selected);
-                        choice = (n == 1) ? selected[0].item.a_int
-                                          : ROLE_NONE;
+                        if (n > 0) {
+                            choice = selected[0].item.a_int;
+                            if (n > 1 && choice == ROLE_RANDOM)
+                                choice = selected[1].item.a_int;
+                        } else
+                            choice = (n == 0) ? ROLE_RANDOM : ROLE_NONE;
                         if (selected)
                             free((genericptr_t) selected), selected = 0;
                         destroy_nhwindow(win);
@@ -767,7 +859,7 @@ makepicks:
      *           q - quit
      *           (end)
      */
-    getconfirmation = (pick4u != 'a' && !flags.randomall);
+    getconfirmation = (picksomething && pick4u != 'a' && !flags.randomall);
     while (getconfirmation) {
         tty_clear_nhwindow(BASE_WINDOW);
         role_selection_prolog(ROLE_NONE, BASE_WINDOW);
@@ -795,11 +887,11 @@ makepicks:
                 (GEND == 1 && roles[ROLE].name.f) ? roles[ROLE].name.f
                                                   : roles[ROLE].name.m);
 #endif
-        add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, pbuf,
+        add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, pbuf,
                  MENU_UNSELECTED);
         /* blank separator */
         any.a_int = 0;
-        add_menu(win, NO_GLYPH, &any, ' ', 0, ATR_NONE, "", MENU_UNSELECTED);
+        add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
         /* [ynaq] menu choices */
         any.a_int = 1;
 /*JP
@@ -1157,6 +1249,8 @@ tty_askname()
         while ((c = tty_nhgetch()) != '\n') {
             if (c == EOF)
                 c = '\033';
+            if (c == '\r')
+                break;
             if (c == '\033') {
                 ct = 0;
                 break;
@@ -1321,9 +1415,7 @@ const char *str;
         }
     }
     WIN_MAP = WIN_MESSAGE = WIN_INVEN = WIN_ERR; /* these are all gone now */
-#ifndef STATUS_VIA_WINDOWPORT
     WIN_STATUS = WIN_ERR;
-#endif
 #ifdef FREE_ALL_MEMORY
     if (BASE_WINDOW != WIN_ERR && wins[BASE_WINDOW]) {
         free_window_info(wins[BASE_WINDOW], TRUE);
@@ -1530,6 +1622,8 @@ winid window;
         panic(winpanicstr, window);
     ttyDisplay->lastwin = window;
 
+    print_vt_code2(AVTC_SELECT_WINDOW, window);
+
     switch (cw->type) {
     case NHW_MESSAGE:
         if (ttyDisplay->toplin) {
@@ -1549,7 +1643,7 @@ winid window;
     case NHW_MAP:
         /* cheap -- clear the whole thing and tell nethack to redraw botl */
         context.botlx = 1;
-    /* fall into ... */
+        /*FALLTHRU*/
     case NHW_BASE:
         clear_screen();
         break;
@@ -1737,6 +1831,31 @@ char acc; /* group accelerator, 0 => all */
     }
 }
 
+/* support menucolor in addition to caller-supplied attribute */
+STATIC_OVL void
+toggle_menu_attr(on, color, attr)
+boolean on;
+int color, attr;
+{
+    if (on) {
+        term_start_attr(attr);
+#ifdef TEXTCOLOR
+        if (color != NO_COLOR)
+            term_start_color(color);
+#endif
+    } else {
+#ifdef TEXTCOLOR
+        if (color != NO_COLOR)
+            term_end_color();
+#endif
+        term_end_attr(attr);
+    }
+
+#ifndef TEXTCOLOR
+    nhUse(color);
+#endif
+}
+
 STATIC_OVL void
 process_menu_window(window, cw)
 winid window;
@@ -1744,7 +1863,7 @@ struct WinDesc *cw;
 {
     tty_menu_item *page_start, *page_end, *curr;
     long count;
-    int n, curr_page, page_lines, resp_len;
+    int n, attr_n, curr_page, page_lines, resp_len;
     boolean finished, counting, reset_count;
     char *cp, *rp, resp[QBUFSZ], gacc[QBUFSZ], *msave, *morestr, really_morc;
 #define MENU_EXPLICIT_CHOICE 0x7f /* pseudo menu manipulation char */
@@ -1815,8 +1934,8 @@ struct WinDesc *cw;
                 page_end = cw->plist[curr_page + 1];
                 for (page_lines = 0, curr = page_start; curr != page_end;
                      page_lines++, curr = curr->next) {
-                    int color = NO_COLOR, attr = ATR_NONE;
-                    boolean menucolr = FALSE;
+                    int attr, color = NO_COLOR;
+
                     if (curr->selector)
                         *rp++ = curr->selector;
 
@@ -1830,6 +1949,23 @@ struct WinDesc *cw;
                    (void) jputchar(' ');
 #endif
                     ++ttyDisplay->curx;
+
+                    if (!iflags.use_menu_color
+                        || !get_menu_coloring(curr->str, &color, &attr))
+                        attr = curr->attr;
+
+                    /* which character to start attribute highlighting;
+                       whole line for headers and such, after the selector
+                       character and space and selection indicator for menu
+                       lines (including fake ones that simulate grayed-out
+                       entries, so we don't rely on curr->identifier here) */
+                    attr_n = 0; /* whole line */
+                    if (curr->str[0] && curr->str[1] == ' '
+                        && curr->str[2] && index("-+#", curr->str[2])
+                        && curr->str[3] == ' ')
+                        /* [0]=letter, [1]==space, [2]=[-+#], [3]=space */
+                        attr_n = 4; /* [4:N]=entry description */
+
                     /*
                      * Don't use xputs() because (1) under unix it calls
                      * tputstr() which will interpret a '*' as some kind
@@ -1837,55 +1973,43 @@ struct WinDesc *cw;
                      * actually output the character.  We're faster doing
                      * this.
                      */
-                    if (iflags.use_menu_color
-                        && (menucolr = get_menu_coloring(curr->str, &color,
-                                                         &attr))) {
-                        term_start_attr(attr);
-#ifdef TEXTCOLOR
-                        if (color != NO_COLOR)
-                            term_start_color(color);
-#endif
-                    } else
-                        term_start_attr(curr->attr);
                     for (n = 0, cp = curr->str;
+                         *cp &&
 #ifndef WIN32CON
-                         *cp
-                         && (int) ++ttyDisplay->curx < (int) ttyDisplay->cols;
-                         cp++, n++)
+                            (int) ++ttyDisplay->curx < (int) ttyDisplay->cols;
 #else
-                         *cp
-                         && (int) ttyDisplay->curx < (int) ttyDisplay->cols;
-                         cp++, n++, ttyDisplay->curx++)
+                            (int) ttyDisplay->curx < (int) ttyDisplay->cols;
+                         ttyDisplay->curx++,
 #endif
-                        if (n == 2 && curr->identifier.a_void != 0
+                         cp++, n++) {
+                        if (n == attr_n && (color != NO_COLOR
+                                            || attr != ATR_NONE))
+                            toggle_menu_attr(TRUE, color, attr);
+                        if (n == 2
+                            && curr->identifier.a_void != 0
                             && curr->selected) {
                             if (curr->count == -1L)
 #if 0 /*JP*/
                                 (void) putchar('+'); /* all selected */
 #else
-                               (void) jputchar('+'); /* all selected */
+                                (void) jputchar('+'); /* all selected */
 #endif
                             else
 #if 0 /*JP*/
                                 (void) putchar('#'); /* count selected */
 #else
-                               (void) jputchar('#'); /* count selected */
+                                (void) jputchar('#'); /* count selected */
 #endif
                         } else
 #if 0 /*JP*/
                             (void) putchar(*cp);
 #else
-                           (void) jputchar(*cp);
-#endif
-                    if (iflags.use_menu_color && menucolr) {
-#ifdef TEXTCOLOR
-                        if (color != NO_COLOR)
-                            term_end_color();
+                            (void) jputchar(*cp);
 #endif
-                        term_end_attr(attr);
-                    } else
-                        term_end_attr(curr->attr);
-                }
+                    } /* for *cp */
+                    if (n > attr_n && (color != NO_COLOR || attr != ATR_NONE))
+                        toggle_menu_attr(FALSE, color, attr);
+                } /* if npages > 0 */
             } else {
                 page_start = 0;
                 page_end = 0;
@@ -1905,6 +2029,7 @@ struct WinDesc *cw;
 
             /* set extra chars.. */
             Strcat(resp, default_menu_cmds);
+            Strcat(resp, " ");                  /* next page or end */
             Strcat(resp, "0123456789\033\n\r"); /* counts, quit */
             Strcat(resp, gacc);                 /* group accelerators */
             Strcat(resp, mapped_menu_cmds);
@@ -1944,7 +2069,8 @@ struct WinDesc *cw;
             /* special case: '0' is also the default ball class */
             if (!counting && index(gacc, morc))
                 goto group_accel;
-        /* fall through to count the zero */
+            /* fall through to count the zero */
+            /*FALLTHRU*/
         case '1':
         case '2':
         case '3':
@@ -1992,12 +2118,15 @@ struct WinDesc *cw;
                 break;
             }
         /* else fall through */
+        case ' ':
         case MENU_NEXT_PAGE:
             if (cw->npages > 0 && curr_page != cw->npages - 1) {
                 curr_page++;
                 page_start = 0;
-            } else
-                finished = TRUE; /* questionable behavior */
+            } else if (morc == ' ') {
+                /* ' ' finishes menus here, but stop '>' doing the same. */
+                finished = TRUE;
+            }
             break;
         case MENU_PREVIOUS_PAGE:
             if (cw->npages > 0 && curr_page != 0) {
@@ -2207,6 +2336,8 @@ boolean blocking; /* with ttys, all windows are blocking */
     ttyDisplay->lastwin = window;
     ttyDisplay->rawprint = 0;
 
+    print_vt_code2(AVTC_SELECT_WINDOW, window);
+
     switch (cw->type) {
     case NHW_MESSAGE:
         if (ttyDisplay->toplin == 1) {
@@ -2227,6 +2358,7 @@ boolean blocking; /* with ttys, all windows are blocking */
             tty_display_nhwindow(WIN_MESSAGE, TRUE);
             return;
         }
+        /*FALLTHRU*/
     case NHW_BASE:
         (void) fflush(stdout);
         break;
@@ -2255,13 +2387,15 @@ boolean blocking; /* with ttys, all windows are blocking */
         if (ttyDisplay->toplin == 1)
             tty_display_nhwindow(WIN_MESSAGE, TRUE);
 #ifdef H2344_BROKEN
-        if (cw->maxrow >= (int) ttyDisplay->rows)
+        if (cw->maxrow >= (int) ttyDisplay->rows
+            || !iflags.menu_overlay)
 #else
-        if (cw->offx == 10 || cw->maxrow >= (int) ttyDisplay->rows)
+        if (cw->offx == 10 || cw->maxrow >= (int) ttyDisplay->rows
+            || !iflags.menu_overlay)
 #endif
         {
             cw->offx = 0;
-            if (cw->offy) {
+            if (cw->offy || iflags.menu_overlay) {
                 tty_curs(window, 1, 0);
                 cl_eos();
             } else
@@ -2290,6 +2424,8 @@ winid window;
     if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0)
         panic(winpanicstr, window);
 
+    print_vt_code2(AVTC_SELECT_WINDOW, window);
+
     switch (cw->type) {
     case NHW_MESSAGE:
         if (ttyDisplay->toplin)
@@ -2359,6 +2495,8 @@ register int x, y; /* not xchar: perhaps xchar is unsigned and
         panic(winpanicstr, window);
     ttyDisplay->lastwin = window;
 
+    print_vt_code2(AVTC_SELECT_WINDOW, window);
+
 #if defined(USE_TILES) && defined(MSDOS)
     adjust_cursor_flags(cw);
 #endif
@@ -2389,7 +2527,13 @@ register int x, y; /* not xchar: perhaps xchar is unsigned and
         }
         debugpline4("bad curs positioning win %d %s (%d,%d)", window, s, x,
                     y);
-        return;
+        /* This return statement caused a functional difference between DEBUG and
+           non-DEBUG operation, so it is being commented out. It caused tty_curs()
+           to fail to move the cursor to the location it needed to be if the x,y
+           range checks failed, leaving the next piece of output to be displayed
+           at whatever random location the cursor happened to be at prior. */
+
+        /* return; */
     }
 #endif
     x += cw->offx;
@@ -2454,6 +2598,8 @@ char ch;
     if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0)
         panic(winpanicstr, window);
 
+    print_vt_code2(AVTC_SELECT_WINDOW, window);
+
     switch (cw->type) {
     case NHW_STATUS:
     case NHW_MAP:
@@ -2487,22 +2633,30 @@ compress_str(str)
 const char *str;
 {
     static char cbuf[BUFSZ];
-    /* compress in case line too long */
-    if ((int) strlen(str) >= CO) {
-        register const char *bp0 = str;
-        register char *bp1 = cbuf;
 
-        do {
-#ifdef CLIPPING
-            if (*bp0 != ' ' || bp0[1] != ' ')
-#else
-            if (*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ')
-#endif
-                *bp1++ = *bp0;
-        } while (*bp0++);
-    } else
-        return str;
-    return cbuf;
+    /* compress out consecutive spaces if line is too long;
+       topline wrapping converts space at wrap point into newline,
+       we reverse that here */
+    if ((int) strlen(str) >= CO || index(str, '\n')) {
+        const char *in_str = str;
+        char c, *outstr = cbuf, *outend = &cbuf[sizeof cbuf - 1];
+        boolean was_space = TRUE; /* True discards all leading spaces;
+                                     False would retain one if present */
+
+        while ((c = *in_str++) != '\0' && outstr < outend) {
+            if (c == '\n')
+                c = ' ';
+            if (was_space && c == ' ')
+                continue;
+            *outstr++ = c;
+            was_space = (c == ' ');
+        }
+        if ((was_space && outstr > cbuf) || outstr == outend)
+            --outstr; /* remove trailing space or make room for terminator */
+        *outstr = '\0';
+        str = cbuf;
+    }
+    return str;
 }
 
 void
@@ -2539,6 +2693,8 @@ const char *str;
 
     ttyDisplay->lastwin = window;
 
+    print_vt_code2(AVTC_SELECT_WINDOW, window);
+
     switch (cw->type) {
     case NHW_MESSAGE:
         /* really do this later */
@@ -2561,7 +2717,16 @@ const char *str;
         nb = str;
         for (i = cw->curx + 1, n0 = cw->cols; i < n0; i++, nb++) {
             if (!*nb) {
+#ifndef STATUS_HILITES
                 if (*ob || context.botlx) {
+#else
+                /* STATUS_HILITES will call cl_end() when finished
+                 * its sequence of putstr's.  We don't want to call
+                 * cl_end() with each putstr() which may cause flashing
+                 * in the Windows port
+                 */
+                if (context.botlx) {
+#endif
                     /* last char printed may be in middle of line */
                     tty_curs(WIN_STATUS, i, cw->cury);
                     cl_end();
@@ -2569,45 +2734,54 @@ const char *str;
                 break;
             }
 #if 0 /*JP*/
-            if (*ob != *nb)
 #else /* this code updates all status line at any time */
 # if 0
-/* check 2-bytes character for Japanese        */
-/* by issei 93/12/2                    */
-           uc = *((unsigned char *)nb);
-           if((!(uc & 0x80) && *ob != *nb) || kflg){
-             tty_putsym(WIN_STATUS, i, cw->cury, *nb);
-           }
-           else{
-             if(*ob != *nb || *(ob+1)!= *(nb+1)){
-               tty_putsym(WIN_STATUS, i, cw->cury, *nb);
-               kflg = 1;
-             }
-           }
-# endif        /* 0 */
-#define ismbchar(c)    (((unsigned char)(c)) & 0x80)
-#define KANJI2 1
-#define KUPDATE        2
-           if (kchar2)                 /* kanji 2nd byte */
-           {
-               if (kchar2 & KUPDATE)
-                   tty_putsym(WIN_STATUS, i, cw->cury, *nb);
-               kchar2 = 0;
-           }
-           else if (ismbchar(*nb))     /* kanji 1st byte */
-           {
-               kchar2 = KANJI2;
-               /* Kanji char must be checked as 2-bytes pair. */
-               /* check i to prevent putting only kanji 1st byte at last. */
-               if ((*nb != *ob || *(nb+1) != *(ob+1)) && i < n0-1)
-               {
-                   tty_putsym(WIN_STATUS, i, cw->cury, *nb);
-                   kchar2 |= KUPDATE;  /* must do update */
-               }
-               /* else nb is the same char as old, so need not to update */
-           }
-           /* not kanji char */
-           else if (*nb != *ob)
+/* check 2-bytes character for Japanese */
+/* by issei 93/12/2                     */
+            uc = *((unsigned char *)nb);
+            if((!(uc & 0x80) && *ob != *nb) || kflg){
+              tty_putsym(WIN_STATUS, i, cw->cury, *nb);
+            }
+            else{
+              if(*ob != *nb || *(ob+1)!= *(nb+1)){
+                tty_putsym(WIN_STATUS, i, cw->cury, *nb);
+                kflg = 1;
+              }
+            }
+# endif /* 0 */
+#define ismbchar(c)     (((unsigned char)(c)) & 0x80)
+#define KANJI2  1
+#define KUPDATE 2
+            if (kchar2)                 /* kanji 2nd byte */
+            {
+                if (kchar2 & KUPDATE)
+                    tty_putsym(WIN_STATUS, i, cw->cury, *nb);
+                kchar2 = 0;
+            }
+            else if (ismbchar(*nb))     /* kanji 1st byte */
+            {
+                kchar2 = KANJI2;
+                /* Kanji char must be checked as 2-bytes pair. */
+                /* check i to prevent putting only kanji 1st byte at last. */
+                if ((*nb != *ob || *(nb+1) != *(ob+1)) && i < n0-1)
+                {
+                    tty_putsym(WIN_STATUS, i, cw->cury, *nb);
+                    kchar2 |= KUPDATE;  /* must do update */
+                }
+                /* else nb is the same char as old, so need not to update */
+            }
+            /* not kanji char */
+            else
+#endif
+#ifdef STATUS_HILITES
+            /* Don't optimize the putsym away, in case it happens
+               to be the same character but different color/attr.
+               We don't optimize on iflags.use_status_hilites either,
+               in case old chars were written with highlighting and
+               that option has just now been toggled off.  [We could
+               do better by tracking color/attr more closely.] */
+#else
+            if (*ob != *nb)
 #endif
                 tty_putsym(WIN_STATUS, i, cw->cury, *nb);
             if (*ob)
@@ -2616,13 +2790,9 @@ const char *str;
 
         (void) strncpy(&cw->data[cw->cury][j], str, cw->cols - j - 1);
         cw->data[cw->cury][cw->cols - 1] = '\0'; /* null terminate */
-#ifdef STATUS_VIA_WINDOWPORT
-        if (!iflags.use_status_hilites) {
-#endif
-            cw->cury = (cw->cury + 1) % 2;
-            cw->curx = 0;
-#ifdef STATUS_VIA_WINDOWPORT
-        }
+#ifndef STATUS_HILITES
+        cw->cury = (cw->cury + 1) % 2;
+        cw->curx = 0;
 #endif
         break;
     case NHW_MAP:
@@ -2698,7 +2868,7 @@ const char *str;
         }
         if (cw->data[cw->cury])
             free((genericptr_t) cw->data[cw->cury]);
-        n0 = strlen(str) + 1;
+        n0 = (long) strlen(str) + 1L;
         ob = cw->data[cw->cury] = (char *) alloc((unsigned) n0 + 1);
         *ob++ = (char) (attr + 1); /* avoid nuls, for convenience */
         Strcpy(ob, str);
@@ -2755,7 +2925,7 @@ boolean complain;
             }
             if (complain)
                 sleep(10); /* want to wait_synch() but stdin is gone */
-            terminate(EXIT_FAILURE);
+            nh_terminate(EXIT_FAILURE);
         }
         (void) close(fd);
 #ifdef notyet
@@ -3127,10 +3297,17 @@ register int xmin, ymax;
     register int y;
     register struct WinDesc *cw = wins[WIN_MAP];
 
+#if 0   /* this optimization is not valuable enough to justify
+           abusing core internals... */
     if (u.uswallow) { /* Can be done more efficiently */
         swallowed(1);
+        /* without this flush, if we happen to follow --More-- displayed in
+           leftmost column, the cursor gets left in the wrong place after
+           <docorner<more<update_topl<tty_putstr calls unwind back to core */
+        flush_screen(0);
         return;
     }
+#endif /*0*/
 
 #if defined(SIGWINCH) && defined(CLIPPING)
     if (ymax > LI)
@@ -3298,9 +3475,13 @@ int bkglyph UNUSED;
     /* map glyph to character and color */
     (void) mapglyph(glyph, &ch, &color, &special, x, y);
 
+    print_vt_code2(AVTC_SELECT_WINDOW, window);
+
     /* Move the cursor. */
     tty_curs(window, x, y);
 
+    print_vt_code3(AVTC_GLYPH_START, glyph2tile[glyph], special);
+
 #ifndef NO_TERMS
     if (ul_hack && ch == '_') { /* non-destructive underscore */
 # if 0 /*JP*/
@@ -3325,7 +3506,8 @@ int bkglyph UNUSED;
     /* must be after color check; term_end_color may turn off inverse too */
     if (((special & MG_PET) && iflags.hilite_pet)
         || ((special & MG_OBJPILE) && iflags.hilite_pile)
-        || ((special & MG_DETECT) && iflags.use_inverse)) {
+        || ((special & MG_DETECT) && iflags.use_inverse)
+        || ((special & MG_BW_LAVA) && iflags.use_inverse)) {
         term_start_attr(ATR_INVERSE);
         reverse_on = TRUE;
     }
@@ -3348,6 +3530,8 @@ int bkglyph UNUSED;
 #endif
     }
 
+    print_vt_code1(AVTC_GLYPH_END);
+
     wins[window]->curx++; /* one character over */
     ttyDisplay->curx++;   /* the real cursor moved too */
 }
@@ -3358,6 +3542,7 @@ const char *str;
 {
     if (ttyDisplay)
         ttyDisplay->rawprint++;
+    print_vt_code2(AVTC_SELECT_WINDOW, NHW_BASE);
 #if defined(MICRO) || defined(WIN32CON)
     msmsg("%s\n", str);
 #else
@@ -3376,6 +3561,7 @@ const char *str;
 {
     if (ttyDisplay)
         ttyDisplay->rawprint++;
+    print_vt_code2(AVTC_SELECT_WINDOW, NHW_BASE);
     term_start_raw_bold();
 #if defined(MICRO) || defined(WIN32CON)
     msmsg("%s", str);
@@ -3411,6 +3597,7 @@ tty_nhgetch()
     char nestbuf;
 #endif
 
+    print_vt_code1(AVTC_INLINE_SYNC);
     (void) fflush(stdout);
     /* Note: if raw_print() and wait_synch() get called to report terminal
      * initialization problems, then wins[] and ttyDisplay might not be
@@ -3433,6 +3620,14 @@ tty_nhgetch()
         i = '\033'; /* same for EOF */
     if (ttyDisplay && ttyDisplay->toplin == 1)
         ttyDisplay->toplin = 2;
+#ifdef TTY_TILES_ESCCODES
+    {
+        /* hack to force output of the window select code */
+        int tmp = vt_tile_current_window;
+        vt_tile_current_window++;
+        print_vt_code2(AVTC_SELECT_WINDOW, tmp);
+    }
+#endif /* TTY_TILES_ESCCODES */
     return i;
 }
 
@@ -3495,58 +3690,40 @@ char *posbar;
 }
 #endif
 
-#ifdef STATUS_VIA_WINDOWPORT
 /*
  * The following data structures come from the genl_ routines in
  * src/windows.c and as such are considered to be on the window-port
  * "side" of things, rather than the NetHack-core "side" of things.
  */
 
-extern const char *status_fieldnm[MAXBLSTATS];
 extern const char *status_fieldfmt[MAXBLSTATS];
 extern char *status_vals[MAXBLSTATS];
 extern boolean status_activefields[MAXBLSTATS];
 extern winid WIN_STATUS;
 
 #ifdef STATUS_HILITES
-typedef struct hilite_data_struct {
-    int thresholdtype;
-    anything threshold;
-    int behavior;
-    int under;
-    int over;
-} hilite_data_t;
-static hilite_data_t tty_status_hilites[MAXBLSTATS];
+static long tty_condition_bits;
 static int tty_status_colors[MAXBLSTATS];
+int hpbar_percent, hpbar_color;
 
-struct color_option {
-    int color;
-    int attr_bits;
-};
-
-static void FDECL(start_color_option, (struct color_option));
-static void FDECL(end_color_option, (struct color_option));
-static void FDECL(apply_color_option, (struct color_option, const char *));
-static void FDECL(add_colored_text, (const char *, char *));
-#endif
+static int FDECL(condcolor, (long, unsigned long *));
+static int FDECL(condattr, (long, unsigned long *));
+#endif /* STATUS_HILITES */
 
 void
 tty_status_init()
 {
+#ifdef STATUS_HILITES
     int i;
 
-    /* let genl_status_init do most of the initialization */
-    genl_status_init();
-
-    for (i = 0; i < MAXBLSTATS; ++i) {
-#ifdef STATUS_HILITES
+    for (i = 0; i < MAXBLSTATS; ++i)
         tty_status_colors[i] = NO_COLOR; /* no color */
-        tty_status_hilites[i].thresholdtype = 0;
-        tty_status_hilites[i].behavior = BL_TH_NONE;
-        tty_status_hilites[i].under = BL_HILITE_NONE;
-        tty_status_hilites[i].over = BL_HILITE_NONE;
+    tty_condition_bits = 0L;
+    hpbar_percent = 0, hpbar_color = NO_COLOR;
 #endif /* STATUS_HILITES */
-    }
+
+    /* let genl_status_init do most of the initialization */
+    genl_status_init();
 }
 
 /*
@@ -3566,35 +3743,119 @@ tty_status_init()
  *      -- ptr is usually a "char *", unless fldindex is BL_CONDITION.
  *         If fldindex is BL_CONDITION, then ptr is a long value with
  *         any or none of the following bits set (from botl.h):
- *              BL_MASK_BLIND           0x00000001L
- *              BL_MASK_CONF            0x00000002L
- *              BL_MASK_FOODPOIS        0x00000004L
- *              BL_MASK_ILL             0x00000008L
- *              BL_MASK_HALLU           0x00000010L
- *              BL_MASK_STUNNED         0x00000020L
- *              BL_MASK_SLIMED          0x00000040L
- *      -- The value passed for BL_GOLD includes a leading
- *         symbol for GOLD "$:nnn". If the window port needs to use
- *         the textual gold amount without the leading "$:" the port
- *         will have to add 2 to the passed "ptr" for the BL_GOLD case.
+ *              BL_MASK_STONE           0x00000001L
+ *              BL_MASK_SLIME           0x00000002L
+ *              BL_MASK_STRNGL          0x00000004L
+ *              BL_MASK_FOODPOIS        0x00000008L
+ *              BL_MASK_TERMILL         0x00000010L
+ *              BL_MASK_BLIND           0x00000020L
+ *              BL_MASK_DEAF            0x00000040L
+ *              BL_MASK_STUN            0x00000080L
+ *              BL_MASK_CONF            0x00000100L
+ *              BL_MASK_HALLU           0x00000200L
+ *              BL_MASK_LEV             0x00000400L
+ *              BL_MASK_FLY             0x00000800L
+ *              BL_MASK_RIDE            0x00001000L
+ *      -- The value passed for BL_GOLD includes an encoded leading
+ *         symbol for GOLD "\GXXXXNNNN:nnn". If the window port needs to use
+ *         the textual gold amount without the leading "$:" the port will
+ *         have to skip past ':' in the passed "ptr" for the BL_GOLD case.
+ *      -- color is an unsigned int.
+ *               color_index = color & 0x00FF;       CLR_* value
+ *               attribute   = color & 0xFF00 >> 8;  BL_* values
+ *         This holds the color and attribute that the field should
+ *         be displayed in.
+ *         This is relevant for everything except BL_CONDITION fldindex.
+ *         If fldindex is BL_CONDITION, this parameter should be ignored,
+ *         as condition hilighting is done via the next colormasks
+ *         parameter instead.
+ *
+ *      -- colormasks - pointer to cond_hilites[] array of colormasks.
+ *         Only relevant for BL_CONDITION fldindex. The window port
+ *         should ignore this parameter for other fldindex values.
+ *         Each condition bit must only ever appear in one of the
+ *         CLR_ array members, but can appear in multiple HL_ATTCLR_
+ *         offsets (because more than one attribute can co-exist).
+ *         See doc/window.doc for more details.
  */
+
+
+/* new approach through status_update() only */
+#define Begin_Attr(m) \
+            if (m) {                                                          \
+                if ((m) & HL_BOLD)                                            \
+                    term_start_attr(ATR_BOLD);                                \
+                if ((m) & HL_INVERSE)                                         \
+                    term_start_attr(ATR_INVERSE);                             \
+                if ((m) & HL_ULINE)                                           \
+                    term_start_attr(ATR_ULINE);                               \
+                if ((m) & HL_BLINK)                                           \
+                    term_start_attr(ATR_BLINK);                               \
+                if ((m) & HL_DIM)                                             \
+                    term_start_attr(ATR_DIM);                                 \
+           }
+
+#define End_Attr(m) \
+            if (m) {                                                          \
+                if ((m) & HL_DIM)                                             \
+                    term_end_attr(ATR_DIM);                                   \
+                if ((m) & HL_BLINK)                                           \
+                    term_end_attr(ATR_BLINK);                                 \
+                if ((m) & HL_ULINE)                                           \
+                    term_end_attr(ATR_ULINE);                                 \
+                if ((m) & HL_INVERSE)                                         \
+                    term_end_attr(ATR_INVERSE);                               \
+                if ((m) & HL_BOLD)                                            \
+                    term_end_attr(ATR_BOLD);                                  \
+           }
+
+#ifdef STATUS_HILITES
+
+#ifdef TEXTCOLOR
+#define MaybeDisplayCond(bm,txt) \
+            if (tty_condition_bits & (bm)) {                                  \
+                putstr(WIN_STATUS, 0, " ");                                   \
+                if (iflags.hilite_delta) {                                    \
+                    attrmask = condattr(bm, colormasks);                      \
+                    Begin_Attr(attrmask);                                     \
+                    if ((coloridx = condcolor(bm, colormasks)) != NO_COLOR)   \
+                        term_start_color(coloridx);                           \
+               }                                                             \
+                putstr(WIN_STATUS, 0, txt);                                   \
+                if (iflags.hilite_delta) {                                    \
+                    if (coloridx != NO_COLOR)                                 \
+                        term_end_color();                                     \
+                    End_Attr(attrmask);                                       \
+               }                                                             \
+            }
+#else
+#define MaybeDisplayCond(bm,txt) \
+            if (tty_condition_bits & (bm)) {                                  \
+                putstr(WIN_STATUS, 0, " ");                                   \
+                if (iflags.hilite_delta) {                                    \
+                    attrmask = condattr(bm, colormasks);                      \
+                    Begin_Attr(attrmask);                                     \
+               }                                                             \
+                putstr(WIN_STATUS, 0, txt);                                   \
+                if (iflags.hilite_delta) {                                    \
+                    End_Attr(attrmask);                                       \
+               }                                                             \
+            }
+#endif
+
 void
-tty_status_update(fldidx, ptr, chg, percent)
-int fldidx, chg, percent;
+tty_status_update(fldidx, ptr, chg, percent, color, colormasks)
+int fldidx, chg UNUSED, percent UNUSED, color;
 genericptr_t ptr;
+unsigned long *colormasks;
 {
-    long cond, *condptr = (long *) ptr;
-    register int i;
+    long *condptr = (long *) ptr;
+    int i, attrmask = 0;
+#ifdef TEXTCOLOR
+    int coloridx = NO_COLOR;
+#endif
     char *text = (char *) ptr;
-    /* Mapping BL attributes to tty attributes
-     * BL_HILITE_NONE     -1 + 3 = 2 (statusattr[2])
-     * BL_HILITE_INVERSE  -2 + 3 = 1 (statusattr[1])
-     * BL_HILITE_BOLD     -3 + 3 = 0 (statusattr[0])
-     */
-    int statusattr[] = { ATR_BOLD, ATR_INVERSE, ATR_NONE };
-    int attridx = 0;
-    long value = -1L;
-    static boolean beenhere = FALSE;
+    static boolean oncearound = FALSE; /* prevent premature partial display */
     enum statusfields fieldorder[2][15] = {
         { BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
           BL_SCORE, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH, BL_FLUSH,
@@ -3603,244 +3864,233 @@ genericptr_t ptr;
           BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER,
           BL_CAP, BL_CONDITION, BL_FLUSH }
     };
+    int attridx = 0;
 
     if (fldidx != BL_FLUSH) {
         if (!status_activefields[fldidx])
             return;
         switch (fldidx) {
         case BL_CONDITION:
-            cond = *condptr;
-            *status_vals[fldidx] = '\0';
-            if (cond & BL_MASK_BLIND)
-                Strcat(status_vals[fldidx], " Blind");
-            if (cond & BL_MASK_CONF)
-                Strcat(status_vals[fldidx], " Conf");
-            if (cond & BL_MASK_FOODPOIS)
-                Strcat(status_vals[fldidx], " FoodPois");
-            if (cond & BL_MASK_ILL)
-                Strcat(status_vals[fldidx], " Ill");
-            if (cond & BL_MASK_STUNNED)
-                Strcat(status_vals[fldidx], " Stun");
-            if (cond & BL_MASK_HALLU)
-                Strcat(status_vals[fldidx], " Hallu");
-            if (cond & BL_MASK_SLIMED)
-                Strcat(status_vals[fldidx], " Slime");
-            value = cond;
+            tty_condition_bits = *condptr;
+            oncearound = TRUE;
             break;
         default:
-            value = atol(text);
             Sprintf(status_vals[fldidx],
+                    (fldidx == BL_TITLE && iflags.wc2_hitpointbar) ? "%-30s" :
                     status_fieldfmt[fldidx] ? status_fieldfmt[fldidx] : "%s",
                     text);
-            break;
-        }
-
-#ifdef STATUS_HILITES
-        switch (tty_status_hilites[fldidx].behavior) {
-        case BL_TH_NONE:
+#ifdef TEXTCOLOR
+            tty_status_colors[fldidx] = color;
+#else
             tty_status_colors[fldidx] = NO_COLOR;
-            break;
-        case BL_TH_UPDOWN:
-            if (chg > 0)
-                tty_status_colors[fldidx] = tty_status_hilites[fldidx].over;
-            else if (chg < 0)
-                tty_status_colors[fldidx] = tty_status_hilites[fldidx].under;
-            else
-                tty_status_colors[fldidx] = NO_COLOR;
-            break;
-        case BL_TH_VAL_PERCENTAGE:  {
-            int pct_th = 0;
-
-            if (tty_status_hilites[fldidx].thresholdtype != ANY_INT) {
-                impossible(
-                "tty_status_update: unsupported percentage threshold type %d",
-                           tty_status_hilites[fldidx].thresholdtype);
-            } else {
-                pct_th = tty_status_hilites[fldidx].threshold.a_int;
-                tty_status_colors[fldidx] = (percent >= pct_th)
-                                           ? tty_status_hilites[fldidx].over
-                                           : tty_status_hilites[fldidx].under;
+#endif
+            if (iflags.wc2_hitpointbar && fldidx == BL_HP) {
+                hpbar_percent = percent;
+#ifdef TEXTCOLOR
+                hpbar_color = color;
+#else
+                hpbar_color = NO_COLOR;
+#endif
             }
             break;
         }
-        case BL_TH_VAL_ABSOLUTE: {
-            int c = NO_COLOR;
-            int o = tty_status_hilites[fldidx].over;
-            int u = tty_status_hilites[fldidx].under;
-            anything *t = &tty_status_hilites[fldidx].threshold;
-
-            switch (tty_status_hilites[fldidx].thresholdtype) {
-            case ANY_LONG:
-                c = (value >= t->a_long) ? o : u;
-                break;
-            case ANY_INT:
-                c = (value >= t->a_int) ? o : u;
-                break;
-            case ANY_UINT:
-                c = ((unsigned long) value >= t->a_uint) ? o : u;
-                break;
-            case ANY_ULONG:
-                c = ((unsigned long) value >= t->a_ulong) ? o : u;
-                break;
-            case ANY_MASK32:
-                c = (value & t->a_ulong) ? o : u;
-                break;
-            default:
-                impossible(
-                "tty_status_update: unsupported absolute threshold type %d\n",
-                           tty_status_hilites[fldidx].thresholdtype);
-                break;
-            }
-            tty_status_colors[fldidx] = c;
-            break;
-        } /* case */
-        } /* switch */
-#endif /* STATUS_HILITES */
     }
 
-    /* For now, this version copied from the genl_ version currently
-     * updates everything on the display, everytime
-     */
-
-    if (!beenhere || !iflags.use_status_hilites) {
-        char newbot1[MAXCO], newbot2[MAXCO];
-
-        newbot1[0] = '\0';
-        for (i = 0; fieldorder[0][i] >= 0; ++i) {
-            int idx1 = fieldorder[0][i];
-
-            if (status_activefields[idx1])
-                Strcat(newbot1, status_vals[idx1]);
-        }
-        newbot2[0] = '\0';
-        for (i = 0; fieldorder[1][i] >= 0; ++i) {
-            int idx2 = fieldorder[1][i];
-
-            if (status_activefields[idx2])
-                Strcat(newbot2, status_vals[idx2]);
-        }
-
-        curs(WIN_STATUS, 1, 0);
-        putstr(WIN_STATUS, 0, newbot1);
-        curs(WIN_STATUS, 1, 1);
-        putmixed(WIN_STATUS, 0, newbot2); /* putmixed() due to GOLD glyph */
-        beenhere = TRUE;
-        return;
-    }
+    if (!oncearound) return;
 
     curs(WIN_STATUS, 1, 0);
     for (i = 0; fieldorder[0][i] != BL_FLUSH; ++i) {
         int fldidx1 = fieldorder[0][i];
-
         if (status_activefields[fldidx1]) {
-            if (tty_status_colors[fldidx1] < 0 &&
-                    tty_status_colors[fldidx1] >= -3) {
-                /* attribute, not a color */
-                attridx = tty_status_colors[fldidx1] + 3;
-                term_start_attr(statusattr[attridx]);
-                putstr(WIN_STATUS, 0, status_vals[fldidx1]);
-                term_end_attr(statusattr[attridx]);
+            if (fldidx1 != BL_TITLE || !iflags.wc2_hitpointbar) {
 #ifdef TEXTCOLOR
-            } else if (tty_status_colors[fldidx1] != CLR_MAX) {
-                if (tty_status_colors[fldidx1] != NO_COLOR)
-                    term_start_color(tty_status_colors[fldidx1]);
-                putstr(WIN_STATUS, 0, status_vals[fldidx1]);
-                if (tty_status_colors[fldidx1] != NO_COLOR)
-                    term_end_color();
+                coloridx = tty_status_colors[fldidx1] & 0x00FF;
 #endif
-            } else
-                putstr(WIN_STATUS, 0, status_vals[fldidx1]);
+                attridx = (tty_status_colors[fldidx1] & 0xFF00) >> 8;
+                text = status_vals[fldidx1];
+                if (iflags.hilite_delta) {
+                    if (*text == ' ') {
+                        putstr(WIN_STATUS, 0, " ");
+                        text++;
+                    }
+                    /* multiple attributes can be in effect concurrently */
+                    Begin_Attr(attridx);
+#ifdef TEXTCOLOR
+                    if (coloridx != NO_COLOR && coloridx != CLR_MAX)
+                       term_start_color(coloridx);
+#endif
+               }
+
+                putstr(WIN_STATUS, 0, text);
+
+                if (iflags.hilite_delta) {
+#ifdef TEXTCOLOR
+                    if (coloridx != NO_COLOR)
+                       term_end_color();
+#endif
+                    End_Attr(attridx);
+                }
+            } else {
+                /* hitpointbar using hp percent calculation */
+                int bar_pos, bar_len;
+                char *bar2 = (char *)0;
+                char bar[MAXCO], savedch;
+                boolean twoparts = FALSE;
+
+                text = status_vals[fldidx1];
+                bar_len = strlen(text);
+                if (bar_len < MAXCO-1) {
+                    Strcpy(bar, text);
+                    bar_pos = (bar_len * hpbar_percent) / 100;
+                    if (bar_pos < 1 && hpbar_percent > 0)
+                        bar_pos = 1;
+                    if (bar_pos >= bar_len && hpbar_percent < 100)
+                        bar_pos = bar_len - 1;
+                    if (bar_pos > 0 && bar_pos < bar_len) {
+                        twoparts = TRUE;
+                        bar2 = &bar[bar_pos];
+                        savedch = *bar2;
+                        *bar2 = '\0';
+                    }
+               }
+                if (iflags.hilite_delta && iflags.wc2_hitpointbar) {
+                    putstr(WIN_STATUS, 0, "[");
+#ifdef TEXTCOLOR
+                    coloridx = hpbar_color & 0x00FF;
+                    /* attridx = (hpbar_color & 0xFF00) >> 8; */
+                    if (coloridx != NO_COLOR)
+                        term_start_color(coloridx);
+#endif
+                    term_start_attr(ATR_INVERSE);
+                    putstr(WIN_STATUS, 0, bar);
+                    term_end_attr(ATR_INVERSE);
+#ifdef TEXTCOLOR
+                    if (coloridx != NO_COLOR)
+                        term_end_color();
+#endif
+                    if (twoparts) {
+                        *bar2 = savedch;
+                        putstr(WIN_STATUS, 0, bar2);
+                    }
+                    putstr(WIN_STATUS, 0, "]");
+                } else
+                    putstr(WIN_STATUS, 0, text);
+            }
         }
     }
+    cl_end();
     curs(WIN_STATUS, 1, 1);
     for (i = 0; fieldorder[1][i] != BL_FLUSH; ++i) {
         int fldidx2 = fieldorder[1][i];
 
         if (status_activefields[fldidx2]) {
-            if (tty_status_colors[fldidx2] < 0 &&
-                    tty_status_colors[fldidx2] >= -3) {
-                /* attribute, not a color */
-                attridx = tty_status_colors[fldidx2] + 3;
-                term_start_attr(statusattr[attridx]);
-                putstr(WIN_STATUS, 0, status_vals[fldidx2]);
-                term_end_attr(statusattr[attridx]);
+            if (fldidx2 != BL_CONDITION) {
 #ifdef TEXTCOLOR
-            } else if (tty_status_colors[fldidx2] != CLR_MAX) {
-                if (tty_status_colors[fldidx2] != NO_COLOR)
-                    term_start_color(tty_status_colors[fldidx2]);
+                coloridx = tty_status_colors[fldidx2] & 0x00FF;
+#endif
+                attridx = (tty_status_colors[fldidx2] & 0xFF00) >> 8;
+                text = status_vals[fldidx2];
+                if (iflags.hilite_delta) {
+                    if (*text == ' ') {
+                        putstr(WIN_STATUS, 0, " ");
+                        text++;
+                    }
+                    /* multiple attributes can be in effect concurrently */
+                    Begin_Attr(attridx);
+#ifdef TEXTCOLOR
+                    if (coloridx != NO_COLOR && coloridx != CLR_MAX)
+                        term_start_color(coloridx);
+#endif
+               }
+
                 if (fldidx2 == BL_GOLD) {
                     /* putmixed() due to GOLD glyph */
-                   putmixed(WIN_STATUS, 0, status_vals[fldidx2]);
+                    putmixed(WIN_STATUS, 0, text);
                 } else {
-                   putstr(WIN_STATUS, 0, status_vals[fldidx2]);
+                    putstr(WIN_STATUS, 0, text);
                 }
-                if (tty_status_colors[fldidx2] != NO_COLOR)
-                    term_end_color();
+
+                if (iflags.hilite_delta) {
+#ifdef TEXTCOLOR
+                           if (coloridx != NO_COLOR)
+                        term_end_color();
 #endif
-            } else
-                putstr(WIN_STATUS, 0, status_vals[fldidx2]);
+                    End_Attr(attridx);
+                }
+            } else {
+                MaybeDisplayCond(BL_MASK_STONE, "Stone");
+                MaybeDisplayCond(BL_MASK_SLIME, "Slime");
+                MaybeDisplayCond(BL_MASK_STRNGL, "Strngl");
+                MaybeDisplayCond(BL_MASK_FOODPOIS, "FoodPois");
+                MaybeDisplayCond(BL_MASK_TERMILL, "TermIll");
+                MaybeDisplayCond(BL_MASK_BLIND, "Blind");
+                MaybeDisplayCond(BL_MASK_DEAF, "Deaf");
+                MaybeDisplayCond(BL_MASK_STUN, "Stun");
+                MaybeDisplayCond(BL_MASK_CONF, "Conf");
+                MaybeDisplayCond(BL_MASK_HALLU, "Hallu");
+                MaybeDisplayCond(BL_MASK_LEV, "Lev");
+                MaybeDisplayCond(BL_MASK_FLY, "Fly");
+                MaybeDisplayCond(BL_MASK_RIDE, "Ride");
+           }
         }
     }
+    cl_end();
     return;
 }
 
-#ifdef STATUS_HILITES
+#ifdef TEXTCOLOR
 /*
- *  status_threshold(int fldidx, int threshholdtype, anything threshold,
- *                   int behavior, int under, int over)
- *
- *        -- called when a hiliting preference is added, changed, or
- *           removed.
- *        -- the fldindex identifies which field is having its hiliting
- *           preference set. It is an integer index value from botl.h
- *        -- fldindex could be any one of the following from botl.h:
- *           BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
- *           BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
- *           BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX,
- *           BL_LEVELDESC, BL_EXP, BL_CONDITION
- *        -- datatype is P_INT, P_UINT, P_LONG, or P_MASK.
- *        -- threshold is an "anything" union which can contain the
- *           datatype value.
- *        -- behavior is used to define how threshold is used and can
- *           be BL_TH_NONE, BL_TH_VAL_PERCENTAGE, BL_TH_VAL_ABSOLUTE,
- *           or BL_TH_UPDOWN. BL_TH_NONE means don't do anything above
- *           or below the threshold.  BL_TH_VAL_PERCENTAGE treats the
- *           threshold value as a precentage of the maximum possible
- *           value. BL_TH_VAL_ABSOLUTE means that the threshold is an
- *           actual value. BL_TH_UPDOWN means that threshold is not
- *           used, and the two below/above hilite values indicate how
- *           to display something going down (under) or rising (over).
- *        -- under is the hilite attribute used if value is below the
- *           threshold. The attribute can be BL_HILITE_NONE,
- *           BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one
- *           of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN,
- *           CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY,
- *           CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE,
- *           CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
- *        -- over is the hilite attribute used if value is at or above
- *           the threshold. The attribute can be BL_HILITE_NONE,
- *           BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one
- *           of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN,
- *           CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY,
- *           CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE,
- *           CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
+ * Return what color this condition should
+ * be displayed in based on user settings.
  */
-void
-tty_status_threshold(fldidx, thresholdtype, threshold, behavior, under, over)
-int fldidx, thresholdtype;
-int behavior, under, over;
-anything threshold;
+int condcolor(bm, bmarray)
+long bm;
+unsigned long *bmarray;
 {
-    tty_status_hilites[fldidx].thresholdtype = thresholdtype;
-    tty_status_hilites[fldidx].threshold = threshold;
-    tty_status_hilites[fldidx].behavior = behavior;
-    tty_status_hilites[fldidx].under = under;
-    tty_status_hilites[fldidx].over = over;
-    return;
+    int i;
+
+    if (bm && bmarray)
+        for (i = 0; i < CLR_MAX; ++i) {
+            if (bmarray[i] && (bm & bmarray[i]))
+                return i;
+        }
+    return NO_COLOR;
 }
+#endif /* TEXTCOLOR */
+
+int condattr(bm, bmarray)
+long bm;
+unsigned long *bmarray;
+{
+    int attr = 0;
+    int i;
 
+    if (bm && bmarray) {
+        for (i = HL_ATTCLR_DIM; i < BL_ATTCLR_MAX; ++i) {
+            if (bmarray[i] && (bm & bmarray[i])) {
+                switch(i) {
+                    case HL_ATTCLR_DIM:
+                        attr |= HL_DIM;
+                        break;
+                    case HL_ATTCLR_BLINK:
+                        attr |= HL_BLINK;
+                        break;
+                    case HL_ATTCLR_ULINE:
+                        attr |= HL_ULINE;
+                        break;
+                    case HL_ATTCLR_INVERSE:
+                        attr |= HL_INVERSE;
+                        break;
+                    case HL_ATTCLR_BOLD:
+                        attr |= HL_BOLD;
+                        break;
+                }
+            }
+        }
+    }
+    return attr;
+}
 #endif /* STATUS_HILITES */
-#endif /*STATUS_VIA_WINDOWPORT*/
 
 #endif /* TTY_GRAPHICS */
 
index 9196c5c..2339a8a 100644 (file)
@@ -1,4 +1,6 @@
-# $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# $NHDT-Date: 1524689255 2018/04/25 20:47:35 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.12 $
+# Copyright (c) 2018 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
 
 # Set all of these or none of them.
 #
@@ -41,11 +43,30 @@ tools:
 # Dungeon Compiler Stuff
 #==========================================
 
-..\util\dgn_yacc.c ..\include\dgn_comp.h : ..\util\dgn_comp.y
+..\include\dgn_comp.h : ..\util\dgn_comp.y
 !IF "$(YACC)"==""
-          @echo Using pre-built dgn_yacc.c and dgn_comp.h
-          @copy ..\sys\share\dgn_yacc.c ..\util\dgn_yacc.c
-          @copy ..\sys\share\dgn_comp.h ..\include\dgn_comp.h
+          @echo Using pre-built dgn_comp.h
+          chdir ..\include
+          copy /y ..\sys\share\dgn_comp.h
+          copy /b dgn_comp.h+,,
+          chdir ..\src
+!ELSE
+          chdir ..\util
+          $(YACC) -d dgn_comp.y
+          copy $(YTABC) $@
+          copy $(YTABH) ..\include\dgn_comp.h
+          @del $(YTABC)
+          @del $(YTABH)
+          chdir ..\build
+!ENDIF
+
+..\util\dgn_yacc.c : ..\util\dgn_comp.y
+!IF "$(YACC)"==""
+          @echo Using pre-built dgn_yacc.c
+          chdir ..\util
+          copy /y ..\sys\share\dgn_yacc.c
+          copy /b dgn_yacc.c+,,
+          chdir ..\src
 !ELSE
           chdir ..\util
           $(YACC) -d dgn_comp.y
@@ -59,7 +80,10 @@ tools:
 ..\util\dgn_lex.c: ..\util\dgn_comp.l
 !IF "$(LEX)"==""
           @echo Using pre-built dgn_lex.c
-          @copy ..\sys\share\dgn_lex.c $@
+          chdir ..\util
+          copy /y ..\sys\share\dgn_lex.c
+          copy /b dgn_lex.c+,,
+          chdir ..\src
 !ELSE
           chdir ..\util
           $(LEX) dgn_comp.l
index 1e92cd6..0a38390 100644 (file)
@@ -1,4 +1,6 @@
-# $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+# $NHDT-Date: 1524689255 2018/04/25 20:47:35 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.12 $
+# Copyright (c) 2018 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
 
 # Set all of these or none of them.
 #
@@ -40,11 +42,13 @@ tools:
 # Level Compiler Stuff
 #==========================================
 
-..\util\lev_yacc.c ..\include\lev_comp.h: ..\util\lev_comp.y
+..\include\lev_comp.h: ..\util\lev_comp.y
 !IFNDEF YACC
-          @echo Using pre-built lev_yacc.c and lev_comp.h
-          @copy ..\sys\share\lev_yacc.c ..\util\lev_yacc.c
-          @copy ..\sys\share\lev_comp.h ..\include\lev_comp.h
+          @echo Using pre-built lev_comp.h
+          chdir ..\include
+          copy /y ..\sys\share\lev_comp.h
+          copy /b lev_comp.h+,,
+          chdir ..\src
 !ELSE
           @echo Generating lev_yacc.c and lev_comp.h
           chdir ..\util
@@ -53,19 +57,40 @@ tools:
           copy $(YTABH) ..\include\lev_comp.h
           @del $(YTABC)
           @del $(YTABH)
-          chdir ..\build
+          chdir ..\src
+!ENDIF
+
+..\util\lev_yacc.c: ..\util\lev_comp.y
+!IFNDEF YACC
+          @echo Using pre-built lev_yacc.c
+          chdir ..\util
+          copy /y ..\sys\share\lev_yacc.c
+          copy /b lev_yacc.c+,,
+          chdir ..\src
+!ELSE
+          @echo Generating lev_yacc.c and lev_comp.h
+          chdir ..\util
+          $(YACC) -d lev_comp.y
+          copy $(YTABC) $@
+          copy $(YTABH) ..\include\lev_comp.h
+          @del $(YTABC)
+          @del $(YTABH)
+          chdir ..\src
 !ENDIF
 
 ..\util\lev_lex.c: ..\util\lev_comp.l
 !IFNDEF LEX
           @echo Using pre-built lev_lex.c
-          @copy ..\sys\share\lev_lex.c $@
+          chdir ..\util
+          copy /y ..\sys\share\lev_lex.c
+          copy /b lev_lex.c+,,
+           chdir ..\src
 !ELSE
           @echo Generating lev_lex.c
           chdir ..\util
           $(LEX) lev_comp.l
           copy $(LEXYYC) $@
           @del $(LEXYYC)
-          chdir ..\build
+          chdir ..\src
 !ENDIF
 
index efd35df..a91eecf 100644 (file)
@@ -10,6 +10,8 @@
 #include "resource.h"
 #include "mhdlg.h"
 
+#include <assert.h>
+
 /*---------------------------------------------------------------*/
 /* data for getlin dialog */
 struct getlin_data {
@@ -256,34 +258,51 @@ ExtCmdDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 }
 
 /*---------------------------------------------------------------*/
-/* player selector dialog data */
-struct plsel_data {
-    int *selection;
-};
+/* player selector dialog */
+typedef struct plsel_data {
+    int config_race;
+    int config_role;
+    int config_gender;
+    int config_alignment;
+    HWND control_role;
+    HWND control_race;
+    HWND control_genders[ROLE_GENDERS];
+    HWND control_aligns[ROLE_ALIGNS];
+    int role_count;
+    int race_count;
+    HWND focus;
+} plsel_data_t;
 
 INT_PTR CALLBACK PlayerSelectorDlgProc(HWND, UINT, WPARAM, LPARAM);
 static void plselInitDialog(HWND hWnd);
-static void plselAdjustLists(HWND hWnd, int changed_opt);
-static int plselFinalSelection(HWND hWnd, int *selection);
+static void plselAdjustSelections(HWND hWnd);
+static boolean plselRandomize(plsel_data_t * data);
+static BOOL plselDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam);
 
-int
-mswin_player_selection_window(int *selection)
+boolean
+mswin_player_selection_window()
 {
     INT_PTR ret;
-    struct plsel_data data;
-
-    /* init dialog data */
-    ZeroMemory(&data, sizeof(data));
-    data.selection = selection;
-
-    /* create modal dialog */
-    ret = DialogBoxParam(
-        GetNHApp()->hApp, MAKEINTRESOURCE(IDD_PLAYER_SELECTOR),
-        GetNHApp()->hMainWnd, PlayerSelectorDlgProc, (LPARAM) &data);
-    if (ret == -1)
-        panic("Cannot create getlin window");
+    plsel_data_t data;
+    boolean ok = TRUE;
+
+    /* save away configuration settings */
+    data.config_role = flags.initrole;
+    data.config_race = flags.initrace;
+    data.config_gender = flags.initgend;
+    data.config_alignment = flags.initalign;
+
+    if (!plselRandomize(&data)) {
+        /* create modal dialog */
+        ret = DialogBoxParam(
+            GetNHApp()->hApp, MAKEINTRESOURCE(IDD_PLAYER_SELECTOR),
+            GetNHApp()->hMainWnd, PlayerSelectorDlgProc, (LPARAM) &data);
+        if (ret == -1)
+            panic("Cannot create getlin window");
+        ok = (ret == IDOK);
+    }
 
-    return (int) ret;
+    return ok;
 }
 
 INT_PTR CALLBACK
@@ -315,11 +334,94 @@ PlayerSelectorDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
         /* init dialog */
         plselInitDialog(hWnd);
 
-        /* set focus on the role checkbox (random) field */
-        SetFocus(GetDlgItem(hWnd, IDC_PLSEL_ROLE_RANDOM));
+        /* tell windows to set the focus */
+        return TRUE;
+        break;
 
-        /* tell windows we set the focus */
-        return FALSE;
+    case WM_DRAWITEM:
+        if (wParam == IDC_PLSEL_ROLE_LIST ||  wParam == IDC_PLSEL_RACE_LIST)
+            return plselDrawItem(hWnd, wParam, lParam);
+        break;
+
+    case WM_NOTIFY:
+        {
+            LPNMHDR nmhdr = (LPNMHDR)lParam;
+            HWND control = nmhdr->hwndFrom;
+
+            data = (struct plsel_data *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+            switch (nmhdr->code) {
+            case LVN_KEYDOWN:
+                {
+                    LPNMLVKEYDOWN lpnmkeydown = (LPNMLVKEYDOWN) lParam;
+
+                    if (lpnmkeydown->wVKey == ' ') {
+                        if (control == data->control_role) {
+                            int i = ListView_GetNextItem(data->control_role, -1, LVNI_FOCUSED);
+                            assert(i == -1 || ListView_GetNextItem(data->control_role, i, LVNI_FOCUSED) == -1);
+                            flags.initrole = i;
+                            plselAdjustSelections(hWnd);
+                        } else if (control == data->control_race) {
+                            int i = ListView_GetNextItem(data->control_race, -1, LVNI_FOCUSED);
+                            assert(i == -1 || ListView_GetNextItem(data->control_race, i, LVNI_FOCUSED) == -1);
+                            if (ok_race(flags.initrole, i, ROLE_RANDOM, ROLE_RANDOM)) {
+                                flags.initrace = i;
+                                plselAdjustSelections(hWnd);
+                            }
+                        }
+                    }
+                }
+            break;
+            case NM_CLICK:
+                {
+                    LPNMLISTVIEW lpnmitem = (LPNMLISTVIEW)lParam;
+                    int i = lpnmitem->iItem;
+                    if (i == -1)
+                        return FALSE;
+                    if (control == data->control_role) {
+                        flags.initrole = i;
+                        plselAdjustSelections(hWnd);
+                    } else if(control == data->control_race) {
+                        if (ok_race(flags.initrole, i, ROLE_RANDOM, ROLE_RANDOM)) {
+                            flags.initrace = i;
+                            plselAdjustSelections(hWnd);
+                        }
+                    }
+                }
+                break;
+            case NM_KILLFOCUS:
+                {
+                    char buf[64];
+                    sprintf(buf, "KILLFOCUS %lx\n", (unsigned long) control);
+                    OutputDebugStringA(buf);
+
+                    if (data->focus == data->control_race) {
+                        data->focus = NULL;
+                        ListView_RedrawItems(data->control_race, 0, data->race_count - 1);
+                    } else if (data->focus == data->control_role) {
+                        data->focus = NULL;
+                        ListView_RedrawItems(data->control_role, 0, data->role_count - 1);
+                    }
+                }
+                break;
+            case NM_SETFOCUS:
+                {
+                    char buf[64];
+                    sprintf(buf, "SETFOCUS %lx\n", (unsigned long) control);
+                    OutputDebugStringA(buf);
+                    data->focus = control;
+
+                    if (control == data->control_race) {
+                        data->focus = data->control_race;
+                        plselAdjustSelections(hWnd);
+                    } else if (control == data->control_role) {
+                        data->focus = data->control_role;
+                        plselAdjustSelections(hWnd);
+                    }
+                }
+                break;
+            }
+        }
         break;
 
     case WM_COMMAND:
@@ -327,483 +429,361 @@ PlayerSelectorDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
         switch (LOWORD(wParam)) {
         /* OK button was clicked */
         case IDOK:
-            if (plselFinalSelection(hWnd, data->selection)) {
-                EndDialog(hWnd, wParam);
-            } else {
-                NHMessageBox(
-                    hWnd, TEXT("Cannot match this role. Try something else."),
-                    MB_ICONSTOP | MB_OK);
-            }
+            EndDialog(hWnd, wParam);
             return TRUE;
 
         /* CANCEL button was clicked */
         case IDCANCEL:
-            *data->selection = -1;
             EndDialog(hWnd, wParam);
             return TRUE;
 
-        /* following are events from dialog controls:
-           "random" checkboxes send BN_CLICKED messages;
-           role/race/... combo-boxes send CBN_SELENDOK
-           if something was selected;
-        */
-        case IDC_PLSEL_ROLE_RANDOM:
-            if (HIWORD(wParam) == BN_CLICKED) {
-                /* enable corresponding list window if "random"
-                   checkbox was "unchecked" */
-                EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST),
-                             SendMessage((HWND) lParam, BM_GETCHECK, 0, 0)
-                                 == BST_UNCHECKED);
-            }
-            break;
+        case IDC_PLSEL_RANDOM:
+            plselRandomize(data);
+            plselAdjustSelections(hWnd);
+            return TRUE;
 
-        case IDC_PLSEL_RACE_RANDOM:
+        case IDC_PLSEL_GENDER_MALE:
+        case IDC_PLSEL_GENDER_FEMALE:
             if (HIWORD(wParam) == BN_CLICKED) {
-                EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST),
-                             SendMessage((HWND) lParam, BM_GETCHECK, 0, 0)
-                                 == BST_UNCHECKED);
+                int i = LOWORD(wParam) - IDC_PLSEL_GENDER_MALE;
+                if (ok_gend(flags.initrole, flags.initrace, i, ROLE_RANDOM)) {
+                    flags.initgend = i;
+                    plselAdjustSelections(hWnd);
+                }
             }
             break;
 
-        case IDC_PLSEL_GENDER_RANDOM:
-            if (HIWORD(wParam) == BN_CLICKED) {
-                EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST),
-                             SendMessage((HWND) lParam, BM_GETCHECK, 0, 0)
-                                 == BST_UNCHECKED);
-            }
-            break;
 
-        case IDC_PLSEL_ALIGN_RANDOM:
+        case IDC_PLSEL_ALIGN_LAWFUL:
+        case IDC_PLSEL_ALIGN_NEUTRAL:
+        case IDC_PLSEL_ALIGN_CHAOTIC:
             if (HIWORD(wParam) == BN_CLICKED) {
-                EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST),
-                             SendMessage((HWND) lParam, BM_GETCHECK, 0, 0)
-                                 == BST_UNCHECKED);
-            }
-            break;
-
-        case IDC_PLSEL_ROLE_LIST:
-            if (HIWORD(wParam) == CBN_SELENDOK) {
-                /* filter out invalid options if
-                   the selection was made */
-                plselAdjustLists(hWnd, LOWORD(wParam));
-            }
-            break;
-
-        case IDC_PLSEL_RACE_LIST:
-            if (HIWORD(wParam) == CBN_SELENDOK) {
-                plselAdjustLists(hWnd, LOWORD(wParam));
-            }
-            break;
-
-        case IDC_PLSEL_GENDER_LIST:
-            if (HIWORD(wParam) == CBN_SELENDOK) {
-                plselAdjustLists(hWnd, LOWORD(wParam));
+                int i = LOWORD(wParam) - IDC_PLSEL_ALIGN_LAWFUL;
+                if (ok_align(flags.initrole, flags.initrace, flags.initgend, i)) {
+                    flags.initalign = i;
+                    plselAdjustSelections(hWnd);
+                }
             }
             break;
 
-        case IDC_PLSEL_ALIGN_LIST:
-            if (HIWORD(wParam) == CBN_SELENDOK) {
-                plselAdjustLists(hWnd, LOWORD(wParam));
-            }
-            break;
         }
         break;
     }
     return FALSE;
 }
 
-void
-setComboBoxValue(HWND hWnd, int combo_box, int value)
-{
-    int index_max =
-        (int) SendDlgItemMessage(hWnd, combo_box, CB_GETCOUNT, 0, 0);
-    int index;
-    int value_to_set = LB_ERR;
-    for (index = 0; index < index_max; index++) {
-        if (SendDlgItemMessage(hWnd, combo_box, CB_GETITEMDATA,
-                               (WPARAM) index, 0) == value) {
-            value_to_set = index;
-            break;
-        }
-    }
-    SendDlgItemMessage(hWnd, combo_box, CB_SETCURSEL, (WPARAM) value_to_set,
-                       0);
-}
-
 /* initialize player selector dialog */
 void
 plselInitDialog(HWND hWnd)
 {
+    struct plsel_data * data = (plsel_data_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
     TCHAR wbuf[BUFSZ];
-
-    /* set player name */
-    SetDlgItemText(hWnd, IDC_PLSEL_NAME, NH_A2W(plname, wbuf, sizeof(wbuf)));
-
-    /* check flags for consistency */
-    if (flags.initrole >= 0) {
-        if (flags.initrace >= 0
-            && !validrace(flags.initrole, flags.initrace)) {
-            flags.initrace = ROLE_NONE;
-        }
-
-        if (flags.initgend >= 0
-            && !validgend(flags.initrole, flags.initrace, flags.initgend)) {
-            flags.initgend = ROLE_NONE;
+    LVCOLUMN lvcol;
+    data->control_role = GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST);
+    data->control_race = GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST);
+
+    ZeroMemory(&lvcol, sizeof(lvcol));
+    lvcol.mask = LVCF_WIDTH;
+    lvcol.cx = GetSystemMetrics(SM_CXFULLSCREEN);
+
+    /* build role list */
+    ListView_InsertColumn(data->control_role, 0, &lvcol);
+    data->role_count = 0;
+    for (int i = 0; roles[i].name.m; i++) {
+        LVITEM lvitem;
+        ZeroMemory(&lvitem, sizeof(lvitem));
+
+        lvitem.mask = LVIF_STATE | LVIF_TEXT;
+        lvitem.iItem = i;
+        lvitem.iSubItem = 0;
+        lvitem.state = 0;
+        lvitem.stateMask = LVIS_FOCUSED;
+        if (flags.female && roles[i].name.f)
+            lvitem.pszText = NH_A2W(roles[i].name.f, wbuf, BUFSZ);
+        else
+            lvitem.pszText = NH_A2W(roles[i].name.m, wbuf, BUFSZ);
+        if (ListView_InsertItem(data->control_role, &lvitem) == -1) {
+            panic("cannot insert menu item");
         }
+        data->role_count++;
+    }
 
-        if (flags.initalign >= 0
-            && !validalign(flags.initrole, flags.initrace, flags.initalign)) {
-            flags.initalign = ROLE_NONE;
+    /* build race list */
+    ListView_InsertColumn(data->control_race, 0, &lvcol);
+    data->race_count = 0;
+    for (int i = 0; races[i].noun; i++) {
+        LVITEM lvitem;
+        ZeroMemory(&lvitem, sizeof(lvitem));
+
+        lvitem.mask = LVIF_STATE | LVIF_TEXT;
+        lvitem.iItem = i;
+        lvitem.iSubItem = 0;
+        lvitem.state = 0;
+        lvitem.stateMask = LVIS_FOCUSED;
+        lvitem.pszText = NH_A2W(races[i].noun, wbuf, BUFSZ);
+        if (ListView_InsertItem(data->control_race, &lvitem) == -1) {
+            panic("cannot insert menu item");
         }
+        data->race_count++;
     }
 
-    /* populate select boxes */
-    plselAdjustLists(hWnd, -1);
+    for(int i = 0; i < ROLE_GENDERS; i++)
+        data->control_genders[i] = GetDlgItem(hWnd, IDC_PLSEL_GENDER_MALE + i);
 
-    /* intialize roles list */
-    if (flags.initrole < 0
-        || !ok_role(flags.initrole, ROLE_NONE, ROLE_NONE, ROLE_NONE)) {
-        CheckDlgButton(hWnd, IDC_PLSEL_ROLE_RANDOM, BST_CHECKED);
-        EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST), FALSE);
-    } else {
-        CheckDlgButton(hWnd, IDC_PLSEL_ROLE_RANDOM, BST_UNCHECKED);
-        EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST), TRUE);
-        setComboBoxValue(hWnd, IDC_PLSEL_ROLE_LIST, flags.initrole);
-    }
+    for(int i = 0; i < ROLE_ALIGNS; i++)
+        data->control_aligns[i] = GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LAWFUL + i);
 
-    /* intialize races list */
-    if (flags.initrace < 0
-        || !ok_race(flags.initrole, flags.initrace, ROLE_NONE, ROLE_NONE)) {
-        CheckDlgButton(hWnd, IDC_PLSEL_RACE_RANDOM, BST_CHECKED);
-        EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST), FALSE);
-    } else {
-        CheckDlgButton(hWnd, IDC_PLSEL_RACE_RANDOM, BST_UNCHECKED);
-        EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST), TRUE);
-        setComboBoxValue(hWnd, IDC_PLSEL_RACE_LIST, flags.initrace);
-    }
+    /* set gender radio button state */
+    for (int i = 0; i < ROLE_GENDERS; i++)
+        Button_Enable(data->control_genders[i], TRUE);
 
-    /* intialize genders list */
-    if (flags.initgend < 0
-        || !ok_gend(flags.initrole, flags.initrace, flags.initgend,
-                    ROLE_NONE)) {
-        CheckDlgButton(hWnd, IDC_PLSEL_GENDER_RANDOM, BST_CHECKED);
-        EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST), FALSE);
-    } else {
-        CheckDlgButton(hWnd, IDC_PLSEL_GENDER_RANDOM, BST_UNCHECKED);
-        EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST), TRUE);
-        setComboBoxValue(hWnd, IDC_PLSEL_GENDER_LIST, flags.initgend);
-    }
+    Button_SetCheck(data->control_genders[0], BST_CHECKED);
 
-    /* intialize alignments list */
-    if (flags.initalign < 0
-        || !ok_align(flags.initrole, flags.initrace, flags.initgend,
-                     flags.initalign)) {
-        CheckDlgButton(hWnd, IDC_PLSEL_ALIGN_RANDOM, BST_CHECKED);
-        EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST), FALSE);
-    } else {
-        CheckDlgButton(hWnd, IDC_PLSEL_ALIGN_RANDOM, BST_UNCHECKED);
-        EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST), TRUE);
-        setComboBoxValue(hWnd, IDC_PLSEL_ALIGN_LIST, flags.initalign);
-    }
-}
+    /* set alignment radio button state */
+    for (int i = 0; i < ROLE_ALIGNS; i++)
+        Button_Enable(data->control_aligns[i], TRUE);
 
-/* adjust role/race/alignment/gender list - filter out
-   invalid combinations
-   changed_sel points to the list where selection occurred
-   (-1 if unknown)
-*/
-void
-plselAdjustLists(HWND hWnd, int changed_sel)
-{
-    HWND control_role, control_race, control_gender, control_align;
-    int initrole, initrace, initgend, initalign;
-    int i;
-    LRESULT ind;
-    int valid_opt;
-    TCHAR wbuf[255];
+    Button_SetCheck(data->control_aligns[0], BST_CHECKED);
 
-    /* get control handles */
-    control_role = GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST);
-    control_race = GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST);
-    control_gender = GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST);
-    control_align = GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST);
-
-    /* get current selections */
-    ind = SendMessage(control_role, CB_GETCURSEL, 0, 0);
-    initrole = (ind == LB_ERR)
-                   ? flags.initrole
-                   : (int) SendMessage(control_role, CB_GETITEMDATA, ind, 0);
-
-    ind = SendMessage(control_race, CB_GETCURSEL, 0, 0);
-    initrace = (ind == LB_ERR)
-                   ? flags.initrace
-                   : (int) SendMessage(control_race, CB_GETITEMDATA, ind, 0);
-
-    ind = SendMessage(control_gender, CB_GETCURSEL, 0, 0);
-    initgend = (ind == LB_ERR) ? flags.initgend
-                               : (int) SendMessage(control_gender,
-                                                   CB_GETITEMDATA, ind, 0);
-
-    ind = SendMessage(control_align, CB_GETCURSEL, 0, 0);
-    initalign = (ind == LB_ERR) ? flags.initalign
-                                : (int) SendMessage(control_align,
-                                                    CB_GETITEMDATA, ind, 0);
-
-    /* intialize roles list */
-    if (changed_sel == -1) {
-        valid_opt = 0;
-
-        /* reset content and populate the list */
-        SendMessage(control_role, CB_RESETCONTENT, 0, 0);
-        for (i = 0; roles[i].name.m; i++) {
-            if (initgend >= 0 && flags.female && roles[i].name.f)
-                ind = SendMessage(
-                    control_role, CB_ADDSTRING, (WPARAM) 0,
-                    (LPARAM) NH_A2W(roles[i].name.f, wbuf, sizeof(wbuf)));
-            else
-                ind = SendMessage(
-                    control_role, CB_ADDSTRING, (WPARAM) 0,
-                    (LPARAM) NH_A2W(roles[i].name.m, wbuf, sizeof(wbuf)));
-
-            SendMessage(control_role, CB_SETITEMDATA, (WPARAM) ind,
-                        (LPARAM) i);
-            if (i == initrole) {
-                SendMessage(control_role, CB_SETCURSEL, (WPARAM) ind,
-                            (LPARAM) 0);
-                valid_opt = 1;
-            }
-        }
+    /* set player name */
+    SetDlgItemText(hWnd, IDC_PLSEL_NAME, NH_A2W(plname, wbuf, sizeof(wbuf)));
 
-        /* set selection to the previously selected role
-           if it is still valid */
-        if (!valid_opt) {
-            initrole = ROLE_NONE;
-            initrace = ROLE_NONE;
-            initgend = ROLE_NONE;
-            initalign = ROLE_NONE;
-            SendMessage(control_role, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
-        }
+    plselRandomize(data);
 
-        /* trigger change of the races list */
-        changed_sel = IDC_PLSEL_ROLE_LIST;
-    }
+    /* populate select boxes */
+    plselAdjustSelections(hWnd);
+
+    /* set tab order */
+    SetWindowPos(GetDlgItem(hWnd, IDCANCEL), NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+    SetWindowPos(GetDlgItem(hWnd, IDC_PLSEL_RANDOM), NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+    SetWindowPos(GetDlgItem(hWnd, IDOK), NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+    for(int i = ROLE_GENDERS - 1; i >= 0; i--)
+        SetWindowPos(data->control_genders[i], NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+    for(int i = ROLE_ALIGNS - 1; i >= 0; i--)
+        SetWindowPos(data->control_aligns[i], NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+    SetWindowPos(data->control_race, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+    SetWindowPos(data->control_role, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 
-    /* intialize races list */
-    if (changed_sel == IDC_PLSEL_ROLE_LIST) {
-        valid_opt = 0;
-
-        /* reset content and populate the list */
-        SendMessage(control_race, CB_RESETCONTENT, 0, 0);
-        for (i = 0; races[i].noun; i++)
-            if (ok_race(initrole, i, ROLE_NONE, ROLE_NONE)) {
-                ind = SendMessage(
-                    control_race, CB_ADDSTRING, (WPARAM) 0,
-                    (LPARAM) NH_A2W(races[i].noun, wbuf, sizeof(wbuf)));
-                SendMessage(control_race, CB_SETITEMDATA, (WPARAM) ind,
-                            (LPARAM) i);
-                if (i == initrace) {
-                    SendMessage(control_race, CB_SETCURSEL, (WPARAM) ind,
-                                (LPARAM) 0);
-                    valid_opt = 1;
-                }
-            }
+}
 
-        /* set selection to the previously selected race
-           if it is still valid */
-        if (!valid_opt) {
-            initrace = ROLE_NONE;
-            initgend = ROLE_NONE;
-            initalign = ROLE_NONE;
-            SendMessage(control_race, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
-        }
+void
+plselAdjustSelections(HWND hWnd)
+{
+    struct plsel_data * data = (plsel_data_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
 
-        /* trigger change of the genders list */
-        changed_sel = IDC_PLSEL_RACE_LIST;
-    }
+    if (!ok_race(flags.initrole, flags.initrace, ROLE_RANDOM, ROLE_RANDOM))
+        flags.initrace = pick_race(flags.initrole, ROLE_RANDOM, ROLE_RANDOM, ROLE_RANDOM);
 
-    /* intialize genders list */
-    if (changed_sel == IDC_PLSEL_RACE_LIST) {
-        valid_opt = 0;
-
-        /* reset content and populate the list */
-        SendMessage(control_gender, CB_RESETCONTENT, 0, 0);
-        for (i = 0; i < ROLE_GENDERS; i++)
-            if (ok_gend(initrole, initrace, i, ROLE_NONE)) {
-                ind = SendMessage(
-                    control_gender, CB_ADDSTRING, (WPARAM) 0,
-                    (LPARAM) NH_A2W(genders[i].adj, wbuf, sizeof(wbuf)));
-                SendMessage(control_gender, CB_SETITEMDATA, (WPARAM) ind,
-                            (LPARAM) i);
-                if (i == initgend) {
-                    SendMessage(control_gender, CB_SETCURSEL, (WPARAM) ind,
-                                (LPARAM) 0);
-                    valid_opt = 1;
-                }
-            }
+    if (!ok_gend(flags.initrole, flags.initrace, flags.initgend, ROLE_RANDOM))
+        flags.initgend = pick_gend(flags.initrole, flags.initrace, ROLE_RANDOM , ROLE_RANDOM);
 
-        /* set selection to the previously selected gender
-           if it is still valid */
-        if (!valid_opt) {
-            initgend = ROLE_NONE;
-            initalign = ROLE_NONE;
-            SendMessage(control_gender, CB_SETCURSEL, (WPARAM) -1,
-                        (LPARAM) 0);
-        }
+    if (!ok_align(flags.initrole, flags.initrace, flags.initgend, flags.initalign))
+        flags.initalign = pick_align(flags.initrole, flags.initrace, flags.initgend , ROLE_RANDOM);
 
-        /* trigger change of the alignments list */
-        changed_sel = IDC_PLSEL_GENDER_LIST;
-    }
+    ListView_RedrawItems(data->control_role, 0, data->role_count - 1);
+    ListView_RedrawItems(data->control_race, 0, data->race_count - 1);
 
-    /* intialize alignments list */
-    if (changed_sel == IDC_PLSEL_GENDER_LIST) {
-        valid_opt = 0;
-
-        /* reset content and populate the list */
-        SendMessage(control_align, CB_RESETCONTENT, 0, 0);
-        for (i = 0; i < ROLE_ALIGNS; i++)
-            if (ok_align(initrole, initrace, initgend, i)) {
-                ind = SendMessage(
-                    control_align, CB_ADDSTRING, (WPARAM) 0,
-                    (LPARAM) NH_A2W(aligns[i].adj, wbuf, sizeof(wbuf)));
-                SendMessage(control_align, CB_SETITEMDATA, (WPARAM) ind,
-                            (LPARAM) i);
-                if (i == initalign) {
-                    SendMessage(control_align, CB_SETCURSEL, (WPARAM) ind,
-                                (LPARAM) 0);
-                    valid_opt = 1;
-                }
-            }
+    /* set gender radio button state */
+    for (int i = 0; i < ROLE_GENDERS; i++) {
+        BOOL enable = ok_gend(flags.initrole, flags.initrace, i, flags.initalign);
+        Button_Enable(data->control_genders[i], enable);
+        LRESULT state = Button_GetCheck(data->control_genders[i]);
+        if (state == BST_CHECKED && flags.initgend != i)
+            Button_SetCheck(data->control_genders[i], BST_UNCHECKED);
+        if (state == BST_UNCHECKED && flags.initgend == i)
+            Button_SetCheck(data->control_genders[i], BST_CHECKED);
+    }
 
-        /* set selection to the previously selected alignment
-           if it is still valid */
-        if (!valid_opt) {
-            initalign = ROLE_NONE;
-            SendMessage(control_align, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
-        }
+    /* set alignment radio button state */
+    for (int i = 0; i < ROLE_ALIGNS; i++) {
+        BOOL enable = ok_align(flags.initrole, flags.initrace, flags.initgend, i);
+        Button_Enable(data->control_aligns[i], enable);
+        LRESULT state = Button_GetCheck(data->control_aligns[i]);
+        if (state == BST_CHECKED && flags.initalign != i)
+            Button_SetCheck(data->control_aligns[i], BST_UNCHECKED);
+        if (state == BST_UNCHECKED && flags.initalign == i)
+            Button_SetCheck(data->control_aligns[i], BST_CHECKED);
     }
+
 }
 
 /* player made up his mind - get final selection here */
 int
-plselFinalSelection(HWND hWnd, int *selection)
+plselFinalSelection(HWND hWnd)
+{
+    int role = flags.initrole;
+    int race = flags.initrace;
+    int gender = flags.initgend;
+    int alignment = flags.initalign;
+
+    assert(role != ROLE_RANDOM && role != ROLE_NONE);
+    assert(race != ROLE_RANDOM && race != ROLE_NONE);
+    assert(gender != ROLE_RANDOM && gender != ROLE_NONE);
+    assert(alignment != ROLE_RANDOM && alignment != ROLE_NONE);
+    assert(ok_role(role, race, gender, alignment));
+    assert(ok_race(role, race, gender, alignment));
+    assert(ok_gend(role, race, gender, alignment));
+    assert(ok_align(role, race, gender, alignment));
+
+    return TRUE;
+}
+
+static boolean plselRandomize(plsel_data_t * data)
 {
-    LRESULT ind;
+    boolean fully_specified = TRUE;
+
+    // restore back to configuration settings
+    flags.initrole = data->config_role;
+    flags.initrace = data->config_race;
+    flags.initgend = data->config_gender;
+    flags.initalign = data->config_alignment;
+
+    if (!flags.randomall) {
+        if(flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE
+            || flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE)
+            fully_specified = FALSE;
+    }
 
-    UNREFERENCED_PARAMETER(selection);
+    if (flags.initrole == ROLE_NONE)
+        flags.initrole = ROLE_RANDOM;
+    if (flags.initrace == ROLE_NONE)
+        flags.initrace = ROLE_RANDOM;
+    if (flags.initgend == ROLE_NONE)
+        flags.initgend = ROLE_RANDOM;
+    if (flags.initalign == ROLE_NONE)
+        flags.initalign = ROLE_RANDOM;
 
-    /* get current selections */
-    if (SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_RANDOM, BM_GETCHECK, 0, 0)
-        == BST_CHECKED) {
+    rigid_role_checks();
+
+    int role = flags.initrole;
+    int race = flags.initrace;
+    int gender = flags.initgend;
+    int alignment = flags.initalign;
+
+    assert(role != ROLE_RANDOM && role != ROLE_NONE);
+    assert(race != ROLE_RANDOM && race != ROLE_NONE);
+    assert(gender != ROLE_RANDOM && gender != ROLE_NONE);
+    assert(alignment != ROLE_RANDOM && alignment != ROLE_NONE);
+
+    if (!ok_role(role, race, gender, alignment)) {
+        fully_specified = FALSE;
         flags.initrole = ROLE_RANDOM;
-    } else {
-        ind =
-            SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_LIST, CB_GETCURSEL, 0, 0);
-        flags.initrole =
-            (ind == LB_ERR)
-                ? ROLE_RANDOM
-                : (int) SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_LIST,
-                                           CB_GETITEMDATA, ind, 0);
     }
 
-    if (SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_RANDOM, BM_GETCHECK, 0, 0)
-        == BST_CHECKED) {
+    if (!ok_race(role, race, gender, alignment)) {
+        fully_specified = FALSE;
         flags.initrace = ROLE_RANDOM;
-    } else {
-        ind =
-            SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_LIST, CB_GETCURSEL, 0, 0);
-        flags.initrace =
-            (ind == LB_ERR)
-                ? ROLE_RANDOM
-                : (int) SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_LIST,
-                                           CB_GETITEMDATA, ind, 0);
     }
 
-    if (SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_RANDOM, BM_GETCHECK, 0, 0)
-        == BST_CHECKED) {
+    if (!ok_gend(role, race, gender, alignment)) {
+        fully_specified = FALSE;
         flags.initgend = ROLE_RANDOM;
-    } else {
-        ind = SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_LIST, CB_GETCURSEL, 0,
-                                 0);
-        flags.initgend =
-            (ind == LB_ERR)
-                ? ROLE_RANDOM
-                : (int) SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_LIST,
-                                           CB_GETITEMDATA, ind, 0);
     }
 
-    if (SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_RANDOM, BM_GETCHECK, 0, 0)
-        == BST_CHECKED) {
+    if(!ok_align(role, race, gender, alignment))
+    {
+        fully_specified = FALSE;
         flags.initalign = ROLE_RANDOM;
-    } else {
-        ind = SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_LIST, CB_GETCURSEL, 0,
-                                 0);
-        flags.initalign =
-            (ind == LB_ERR)
-                ? ROLE_RANDOM
-                : (int) SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_LIST,
-                                           CB_GETITEMDATA, ind, 0);
     }
 
-    /* check the role */
-    if (flags.initrole == ROLE_RANDOM) {
-        flags.initrole = pick_role(flags.initrace, flags.initgend,
-                                   flags.initalign, PICK_RANDOM);
-        if (flags.initrole < 0) {
-            NHMessageBox(hWnd, TEXT("Incompatible role!"),
-                         MB_ICONSTOP | MB_OK);
-            return FALSE;
-        }
-    }
+    rigid_role_checks();
 
-    /* Select a race, if necessary */
-    /* force compatibility with role */
-    if (flags.initrace == ROLE_RANDOM
-        || !validrace(flags.initrole, flags.initrace)) {
-        /* pre-selected race not valid */
-        if (flags.initrace == ROLE_RANDOM) {
-            flags.initrace = pick_race(flags.initrole, flags.initgend,
-                                       flags.initalign, PICK_RANDOM);
-        }
+    role = flags.initrole;
+    race = flags.initrace;
+    gender = flags.initgend;
+    alignment = flags.initalign;
 
-        if (flags.initrace < 0) {
-            NHMessageBox(hWnd, TEXT("Incompatible race!"),
-                         MB_ICONSTOP | MB_OK);
-            return FALSE;
-        }
+    assert(role != ROLE_RANDOM && role != ROLE_NONE);
+    assert(race != ROLE_RANDOM && race != ROLE_NONE);
+    assert(gender != ROLE_RANDOM && gender != ROLE_NONE);
+    assert(alignment != ROLE_RANDOM && alignment != ROLE_NONE);
+    assert(ok_role(role, race, gender, alignment));
+    assert(ok_race(role, race, gender, alignment));
+    assert(ok_gend(role, race, gender, alignment));
+    assert(ok_align(role, race, gender, alignment));
+
+    return fully_specified;
+}
+
+/*-----------------------------------------------------------------------------*/
+BOOL
+plselDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+     LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
+    struct plsel_data * data = (plsel_data_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+    /* If there are no list box items, skip this message. */
+    if (lpdis->itemID < 0)
+        return FALSE;
+
+    HWND control = GetDlgItem(hWnd, wParam);
+    int i = lpdis->itemID;
+
+    {
+        char buf[64];
+        sprintf(buf, "DRAW %lx %d\n", (unsigned long)control, i);
+        OutputDebugStringA(buf);
     }
 
-    /* Select a gender, if necessary */
-    /* force compatibility with role/race, try for compatibility with
-     * pre-selected alignment */
-    if (flags.initgend < 0
-        || !validgend(flags.initrole, flags.initrace, flags.initgend)) {
-        /* pre-selected gender not valid */
-        if (flags.initgend == ROLE_RANDOM) {
-            flags.initgend = pick_gend(flags.initrole, flags.initrace,
-                                       flags.initalign, PICK_RANDOM);
-        }
+    const char * string;
 
-        if (flags.initgend < 0) {
-            NHMessageBox(hWnd, TEXT("Incompatible gender!"),
-                         MB_ICONSTOP | MB_OK);
-            return FALSE;
-        }
+    boolean ok = TRUE;
+    boolean selected;
+
+    if (wParam == IDC_PLSEL_ROLE_LIST) {
+        if (flags.female && roles[i].name.f)
+            string = roles[i].name.f;
+        else
+            string = roles[i].name.m;
+        selected = (flags.initrole == i);
+    } else {
+        assert(wParam == IDC_PLSEL_RACE_LIST);
+        ok = ok_race(flags.initrole, i, ROLE_RANDOM, ROLE_RANDOM);
+        string = races[i].noun;
+        selected = (flags.initrace == i);
     }
 
-    /* Select an alignment, if necessary */
-    /* force compatibility with role/race/gender */
-    if (flags.initalign < 0
-        || !validalign(flags.initrole, flags.initrace, flags.initalign)) {
-        /* pre-selected alignment not valid */
-        if (flags.initalign == ROLE_RANDOM) {
-            flags.initalign = pick_align(flags.initrole, flags.initrace,
-                                         flags.initgend, PICK_RANDOM);
-        } else {
-            NHMessageBox(hWnd, TEXT("Incompatible alignment!"),
-                         MB_ICONSTOP | MB_OK);
-            return FALSE;
+    SetBkMode(lpdis->hDC, OPAQUE);
+    HBRUSH brush;
+    if (selected) {
+        brush = CreateSolidBrush(RGB(0, 0, 0));
+        SetTextColor(lpdis->hDC, RGB(255, 255, 255));
+        SetBkColor(lpdis->hDC, RGB(0, 0, 0));
+    } else {
+        brush = CreateSolidBrush(RGB(255, 255, 255));
+        if (!ok)
+            SetTextColor(lpdis->hDC, RGB(220, 0, 0));
+        else
+            SetTextColor(lpdis->hDC, RGB(0, 0, 0));
+        SetBkColor(lpdis->hDC, RGB(255, 255, 255));
+    }
+
+    FillRect(lpdis->hDC, &lpdis->rcItem, brush);
+    RECT rect = lpdis->rcItem;
+    rect.left += 5;
+    DrawTextA(lpdis->hDC, string, strlen(string), &rect,
+        DT_LEFT | DT_SINGLELINE | DT_VCENTER);
+
+    if (data->focus == control) {
+        if (lpdis->itemState & LVIS_FOCUSED) {
+            /* draw focus rect */
+            RECT client_rt;
+
+            GetClientRect(lpdis->hwndItem, &client_rt);
+            SetRect(&rect, client_rt.left, lpdis->rcItem.top,
+                    client_rt.left + ListView_GetColumnWidth(lpdis->hwndItem, 0),
+                    lpdis->rcItem.bottom);
+            DrawFocusRect(lpdis->hDC, &rect);
+
+            {
+                char buf[64];
+                sprintf(buf, "FOCUS %lx %d\n", (unsigned long)control, i);
+                OutputDebugStringA(buf);
+            }
         }
     }
 
+    DeleteObject(brush);
+
     return TRUE;
 }
index 60f3929..c028fc8 100644 (file)
@@ -12,6 +12,6 @@
 int mswin_getlin_window(const char *question, char *result,
                         size_t result_size);
 int mswin_ext_cmd_window(int *selection);
-int mswin_player_selection_window(int *selection);
+boolean mswin_player_selection_window();
 
 #endif /* MSWINDlgWindow_h */
index c044199..1b802f2 100644 (file)
@@ -206,11 +206,11 @@ mswin_charset()
 {
     CHARSETINFO cis;
     if (SYMHANDLING(H_IBM))
-        if (TranslateCharsetInfo((DWORD *) GetOEMCP(), &cis, TCI_SRCCODEPAGE))
+        if (TranslateCharsetInfo((DWORD *) (uintptr_t) GetOEMCP(), &cis, TCI_SRCCODEPAGE))
             return cis.ciCharset;
         else
             return OEM_CHARSET;
-    else if (TranslateCharsetInfo((DWORD *) GetACP(), &cis, TCI_SRCCODEPAGE))
+    else if (TranslateCharsetInfo((DWORD *) (uintptr_t) GetACP(), &cis, TCI_SRCCODEPAGE))
         return cis.ciCharset;
     else
         return ANSI_CHARSET;
index 707ac3d..bb58a6b 100644 (file)
@@ -39,6 +39,7 @@ static int menuid2mapmode(int menuid);
 static int mapmode2menuid(int map_mode);
 static void nhlock_windows(BOOL lock);
 static char *nh_compose_ascii_screenshot();
+static void mswin_apply_window_style_all();
 // returns strdup() created pointer - callee assumes the ownership
 
 HWND
@@ -108,7 +109,7 @@ register_main_window_class()
     wcex.hInstance = GetNHApp()->hApp;
     wcex.hIcon = LoadIcon(GetNHApp()->hApp, (LPCTSTR) IDI_NETHACKW);
     wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
-    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+    wcex.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
     wcex.lpszMenuName = (TCHAR *) IDC_NETHACKW;
     wcex.lpszClassName = szMainWindowClass;
 
@@ -377,7 +378,7 @@ MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
             ZeroMemory(kbd_state, sizeof(kbd_state));
             GetKeyboardState(kbd_state);
 
-            if (ToAscii(wParam, (lParam >> 16) & 0xFF, kbd_state, &c, 0)) {
+            if (ToAscii((UINT) wParam, (lParam >> 16) & 0xFF, kbd_state, &c, 0)) {
                 NHEVENT_KBD(c & 0xFF);
                 return 0;
             } else {
@@ -737,11 +738,12 @@ mswin_layout_main_window(HWND changed_child)
             /* kludge - inventory window should have its own type (same as
                menu-text
                as a matter of fact) */
-            if (flags.perm_invent && i == WIN_INVEN)
+            if (flags.perm_invent && i == WIN_INVEN) {
                 mswin_get_window_placement(NHW_INVEN, &rt);
-            else
+            } else {
                 mswin_get_window_placement(GetNHApp()->windowlist[i].type,
                                            &rt);
+            }
 
             MoveWindow(GetNHApp()->windowlist[i].win, rt.left, rt.top,
                        rt.right - rt.left, rt.bottom - rt.top, TRUE);
@@ -905,6 +907,7 @@ onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
     case IDM_NHMODE: {
         GetNHApp()->regNetHackMode = GetNHApp()->regNetHackMode ? 0 : 1;
         mswin_menu_check_intf_mode();
+        mswin_apply_window_style_all();
         break;
     }
     case IDM_CLEARSETTINGS: {
@@ -1125,29 +1128,50 @@ mapmode2menuid(int map_mode)
 void
 nhlock_windows(BOOL lock)
 {
-    int i;
+    /* update menu */
+    GetNHApp()->bWindowsLocked = lock;
+    CheckMenuItem(GetMenu(GetNHApp()->hMainWnd), IDM_SETTING_LOCKWINDOWS,
+                  MF_BYCOMMAND | (lock ? MF_CHECKED : MF_UNCHECKED));
 
-    /* go through the windows list and adjust sizes */
+    /* restyle windows */
+    mswin_apply_window_style_all();
+}
+
+void
+mswin_apply_window_style(HWND hwnd) {
+    DWORD style = 0, exstyle = 0;
+
+    style = GetWindowLong(hwnd, GWL_STYLE);
+    exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+
+    if( !GetNHApp()->bWindowsLocked ) {
+        style = WS_CHILD|WS_CLIPSIBLINGS|WS_CAPTION|WS_SIZEBOX|(style & (WS_VISIBLE|WS_VSCROLL|WS_HSCROLL));
+        exstyle = WS_EX_WINDOWEDGE;
+    } else if (GetNHApp()->regNetHackMode) {
+        /* do away borders */
+        style = WS_CHILD|WS_CLIPSIBLINGS|(style & (WS_VISIBLE|WS_VSCROLL|WS_HSCROLL));
+        exstyle = 0;
+    } else {
+        style = WS_CHILD|WS_CLIPSIBLINGS|WS_THICKFRAME|(style & (WS_VISIBLE|WS_VSCROLL|WS_HSCROLL));
+        exstyle = WS_EX_WINDOWEDGE;
+    }
+
+    SetWindowLong(hwnd, GWL_STYLE, style);
+    SetWindowLong(hwnd, GWL_EXSTYLE, exstyle);
+    SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
+                 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOCOPYBITS);
+}
+
+void
+mswin_apply_window_style_all() {
+    int i;
     for (i = 0; i < MAXWINDOWS; i++) {
         if (IsWindow(GetNHApp()->windowlist[i].win)
             && !GetNHApp()->windowlist[i].dead) {
-            DWORD style;
-            style = GetWindowLong(GetNHApp()->windowlist[i].win, GWL_STYLE);
-            if (lock)
-                style &= ~WS_CAPTION;
-            else
-                style |= WS_CAPTION;
-            SetWindowLong(GetNHApp()->windowlist[i].win, GWL_STYLE, style);
-            SetWindowPos(GetNHApp()->windowlist[i].win, NULL, 0, 0, 0, 0,
-                         SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER
-                             | SWP_FRAMECHANGED);
+            mswin_apply_window_style(GetNHApp()->windowlist[i].win);
         }
     }
-
-    /* update menu */
-    GetNHApp()->bWindowsLocked = lock;
-    CheckMenuItem(GetMenu(GetNHApp()->hMainWnd), IDM_SETTING_LOCKWINDOWS,
-                  MF_BYCOMMAND | (lock ? MF_CHECKED : MF_UNCHECKED));
+    mswin_layout_main_window(NULL);
 }
 
 // returns strdup() created pointer - callee assumes the ownership
index 2350157..8b301da 100644 (file)
@@ -9,6 +9,7 @@
 #include "mhinput.h"
 #include "mhfont.h"
 
+#include "color.h"
 #include "patchlevel.h"
 
 #define NHMAP_FONT_NAME TEXT("Terminal")
@@ -89,6 +90,8 @@ mswin_init_map_window()
     /* Set window caption */
     SetWindowText(ret, "Map");
 
+    mswin_apply_window_style(ret);
+
     return ret;
 }
 
@@ -680,7 +683,7 @@ onPaint(HWND hWnd)
                                         &special, i, j);
                         ch = (char) mgch;
                         if (((special & MG_PET) && iflags.hilite_pet)
-                            || ((special & MG_DETECT)
+                            || ((special & (MG_DETECT | MG_BW_LAVA))
                                 && iflags.use_inverse)) {
                             back_brush =
                                 CreateSolidBrush(nhcolor_to_RGB(CLR_GRAY));
@@ -1023,41 +1026,8 @@ nhglyph2charcolor(short g, uchar *ch, int *color)
 COLORREF
 nhcolor_to_RGB(int c)
 {
-    switch (c) {
-    case CLR_BLACK:
-        return RGB(0x55, 0x55, 0x55);
-    case CLR_RED:
-        return RGB(0xFF, 0x00, 0x00);
-    case CLR_GREEN:
-        return RGB(0x00, 0x80, 0x00);
-    case CLR_BROWN:
-        return RGB(0xA5, 0x2A, 0x2A);
-    case CLR_BLUE:
-        return RGB(0x00, 0x00, 0xFF);
-    case CLR_MAGENTA:
-        return RGB(0xFF, 0x00, 0xFF);
-    case CLR_CYAN:
-        return RGB(0x00, 0xFF, 0xFF);
-    case CLR_GRAY:
-        return RGB(0xC0, 0xC0, 0xC0);
-    case NO_COLOR:
-        return RGB(0xFF, 0xFF, 0xFF);
-    case CLR_ORANGE:
-        return RGB(0xFF, 0xA5, 0x00);
-    case CLR_BRIGHT_GREEN:
-        return RGB(0x00, 0xFF, 0x00);
-    case CLR_YELLOW:
-        return RGB(0xFF, 0xFF, 0x00);
-    case CLR_BRIGHT_BLUE:
-        return RGB(0x00, 0xC0, 0xFF);
-    case CLR_BRIGHT_MAGENTA:
-        return RGB(0xFF, 0x80, 0xFF);
-    case CLR_BRIGHT_CYAN:
-        return RGB(0x80, 0xFF, 0xFF); /* something close to aquamarine */
-    case CLR_WHITE:
-        return RGB(0xFF, 0xFF, 0xFF);
-    default:
-        return RGB(0x00, 0x00, 0x00); /* black */
-    }
+    if (c >= 0 && c < CLR_MAX)
+        return GetNHApp()->regMapColors[c];
+    return RGB(0x00, 0x00, 0x00);
 }
 
index 258eed4..b541af3 100644 (file)
@@ -119,15 +119,7 @@ mswin_init_menu_window(int type)
     /* Set window caption */
     SetWindowText(ret, "Menu/Text");
 
-    if (!GetNHApp()->bWindowsLocked) {
-        DWORD style;
-        style = GetWindowLong(ret, GWL_STYLE);
-        style |= WS_CAPTION;
-        SetWindowLong(ret, GWL_STYLE, style);
-        SetWindowPos(ret, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
-                                                | SWP_NOZORDER
-                                                | SWP_FRAMECHANGED);
-    }
+    mswin_apply_window_style(ret);
 
     SetMenuType(ret, type);
     return ret;
@@ -155,7 +147,7 @@ mswin_menu_window_select_menu(HWND hWnd, int how, MENU_ITEM_P **_selected,
         activate = TRUE;
     }
 
-    data->is_active = activate;
+    data->is_active = activate && !GetNHApp()->regNetHackMode;
 
     /* set menu type */
     SetMenuListType(hWnd, how);
@@ -168,16 +160,17 @@ mswin_menu_window_select_menu(HWND hWnd, int how, MENU_ITEM_P **_selected,
         ap = data->menu.gacc;
         for (i = 0; i < data->menu.size; i++) {
             if (data->menu.items[i].accelerator != 0) {
-                next_char = (char) (data->menu.items[i].accelerator + 1);
+                if (isalpha(data->menu.items[i].accelerator)) {
+                    next_char = (char)(data->menu.items[i].accelerator + 1);
+                }
             } else if (NHMENU_IS_SELECTABLE(data->menu.items[i])) {
-                if ((next_char >= 'a' && next_char <= 'z')
-                    || (next_char >= 'A' && next_char <= 'Z')) {
+                if (isalpha(next_char)) {
                     data->menu.items[i].accelerator = next_char;
                 } else {
                     if (next_char > 'z')
                         next_char = 'A';
                     else if (next_char > 'Z')
-                        break;
+                        next_char = 'a';
 
                     data->menu.items[i].accelerator = next_char;
                 }
@@ -254,7 +247,20 @@ mswin_menu_window_select_menu(HWND hWnd, int how, MENU_ITEM_P **_selected,
         data->is_active = FALSE;
         LayoutMenu(hWnd); // hide dialog buttons
         mswin_popup_destroy(hWnd);
+
+        /* If we just used the permanent inventory window to pick something,
+         * set the menu back to its display inventory state.
+         */
+        if (flags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN
+            && how != PICK_NONE) {
+            data->menu.prompt[0] = '\0';
+            SetMenuListType(hWnd, PICK_NONE);
+            for (i = 0; i < data->menu.size; i++)
+                data->menu.items[i].count = 0;
+            LayoutMenu(hWnd);
+        }
     }
+
     return ret_val;
 }
 /*-----------------------------------------------------------------------------*/
@@ -485,7 +491,12 @@ MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                                  : SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_TEXT));
         }
     }
-        return FALSE;
+    return FALSE;
+
+    case WM_CTLCOLORDLG:
+        return (INT_PTR)(text_bg_brush
+                            ? text_bg_brush
+                            : SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_TEXT));
 
     case WM_DESTROY:
         if (data) {
@@ -589,8 +600,6 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
 
         if (data->type != MENU_TYPE_MENU)
             break;
-        if (strlen(msg_data->str) == 0)
-            break;
 
         if (data->menu.size == data->menu.allocated) {
             data->menu.allocated += 10;
@@ -608,6 +617,8 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
         data->menu.items[new_item].attr = msg_data->attr;
         strncpy(data->menu.items[new_item].str, msg_data->str,
                 NHMENU_STR_SIZE);
+       /* prevent & being interpreted as a mnemonic start */
+        strNsubst(data->menu.items[new_item].str, "&", "&&", 0);
         data->menu.items[new_item].presel = msg_data->presel;
 
         /* calculate tabstop size */
@@ -801,17 +812,17 @@ SetMenuListType(HWND hWnd, int how)
 
     switch (how) {
     case PICK_NONE:
-        dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD | WS_VSCROLL
+        dwStyles = WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_VSCROLL
                    | WS_HSCROLL | LVS_REPORT | LVS_OWNERDRAWFIXED
                    | LVS_SINGLESEL;
         break;
     case PICK_ONE:
-        dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD | WS_VSCROLL
+        dwStyles = WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_VSCROLL
                    | WS_HSCROLL | LVS_REPORT | LVS_OWNERDRAWFIXED
                    | LVS_SINGLESEL;
         break;
     case PICK_ANY:
-        dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD | WS_VSCROLL
+        dwStyles = WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_VSCROLL
                    | WS_HSCROLL | LVS_REPORT | LVS_OWNERDRAWFIXED
                    | LVS_SINGLESEL;
         break;
@@ -887,6 +898,11 @@ GetMenuControl(HWND hWnd)
 
     data = (PNHMenuWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
 
+       /* We may continue getting window messages after a window's WM_DESTROY is
+          called.  We need to handle the case that USERDATA has been freed. */
+       if (data == NULL)
+               return NULL;
+
     if (data->type == MENU_TYPE_TEXT) {
         return GetDlgItem(hWnd, IDC_MENU_TEXT);
     } else {
@@ -1024,7 +1040,8 @@ onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
 
             if (iflags.use_menu_color
                 && (menucolr = get_menu_coloring(item->str, &color, &attr))) {
-                /* TODO: use attr too */
+                SelectObject(lpdis->hDC, 
+                             mswin_get_font(NHW_MENU, attr, lpdis->hDC, FALSE));
                 if (color != NO_COLOR)
                     SetTextColor(lpdis->hDC, nhcolor_to_RGB(color));
             }
@@ -1414,7 +1431,7 @@ onListChar(HWND hWnd, HWND hwndList, WORD ch)
             }
         }
 
-        if (isdigit(ch)) {
+        if (isdigit((uchar) ch)) {
             int count;
             i = ListView_GetNextItem(hwndList, -1, LVNI_FOCUSED);
             if (i >= 0) {
@@ -1444,7 +1461,11 @@ onListChar(HWND hWnd, HWND hwndList, WORD ch)
         if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
             || is_accelerator) {
             if (data->how == PICK_ANY || data->how == PICK_ONE) {
-                for (i = 0; i < data->menu.size; i++) {
+                topIndex = ListView_GetTopIndex(hwndList);
+                if( topIndex < 0 || topIndex > data->menu.size ) break; // impossible?
+                int iter = topIndex;
+                do {
+                    i = iter % data->menu.size;
                     if (data->menu.items[i].accelerator == ch) {
                         if (data->how == PICK_ANY) {
                             SelectMenuItem(
@@ -1462,7 +1483,7 @@ onListChar(HWND hWnd, HWND hwndList, WORD ch)
                             return -2;
                         }
                     }
-                }
+                } while( (++iter % data->menu.size) != topIndex ); 
             }
         }
         break;
index 926f7d0..090068d 100644 (file)
@@ -72,6 +72,7 @@ typedef struct mswin_nhmsg_update_status {
     int n_fields;
     const char **vals;
     boolean *activefields;
+    int *percents;
     int *colors;
 } MSNHMsgUpdateStatus, *PMSNHMsgUpdateStatus;
 
index 4df1c53..c1345e6 100644 (file)
@@ -9,7 +9,7 @@
 
 #define MSG_WRAP_TEXT
 
-#define MSG_VISIBLE_LINES max(iflags.wc_vary_msgcount, 2)
+#define MSG_VISIBLE_LINES max(iflags.wc_vary_msgcount, 1)
 #define MAX_MSG_LINES 128
 #define MSG_LINES (int) min(iflags.msg_history, MAX_MSG_LINES)
 #define MAXWINDOWTEXT TBUFSZ
@@ -41,6 +41,8 @@ typedef struct mswin_nethack_message_window {
     int yMax;   /* maximum vertical scrolling position */
     int xPage;  /* page size of horizontal scroll bar */
 } NHMessageWindow, *PNHMessageWindow;
+#define LINE_PADDING_LEFT(data)  (data->xChar * (2 - data->xPos))
+#define LINE_PADDING_RIGHT(data)  (0)
 
 static TCHAR szMessageWindowClass[] = TEXT("MSNHMessageWndClass");
 LRESULT CALLBACK NHMessageWndProc(HWND, UINT, WPARAM, LPARAM);
@@ -108,6 +110,8 @@ mswin_init_message_window()
     /* Set window caption */
     SetWindowText(ret, "Messages");
 
+    mswin_apply_window_style(ret);
+
     return ret;
 }
 
@@ -243,6 +247,25 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
     data = (PNHMessageWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
     switch (wParam) {
     case MSNH_MSG_PUTSTR: {
+        /* Add the passed in message to the existing text.  Support the
+         * adding of text that ends in newline.  A newline in text
+         * will force any subsequent text that is added to be added on
+         * a new output line.
+         *
+         * TODO: Text can be added with newlines occurring within the text not
+         *       just at the end.  As currently implemented, this can cause
+         *       the text to be rendered such that the text following the
+         *       newline is rendered on a new line.  This can cause a poor
+         *       user experience when the user has set only a single text line
+         *       for the message window.  In this case, the user will not see
+         *       any line other then the last line of text and the --MORE--
+         *       message thus missing any text that appears before the last
+         *       embedded newline.  This does not meet the requirements of the
+         *       message window.
+         *       This code should be changed to do the right thing and split
+         *       the text so that only lines that end in newlines are added to
+         *       the stored window text.
+         */
         PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr) lParam;
         SCROLLINFO si;
 #if 0 /*JP*/
@@ -273,10 +296,17 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
                 /* check for "--more--" */
                 if (!data->nevermore && more_prompt_check(hWnd)) {
                     int okkey = 0;
-                    int chop;
+                    char tmptext[MAXWINDOWTEXT + 1];
+
                     // @@@ Ok respnses
 
-                    /* append more prompt and inticate the update */
+                    /* save original text */
+                    strcpy(tmptext, data->window_text[MSG_LINES - 1].text);
+
+                    /* text could end in newline so strip it */
+                    strip_newline(data->window_text[MSG_LINES - 1].text);
+
+                    /* append more prompt and indicate the update */
                     strncat(
                         data->window_text[MSG_LINES - 1].text, MORE,
                         MAXWINDOWTEXT
@@ -303,16 +333,15 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
                         }
                     }
 
-                    /* erase the "--more--" prompt */
-                    chop = strlen(data->window_text[MSG_LINES - 1].text)
-                           - strlen(MORE);
-                    data->window_text[MSG_LINES - 1].text[chop] = '\0';
+                    /* restore original text */
+                    strcpy(data->window_text[MSG_LINES - 1].text, tmptext);
+
                     data->lines_not_seen = 0;
                 }
 
                 /* check if the string is empty */
                 for (p = data->window_text[MSG_LINES - 1].text;
-                     *p && isspace(*p); p++)
+                     *p && isspace((uchar) *p); p++)
                     ;
 
                 if (*p) {
@@ -576,7 +605,7 @@ onPaint(HWND hWnd)
     PNHMessageWindow data;
     RECT client_rt, draw_rt;
     int FirstLine, LastLine;
-    int i, x, y;
+    int i, y;
     HGDIOBJ oldFont;
     TCHAR wbuf[MAXWINDOWTEXT + 2];
     size_t wlen;
@@ -603,10 +632,10 @@ onPaint(HWND hWnd)
                     - (client_rt.bottom - ps.rcPaint.bottom) / data->yChar);
         y = min(ps.rcPaint.bottom, client_rt.bottom);
         for (i = LastLine; i >= FirstLine; i--) {
-            x = data->xChar * (2 - data->xPos);
+            char tmptext[MAXWINDOWTEXT + 1];
 
-            draw_rt.left = x;
-            draw_rt.right = client_rt.right;
+            draw_rt.left = LINE_PADDING_LEFT(data);
+            draw_rt.right = client_rt.right - LINE_PADDING_RIGHT(data);
             draw_rt.top = y - data->yChar;
             draw_rt.bottom = y;
 
@@ -614,8 +643,10 @@ onPaint(HWND hWnd)
                 hdc, mswin_get_font(NHW_MESSAGE, data->window_text[i].attr,
                                     hdc, FALSE));
 
-            /* convert to UNICODE */
-            NH_A2W(data->window_text[i].text, wbuf, sizeof(wbuf));
+            /* convert to UNICODE stripping newline */
+            strcpy(tmptext, data->window_text[i].text);
+            strip_newline(tmptext);
+            NH_A2W(tmptext, wbuf, sizeof(wbuf));
             wlen = _tcslen(wbuf);
             setMsgTextColor(hdc, i < (MSG_LINES - data->lines_last_turn));
 #ifdef MSG_WRAP_TEXT
@@ -767,6 +798,10 @@ can_append_text(HWND hWnd, int attr, const char *text)
     if (data->window_text[MSG_LINES - 1].attr != attr)
         return FALSE;
 
+    /* cannot append if current line ends in newline */
+    if (str_end_is(data->window_text[MSG_LINES - 1].text, "\n"))
+        return FALSE;
+
     /* check if the maximum string langth will be exceeded */
     if (strlen(data->window_text[MSG_LINES - 1].text) + 2
             + /* space characters */
@@ -774,10 +809,11 @@ can_append_text(HWND hWnd, int attr, const char *text)
         >= MAXWINDOWTEXT)
         return FALSE;
 
-    /* check if the text is goinf to fin into a single line */
+    /* check if the text is going to fit into a single line */
     strcpy(tmptext, data->window_text[MSG_LINES - 1].text);
     strcat(tmptext, "  ");
     strcat(tmptext, text);
+    strip_newline(tmptext);
     strcat(tmptext, MORE);
 
     hdc = GetDC(hWnd);
@@ -786,6 +822,8 @@ can_append_text(HWND hWnd, int attr, const char *text)
         mswin_get_font(NHW_MESSAGE, data->window_text[MSG_LINES - 1].attr,
                        hdc, FALSE));
     GetClientRect(hWnd, &draw_rt);
+    draw_rt.left += LINE_PADDING_LEFT(data);
+    draw_rt.right -= LINE_PADDING_RIGHT(data);
     draw_rt.bottom = draw_rt.top; /* we only need width for the DrawText */
     DrawText(hdc, tmptext, strlen(tmptext), &draw_rt,
              DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT);
@@ -830,14 +868,17 @@ more_prompt_check(HWND hWnd)
         SelectObject(hdc, mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, FALSE));
     for (i = 0; i < data->lines_not_seen; i++) {
         /* we only need width for the DrawText */
-        SetRect(&draw_rt, client_rt.left, client_rt.top, client_rt.right,
-                client_rt.top);
+        SetRect(&draw_rt,
+            client_rt.left + LINE_PADDING_LEFT(data), client_rt.top,
+            client_rt.right - LINE_PADDING_RIGHT(data), client_rt.top);
         SelectObject(hdc,
                      mswin_get_font(NHW_MESSAGE,
                                     data->window_text[MSG_LINES - i - 1].attr,
                                     hdc, FALSE));
 
         strcpy(tmptext, data->window_text[MSG_LINES - i - 1].text);
+        strip_newline(tmptext);
+
         if (i == 0)
             strcat(tmptext, MORE);
 
index 19e4b3b..d1bceaa 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 mhsplash.c      $NHDT-Date: 1432512813 2015/05/25 00:13:33 $  $NHDT-Branch: master $:$NHDT-Revision: 1.25 $ */
+/* NetHack 3.6 mhsplash.c      $NHDT-Date: 1449751714 2015/12/10 12:48:34 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.27 $ */
 /* Copyright (C) 2001 by Alex Kompel    */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -36,13 +36,9 @@ mswin_display_splash_window(BOOL show_ver)
     RECT controlrt;
     HWND hWnd;
     int buttop;
-    int strsize = 0;
-    int bufsize = BUFSZ;
-    char *buf = malloc(bufsize);
+    strbuf_t strbuf;
 
-    if (buf == NULL)
-        panic("out of memory");
-    buf[0] = '\0';
+    strbuf_init(&strbuf);
 
     hWnd = CreateDialog(GetNHApp()->hApp, MAKEINTRESOURCE(IDD_SPLASH),
                         GetNHApp()->hMainWnd, NHSplashWndProc);
@@ -87,60 +83,27 @@ mswin_display_splash_window(BOOL show_ver)
                clientrt.right - 2 * SPLASH_OFFSET_X, controlrt.bottom, TRUE);
 
     /* Fill the text control */
-    Sprintf(buf, "%s\r\n%s\r\n%s\r\n%s\r\n\r\n", COPYRIGHT_BANNER_A,
+    strbuf_reserve(&strbuf, BUFSIZ);
+    Sprintf(strbuf.str, "%s\n%s\n%s\n%s\n\n", COPYRIGHT_BANNER_A,
             COPYRIGHT_BANNER_B, COPYRIGHT_BANNER_C, COPYRIGHT_BANNER_D);
-    strsize = strlen(buf);
 
     if (show_ver) {
         /* Show complete version information */
         dlb *f;
-
-#if 0 /*W360-1*/
-        getversionstring(buf + strsize);
-        strcat(buf, "\r\n\r\n");
-#else
         char verbuf[BUFSZ];
         int verstrsize = 0;
-
         getversionstring(verbuf);
-        verstrsize = strlen(verbuf);
-        if (verstrsize + strlen("\r\n\r\n") + 1  <  BUFSZ - 1)
-            strcat(verbuf, "\r\n\r\n");
-        verstrsize = strlen(verbuf);
-
-        if (strsize + verstrsize + 1 > bufsize) {
-            bufsize += BUFSZ;
-            buf = realloc(buf, bufsize);
-            if (buf == NULL)
-                panic("out of memory");
-        }
-        strcat(buf, verbuf);
-#endif
-        strsize = strlen(buf);
-
+        strbuf_append(&strbuf, verbuf);
+        strbuf_append(&strbuf, "\n\n");
+            
         /* Add compile options */
         f = dlb_fopen(OPTIONS_USED, RDTMODE);
         if (f) {
             char line[LLEN + 1];
 
-            while (dlb_fgets(line, LLEN, f)) {
-                size_t len;
-                len = strlen(line);
-                if (len > 0 && line[len - 1] == '\n') {
-                    line[len - 1] = '\r';
-                    line[len] = '\n';
-                    line[len + 1] = '\0';
-                    len++;
-                }
-                if (strsize + (int) len + 1 > bufsize) {
-                    bufsize += BUFSZ;
-                    buf = realloc(buf, bufsize);
-                    if (buf == NULL)
-                        panic("out of memory");
-                }
-                strcat(buf, line);
-                strsize += len;
-            }
+            while (dlb_fgets(line, LLEN, f))
+                strbuf_append(&strbuf, line);
             (void) dlb_fclose(f);
         }
     } else {
@@ -153,32 +116,18 @@ mswin_display_splash_window(BOOL show_ver)
             if (nf != NULL) {
                 char line[LLEN + 1];
 
-                while (fgets(line, LLEN, nf)) {
-                    size_t len;
-                    len = strlen(line);
-                    if (len > 0 && line[len - 1] == '\n') {
-                        line[len - 1] = '\r';
-                        line[len] = '\n';
-                        line[len + 1] = '\0';
-                        len++;
-                    }
-                    if (strsize + (int) len + 1 > bufsize) {
-                        bufsize += BUFSZ;
-                        buf = realloc(buf, bufsize);
-                        if (buf == NULL)
-                            panic("out of memory");
-                    }
-                    strcat(buf, line);
-                    strsize += len;
-                }
+                while (fgets(line, LLEN, nf))
+                    strbuf_append(&strbuf, line);
                 (void) fclose(nf);
             } else {
-                strcat(buf, "No news.");
+                strbuf_append(&strbuf, "No news.");
             }
         }
     }
-    SetWindowText(GetDlgItem(hWnd, IDC_EXTRAINFO), buf);
-    free(buf);
+
+    strbuf_nl_to_crlf(&strbuf);
+    SetWindowText(GetDlgItem(hWnd, IDC_EXTRAINFO), strbuf.str);
+    strbuf_empty(&strbuf);
     ShowWindow(hWnd, SW_SHOW);
 
     while (IsWindow(hWnd) && GetMessage(&msg, NULL, 0, 0) != 0) {
index 21d3b7b..52d2462 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright (C) 2001 by Alex Kompel    */
 /* NetHack may be freely redistributed.  See license for details. */
 
+#include <assert.h>
 #include "winMS.h"
 #include "mhstatus.h"
 #include "mhmsg.h"
 
 extern COLORREF nhcolor_to_RGB(int c); /* from mhmap */
 
+typedef struct back_buffer {
+    HWND hWnd;
+    HDC hdc;
+    HBITMAP bm;
+    HBITMAP orig_bm;
+    int width;
+    int height;
+} back_buffer_t;
+
+void back_buffer_free(back_buffer_t * back_buffer)
+{
+    if (back_buffer->bm != NULL) {
+        SelectObject(back_buffer->hdc, back_buffer->orig_bm);
+        DeleteObject(back_buffer->bm);
+        back_buffer->bm = NULL;
+    }
+}
+
+void back_buffer_allocate(back_buffer_t * back_buffer, int width, int height)
+{
+    HDC hdc = GetDC(back_buffer->hWnd);
+    back_buffer->bm = CreateCompatibleBitmap(hdc, width, height);
+    back_buffer->orig_bm =  SelectObject(back_buffer->hdc, back_buffer->bm);
+    back_buffer->width = width;
+    back_buffer->height = height;
+    ReleaseDC(back_buffer->hWnd, hdc);
+}
+
+void back_buffer_size(back_buffer_t * back_buffer, int width, int height)
+{
+    if (back_buffer->bm == NULL || back_buffer->width != width
+                                || back_buffer->height != height) {
+        back_buffer_free(back_buffer);
+        back_buffer_allocate(back_buffer, width, height);
+    }
+}
+
+void back_buffer_init(back_buffer_t * back_buffer, HWND hWnd, int width, int height)
+{
+    back_buffer->hWnd = hWnd;
+    back_buffer->hdc = CreateCompatibleDC(NULL);
+    back_buffer->bm = NULL;
+
+    back_buffer_size(back_buffer, width, height);
+}
+
 typedef struct mswin_nethack_status_window {
     int index;
     char window_text[NHSW_LINES][MAXWINDOWTEXT + 1];
     int n_fields;
     const char **vals;
     boolean *activefields;
+    int *percents;
     int *colors;
+    back_buffer_t back_buffer;
 } NHStatusWindow, *PNHStatusWindow;
 
-#ifdef STATUS_VIA_WINDOWPORT
 static int fieldorder1[] = { BL_TITLE, BL_STR, BL_DX,    BL_CO,    BL_IN,
                              BL_WI,    BL_CH,  BL_ALIGN, BL_SCORE, -1 };
 static int fieldorder2[] = { BL_LEVELDESC, BL_GOLD,      BL_HP,   BL_HPMAX,
@@ -29,7 +77,6 @@ static int fieldorder2[] = { BL_LEVELDESC, BL_GOLD,      BL_HP,   BL_HPMAX,
                              BL_EXP,       BL_HD,        BL_TIME, BL_HUNGER,
                              BL_CAP,       BL_CONDITION, -1 };
 static int *fieldorders[] = { fieldorder1, fieldorder2, NULL };
-#endif /*  STATUS_VIA_WINDOWPORT */
 
 static TCHAR szStatusWindowClass[] = TEXT("MSNHStatusWndClass");
 LRESULT CALLBACK StatusWndProc(HWND, UINT, WPARAM, LPARAM);
@@ -46,6 +93,7 @@ mswin_init_status_window()
     HWND ret;
     NHStatusWindow *data;
     RECT rt;
+    int width, height;
 
     if (!run_once) {
         register_status_window_class();
@@ -60,12 +108,14 @@ mswin_init_status_window()
     }
 
     /* create status window object */
+    width = rt.right - rt.left;
+    height = rt.bottom - rt.top;
     ret = CreateWindow(szStatusWindowClass, NULL,
                        WS_CHILD | WS_CLIPSIBLINGS | WS_SIZEBOX,
-                       rt.left,            /* horizontal position of window */
-                       rt.top,             /* vertical position of window */
-                       rt.right - rt.left, /* window width */
-                       rt.bottom - rt.top, /* window height */
+                       rt.left, /* horizontal position of window */
+                       rt.top,  /* vertical position of window */
+                       width,   /* window width */
+                       height,  /* window height */
                        GetNHApp()->hMainWnd, NULL, GetNHApp()->hApp, NULL);
     if (!ret)
         panic("Cannot create status window");
@@ -80,6 +130,21 @@ mswin_init_status_window()
 
     ZeroMemory(data, sizeof(NHStatusWindow));
     SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR) data);
+
+    back_buffer_init(&data->back_buffer, ret, width, height);
+
+    mswin_apply_window_style(ret);
+
+    if (status_bg_brush == NULL) {
+        status_bg_color = (COLORREF)GetSysColor(DEFAULT_COLOR_BG_STATUS);
+        status_bg_brush = CreateSolidBrush(status_bg_color);
+    }
+
+    if (status_fg_brush == NULL) {
+        status_fg_color = (COLORREF)GetSysColor(DEFAULT_COLOR_FG_STATUS);
+        status_fg_brush = CreateSolidBrush(status_fg_color);
+    }
+
     return ret;
 }
 
@@ -96,9 +161,7 @@ register_status_window_class()
     wcex.hInstance = GetNHApp()->hApp;
     wcex.hIcon = NULL;
     wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
-    wcex.hbrBackground = status_bg_brush
-                             ? status_bg_brush
-                             : SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_STATUS);
+    wcex.hbrBackground = NULL;
     wcex.lpszMenuName = NULL;
     wcex.lpszClassName = szStatusWindowClass;
 
@@ -130,9 +193,10 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
         case MSNH_MSG_GETTEXT: {
             PMSNHMsgGetText msg_data = (PMSNHMsgGetText) lParam;
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
             int **fop;
             int *f;
+
             msg_data->buffer[0] = '\0';
             if (data->n_fields > 0) {
                 for (fop = fieldorders; *fop; fop++) {
@@ -140,20 +204,20 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                         if (data->activefields[*f])
                             strncat(msg_data->buffer, data->vals[*f],
                                     msg_data->max_size
-                                        - strlen(msg_data->buffer));
+                                    - strlen(msg_data->buffer));
                     }
                     strncat(msg_data->buffer, "\r\n",
                             msg_data->max_size - strlen(msg_data->buffer));
                 }
             }
-#else  /*  STATUS_VIA_WINDOWPORT */
+#else
             strncpy(msg_data->buffer, data->window_text[0],
                     msg_data->max_size);
             strncat(msg_data->buffer, "\r\n",
                     msg_data->max_size - strlen(msg_data->buffer));
             strncat(msg_data->buffer, data->window_text[1],
                     msg_data->max_size - strlen(msg_data->buffer));
-#endif /*  STATUS_VIA_WINDOWPORT */
+#endif
         } break;
 
         case MSNH_MSG_UPDATE_STATUS: {
@@ -161,6 +225,7 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
             data->n_fields = msg_data->n_fields;
             data->vals = msg_data->vals;
             data->activefields = msg_data->activefields;
+            data->percents = msg_data->percents;
             data->colors = msg_data->colors;
             InvalidateRect(hWnd, NULL, TRUE);
         } break;
@@ -203,88 +268,155 @@ StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     return 0;
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
+#ifdef STATUS_HILITES
 static LRESULT
 onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
 {
+    int hpbar_percent = 100;
+    int hpbar_color = NO_COLOR;
     int *f;
     int **fop;
     SIZE sz;
-    HGDIOBJ oldFont, normalFont, boldFont;
+    HGDIOBJ normalFont, boldFont;
     TCHAR wbuf[BUFSZ];
-    COLORREF OldBg, OldFg, Bg, Fg;
     RECT rt;
     PAINTSTRUCT ps;
     HDC hdc;
     PNHStatusWindow data;
+    int width, height;
+    RECT clear_rect;
+    HDC front_buffer_hdc;
 
     data = (PNHStatusWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
 
-    hdc = BeginPaint(hWnd, &ps);
+    front_buffer_hdc = BeginPaint(hWnd, &ps);
     GetClientRect(hWnd, &rt);
 
+    width = rt.right - rt.left;
+    height = rt.bottom - rt.top;
+
+    back_buffer_size(&data->back_buffer, width, height);
+
+    hdc = data->back_buffer.hdc;
+
     normalFont = mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE);
     boldFont = mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, FALSE);
-    oldFont = SelectObject(hdc, normalFont);
 
-    Bg = status_bg_brush ? status_bg_color
-                         : (COLORREF) GetSysColor(DEFAULT_COLOR_BG_STATUS);
-    OldBg = SetBkColor(hdc, Bg);
+    SelectObject(hdc, normalFont);
+
+    SetBkColor(hdc, status_bg_color);
+    SetTextColor(hdc, status_fg_color);
+
+    if (iflags.wc2_hitpointbar && BL_HP < data->n_fields
+        && data->activefields[BL_HP]) {
+        hpbar_percent = data->percents[BL_HP];
+        hpbar_color = data->colors[BL_HP] & 0x00ff;
+    }
+
+    clear_rect.left = 0;
+    clear_rect.top = 0;
+    clear_rect.right = width;
+    clear_rect.bottom = height;
 
-    Fg = status_fg_brush ? status_fg_color
-                         : (COLORREF) GetSysColor(DEFAULT_COLOR_FG_STATUS);
-    OldFg = SetTextColor(hdc, Fg);
+    FillRect(hdc, &clear_rect, status_bg_brush);
 
     for (fop = fieldorders; *fop; fop++) {
         LONG left = rt.left;
         LONG cy = 0;
         int vlen;
         for (f = *fop; *f != -1; f++) {
+            int clr, atr;
+            int fntatr = ATR_NONE;
+            HGDIOBJ fnt;
+            COLORREF nFg, nBg;
+
             if (((*f) >= data->n_fields) || (!data->activefields[*f]))
                 continue;
+            clr = data->colors[*f] & 0x00ff;
+            atr = (data->colors[*f] & 0xff00) >> 8;
             vlen = strlen(data->vals[*f]);
             NH_A2W(data->vals[*f], wbuf, SIZE(wbuf));
 
-            if (!iflags.use_status_hilites) {
-                SelectObject(hdc, normalFont);
-                SetBkColor(hdc, Bg);
-                SetTextColor(hdc, Fg);
-            } else if (data->colors[*f] == CLR_MAX
-                || data->colors[*f] == BL_HILITE_NONE) {
-                SelectObject(hdc, normalFont);
-                SetBkColor(hdc, Bg);
-                SetTextColor(hdc, Fg);
-            } else if (data->colors[*f] > 0) {
-                SelectObject(hdc, normalFont);
-                SetBkColor(hdc, Bg);
-                SetTextColor(hdc, nhcolor_to_RGB(data->colors[*f]));
-            } else if (data->colors[*f] == BL_HILITE_INVERSE) {
-                SelectObject(hdc, normalFont);
-                SetBkColor(hdc, Fg);
-                SetTextColor(hdc, Bg);
-            } else if (data->colors[*f] == BL_HILITE_BOLD) {
-                SelectObject(hdc, boldFont);
-                SetBkColor(hdc, Bg);
-                SetTextColor(hdc, Fg);
+            if (atr & HL_BOLD)
+                fntatr = ATR_BOLD;
+            else if (atr & HL_INVERSE)
+                fntatr = ATR_INVERSE;
+            else if (atr & HL_ULINE)
+                fntatr = ATR_ULINE;
+            else if (atr & HL_BLINK)
+                fntatr = ATR_BLINK;
+            else if (atr & HL_DIM)
+                fntatr = ATR_DIM;
+            fnt = mswin_get_font(NHW_STATUS, fntatr, hdc, FALSE);
+            nFg = (clr == NO_COLOR ? status_fg_color
+                   : ((clr >= 0 && clr < CLR_MAX) ? nhcolor_to_RGB(clr)
+                      : status_fg_color));
+            nBg = status_bg_color;
+
+            sz.cy = -1;
+            if (*f == BL_TITLE && iflags.wc2_hitpointbar) {
+                HBRUSH back_brush = CreateSolidBrush(nhcolor_to_RGB(hpbar_color));
+                RECT barrect;
+
+                /* prepare for drawing */
+                SelectObject(hdc, fnt);
+                SetBkMode(hdc, OPAQUE);
+                SetBkColor(hdc, status_bg_color);
+                SetTextColor(hdc, nhcolor_to_RGB(hpbar_color));
+
+                /* get bounding rectangle */
+                GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
+
+                /* first draw title normally */
+                DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
+
+                /* calc bar length */
+                barrect.left = rt.left;
+                barrect.top = rt.top;
+                barrect.bottom = sz.cy;
+                if (hpbar_percent > 0)
+                    barrect.right = (int)((hpbar_percent * sz.cx) / 100);
+                else
+                    barrect.right = sz.cx;
+
+                /* then draw hpbar on top of title */
+                FillRect(hdc, &barrect, back_brush);
+                SetBkMode(hdc, TRANSPARENT);
+                SetTextColor(hdc, nBg);
+                DrawText(hdc, wbuf, vlen, &barrect, DT_LEFT);
+
+                DeleteObject(back_brush);
             } else {
-                SelectObject(hdc, normalFont);
-                SetBkColor(hdc, Bg);
-                SetTextColor(hdc, Fg);
-            }
+                if (atr & HL_INVERSE) {
+                    COLORREF tmp = nFg;
+                    nFg = nBg;
+                    nBg = tmp;
+                }
 
-            GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
-            DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
+                /* prepare for drawing */
+                SelectObject(hdc, fnt);
+                SetBkMode(hdc, OPAQUE);
+                SetBkColor(hdc, nBg);
+                SetTextColor(hdc, nFg);
+
+                /* get bounding rectangle */
+                GetTextExtentPoint32(hdc, wbuf, vlen, &sz);
+
+                /* draw */
+                DrawText(hdc, wbuf, vlen, &rt, DT_LEFT);
+            }
+            assert(sz.cy >= 0);
 
             rt.left += sz.cx;
             cy = max(cy, sz.cy);
         }
+
         rt.left = left;
         rt.top += cy;
     }
 
-    SelectObject(hdc, oldFont);
-    SetTextColor(hdc, OldFg);
-    SetBkColor(hdc, OldBg);
+    BitBlt(front_buffer_hdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
+
     EndPaint(hWnd, &ps);
 
     return 0;
@@ -333,7 +465,7 @@ onWMPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
 
     return 0;
 }
-#endif /*STATUS_VIA_WINDOWPORT*/
+#endif /* !STATUS_HILITES */
 
 void
 mswin_status_window_size(HWND hWnd, LPSIZE sz)
index 4dd7a10..626e46e 100644 (file)
@@ -51,15 +51,6 @@ mswin_init_text_window()
 
     /* Set window caption */
     SetWindowText(ret, "Text");
-    if (!GetNHApp()->bWindowsLocked) {
-        DWORD style;
-        style = GetWindowLong(ret, GWL_STYLE);
-        style |= WS_CAPTION;
-        SetWindowLong(ret, GWL_STYLE, style);
-        SetWindowPos(ret, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
-                                                | SWP_NOZORDER
-                                                | SWP_FRAMECHANGED);
-    }
 
     /* create and set window data */
     data = (PNHTextWindow) malloc(sizeof(NHTextWindow));
@@ -67,6 +58,9 @@ mswin_init_text_window()
         panic("out of memory");
     ZeroMemory(data, sizeof(NHTextWindow));
     SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR) data);
+
+    mswin_apply_window_style(ret);
+
     return ret;
 }
 
@@ -239,20 +233,35 @@ LayoutText(HWND hWnd)
     /* get window coordinates */
     GetClientRect(hWnd, &clrt);
 
-    /* set window placements */
-    GetWindowRect(btn_ok, &rt);
-    sz_ok.cx = clrt.right - clrt.left;
-    sz_ok.cy = rt.bottom - rt.top;
-    pt_ok.x = clrt.left;
-    pt_ok.y = clrt.bottom - sz_ok.cy;
+    if( !GetNHApp()->regNetHackMode ) {
+        /* set window placements */
+        GetWindowRect(btn_ok, &rt);
+        sz_ok.cx = clrt.right - clrt.left;
+        sz_ok.cy = rt.bottom - rt.top;
+        pt_ok.x = clrt.left;
+        pt_ok.y = clrt.bottom - sz_ok.cy;
+
+        pt_elem.x = clrt.left;
+        pt_elem.y = clrt.top;
+        sz_elem.cx = clrt.right - clrt.left;
+        sz_elem.cy = pt_ok.y;
+
+        MoveWindow(text, pt_elem.x, pt_elem.y, sz_elem.cx, sz_elem.cy, TRUE);
+        MoveWindow(btn_ok, pt_ok.x, pt_ok.y, sz_ok.cx, sz_ok.cy, TRUE);
+    } else {
+        sz_ok.cx = sz_ok.cy = 0;
+
+        pt_ok.x = pt_ok.y = 0;
+        pt_elem.x = clrt.left;
+        pt_elem.y = clrt.top;
 
-    pt_elem.x = clrt.left;
-    pt_elem.y = clrt.top;
-    sz_elem.cx = clrt.right - clrt.left;
-    sz_elem.cy = pt_ok.y;
+        sz_elem.cx = clrt.right - clrt.left;
+        sz_elem.cy = clrt.bottom - clrt.top;
 
-    MoveWindow(text, pt_elem.x, pt_elem.y, sz_elem.cx, sz_elem.cy, TRUE);
-    MoveWindow(btn_ok, pt_ok.x, pt_ok.y, sz_ok.cx, sz_ok.cy, TRUE);
+        ShowWindow(btn_ok, SW_HIDE);
+        MoveWindow(text, pt_elem.x, pt_elem.y, sz_elem.cx, sz_elem.cy, TRUE );
+    }
+    mswin_apply_window_style(text);
 }
 
 /* Edit box hook */
index 377f1ff..ad880df 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 mswproc.c       $NHDT-Date: 1449116670 2015/12/03 04:24:30 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.94 $ */
+/* NetHack 3.6 mswproc.c       $NHDT-Date: 1451611595 2016/01/01 01:26:35 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */
 /* Copyright (C) 2001 by Alex Kompel    */
 /* NetHack may be freely redistributed.  See license for details. */
 
 */
 
 #include "hack.h"
+#include "color.h"
 #include "dlb.h"
 #include "func_tab.h" /* for extended commands */
 #include "winMS.h"
 #include <assert.h>
-#if 1 /*W360-1*/
 #include <mmsystem.h>
-#endif
 #include "mhmap.h"
 #include "mhstatus.h"
 #include "mhtext.h"
@@ -43,7 +42,9 @@
 static FILE* _s_debugfp = NULL;
 extern void logDebug(const char *fmt, ...);
 # endif
-#else
+#endif
+
+#ifndef _DEBUG
 void
 logDebug(const char *fmt, ...)
 {
@@ -78,6 +79,8 @@ COLORREF status_fg_color = RGB(0xFF, 0xFF, 0xFF);
 COLORREF message_bg_color = RGB(0, 0, 0);
 COLORREF message_fg_color = RGB(0xFF, 0xFF, 0xFF);
 
+strbuf_t raw_print_strbuf = { 0 };
+
 /* Interface definition, for windows.c */
 struct window_procs mswin_procs = {
     "MSWIN",
@@ -87,7 +90,10 @@ struct window_procs mswin_procs = {
         | WC_FONTSIZ_MESSAGE | WC_FONTSIZ_STATUS | WC_FONTSIZ_MENU
         | WC_FONTSIZ_TEXT | WC_TILE_WIDTH | WC_TILE_HEIGHT | WC_TILE_FILE
         | WC_VARY_MSGCOUNT | WC_WINDOWCOLORS | WC_PLAYER_SELECTION
-        | WC_SPLASH_SCREEN | WC_POPUP_DIALOG,
+        | WC_SPLASH_SCREEN | WC_POPUP_DIALOG | WC_MOUSE_SUPPORT,
+#ifdef STATUS_HILITES
+    WC2_HITPOINTBAR | WC2_FLUSH_STATUS | WC2_HILITE_STATUS |
+#endif
     0L, mswin_init_nhwindows, mswin_player_selection, mswin_askname,
     mswin_get_nh_event, mswin_exit_nhwindows, mswin_suspend_nhwindows,
     mswin_resume_nhwindows, mswin_create_nhwindow, mswin_clear_nhwindow,
@@ -111,13 +117,8 @@ struct window_procs mswin_procs = {
     /* other defs that really should go away (they're tty specific) */
     mswin_start_screen, mswin_end_screen, mswin_outrip,
     mswin_preference_update, mswin_getmsghistory, mswin_putmsghistory,
-#ifdef STATUS_VIA_WINDOWPORT
     mswin_status_init, mswin_status_finish, mswin_status_enablefield,
     mswin_status_update,
-#ifdef STATUS_HILITES
-    mswin_status_threshold,
-#endif
-#endif
     genl_can_suspend_yes,
 };
 
@@ -214,7 +215,8 @@ mswin_init_nhwindows(int *argc, char **argv)
      */
     iflags.toptenwin = 1;
     set_option_mod_status("toptenwin", SET_IN_FILE);
-    set_option_mod_status("perm_invent", SET_IN_FILE);
+    //set_option_mod_status("perm_invent", SET_IN_FILE);
+    set_option_mod_status("mouse_support", SET_IN_GAME);
 
     /* initialize map tiles bitmap */
     initMapTiles();
@@ -262,8 +264,6 @@ mswin_init_nhwindows(int *argc, char **argv)
 void
 mswin_player_selection(void)
 {
-    int nRole;
-
     logDebug("mswin_player_selection()\n");
 
     if (iflags.wc_player_selection == VIA_DIALOG) {
@@ -313,7 +313,7 @@ mswin_player_selection(void)
             }
         } else {
             /* select a role */
-            if (mswin_player_selection_window(&nRole) == IDCANCEL) {
+            if (!mswin_player_selection_window()) {
                 bail(0);
             }
         }
@@ -721,8 +721,7 @@ mswin_exit_nhwindows(const char *str)
 
     /* Write Window settings to the registry */
     mswin_write_reg();
-    while (max_brush)
-        DeleteObject(brush_table[--max_brush]);
+
 }
 
 /* Prepare the window to be suspended. */
@@ -1242,6 +1241,7 @@ void
 mswin_wait_synch()
 {
     logDebug("mswin_wait_synch()\n");
+    mswin_raw_print_flush();
 }
 
 /*
@@ -1298,6 +1298,40 @@ mswin_print_glyph(winid wid, XCHAR_P x, XCHAR_P y, int glyph, int bkglyph)
 }
 
 /*
+ * mswin_raw_print_accumulate() accumulate the given text into
+ *   raw_print_strbuf.
+ */
+void
+mswin_raw_print_accumulate(const char * str, boolean bold)
+{
+    bold; // ignored for now
+
+    if (raw_print_strbuf.str != NULL) strbuf_append(&raw_print_strbuf, "\n");
+    strbuf_append(&raw_print_strbuf, str);
+}
+
+/*
+ * mswin_raw_print_flush() - display any text found in raw_print_strbuf in a
+ *   dialog box and clear raw_print_strbuf.
+ */
+void
+mswin_raw_print_flush()
+{
+    if (raw_print_strbuf.str != NULL) {
+        int wlen = strlen(raw_print_strbuf.str) + 1;
+        TCHAR * wbuf = (TCHAR *) alloc(wlen * sizeof(TCHAR));
+        if (wbuf != NULL) {
+            NHMessageBox(GetNHApp()->hMainWnd,
+                            NH_A2W(raw_print_strbuf.str, wbuf, wlen),
+                            MB_ICONINFORMATION | MB_OK);
+            free(wbuf);
+        }
+        strbuf_empty(&raw_print_strbuf);
+    }
+}
+
+
+/*
 raw_print(str)  -- Print directly to a screen, or otherwise guarantee that
                    the user sees str.  raw_print() appends a newline to str.
                    It need not recognize ASCII control characters.  This is
@@ -1309,14 +1343,12 @@ raw_print(str)  -- Print directly to a screen, or otherwise guarantee that
 void
 mswin_raw_print(const char *str)
 {
-    TCHAR wbuf[255];
     logDebug("mswin_raw_print(%s)\n", str);
+
     if (str && *str) {
         extern int redirect_stdout;
         if (!redirect_stdout)
-            NHMessageBox(GetNHApp()->hMainWnd,
-                         NH_A2W(str, wbuf, sizeof(wbuf)),
-                         MB_ICONINFORMATION | MB_OK);
+            mswin_raw_print_accumulate(str, FALSE);
         else
             fprintf(stdout, "%s", str);
     }
@@ -1330,11 +1362,14 @@ possible).
 void
 mswin_raw_print_bold(const char *str)
 {
-    TCHAR wbuf[255];
     logDebug("mswin_raw_print_bold(%s)\n", str);
-    if (str && *str)
-        NHMessageBox(GetNHApp()->hMainWnd, NH_A2W(str, wbuf, sizeof(wbuf)),
-                     MB_ICONINFORMATION | MB_OK);
+    if (str && *str) {
+        extern int redirect_stdout;
+        if (!redirect_stdout)
+            mswin_raw_print_accumulate(str, TRUE);
+        else
+            fprintf(stdout, "%s", str);
+    }
 }
 
 /*
@@ -1385,9 +1420,11 @@ mswin_nh_poskey(int *x, int *y, int *mod)
         mswin_main_loop();
 
     if (event->type == NHEVENT_MOUSE) {
-        *mod = event->ms.mod;
-        *x = event->ms.x;
-        *y = event->ms.y;
+       if (iflags.wc_mouse_support) {
+            *mod = event->ms.mod;
+            *x = event->ms.x;
+            *y = event->ms.y;
+        }
         key = 0;
     } else {
         key = event->kbd.ch;
@@ -1587,7 +1624,7 @@ mswin_yn_function(const char *question, const char *choices, CHAR_P def)
                 (WPARAM) MSNH_MSG_CARET, (LPARAM) &createcaret);
 
     /* display selection in the message window */
-    if (isprint(ch) && ch != '#') {
+    if (isprint((uchar) ch) && ch != '#') {
         res_ch[0] = ch;
         res_ch[1] = '\x0';
         mswin_putstr_ex(WIN_MESSAGE, ATR_BOLD, res_ch, 1);
@@ -1625,11 +1662,16 @@ mswin_getlin(const char *question, char *input)
         SendMessage(mswin_hwnd_from_winid(WIN_MESSAGE), WM_MSNH_COMMAND,
                     (WPARAM) MSNH_MSG_CARET, (LPARAM) &createcaret);
 
-        mswin_clear_nhwindow(WIN_MESSAGE);
+        /* mswin_clear_nhwindow(WIN_MESSAGE); */
         mswin_putstr_ex(WIN_MESSAGE, ATR_BOLD, question, 0);
         mswin_putstr_ex(WIN_MESSAGE, ATR_BOLD, " ", 1);
+#ifdef EDIT_GETLIN
+        mswin_putstr_ex(WIN_MESSAGE, ATR_BOLD, input, 0);
+        len = strlen(input);
+#else
         input[0] = '\0';
         len = 0;
+#endif
         ShowCaret(mswin_hwnd_from_winid(WIN_MESSAGE));
         done = FALSE;
         while (!done) {
@@ -1655,10 +1697,8 @@ mswin_getlin(const char *question, char *input)
                         len--;
 #endif
                     input[len] = '\0';
-#if 1 /*W360-1*/
                 } else if (len>=(BUFSZ-1)) {
                     PlaySound((LPCSTR)SND_ALIAS_SYSTEMEXCLAMATION, NULL, SND_ALIAS_ID|SND_ASYNC);
-#endif
                 } else {
                     input[len++] = c;
 #if 1 /*JP*//*2\83o\83C\83g\95\8e\9a\82È\82ç\82»\82Ì\8fê\82Å\82à\82¤1\83o\83C\83g\93Ç\82Ý\8d\9e\82Þ*/
@@ -1746,7 +1786,9 @@ mswin_get_ext_cmd()
                     com_index = -1;
                     for (oindex = 0; extcmdlist[oindex].ef_txt != (char *) 0;
                          oindex++) {
-                        if (!strncmpi(cmd, extcmdlist[oindex].ef_txt, len)) {
+                        if ((extcmdlist[oindex].flags & AUTOCOMPLETE)
+                            && !(!wizard && (extcmdlist[oindex].flags & WIZMODECMD))
+                            && !strncmpi(cmd, extcmdlist[oindex].ef_txt, len)) {
                             if (com_index == -1) /* no matches yet */
                                 com_index = oindex;
                             else
@@ -1867,7 +1909,7 @@ mswin_outrip(winid wid, int how, time_t when)
     putstr(wid, 0, buf);
 
     /* Put together death description */
-    formatkiller(buf, sizeof buf, how);
+    formatkiller(buf, sizeof buf, how, FALSE);
 
     /* Put death type on stone */
     putstr(wid, 0, buf);
@@ -2000,6 +2042,11 @@ mswin_preference_update(const char *pref)
         mswin_layout_main_window(NULL);
         return;
     }
+
+    if (stricmp(pref, "perm_invent") == 0) {
+        mswin_update_inventory();
+        return;
+    }
 }
 
 #define TEXT_BUFFER_SIZE 4096
@@ -2034,7 +2081,7 @@ mswin_getmsghistory(BOOLEAN_P init)
         if (next_message)
             next_message++;
         if (p)
-            while (p >= retval && isspace(*p))
+            while (p >= retval && isspace((uchar) *p))
                 *p-- = (char) 0; /* delete trailing whitespace */
         return retval;
     }
@@ -2079,7 +2126,7 @@ bail(const char *mesg)
 {
     clearlocks();
     mswin_exit_nhwindows(mesg);
-    terminate(EXIT_SUCCESS);
+    nh_terminate(EXIT_SUCCESS);
     /*NOTREACHED*/
 }
 
@@ -2213,7 +2260,10 @@ mswin_popup_destroy(HWND hWnd)
     }
     DrawMenuBar(GetNHApp()->hMainWnd);
 
-    ShowWindow(hWnd, SW_HIDE);
+    /* Don't hide the permanent inventory window ... leave it showing */
+    if (!flags.perm_invent || mswin_winid_from_handle(hWnd) != WIN_INVEN)
+        ShowWindow(hWnd, SW_HIDE);
+
     GetNHApp()->hPopupWnd = NULL;
 
     mswin_layout_main_window(hWnd);
@@ -2244,7 +2294,7 @@ logDebug(const char *fmt, ...)
 /* Reading and writing settings from the registry. */
 #define CATEGORYKEY "Software"
 #define COMPANYKEY "NetHack"
-#define PRODUCTKEY "NetHack 3.6.0"
+#define PRODUCTKEY "NetHack 3.6.1"
 #define SETTINGSKEY "Settings"
 #define MAINSHOWSTATEKEY "MainShowState"
 #define MAINMINXKEY "MainMinX"
@@ -2291,6 +2341,25 @@ mswin_read_reg()
     DWORD size;
     DWORD safe_buf;
     char keystring[MAX_PATH];
+    int i;
+    COLORREF default_mapcolors[CLR_MAX] = {
+       RGB(0x55, 0x55, 0x55), /* CLR_BLACK */
+       RGB(0xFF, 0x00, 0x00), /* CLR_RED */
+       RGB(0x00, 0x80, 0x00), /* CLR_GREEN */
+       RGB(0xA5, 0x2A, 0x2A), /* CLR_BROWN */
+       RGB(0x00, 0x00, 0xFF), /* CLR_BLUE */
+       RGB(0xFF, 0x00, 0xFF), /* CLR_MAGENTA */
+       RGB(0x00, 0xFF, 0xFF), /* CLR_CYAN */
+       RGB(0xC0, 0xC0, 0xC0), /* CLR_GRAY */
+       RGB(0xFF, 0xFF, 0xFF), /* NO_COLOR */
+       RGB(0xFF, 0xA5, 0x00), /* CLR_ORANGE */
+       RGB(0x00, 0xFF, 0x00), /* CLR_BRIGHT_GREEN */
+       RGB(0xFF, 0xFF, 0x00), /* CLR_YELLOW */
+       RGB(0x00, 0xC0, 0xFF), /* CLR_BRIGHT_BLUE */
+       RGB(0xFF, 0x80, 0xFF), /* CLR_BRIGHT_MAGENTA */
+       RGB(0x80, 0xFF, 0xFF), /* CLR_BRIGHT_CYAN */
+       RGB(0xFF, 0xFF, 0xFF)  /* CLR_WHITE */
+    };
 
     sprintf(keystring, "%s\\%s\\%s\\%s", CATEGORYKEY, COMPANYKEY, PRODUCTKEY,
             SETTINGSKEY);
@@ -2299,7 +2368,10 @@ mswin_read_reg()
        is
        read from the registry, so these defaults apply. */
     GetNHApp()->saveRegistrySettings = 1; /* Normally, we always save */
-    GetNHApp()->regNetHackMode = 0;
+    GetNHApp()->regNetHackMode = TRUE;
+
+    for (i = 0; i < CLR_MAX; i++)
+        GetNHApp()->regMapColors[i] = default_mapcolors[i];
 
     if (RegOpenKeyEx(HKEY_CURRENT_USER, keystring, 0, KEY_READ, &key)
         != ERROR_SUCCESS)
@@ -2353,6 +2425,14 @@ mswin_read_reg()
     NHGETREG_DWORD(INVENTBOTTOM, GetNHApp()->rtInvenWindow.bottom);
 #undef NHGETREG_DWORD
 
+    for (i = 0; i < CLR_MAX; i++) {
+        COLORREF cl;
+        char mapcolorkey[64];
+        sprintf(mapcolorkey, "MapColor%02d", i);
+        if (RegQueryValueEx(key, mapcolorkey, NULL, NULL, (BYTE *)&cl, &size) == ERROR_SUCCESS)
+            GetNHApp()->regMapColors[i] = cl;
+    }
+
     RegCloseKey(key);
 
     /* check the data for validity */
@@ -2371,6 +2451,7 @@ mswin_write_reg()
 {
     HKEY key;
     DWORD disposition;
+    int i;
 
     if (GetNHApp()->saveRegistrySettings) {
         char keystring[MAX_PATH];
@@ -2432,6 +2513,13 @@ mswin_write_reg()
         NHSETREG_DWORD(INVENTBOTTOM, GetNHApp()->rtInvenWindow.bottom);
 #undef NHSETREG_DWORD
 
+        for (i = 0; i < CLR_MAX; i++) {
+            COLORREF cl = GetNHApp()->regMapColors[i];
+            char mapcolorkey[64];
+            sprintf(mapcolorkey, "MapColor%02d", i);
+            RegSetValueEx(key, mapcolorkey, 0, REG_DWORD, (BYTE *)&cl, sizeof(DWORD));
+        }
+
         RegCloseKey(key);
     }
 }
@@ -2554,23 +2642,32 @@ mswin_color_from_string(char *colorstring, HBRUSH *brushptr,
         if (strlen(++colorstring) != 6)
             return;
 
-        red_value = (int) (index(hexadecimals, tolower(*colorstring++))
+        red_value = (int) (index(hexadecimals, tolower((uchar) *colorstring))
                            - hexadecimals);
+        ++colorstring;
         red_value *= 16;
-        red_value += (int) (index(hexadecimals, tolower(*colorstring++))
+        red_value += (int) (index(hexadecimals, tolower((uchar) *colorstring))
                             - hexadecimals);
+        ++colorstring;
 
-        green_value = (int) (index(hexadecimals, tolower(*colorstring++))
+        green_value = (int) (index(hexadecimals,
+                                   tolower((uchar) *colorstring))
                              - hexadecimals);
+        ++colorstring;
         green_value *= 16;
-        green_value += (int) (index(hexadecimals, tolower(*colorstring++))
+        green_value += (int) (index(hexadecimals,
+                                    tolower((uchar) *colorstring))
                               - hexadecimals);
+        ++colorstring;
 
-        blue_value = (int) (index(hexadecimals, tolower(*colorstring++))
+        blue_value = (int) (index(hexadecimals, tolower((uchar) *colorstring))
                             - hexadecimals);
+        ++colorstring;
         blue_value *= 16;
-        blue_value += (int) (index(hexadecimals, tolower(*colorstring++))
+        blue_value += (int) (index(hexadecimals,
+                                   tolower((uchar) *colorstring))
                              - hexadecimals);
+        ++colorstring;
 
         *colorptr = RGB(red_value, green_value, blue_value);
     } else {
@@ -2675,18 +2772,18 @@ NHMessageBox(HWND hWnd, LPCTSTR text, UINT type)
     return MessageBox(hWnd, text, title, type);
 }
 
-#ifdef STATUS_VIA_WINDOWPORT
 static const char *_status_fieldnm[MAXBLSTATS];
 static const char *_status_fieldfmt[MAXBLSTATS];
 static char *_status_vals[MAXBLSTATS];
 static int _status_colors[MAXBLSTATS];
+static int _status_percents[MAXBLSTATS];
 static boolean _status_activefields[MAXBLSTATS];
 extern winid WIN_STATUS;
 
 #ifdef STATUS_HILITES
 typedef struct hilite_data_struct {
     int thresholdtype;
-    anything threshold;
+    anything value;
     int behavior;
     int under;
     int over;
@@ -2709,6 +2806,7 @@ mswin_status_init(void)
         _status_activefields[i] = FALSE;
         _status_fieldfmt[i] = (const char *) 0;
         _status_colors[i] = CLR_MAX; /* no color */
+        _status_percents[i] = 0;
 #ifdef STATUS_HILITES
         _status_hilites[i].thresholdtype = 0;
         _status_hilites[i].behavior = BL_TH_NONE;
@@ -2766,64 +2864,9 @@ mswin_status_enablefield(int fieldidx, const char *nm, const char *fmt,
     _status_activefields[fieldidx] = enable;
 }
 
-#ifdef STATUS_HILITES
-/*
-status_threshold(int fldidx, int threshholdtype, anything threshold,
-                                        int behavior, int under, int over)
-                -- called when a hiliting preference is added, changed, or
-                   removed.
-                -- the fldindex identifies which field is having its hiliting
-                   preference set. It is an integer index value from botl.h
-                -- fldindex could be any one of the following from botl.h:
-                   BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
-                   BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
-                   BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX,
-                   BL_LEVELDESC, BL_EXP, BL_CONDITION
-                -- datatype is P_INT, P_UINT, P_LONG, or P_MASK.
-                -- threshold is an "anything" union which can contain the
-                   datatype value.
-                -- behavior is used to define how threshold is used and can
-                   be BL_TH_NONE, BL_TH_VAL_PERCENTAGE, BL_TH_VAL_ABSOLUTE,
-                   or BL_TH_UPDOWN. BL_TH_NONE means don't do anything above
-                   or below the threshold.  BL_TH_VAL_PERCENTAGE treats the
-                   threshold value as a precentage of the maximum possible
-                   value. BL_TH_VAL_ABSOLUTE means that the threshold is an
-                   actual value. BL_TH_UPDOWN means that threshold is not
-                   used, and the two below/above hilite values indicate how
-                   to display something going down (under) or rising (over).
-                -- under is the hilite attribute used if value is below the
-                   threshold. The attribute can be BL_HILITE_NONE,
-                   BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one
-                   of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN,
-                   CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY,
-                   CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE,
-                   CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
-                -- over is the hilite attribute used if value is at or above
-                   the threshold. The attribute can be BL_HILITE_NONE,
-                   BL_HILITE_INVERSE, BL_HILITE_BOLD (-1, -2, or -3), or one
-                   of the color indexes of CLR_BLACK, CLR_RED, CLR_GREEN,
-                   CLR_BROWN, CLR_BLUE, CLR_MAGENTA, CLR_CYAN, CLR_GRAY,
-                   CLR_ORANGE, CLR_BRIGHT_GREEN, CLR_YELLOW, CLR_BRIGHT_BLUE,
-                   CLR_BRIGHT_MAGENTA, CLR_BRIGHT_CYAN, or CLR_WHITE (0 - 15).
-*/
-void
-mswin_status_threshold(int fldidx, int thresholdtype, anything threshold,
-                       int behavior, int under, int over)
-{
-    logDebug("mswin_status_threshold(%d, %d, %d, %d, %d)\n", fldidx,
-             thresholdtype, behavior, under, over);
-    assert(fldidx >= 0 && fldidx < MAXBLSTATS);
-    _status_hilites[fldidx].thresholdtype = thresholdtype;
-    _status_hilites[fldidx].threshold = threshold;
-    _status_hilites[fldidx].behavior = behavior;
-    _status_hilites[fldidx].under = under;
-    _status_hilites[fldidx].over = over;
-}
-#endif /* STATUS_HILITES */
-
 /*
 
-status_update(int fldindex, genericptr_t ptr, int chg, int percentage)
+status_update(int fldindex, genericptr_t ptr, int chg, int percent, int color, unsigned long *colormasks)
                 -- update the value of a status field.
                 -- the fldindex identifies which field is changing and
                    is an integer index value from botl.h
@@ -2839,21 +2882,30 @@ status_update(int fldindex, genericptr_t ptr, int chg, int percentage)
                 -- ptr is usually a "char *", unless fldindex is BL_CONDITION.
                    If fldindex is BL_CONDITION, then ptr is a long value with
                    any or none of the following bits set (from botl.h):
-                        BL_MASK_BLIND          0x00000001L
-                        BL_MASK_CONF           0x00000002L
-                        BL_MASK_FOODPOIS       0x00000004L
-                        BL_MASK_ILL            0x00000008L
-                        BL_MASK_HALLU          0x00000010L
-                        BL_MASK_STUNNED                0x00000020L
-                        BL_MASK_SLIMED         0x00000040L
-                -- The value passed for BL_GOLD includes a leading
-                   symbol for GOLD "$:nnn". If the window port needs to use
-                   the textual gold amount without the leading "$:" the port
-                   will have to add 2 to the passed "ptr" for the BL_GOLD
-case.
+                        BL_MASK_STONE           0x00000001L
+                        BL_MASK_SLIME           0x00000002L
+                        BL_MASK_STRNGL          0x00000004L
+                        BL_MASK_FOODPOIS        0x00000008L
+                        BL_MASK_TERMILL         0x00000010L
+                        BL_MASK_BLIND           0x00000020L
+                        BL_MASK_DEAF            0x00000040L
+                        BL_MASK_STUN            0x00000080L
+                        BL_MASK_CONF            0x00000100L
+                        BL_MASK_HALLU           0x00000200L
+                        BL_MASK_LEV             0x00000400L
+                        BL_MASK_FLY             0x00000800L
+                        BL_MASK_RIDE            0x00001000L
+                -- The value passed for BL_GOLD includes an encoded leading
+                   symbol for GOLD "\GXXXXNNNN:nnn". If window port needs
+                   textual gold amount without the leading "$:" the port will
+                   have to skip past ':' in passed "ptr" for the BL_GOLD case.
+                -- color is the color that the NetHack core is telling you to
+                   use to display the text.
+                -- colormasks is a pointer to a set of CLR_MAX unsigned longs
+                   telling you which fields should be displayed in each color.
 */
 void
-mswin_status_update(int idx, genericptr_t ptr, int chg, int percent)
+mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, unsigned long *colormasks)
 {
     long cond, *condptr = (long *) ptr;
     char *text = (char *) ptr;
@@ -2862,29 +2914,42 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent)
     unsigned ospecial;
     long value = -1;
 
-    logDebug("mswin_status_update(%d, %p, %d, %d)\n", idx, ptr, chg, percent);
+    logDebug("mswin_status_update(%d, %p, %d, %d, %x, %p)\n", idx, ptr, chg, percent, color, colormasks);
 
     if (idx != BL_FLUSH) {
         if (!_status_activefields[idx])
             return;
+        _status_percents[idx] = percent;
         switch (idx) {
         case BL_CONDITION: {
             cond = *condptr;
             *_status_vals[idx] = '\0';
+            if (cond & BL_MASK_STONE)
+                Strcat(_status_vals[idx], " Stone");
+            if (cond & BL_MASK_SLIME)
+                Strcat(_status_vals[idx], " Slime");
+            if (cond & BL_MASK_STRNGL)
+                Strcat(_status_vals[idx], " Strngl");
+            if (cond & BL_MASK_FOODPOIS)
+                Strcat(_status_vals[idx], " FoodPois");
+            if (cond & BL_MASK_TERMILL)
+                Strcat(_status_vals[idx], " TermIll");
             if (cond & BL_MASK_BLIND)
                 Strcat(_status_vals[idx], " Blind");
+            if (cond & BL_MASK_DEAF)
+                Strcat(_status_vals[idx], " Deaf");
+            if (cond & BL_MASK_STUN)
+                Strcat(_status_vals[idx], " Stun");
             if (cond & BL_MASK_CONF)
                 Strcat(_status_vals[idx], " Conf");
-            if (cond & BL_MASK_FOODPOIS)
-                Strcat(_status_vals[idx], " FoodPois");
-            if (cond & BL_MASK_ILL)
-                Strcat(_status_vals[idx], " Ill");
-            if (cond & BL_MASK_STUNNED)
-                Strcat(_status_vals[idx], " Stun");
             if (cond & BL_MASK_HALLU)
                 Strcat(_status_vals[idx], " Hallu");
-            if (cond & BL_MASK_SLIMED)
-                Strcat(_status_vals[idx], " Slime");
+            if (cond & BL_MASK_LEV)
+                Strcat(_status_vals[idx], " Lev");
+            if (cond & BL_MASK_FLY)
+                Strcat(_status_vals[idx], " Fly");
+            if (cond & BL_MASK_RIDE)
+                Strcat(_status_vals[idx], " Ride");
             value = cond;
         } break;
         case BL_GOLD: {
@@ -2916,75 +2981,16 @@ mswin_status_update(int idx, genericptr_t ptr, int chg, int percent)
         }
     }
 
-#ifdef STATUS_HILITES
-    switch (_status_hilites[idx].behavior) {
-    case BL_TH_NONE: {
-        _status_colors[idx] = CLR_MAX;
-    } break;
-
-    case BL_TH_UPDOWN: {
-        if (chg > 0)
-            _status_colors[idx] = _status_hilites[idx].over;
-        else if (chg < 0)
-            _status_colors[idx] = _status_hilites[idx].under;
-        else
-            _status_colors[idx] = CLR_MAX;
-    } break;
-
-    case BL_TH_VAL_PERCENTAGE: {
-        int pct_th = 0;
-        if (_status_hilites[idx].thresholdtype != ANY_INT) {
-            impossible("mswin_status_update: unsupported percentage "
-                       "threshold type %d",
-                       _status_hilites[idx].thresholdtype);
-            break;
-        }
-        pct_th = _status_hilites[idx].threshold.a_int;
-        _status_colors[idx] = (percent >= pct_th)
-                                  ? _status_hilites[idx].over
-                                  : _status_hilites[idx].under;
-    } break;
-
-    case BL_TH_VAL_ABSOLUTE: {
-        int c = CLR_MAX;
-        int o = _status_hilites[idx].over;
-        int u = _status_hilites[idx].under;
-        anything *t = &_status_hilites[idx].threshold;
-        switch (_status_hilites[idx].thresholdtype) {
-        case ANY_LONG:
-            c = (value >= t->a_long) ? o : u;
-            break;
-        case ANY_INT:
-            c = (value >= t->a_int) ? o : u;
-            break;
-        case ANY_UINT:
-            c = ((unsigned long) value >= t->a_uint) ? o : u;
-            break;
-        case ANY_ULONG:
-            c = ((unsigned long) value >= t->a_ulong) ? o : u;
-            break;
-        case ANY_MASK32:
-            c = (value & t->a_ulong) ? o : u;
-            break;
-        default:
-            impossible("mswin_status_update: unsupported absolute threshold "
-                       "type %d\n",
-                       _status_hilites[idx].thresholdtype);
-            break;
-        }
-        _status_colors[idx] = c;
-    } break;
-    }
-#endif /* STATUS_HILITES */
+    _status_colors[idx] = color;
 
     /* send command to status window */
     ZeroMemory(&update_cmd_data, sizeof(update_cmd_data));
     update_cmd_data.n_fields = MAXBLSTATS;
     update_cmd_data.vals = _status_vals;
     update_cmd_data.activefields = _status_activefields;
+    update_cmd_data.percents = _status_percents;
     update_cmd_data.colors = _status_colors;
     SendMessage(mswin_hwnd_from_winid(WIN_STATUS), WM_MSNH_COMMAND,
                 (WPARAM) MSNH_MSG_UPDATE_STATUS, (LPARAM) &update_cmd_data);
 }
 
-#endif /*STATUS_VIA_WINDOWPORT*/
diff --git a/win/win32/nethack.rc b/win/win32/nethack.rc
new file mode 100644 (file)
index 0000000..04ff88d
--- /dev/null
@@ -0,0 +1,107 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "nhresource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "nhresource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+    "#include ""winres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1               ICON                    "nethack.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 3,6,1,0
+ PRODUCTVERSION 3,6,1,0
+ FILEFLAGSMASK 0x1fL
+#ifdef _DEBUG
+ FILEFLAGS 0x9L
+#else
+ FILEFLAGS 0x8L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x0L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "FileDescription", "NetHack for Windows - TTY Interface"
+            VALUE "FileVersion", "3.6.1"
+            VALUE "InternalName", "NetHack"
+            VALUE "LegalCopyright", "Copyright (C) 1985 - 2018.  By Stichting Mathematisch Centrum and M. Stephenson.  See license for details."
+            VALUE "OriginalFilename", "NetHack.exe"
+            VALUE "ProductName", "NetHack"
+            VALUE "ProductVersion", "3.6.1"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+#endif    // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
diff --git a/win/win32/nhresource.h b/win/win32/nhresource.h
new file mode 100644 (file)
index 0000000..119608c
--- /dev/null
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by NetHack.rc
+//
+#define IDI_ICON1                       101
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/win/win32/record.uu b/win/win32/record.uu
new file mode 100644 (file)
index 0000000..e517831
--- /dev/null
@@ -0,0 +1,3 @@
+begin 600 record.
+`
+end
index 98b6ba1..899007b 100644 (file)
 // Microsoft Visual C++ generated include file.
 // Used by winhack.rc
 //
-#define IDC_MYICON 2
-#define IDD_WINHACK_DIALOG 102
-#define IDD_ABOUTBOX 103
-#define IDS_APP_TITLE 103
-#define IDM_ABOUT 104
-#define IDM_EXIT 105
-#define IDS_HELLO 106
-#define IDI_NETHACKW 107
-#define IDC_NETHACKW 109
-#define IDS_APP_TITLE_SHORT 110
-#define IDR_MAINFRAME 128
-#define IDB_TILES 129
-#define IDD_TEXT 130
-#define IDD_NHTEXT 130
-#define IDD_MENU 132
-#define IDB_MENU_SEL 133
-#define IDB_MENU_UNSEL 134
-#define IDD_COMMANDS 136
-#define IDD_GETLIN 138
-#define IDD_EXTCMD 139
-#define IDD_PLAYER_SELECTOR 141
-#define IDB_PETMARK 143
-#define IDB_MENU_SEL_COUNT 144
-#define IDD_NHRIP 145
-#define IDB_SPLASH 146
-#define IDB_RIP 147
-#define IDD_SPLASH 148
-#define IDB_PILEMARK 149
-#define IDC_TEXT_VIEW 1000
-#define IDC_TEXT_CONTROL 1000
-#define IDC_CMD_MOVE_NW 1001
-#define IDC_CMD_MOVE_N 1002
-#define IDC_MENU_LIST 1003
-#define IDC_CMD_MOVE_NE 1003
-#define IDC_MENU_TEXT 1004
-#define IDC_CMD_MOVE_W 1004
-#define IDC_CMD_MOVE_SELF 1005
-#define IDC_CMD_MOVE_E 1006
-#define IDC_CMD_MOVE_SW 1007
-#define IDC_CMD_MOVE_S 1008
-#define IDC_CMD_MOVE_SE 1009
-#define IDC_CMD_MOVE_UP 1010
-#define IDC_CMD_MOVE_DOWN 1011
-#define IDC_CMD_5 1012
-#define IDC_CMD_A 1013
-#define IDC_CMD_B 1014
-#define IDC_CMD_C 1015
-#define IDC_CMD_D 1016
-#define IDC_CMD_E 1017
-#define IDC_CMD_F 1018
-#define IDC_CMD_G 1019
-#define IDC_CMD_H 1020
-#define IDC_CMD_I 1021
-#define IDC_CMD_J 1022
-#define IDC_CMD_K 1023
-#define IDC_CMD_L 1024
-#define IDC_CMD_M 1025
-#define IDC_CMD_N 1026
-#define IDC_CMD_O 1027
-#define IDC_CMD_P 1028
-#define IDC_CMD_Q 1029
-#define IDC_CMD_R 1030
-#define IDC_CMD_S 1031
-#define IDC_CMD_T 1032
-#define IDC_CMD_U 1033
-#define IDC_CMD_V 1034
-#define IDC_CMD_W 1035
-#define IDC_CMD_X 1036
-#define IDC_CMD_Y 1037
-#define IDC_CMD_Z 1038
-#define IDC_CMD_AA 1039
-#define IDC_CMD_BB 1040
-#define IDC_CMD_CC 1041
-#define IDC_CMD_DD 1042
-#define IDC_CMD_EE 1043
-#define IDC_CMD_FF 1044
-#define IDC_CMD_GG 1045
-#define IDC_CMD_HH 1046
-#define IDC_CMD_II 1047
-#define IDC_CMD_JJ 1048
-#define IDC_CMD_KK 1049
-#define IDC_CMD_LL 1050
-#define IDC_CMD_MM 1051
-#define IDC_CMD_NN 1052
-#define IDC_CMD_OO 1053
-#define IDC_CMD_PP 1054
-#define IDC_CMD_QQ 1055
-#define IDC_CMD_RR 1056
-#define IDC_CMD_SS 1057
-#define IDC_CMD_TT 1058
-#define IDC_CMD_UU 1059
-#define IDC_CMD_VV 1060
-#define IDC_CMD_WW 1061
-#define IDC_CMD_XX 1062
-#define IDC_CMD_YY 1063
-#define IDC_CMD_ZZ 1064
-#define IDC_CMD_FIRST 1100
-#define IDC_CMD_LAST 1300
-#define IDC_GETLIN_EDIT 1309
-#define IDC_EXTCMD_LIST 1310
-#define IDC_PLSEL_NAME 1314
-#define IDC_PLSEL_ROLE_RANDOM 1315
-#define IDC_PLSEL_RACE_RANDOM 1318
-#define IDC_PLSEL_GENDER_RANDOM 1319
-#define IDC_PLSEL_ALIGN_RANDOM 1320
-#define IDC_PLSEL_ROLE_LIST 1323
-#define IDC_PLSEL_RACE_LIST 1324
-#define IDC_PLSEL_ALIGN_LIST 1325
-#define IDC_PLSEL_GENDER_LIST 1326
-#define IDC_ABOUT_VERSION 1327
-#define IDC_ABOUT_COPYRIGHT 1328
-#define IDC_EXTRAINFO 1331
-#define IDM_SAVE 32771
-#define IDM_HELP_LONG 32772
-#define IDM_HELP_COMMANDS 32773
-#define IDM_HELP_HISTORY 32774
-#define IDM_HELP_INFO_CHAR 32775
-#define IDM_HELP_INFO_KEY 32776
-#define IDM_HELP_OPTIONS 32777
-#define IDM_HELP_OPTIONS_LONG 32778
-#define IDM_HELP_EXTCMD 32779
-#define IDM_HELP_LICENSE 32780
-#define IDM_HELP_PORTHELP 32781
-#define IDM_MAP_TILES 32782
-#define IDM_MAP_ASCII4X6 32783
-#define IDM_MAP_ASCII6X8 32784
-#define IDM_MAP_ASCII8X8 32785
-#define IDM_MAP_ASCII16X8 32786
-#define IDM_MAP_ASCII7X12 32787
-#define IDM_MAP_ASCII8X12 32788
-#define IDM_MAP_ASCII16X12 32789
-#define IDM_MAP_ASCII12X16 32790
-#define IDM_MAP_ASCII10X18 32791
-#define IDM_MAP_FIT_TO_SCREEN 32792
-#define IDM_NHMODE 32794
-#define IDM_CLEARSETTINGS 32795
-#define IDM_SETTING_AUTOLAYOUT 32796
-#define IDM_SETTING_LOCKWINDOWS 32797
+#define IDC_MYICON                      2
+#define IDD_WINHACK_DIALOG              102
+#define IDD_ABOUTBOX                    103
+#define IDS_APP_TITLE                   103
+#define IDM_ABOUT                       104
+#define IDM_EXIT                        105
+#define IDS_HELLO                       106
+#define IDI_NETHACKW                    107
+#define IDC_NETHACKW                    109
+#define IDS_APP_TITLE_SHORT             110
+#define IDR_MAINFRAME                   128
+#define IDB_TILES                       129
+#define IDD_TEXT                        130
+#define IDD_NHTEXT                      130
+#define IDD_MENU                        132
+#define IDB_MENU_SEL                    133
+#define IDB_MENU_UNSEL                  134
+#define IDD_COMMANDS                    136
+#define IDD_GETLIN                      138
+#define IDD_EXTCMD                      139
+#define IDD_PLAYER_SELECTOR             141
+#define IDB_PETMARK                     143
+#define IDB_MENU_SEL_COUNT              144
+#define IDD_NHRIP                       145
+#define IDB_SPLASH                      146
+#define IDB_RIP                         147
+#define IDD_SPLASH                      148
+#define IDB_PILEMARK                    149
+#define IDC_TEXT_VIEW                   1000
+#define IDC_TEXT_CONTROL                1000
+#define IDC_CMD_MOVE_NW                 1001
+#define IDC_CMD_MOVE_N                  1002
+#define IDC_MENU_LIST                   1003
+#define IDC_CMD_MOVE_NE                 1003
+#define IDC_MENU_TEXT                   1004
+#define IDC_CMD_MOVE_W                  1004
+#define IDC_CMD_MOVE_SELF               1005
+#define IDC_CMD_MOVE_E                  1006
+#define IDC_CMD_MOVE_SW                 1007
+#define IDC_CMD_MOVE_S                  1008
+#define IDC_CMD_MOVE_SE                 1009
+#define IDC_CMD_MOVE_UP                 1010
+#define IDC_CMD_MOVE_DOWN               1011
+#define IDC_CMD_5                       1012
+#define IDC_CMD_A                       1013
+#define IDC_CMD_B                       1014
+#define IDC_CMD_C                       1015
+#define IDC_CMD_D                       1016
+#define IDC_CMD_E                       1017
+#define IDC_CMD_F                       1018
+#define IDC_CMD_G                       1019
+#define IDC_CMD_H                       1020
+#define IDC_CMD_I                       1021
+#define IDC_CMD_J                       1022
+#define IDC_CMD_K                       1023
+#define IDC_CMD_L                       1024
+#define IDC_CMD_M                       1025
+#define IDC_CMD_N                       1026
+#define IDC_CMD_O                       1027
+#define IDC_CMD_P                       1028
+#define IDC_CMD_Q                       1029
+#define IDC_CMD_R                       1030
+#define IDC_CMD_S                       1031
+#define IDC_CMD_T                       1032
+#define IDC_CMD_U                       1033
+#define IDC_CMD_V                       1034
+#define IDC_CMD_W                       1035
+#define IDC_CMD_X                       1036
+#define IDC_CMD_Y                       1037
+#define IDC_CMD_Z                       1038
+#define IDC_CMD_AA                      1039
+#define IDC_CMD_BB                      1040
+#define IDC_CMD_CC                      1041
+#define IDC_CMD_DD                      1042
+#define IDC_CMD_EE                      1043
+#define IDC_CMD_FF                      1044
+#define IDC_CMD_GG                      1045
+#define IDC_CMD_HH                      1046
+#define IDC_CMD_II                      1047
+#define IDC_CMD_JJ                      1048
+#define IDC_CMD_KK                      1049
+#define IDC_CMD_LL                      1050
+#define IDC_CMD_MM                      1051
+#define IDC_CMD_NN                      1052
+#define IDC_CMD_OO                      1053
+#define IDC_CMD_PP                      1054
+#define IDC_CMD_QQ                      1055
+#define IDC_CMD_RR                      1056
+#define IDC_CMD_SS                      1057
+#define IDC_CMD_TT                      1058
+#define IDC_CMD_UU                      1059
+#define IDC_CMD_VV                      1060
+#define IDC_CMD_WW                      1061
+#define IDC_CMD_XX                      1062
+#define IDC_CMD_YY                      1063
+#define IDC_CMD_ZZ                      1064
+#define IDC_CMD_FIRST                   1100
+#define IDC_CMD_LAST                    1300
+#define IDC_GETLIN_EDIT                 1309
+#define IDC_EXTCMD_LIST                 1310
+#define IDC_PLSEL_NAME                  1314
+#define IDC_PLSEL_RANDOM                1315
+#define IDC_ABOUT_VERSION               1327
+#define IDC_ABOUT_COPYRIGHT             1328
+#define IDC_EXTRAINFO                   1331
+#define IDC_PLSEL_ROLE_LIST             1332
+#define IDC_PLSEL_RACE_LIST             1333
+#define IDC_PLSEL_ALIGN_LAWFUL          1334
+#define IDC_PLSEL_ALIGN_NEUTRAL         1335
+#define IDC_PLSEL_ALIGN_CHAOTIC         1336
+#define IDC_PLSEL_GENDER_MALE           1337
+#define IDC_PLSEL_GENDER_FEMALE         1338
+#define IDM_SAVE                        32771
+#define IDM_HELP_LONG                   32772
+#define IDM_HELP_COMMANDS               32773
+#define IDM_HELP_HISTORY                32774
+#define IDM_HELP_INFO_CHAR              32775
+#define IDM_HELP_INFO_KEY               32776
+#define IDM_HELP_OPTIONS                32777
+#define IDM_HELP_OPTIONS_LONG           32778
+#define IDM_HELP_EXTCMD                 32779
+#define IDM_HELP_LICENSE                32780
+#define IDM_HELP_PORTHELP               32781
+#define IDM_MAP_TILES                   32782
+#define IDM_MAP_ASCII4X6                32783
+#define IDM_MAP_ASCII6X8                32784
+#define IDM_MAP_ASCII8X8                32785
+#define IDM_MAP_ASCII16X8               32786
+#define IDM_MAP_ASCII7X12               32787
+#define IDM_MAP_ASCII8X12               32788
+#define IDM_MAP_ASCII16X12              32789
+#define IDM_MAP_ASCII12X16              32790
+#define IDM_MAP_ASCII10X18              32791
+#define IDM_MAP_FIT_TO_SCREEN           32792
+#define IDM_NHMODE                      32794
+#define IDM_CLEARSETTINGS               32795
+#define IDM_SETTING_AUTOLAYOUT          32796
+#define IDM_SETTING_LOCKWINDOWS         32797
 #define IDM_SETTING_SCREEN_TO_CLIPBOARD 32798
-#define IDM_SETTING_SCREEN_TO_FILE 32799
-#define IDC_STATIC -1
+#define IDM_SETTING_SCREEN_TO_FILE      32799
+#define IDC_STATIC                      -1
 
 // Next default values for new objects
-//
+// 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 145
-#define _APS_NEXT_COMMAND_VALUE 32800
-#define _APS_NEXT_CONTROL_VALUE 1332
-#define _APS_NEXT_SYMED_VALUE 110
+#define _APS_NEXT_RESOURCE_VALUE        146
+#define _APS_NEXT_COMMAND_VALUE         32800
+#define _APS_NEXT_CONTROL_VALUE         1341
+#define _APS_NEXT_SYMED_VALUE           110
 #endif
 #endif
index 0d7f35e..2c87c48 100644 (file)
@@ -1,4 +1,6 @@
-#$NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$
+#$NHDT-Date: 1524689255 2018/04/25 20:47:35 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.4 $
+# Copyright (c) 2002 by Michael Allison
+# NetHack may be freely redistributed.  See license for details.
 
 default: all
 
diff --git a/win/win32/vs2010/NetHack.sln b/win/win32/vs2010/NetHack.sln
deleted file mode 100644 (file)
index d4937c4..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual C++ Express 2010
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetHackW", "build\NetHackW.vcxproj", "{CEC5D360-8804-454F-8591-002184C23499}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dgncomp", "build\dgncomp.vcxproj", "{8A3F81C7-2968-49A8-86BF-2669412AD7DE}"
-       ProjectSection(ProjectDependencies) = postProject
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42} = {642BC75D-ABAF-403E-8224-7C725FD4CB42}
-       EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dgnstuff", "build\dgnstuff.vcxproj", "{B9E02F2C-8851-442B-BF2A-3581802B78D4}"
-       ProjectSection(ProjectDependencies) = postProject
-               {FF144DFB-83A5-4D26-A598-715A2B354782} = {FF144DFB-83A5-4D26-A598-715A2B354782}
-       EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dlb_main", "build\dlb_main.vcxproj", "{0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "levcomp", "build\levcomp.vcxproj", "{9DD9C52E-E8C9-4533-BD22-83C055C0AABA}"
-       ProjectSection(ProjectDependencies) = postProject
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4} = {B9E02F2C-8851-442B-BF2A-3581802B78D4}
-       EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "levstuff", "build\levstuff.vcxproj", "{FF144DFB-83A5-4D26-A598-715A2B354782}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makedefs", "build\makedefs.vcxproj", "{BA3DD34C-04B7-40D0-B373-9329AA9E8945}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "recover", "build\recover.vcxproj", "{2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tile2bmp", "build\tile2bmp.vcxproj", "{642BC75D-ABAF-403E-8224-7C725FD4CB42}"
-       ProjectSection(ProjectDependencies) = postProject
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}
-       EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tilemap", "build\tilemap.vcxproj", "{93F10526-209E-41D7-BBEA-775787876895}"
-       ProjectSection(ProjectDependencies) = postProject
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE} = {8A3F81C7-2968-49A8-86BF-2669412AD7DE}
-       EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tiles", "build\tiles.vcxproj", "{55946465-FC65-47B3-BB48-742C7694C0D6}"
-       ProjectSection(ProjectDependencies) = postProject
-               {93F10526-209E-41D7-BBEA-775787876895} = {93F10526-209E-41D7-BBEA-775787876895}
-       EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uudecode", "build\uudecode.vcxproj", "{63F9B82B-F589-4082-ABE5-D4F0682050AB}"
-       ProjectSection(ProjectDependencies) = postProject
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945}
-       EndProjectSection
-EndProject
-Global
-       GlobalSection(SolutionConfigurationPlatforms) = preSolution
-               Debug|Win32 = Debug|Win32
-               Debug|x64 = Debug|x64
-               Release|Win32 = Release|Win32
-               Release|x64 = Release|x64
-       EndGlobalSection
-       GlobalSection(ProjectConfigurationPlatforms) = postSolution
-               {CEC5D360-8804-454F-8591-002184C23499}.Debug|Win32.ActiveCfg = Debug|Win32
-               {CEC5D360-8804-454F-8591-002184C23499}.Debug|Win32.Build.0 = Debug|Win32
-               {CEC5D360-8804-454F-8591-002184C23499}.Debug|x64.ActiveCfg = Debug|x64
-               {CEC5D360-8804-454F-8591-002184C23499}.Debug|x64.Build.0 = Debug|x64
-               {CEC5D360-8804-454F-8591-002184C23499}.Release|Win32.ActiveCfg = Release|Win32
-               {CEC5D360-8804-454F-8591-002184C23499}.Release|Win32.Build.0 = Release|Win32
-               {CEC5D360-8804-454F-8591-002184C23499}.Release|x64.ActiveCfg = Release|x64
-               {CEC5D360-8804-454F-8591-002184C23499}.Release|x64.Build.0 = Release|x64
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Debug|Win32.ActiveCfg = Debug|Win32
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Debug|Win32.Build.0 = Debug|Win32
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Debug|x64.ActiveCfg = Debug|x64
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Debug|x64.Build.0 = Debug|x64
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Release|Win32.ActiveCfg = Release|Win32
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Release|Win32.Build.0 = Release|Win32
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Release|x64.ActiveCfg = Release|x64
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Release|x64.Build.0 = Release|x64
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Debug|Win32.ActiveCfg = Debug|Win32
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Debug|Win32.Build.0 = Debug|Win32
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Debug|x64.ActiveCfg = Debug|x64
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Debug|x64.Build.0 = Debug|x64
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Release|Win32.ActiveCfg = Release|Win32
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Release|Win32.Build.0 = Release|Win32
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Release|x64.ActiveCfg = Release|x64
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Release|x64.Build.0 = Release|x64
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Debug|Win32.ActiveCfg = Debug|Win32
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Debug|Win32.Build.0 = Debug|Win32
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Debug|x64.ActiveCfg = Debug|x64
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Debug|x64.Build.0 = Debug|x64
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Release|Win32.ActiveCfg = Release|Win32
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Release|Win32.Build.0 = Release|Win32
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Release|x64.ActiveCfg = Release|x64
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Release|x64.Build.0 = Release|x64
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Debug|Win32.ActiveCfg = Debug|Win32
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Debug|Win32.Build.0 = Debug|Win32
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Debug|x64.ActiveCfg = Debug|x64
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Debug|x64.Build.0 = Debug|x64
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Release|Win32.ActiveCfg = Release|Win32
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Release|Win32.Build.0 = Release|Win32
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Release|x64.ActiveCfg = Release|x64
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Release|x64.Build.0 = Release|x64
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Debug|Win32.ActiveCfg = Debug|Win32
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Debug|Win32.Build.0 = Debug|Win32
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Debug|x64.ActiveCfg = Debug|x64
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Debug|x64.Build.0 = Debug|x64
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Release|Win32.ActiveCfg = Release|Win32
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Release|Win32.Build.0 = Release|Win32
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Release|x64.ActiveCfg = Release|x64
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Release|x64.Build.0 = Release|x64
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Debug|Win32.ActiveCfg = Debug|Win32
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Debug|Win32.Build.0 = Debug|Win32
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Debug|x64.ActiveCfg = Debug|x64
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Debug|x64.Build.0 = Debug|x64
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Release|Win32.ActiveCfg = Release|Win32
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Release|Win32.Build.0 = Release|Win32
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Release|x64.ActiveCfg = Release|x64
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Release|x64.Build.0 = Release|x64
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Debug|Win32.ActiveCfg = Debug|Win32
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Debug|Win32.Build.0 = Debug|Win32
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Debug|x64.ActiveCfg = Debug|x64
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Debug|x64.Build.0 = Debug|x64
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Release|Win32.ActiveCfg = Release|Win32
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Release|Win32.Build.0 = Release|Win32
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Release|x64.ActiveCfg = Release|x64
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Release|x64.Build.0 = Release|x64
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Debug|Win32.ActiveCfg = Debug|Win32
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Debug|Win32.Build.0 = Debug|Win32
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Debug|x64.ActiveCfg = Debug|x64
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Debug|x64.Build.0 = Debug|x64
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Release|Win32.ActiveCfg = Release|Win32
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Release|Win32.Build.0 = Release|Win32
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Release|x64.ActiveCfg = Release|x64
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Release|x64.Build.0 = Release|x64
-               {93F10526-209E-41D7-BBEA-775787876895}.Debug|Win32.ActiveCfg = Debug|Win32
-               {93F10526-209E-41D7-BBEA-775787876895}.Debug|Win32.Build.0 = Debug|Win32
-               {93F10526-209E-41D7-BBEA-775787876895}.Debug|x64.ActiveCfg = Debug|x64
-               {93F10526-209E-41D7-BBEA-775787876895}.Debug|x64.Build.0 = Debug|x64
-               {93F10526-209E-41D7-BBEA-775787876895}.Release|Win32.ActiveCfg = Release|Win32
-               {93F10526-209E-41D7-BBEA-775787876895}.Release|Win32.Build.0 = Release|Win32
-               {93F10526-209E-41D7-BBEA-775787876895}.Release|x64.ActiveCfg = Release|x64
-               {93F10526-209E-41D7-BBEA-775787876895}.Release|x64.Build.0 = Release|x64
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Debug|Win32.ActiveCfg = Debug|Win32
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Debug|Win32.Build.0 = Debug|Win32
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Debug|x64.ActiveCfg = Debug|x64
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Debug|x64.Build.0 = Debug|x64
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Release|Win32.ActiveCfg = Release|Win32
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Release|Win32.Build.0 = Release|Win32
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Release|x64.ActiveCfg = Release|x64
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Release|x64.Build.0 = Release|x64
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Debug|Win32.ActiveCfg = Debug|Win32
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Debug|Win32.Build.0 = Debug|Win32
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Debug|x64.ActiveCfg = Debug|x64
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Debug|x64.Build.0 = Debug|x64
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Release|Win32.ActiveCfg = Release|Win32
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Release|Win32.Build.0 = Release|Win32
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Release|x64.ActiveCfg = Release|x64
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Release|x64.Build.0 = Release|x64
-       EndGlobalSection
-       GlobalSection(SolutionProperties) = preSolution
-               HideSolutionNode = FALSE
-       EndGlobalSection
-EndGlobal
diff --git a/win/win32/vs2010/NetHackW.vcxproj b/win/win32/vs2010/NetHackW.vcxproj
deleted file mode 100644 (file)
index 3919d8c..0000000
+++ /dev/null
@@ -1,1789 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{CEC5D360-8804-454F-8591-002184C23499}</ProjectGuid>
-    <RootNamespace>NetHackW</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Midl>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MkTypLibCompatible>true</MkTypLibCompatible>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <TargetEnvironment>Win32</TargetEnvironment>
-      <TypeLibraryName>.\Release/NetHackW.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <AdditionalOptions>/Gs /Oi-  %(AdditionalOptions)</AdditionalOptions>
-      <Optimization>Disabled</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
-      <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/NetHackW.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x0409</Culture>
-    </ResourceCompile>
-    <Link>
-      <AdditionalOptions>/MAPINFO:EXPORTS %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalDependencies>comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Release/NetHackW.pdb</ProgramDatabaseFile>
-      <GenerateMapFile>true</GenerateMapFile>
-      <MapFileName>.\Release/NetHackW.map</MapFileName>
-      <SubSystem>Windows</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Release/NetHackW.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Install exe</Message>
-      <Command>copy $(OutDir)NetHackW.exe ..\binary
-copy ..\dat\nhdat ..\binary
-copy ..\dat\license ..\binary
-if exist tiles.bmp copy tiles.bmp ..\binary
-if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt
-if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt
-copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <Midl>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MkTypLibCompatible>true</MkTypLibCompatible>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <TypeLibraryName>.\Release/NetHackW.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <AdditionalOptions>/Gs /Oi-  %(AdditionalOptions)</AdditionalOptions>
-      <Optimization>Disabled</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
-      <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/NetHackW.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x0409</Culture>
-    </ResourceCompile>
-    <Link>
-      <AdditionalOptions>/MAPINFO:EXPORTS %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalDependencies>comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Release/NetHackW.pdb</ProgramDatabaseFile>
-      <GenerateMapFile>true</GenerateMapFile>
-      <MapFileName>.\Release/NetHackW.map</MapFileName>
-      <SubSystem>Windows</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Release/NetHackW.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Install exe</Message>
-      <Command>copy $(OutDir)NetHackW.exe ..\binary
-copy ..\dat\nhdat ..\binary
-copy ..\dat\license ..\binary
-if exist tiles.bmp copy tiles.bmp ..\binary
-if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt
-if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt
-copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Midl>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MkTypLibCompatible>true</MkTypLibCompatible>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <TargetEnvironment>Win32</TargetEnvironment>
-      <TypeLibraryName>.\Debug/NetHackW.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/NetHackW.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x0409</Culture>
-    </ResourceCompile>
-    <Link>
-      <AdditionalDependencies>comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Debug/NetHackW.pdb</ProgramDatabaseFile>
-      <SubSystem>Windows</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Debug/NetHackW.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Install exe</Message>
-      <Command>if NOT exist ..\binary\*.* mkdir ..\binary
-copy $(OutDir)NetHackW.exe ..\binary
-copy ..\dat\nhdat ..\binary
-copy ..\dat\license ..\binary
-copy ..\dat\symbols ..\binary
-if exist tiles.bmp copy tiles.bmp ..\binary
-if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt
-if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt
-copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <Midl>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MkTypLibCompatible>true</MkTypLibCompatible>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <TypeLibraryName>.\Debug/NetHackW.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/NetHackW.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x0409</Culture>
-    </ResourceCompile>
-    <Link>
-      <AdditionalDependencies>comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Debug/NetHackW.pdb</ProgramDatabaseFile>
-      <SubSystem>Windows</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Debug/NetHackW.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Install exe</Message>
-      <Command>if NOT exist ..\binary\*.* mkdir ..\binary
-copy $(OutDir)NetHackW.exe ..\binary
-copy ..\dat\nhdat ..\binary
-copy ..\dat\license ..\binary
-copy ..\dat\symbols ..\binary
-if exist tiles.bmp copy tiles.bmp ..\binary
-if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt
-if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt
-copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\src\allmain.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\alloc.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\apply.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\artifact.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\attrib.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\ball.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\bones.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\botl.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\cmd.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\dbridge.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\decl.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\detect.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\dig.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\display.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\dlb.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\do.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\do_name.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\do_wear.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\dog.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\dogmove.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\dokick.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\dothrow.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\drawing.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\dungeon.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\eat.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\end.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\engrave.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\exper.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\explode.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\extralev.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\files.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\fountain.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\sys\share\cppregex.cpp">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\tty\getline.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\hack.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\hacklib.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\invent.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\light.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\lock.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mail.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\makemon.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mapglyph.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mcastu.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mhitm.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mhitu.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\minion.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mklev.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mkmap.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mkmaze.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mkobj.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mkroom.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mon.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mondata.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\monmove.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\monst.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\monstr.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mplayer.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\mthrowu.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\muse.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\music.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\sys\winnt\ntsound.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\o_init.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\objects.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\objnam.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\options.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\pager.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\sys\share\pcmain.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\sys\share\pcsys.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\sys\share\pcunix.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\pickup.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\pline.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\polyself.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\potion.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\pray.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\priest.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\quest.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\questpgr.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\sys\share\random.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\read.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\rect.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\region.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\restore.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\rip.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\rnd.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\role.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\rumors.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\save.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\shk.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\shknam.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\sit.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\sounds.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\sp_lev.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\spell.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\steal.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\steed.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\sys.c" />
-    <ClCompile Include="..\src\teleport.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\tile.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\timeout.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\topten.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\track.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\trap.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\u_init.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\uhitm.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\vault.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\version.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\vision.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\weapon.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\were.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\wield.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\windows.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\sys\winnt\winnt.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\tty\wintty.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\wizard.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\worm.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\worn.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\write.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\zap.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhaskyn.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhdlg.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhfont.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhinput.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhmain.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhmap.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhmenu.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhmsgwnd.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhrip.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhsplash.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhstatus.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mhtext.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\mswproc.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\win32\winhack.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\include\align.h" />
-    <ClInclude Include="..\include\amiconf.h" />
-    <ClInclude Include="..\include\artifact.h" />
-    <ClInclude Include="..\include\artilist.h" />
-    <ClInclude Include="..\include\attrib.h" />
-    <ClInclude Include="..\include\beconf.h" />
-    <ClInclude Include="..\include\bitmfile.h" />
-    <ClInclude Include="..\include\color.h" />
-    <ClInclude Include="..\include\config.h" />
-    <ClInclude Include="..\include\config1.h" />
-    <ClInclude Include="..\include\context.h" />
-    <ClInclude Include="..\include\coord.h" />
-    <ClInclude Include="..\include\decl.h" />
-    <ClInclude Include="..\include\def_os2.h" />
-    <ClInclude Include="..\include\dgn_file.h" />
-    <ClInclude Include="..\include\display.h" />
-    <ClInclude Include="..\include\dlb.h" />
-    <ClInclude Include="..\include\dungeon.h" />
-    <ClInclude Include="..\include\engrave.h" />
-    <ClInclude Include="..\include\extern.h" />
-    <ClInclude Include="..\include\flag.h" />
-    <ClInclude Include="..\include\func_tab.h" />
-    <ClInclude Include="..\include\gem_rsc.h" />
-    <ClInclude Include="..\include\global.h" />
-    <ClInclude Include="..\include\hack.h" />
-    <ClInclude Include="..\include\lev.h" />
-    <ClInclude Include="..\include\load_img.h" />
-    <ClInclude Include="..\include\macconf.h" />
-    <ClInclude Include="..\include\macpopup.h" />
-    <ClInclude Include="..\include\mactty.h" />
-    <ClInclude Include="..\include\macwin.h" />
-    <ClInclude Include="..\include\mail.h" />
-    <ClInclude Include="..\include\mextra.h" />
-    <ClInclude Include="..\include\mfndpos.h" />
-    <ClInclude Include="..\include\micro.h" />
-    <ClInclude Include="..\include\mkroom.h" />
-    <ClInclude Include="..\include\monattk.h" />
-    <ClInclude Include="..\include\mondata.h" />
-    <ClInclude Include="..\include\monflag.h" />
-    <ClInclude Include="..\include\monst.h" />
-    <ClInclude Include="..\include\monsym.h" />
-    <ClInclude Include="..\include\mttypriv.h" />
-    <ClInclude Include="..\include\nhlan.h" />
-    <ClInclude Include="..\include\ntconf.h" />
-    <ClInclude Include="..\include\obj.h" />
-    <ClInclude Include="..\include\objclass.h" />
-    <ClInclude Include="..\include\os2conf.h" />
-    <ClInclude Include="..\include\patchlevel.h" />
-    <ClInclude Include="..\include\pcconf.h" />
-    <ClInclude Include="..\include\permonst.h" />
-    <ClInclude Include="..\include\prop.h" />
-    <ClInclude Include="..\include\qt_clust.h" />
-    <ClInclude Include="..\include\qt_kde0.h" />
-    <ClInclude Include="..\include\qt_win.h" />
-    <ClInclude Include="..\include\qt_xpms.h" />
-    <ClInclude Include="..\include\qtext.h" />
-    <ClInclude Include="..\include\quest.h" />
-    <ClInclude Include="..\include\rect.h" />
-    <ClInclude Include="..\include\region.h" />
-    <ClInclude Include="..\include\rm.h" />
-    <ClInclude Include="..\include\skills.h" />
-    <ClInclude Include="..\include\sp_lev.h" />
-    <ClInclude Include="..\include\spell.h" />
-    <ClInclude Include="..\include\system.h" />
-    <ClInclude Include="..\include\tcap.h" />
-    <ClInclude Include="..\include\tile2x11.h" />
-    <ClInclude Include="..\include\timeout.h" />
-    <ClInclude Include="..\include\tosconf.h" />
-    <ClInclude Include="..\include\tradstdc.h" />
-    <ClInclude Include="..\include\trampoli.h" />
-    <ClInclude Include="..\include\trap.h" />
-    <ClInclude Include="..\include\unixconf.h" />
-    <ClInclude Include="..\include\vision.h" />
-    <ClInclude Include="..\include\vmsconf.h" />
-    <ClInclude Include="..\include\winami.h" />
-    <ClInclude Include="..\include\wingem.h" />
-    <ClInclude Include="..\include\winGnome.h" />
-    <ClInclude Include="..\include\winprocs.h" />
-    <ClInclude Include="..\include\wintty.h" />
-    <ClInclude Include="..\include\wintype.h" />
-    <ClInclude Include="..\include\winX.h" />
-    <ClInclude Include="..\include\xwindow.h" />
-    <ClInclude Include="..\include\xwindowp.h" />
-    <ClInclude Include="..\include\you.h" />
-    <ClInclude Include="..\include\youprop.h" />
-    <ClInclude Include="..\win\win32\mhaskyn.h" />
-    <ClInclude Include="..\win\win32\mhdlg.h" />
-    <ClInclude Include="..\win\win32\mhfont.h" />
-    <ClInclude Include="..\win\win32\mhinput.h" />
-    <ClInclude Include="..\win\win32\mhmain.h" />
-    <ClInclude Include="..\win\win32\mhmap.h" />
-    <ClInclude Include="..\win\win32\mhmenu.h" />
-    <ClInclude Include="..\win\win32\mhmsg.h" />
-    <ClInclude Include="..\win\win32\mhmsgwnd.h" />
-    <ClInclude Include="..\win\win32\mhrip.h" />
-    <ClInclude Include="..\win\win32\mhsplash.h" />
-    <ClInclude Include="..\win\win32\mhstatus.h" />
-    <ClInclude Include="..\win\win32\mhtext.h" />
-    <ClInclude Include="..\win\win32\resource.h" />
-    <ClInclude Include="..\win\win32\winMS.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="..\win\win32\bitmap1.bmp" />
-    <None Include="..\win\win32\bitmap2.bmp" />
-    <None Include="..\win\win32\mnsel.bmp" />
-    <None Include="..\win\win32\mnunsel.bmp" />
-    <None Include="..\win\win32\NETHACK.ICO" />
-    <None Include="..\win\win32\small.ico" />
-    <None Include="..\win\win32\tiles.bmp" />
-    <None Include="..\win\win32\winhack.ico" />
-    <None Include="..\win\win32\ReadMe.txt" />
-  </ItemGroup>
-  <ItemGroup>
-    <ResourceCompile Include="..\win\win32\winhack.rc">
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\win\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\win\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\win\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\win\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-    </ResourceCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="dgncomp.vcxproj">
-      <Project>{8a3f81c7-2968-49a8-86bf-2669412ad7de}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include="dlb_main.vcxproj">
-      <Project>{0303a585-3f83-4bb7-af6b-1e12c8fb54ac}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include="levcomp.vcxproj">
-      <Project>{9dd9c52e-e8c9-4533-bd22-83c055c0aaba}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include="makedefs.vcxproj">
-      <Project>{ba3dd34c-04b7-40d0-b373-9329aa9e8945}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include="tilemap.vcxproj">
-      <Project>{93f10526-209e-41d7-bbea-775787876895}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include="tiles.vcxproj">
-      <Project>{55946465-fc65-47b3-bb48-742c7694c0d6}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include="uudecode.vcxproj">
-      <Project>{63f9b82b-f589-4082-abe5-d4f0682050ab}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
diff --git a/win/win32/vs2010/dgncomp.vcxproj b/win/win32/vs2010/dgncomp.vcxproj
deleted file mode 100644 (file)
index 82bfcad..0000000
+++ /dev/null
@@ -1,387 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{8A3F81C7-2968-49A8-86BF-2669412AD7DE}</ProjectGuid>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Midl>
-      <TypeLibraryName>.\..\util/dgncomp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/dgncomp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\..\util/dgncomp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/dgncomp.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>dgncomp</Message>
-      <Command>echo Building dungeon
-echo chdir ..\dat
-chdir ..\dat
-echo ..\util\dgncomp.exe dungeon.pdf
-..\util\dgncomp.exe dungeon.pdf
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <Midl>
-      <TypeLibraryName>.\..\util/dgncomp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/dgncomp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\..\util/dgncomp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/dgncomp.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>dgncomp</Message>
-      <Command>echo Building dungeon
-echo chdir ..\dat
-chdir ..\dat
-echo ..\util\dgncomp.exe dungeon.pdf
-..\util\dgncomp.exe dungeon.pdf
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Midl>
-      <TypeLibraryName>.\..\util/dgncomp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/dgncomp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\..\util/dgncomp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/dgncomp.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>dgncomp</Message>
-      <Command>echo Building dungeon
-echo chdir ..\dat
-chdir ..\dat
-echo ..\util\dgncomp.exe dungeon.pdf
-..\util\dgncomp.exe dungeon.pdf
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <Midl>
-      <TypeLibraryName>.\..\util/dgncomp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/dgncomp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\..\util/dgncomp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/dgncomp.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>dgncomp</Message>
-      <Command>echo Building dungeon
-echo chdir ..\dat
-chdir ..\dat
-echo ..\util\dgncomp.exe dungeon.pdf
-..\util\dgncomp.exe dungeon.pdf
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\src\alloc.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\util\dgn_lex.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\util\dgn_main.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\util\dgn_yacc.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\util\panic.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\include\align.h" />
-    <ClInclude Include="..\include\attrib.h" />
-    <ClInclude Include="..\include\color.h" />
-    <ClInclude Include="..\include\config.h" />
-    <ClInclude Include="..\include\config1.h" />
-    <ClInclude Include="..\include\context.h" />
-    <ClInclude Include="..\include\coord.h" />
-    <ClInclude Include="..\include\decl.h" />
-    <ClInclude Include="..\include\dgn_comp.h" />
-    <ClInclude Include="..\include\dgn_file.h" />
-    <ClInclude Include="..\include\display.h" />
-    <ClInclude Include="..\include\dungeon.h" />
-    <ClInclude Include="..\include\engrave.h" />
-    <ClInclude Include="..\include\flag.h" />
-    <ClInclude Include="..\include\global.h" />
-    <ClInclude Include="..\include\mkroom.h" />
-    <ClInclude Include="..\include\monattk.h" />
-    <ClInclude Include="..\include\monst.h" />
-    <ClInclude Include="..\include\monsym.h" />
-    <ClInclude Include="..\include\nhlan.h" />
-    <ClInclude Include="..\include\ntconf.h" />
-    <ClInclude Include="..\include\obj.h" />
-    <ClInclude Include="..\include\objclass.h" />
-    <ClInclude Include="..\include\onames.h" />
-    <ClInclude Include="..\include\permonst.h" />
-    <ClInclude Include="..\include\pm.h" />
-    <ClInclude Include="..\include\prop.h" />
-    <ClInclude Include="..\include\quest.h" />
-    <ClInclude Include="..\include\rect.h" />
-    <ClInclude Include="..\include\region.h" />
-    <ClInclude Include="..\include\rm.h" />
-    <ClInclude Include="..\include\skills.h" />
-    <ClInclude Include="..\include\spell.h" />
-    <ClInclude Include="..\include\timeout.h" />
-    <ClInclude Include="..\include\tradstdc.h" />
-    <ClInclude Include="..\include\trampoli.h" />
-    <ClInclude Include="..\include\trap.h" />
-    <ClInclude Include="..\include\vision.h" />
-    <ClInclude Include="..\include\winprocs.h" />
-    <ClInclude Include="..\include\wintty.h" />
-    <ClInclude Include="..\include\wintype.h" />
-    <ClInclude Include="..\include\you.h" />
-    <ClInclude Include="..\include\youprop.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="dgnstuff.vcxproj">
-      <Project>{b9e02f2c-8851-442b-bf2a-3581802b78d4}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2010/dgnstuff.vcxproj b/win/win32/vs2010/dgnstuff.vcxproj
deleted file mode 100644 (file)
index 829b5c9..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{B9E02F2C-8851-442B-BF2A-3581802B78D4}</ProjectGuid>
-    <Keyword>MakeFileProj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\dgnstuff___Win32_Debug\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\dgnstuff___Win32_Debug\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">nmake /f "dgnstuff.mak"</NMakeBuildCommandLine>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">nmake /f "dgnstuff.mak"</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">nmake /f "dgnstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">nmake /f "dgnstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\util\dgncomp.exe</NMakeOutput>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\util\dgncomp.exe</NMakeOutput>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">nmake /f "dgnstuff.mak"</NMakeBuildCommandLine>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">nmake /f "dgnstuff.mak"</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">nmake /f "dgnstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">nmake /f "dgnstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\util\dgncomp.exe</NMakeOutput>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\util\dgncomp.exe</NMakeOutput>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ProjectReference Include="makedefs.vcxproj">
-      <Project>{ba3dd34c-04b7-40d0-b373-9329aa9e8945}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2010/dlb_main.vcxproj b/win/win32/vs2010/dlb_main.vcxproj
deleted file mode 100644 (file)
index 6c44a19..0000000
+++ /dev/null
@@ -1,419 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}</ProjectGuid>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Midl>
-      <TypeLibraryName>.\Release/dlb_main.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;DLB;WIN32CON;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/dlb_main.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\Release/dlb_main.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Release/dlb_main.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Packaging via DLB</Message>
-      <Command>echo chdir ..\dat
-chdir ..\dat
-chdir
-echo data &gt;dlb.lst
-echo oracles &gt;&gt;dlb.lst
-if exist options echo options &gt;&gt;dlb.lst
-if exist ttyoptions echo ttyoptions &gt;&gt;dlb.lst
-if exist guioptions echo guioptions &gt;&gt;dlb.lst
-if NOT exist porthelp copy ..\sys\winnt\porthelp porthelp
-if exist porthelp echo porthelp &gt;&gt;dlb.lst
-echo quest.dat &gt;&gt;dlb.lst
-echo rumors &gt;&gt;dlb.lst
-echo help &gt;&gt;dlb.lst
-echo hh &gt;&gt;dlb.lst
-echo cmdhelp &gt;&gt;dlb.lst
-echo history &gt;&gt;dlb.lst
-echo opthelp &gt;&gt;dlb.lst
-echo wizhelp &gt;&gt;dlb.lst
-echo dungeon &gt;&gt;dlb.lst
-echo license &gt;&gt;dlb.lst
-for %%N in (*.lev) do echo %%N &gt;&gt;dlb.lst
-..\util\dlb_main.exe cIf dlb.lst nhdat
-echo chdir ..\build
-chdir ..\build
-echo if NOT exist ..\binary\*.* mkdir ..\binary
-if NOT exist ..\binary\*.* mkdir ..\binary
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <Midl>
-      <TypeLibraryName>.\Release/dlb_main.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;DLB;WIN32CON;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/dlb_main.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\Release/dlb_main.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Release/dlb_main.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Packaging via DLB</Message>
-      <Command>echo chdir ..\dat
-chdir ..\dat
-chdir
-echo data &gt;dlb.lst
-echo oracles &gt;&gt;dlb.lst
-if exist options echo options &gt;&gt;dlb.lst
-if exist ttyoptions echo ttyoptions &gt;&gt;dlb.lst
-if exist guioptions echo guioptions &gt;&gt;dlb.lst
-if NOT exist porthelp copy ..\sys\winnt\porthelp porthelp
-if exist porthelp echo porthelp &gt;&gt;dlb.lst
-echo quest.dat &gt;&gt;dlb.lst
-echo rumors &gt;&gt;dlb.lst
-echo help &gt;&gt;dlb.lst
-echo hh &gt;&gt;dlb.lst
-echo cmdhelp &gt;&gt;dlb.lst
-echo history &gt;&gt;dlb.lst
-echo opthelp &gt;&gt;dlb.lst
-echo wizhelp &gt;&gt;dlb.lst
-echo dungeon &gt;&gt;dlb.lst
-echo license &gt;&gt;dlb.lst
-for %%N in (*.lev) do echo %%N &gt;&gt;dlb.lst
-..\util\dlb_main.exe cIf dlb.lst nhdat
-echo chdir ..\build
-chdir ..\build
-echo if NOT exist ..\binary\*.* mkdir ..\binary
-if NOT exist ..\binary\*.* mkdir ..\binary
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Midl>
-      <TypeLibraryName>.\Debug/dlb_main.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;DLB;WIN32CON;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/dlb_main.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Debug/dlb_main.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Debug/dlb_main.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Packaging via dlb</Message>
-      <Command>echo chdir ..\dat
-chdir ..\dat
-chdir
-echo data &gt;dlb.lst
-echo oracles &gt;&gt;dlb.lst
-if exist options echo options &gt;&gt;dlb.lst
-if exist ttyoptions echo ttyoptions &gt;&gt;dlb.lst
-if exist guioptions echo guioptions &gt;&gt;dlb.lst
-if NOT exist porthelp copy ..\sys\winnt\porthelp porthelp
-if exist porthelp echo porthelp &gt;&gt;dlb.lst
-echo quest.dat &gt;&gt;dlb.lst
-echo rumors &gt;&gt;dlb.lst
-echo help &gt;&gt;dlb.lst
-echo hh &gt;&gt;dlb.lst
-echo cmdhelp &gt;&gt;dlb.lst
-echo history &gt;&gt;dlb.lst
-echo opthelp &gt;&gt;dlb.lst
-echo wizhelp &gt;&gt;dlb.lst
-echo dungeon &gt;&gt;dlb.lst
-echo license &gt;&gt;dlb.lst
-for %%N in (*.lev) do echo %%N &gt;&gt;dlb.lst
-..\util\dlb_main.exe cIf dlb.lst nhdat
-echo chdir ..\build
-chdir ..\build
-echo if NOT exist ..\binary\*.* mkdir ..\binary
-if NOT exist ..\binary\*.* mkdir ..\binary
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <Midl>
-      <TypeLibraryName>.\Debug/dlb_main.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;DLB;WIN32CON;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/dlb_main.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Debug/dlb_main.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Debug/dlb_main.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Packaging via dlb</Message>
-      <Command>echo chdir ..\dat
-chdir ..\dat
-chdir
-echo data &gt;dlb.lst
-echo oracles &gt;&gt;dlb.lst
-if exist options echo options &gt;&gt;dlb.lst
-if exist ttyoptions echo ttyoptions &gt;&gt;dlb.lst
-if exist guioptions echo guioptions &gt;&gt;dlb.lst
-if NOT exist porthelp copy ..\sys\winnt\porthelp porthelp
-if exist porthelp echo porthelp &gt;&gt;dlb.lst
-echo quest.dat &gt;&gt;dlb.lst
-echo rumors &gt;&gt;dlb.lst
-echo help &gt;&gt;dlb.lst
-echo hh &gt;&gt;dlb.lst
-echo cmdhelp &gt;&gt;dlb.lst
-echo history &gt;&gt;dlb.lst
-echo opthelp &gt;&gt;dlb.lst
-echo wizhelp &gt;&gt;dlb.lst
-echo dungeon &gt;&gt;dlb.lst
-echo license &gt;&gt;dlb.lst
-for %%N in (*.lev) do echo %%N &gt;&gt;dlb.lst
-..\util\dlb_main.exe cIf dlb.lst nhdat
-echo chdir ..\build
-chdir ..\build
-echo if NOT exist ..\binary\*.* mkdir ..\binary
-if NOT exist ..\binary\*.* mkdir ..\binary
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\src\alloc.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\dlb.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\util\dlb_main.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\util\panic.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\include\dlb.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="dgncomp.vcxproj">
-      <Project>{8a3f81c7-2968-49a8-86bf-2669412ad7de}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include="levcomp.vcxproj">
-      <Project>{9dd9c52e-e8c9-4533-bd22-83c055c0aaba}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include="makedefs.vcxproj">
-      <Project>{ba3dd34c-04b7-40d0-b373-9329aa9e8945}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2010/levcomp.vcxproj b/win/win32/vs2010/levcomp.vcxproj
deleted file mode 100644 (file)
index 8bcad70..0000000
+++ /dev/null
@@ -1,569 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{9DD9C52E-E8C9-4533-BD22-83C055C0AABA}</ProjectGuid>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Midl>
-      <TypeLibraryName>.\..\util/levcomp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/levcomp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\..\util/levcomp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/levcomp.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>levcomp</Message>
-      <Command>echo Building special levels
-echo chdir ..\dat
-chdir ..\dat
-echo arch.des
-..\util\levcomp.exe arch.des
-echo barb.des
-..\util\levcomp.exe barb.des
-echo bigroom.des
-..\util\levcomp.exe bigroom.des
-echo castle.des
-..\util\levcomp.exe castle.des
-echo caveman.des
-..\util\levcomp.exe caveman.des
-echo endgame.des
-..\util\levcomp.exe endgame.des
-echo gehennom.des
-..\util\levcomp.exe gehennom.des
-echo healer.des
-..\util\levcomp.exe healer.des
-echo knight.des
-..\util\levcomp.exe knight.des
-echo knox.des
-..\util\levcomp.exe knox.des
-echo medusa.des
-..\util\levcomp.exe medusa.des
-echo mines.des
-..\util\levcomp.exe mines.des
-echo monk.des
-..\util\levcomp.exe monk.des
-echo oracle.des
-..\util\levcomp.exe oracle.des
-echo priest.des
-..\util\levcomp.exe priest.des
-echo ranger.des
-..\util\levcomp.exe ranger.des
-echo rogue.des
-..\util\levcomp.exe rogue.des
-echo samurai.des
-..\util\levcomp.exe samurai.des
-echo sokoban.des
-..\util\levcomp.exe sokoban.des
-echo tourist.des
-..\util\levcomp.exe tourist.des
-echo tower.des
-..\util\levcomp.exe tower.des
-echo valkyrie.des
-..\util\levcomp.exe valkyrie.des
-echo wizard .des
-..\util\levcomp.exe wizard.des
-echo yendor.des
-..\util\levcomp.exe yendor.des
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <Midl>
-      <TypeLibraryName>.\..\util/levcomp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/levcomp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\..\util/levcomp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/levcomp.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>levcomp</Message>
-      <Command>echo Building special levels
-echo chdir ..\dat
-chdir ..\dat
-echo arch.des
-..\util\levcomp.exe arch.des
-echo barb.des
-..\util\levcomp.exe barb.des
-echo bigroom.des
-..\util\levcomp.exe bigroom.des
-echo castle.des
-..\util\levcomp.exe castle.des
-echo caveman.des
-..\util\levcomp.exe caveman.des
-echo endgame.des
-..\util\levcomp.exe endgame.des
-echo gehennom.des
-..\util\levcomp.exe gehennom.des
-echo healer.des
-..\util\levcomp.exe healer.des
-echo knight.des
-..\util\levcomp.exe knight.des
-echo knox.des
-..\util\levcomp.exe knox.des
-echo medusa.des
-..\util\levcomp.exe medusa.des
-echo mines.des
-..\util\levcomp.exe mines.des
-echo monk.des
-..\util\levcomp.exe monk.des
-echo oracle.des
-..\util\levcomp.exe oracle.des
-echo priest.des
-..\util\levcomp.exe priest.des
-echo ranger.des
-..\util\levcomp.exe ranger.des
-echo rogue.des
-..\util\levcomp.exe rogue.des
-echo samurai.des
-..\util\levcomp.exe samurai.des
-echo sokoban.des
-..\util\levcomp.exe sokoban.des
-echo tourist.des
-..\util\levcomp.exe tourist.des
-echo tower.des
-..\util\levcomp.exe tower.des
-echo valkyrie.des
-..\util\levcomp.exe valkyrie.des
-echo wizard .des
-..\util\levcomp.exe wizard.des
-echo yendor.des
-..\util\levcomp.exe yendor.des
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Midl>
-      <TypeLibraryName>.\..\util/levcomp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/levcomp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\..\util/levcomp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/levcomp.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>levcomp</Message>
-      <Command>echo Building special levels
-echo chdir ..\dat
-chdir ..\dat
-echo arch.des
-..\util\levcomp.exe arch.des
-echo barb.des
-..\util\levcomp.exe barb.des
-echo bigroom.des
-..\util\levcomp.exe bigroom.des
-echo castle.des
-..\util\levcomp.exe castle.des
-echo caveman.des
-..\util\levcomp.exe caveman.des
-echo endgame.des
-..\util\levcomp.exe endgame.des
-echo gehennom.des
-..\util\levcomp.exe gehennom.des
-echo healer.des
-..\util\levcomp.exe healer.des
-echo knight.des
-..\util\levcomp.exe knight.des
-echo knox.des
-..\util\levcomp.exe knox.des
-echo medusa.des
-..\util\levcomp.exe medusa.des
-echo mines.des
-..\util\levcomp.exe mines.des
-echo monk.des
-..\util\levcomp.exe monk.des
-echo oracle.des
-..\util\levcomp.exe oracle.des
-echo priest.des
-..\util\levcomp.exe priest.des
-echo ranger.des
-..\util\levcomp.exe ranger.des
-echo rogue.des
-..\util\levcomp.exe rogue.des
-echo samurai.des
-..\util\levcomp.exe samurai.des
-echo sokoban.des
-..\util\levcomp.exe sokoban.des
-echo tourist.des
-..\util\levcomp.exe tourist.des
-echo tower.des
-..\util\levcomp.exe tower.des
-echo valkyrie.des
-..\util\levcomp.exe valkyrie.des
-echo wizard .des
-..\util\levcomp.exe wizard.des
-echo yendor.des
-..\util\levcomp.exe yendor.des
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <Midl>
-      <TypeLibraryName>.\..\util/levcomp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/levcomp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\..\util/levcomp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/levcomp.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>levcomp</Message>
-      <Command>echo Building special levels
-echo chdir ..\dat
-chdir ..\dat
-echo arch.des
-..\util\levcomp.exe arch.des
-echo barb.des
-..\util\levcomp.exe barb.des
-echo bigroom.des
-..\util\levcomp.exe bigroom.des
-echo castle.des
-..\util\levcomp.exe castle.des
-echo caveman.des
-..\util\levcomp.exe caveman.des
-echo endgame.des
-..\util\levcomp.exe endgame.des
-echo gehennom.des
-..\util\levcomp.exe gehennom.des
-echo healer.des
-..\util\levcomp.exe healer.des
-echo knight.des
-..\util\levcomp.exe knight.des
-echo knox.des
-..\util\levcomp.exe knox.des
-echo medusa.des
-..\util\levcomp.exe medusa.des
-echo mines.des
-..\util\levcomp.exe mines.des
-echo monk.des
-..\util\levcomp.exe monk.des
-echo oracle.des
-..\util\levcomp.exe oracle.des
-echo priest.des
-..\util\levcomp.exe priest.des
-echo ranger.des
-..\util\levcomp.exe ranger.des
-echo rogue.des
-..\util\levcomp.exe rogue.des
-echo samurai.des
-..\util\levcomp.exe samurai.des
-echo sokoban.des
-..\util\levcomp.exe sokoban.des
-echo tourist.des
-..\util\levcomp.exe tourist.des
-echo tower.des
-..\util\levcomp.exe tower.des
-echo valkyrie.des
-..\util\levcomp.exe valkyrie.des
-echo wizard .des
-..\util\levcomp.exe wizard.des
-echo yendor.des
-..\util\levcomp.exe yendor.des
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\src\alloc.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\decl.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\drawing.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\util\lev_lex.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\util\lev_main.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\util\lev_yacc.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\monst.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\objects.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\util\panic.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\include\lev_comp.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="levstuff.vcxproj">
-      <Project>{ff144dfb-83a5-4d26-a598-715a2b354782}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
diff --git a/win/win32/vs2010/levstuff.vcxproj b/win/win32/vs2010/levstuff.vcxproj
deleted file mode 100644 (file)
index 67d0c58..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{FF144DFB-83A5-4D26-A598-715A2B354782}</ProjectGuid>
-    <Keyword>MakeFileProj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">nmake /f "levstuff.mak"</NMakeBuildCommandLine>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">nmake /f "levstuff.mak"</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">nmake /f "levstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">nmake /f "levstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\util\lev_lex.c</NMakeOutput>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\util\lev_lex.c</NMakeOutput>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\levstuff___Win32_Debug0\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\levstuff___Win32_Debug0\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\levstuff___Win32_Debug0\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\levstuff___Win32_Debug0\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">nmake /f "levstuff.mak"</NMakeBuildCommandLine>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">nmake /f "levstuff.mak"</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">nmake /f "levstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">nmake /f "levstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\util\lev_lex.c</NMakeOutput>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\util\lev_lex.c</NMakeOutput>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ProjectReference Include="makedefs.vcxproj">
-      <Project>{ba3dd34c-04b7-40d0-b373-9329aa9e8945}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2010/makedefs.vcxproj b/win/win32/vs2010/makedefs.vcxproj
deleted file mode 100644 (file)
index cc4d784..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{BA3DD34C-04B7-40D0-B373-9329AA9E8945}</ProjectGuid>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Midl>
-      <TypeLibraryName>.\..\util/makedefs.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>.;..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/makedefs.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x0409</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\..\util/makedefs.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/makedefs.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Running makedefs</Message>
-      <Command>echo chdir ..\util
-chdir ..\util
-chdir
-echo makedefs.exe -v
-makedefs.exe -v
-echo makedefs.exe -o
-makedefs.exe  -o
-echo makedefs.exe -p
-makedefs.exe -p
-echo makedefs.exe -m
-makedefs.exe -m
-echo makedefs.exe -z
-makedefs.exe -z
-echo chdir ..\dat
-chdir ..\dat
-chdir
-echo Generating NetHack database
-echo ..\util\makedefs.exe -d
-..\util\makedefs.exe -d
-echo Generating rumors
-echo ..\util\makedefs.exe -r
-..\util\makedefs.exe -r
-echo Generating quests
-echo ..\util\makedefs.exe -q
-..\util\makedefs.exe -q
-echo Generating oracles
-echo ..\util\makedefs.exe -h
-..\util\makedefs.exe -h
-echo Generating dungeon.pdf
-echo ..\util\makedefs.exe -e
-..\util\makedefs.exe -e
-echo chdir ..\build
-chdir ..\build
-copy ..\win\share\tilemap.c ..\win\share\tiletxt.c
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <Midl>
-      <TypeLibraryName>.\..\util/makedefs.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>.;..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/makedefs.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x0409</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\..\util/makedefs.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/makedefs.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Running makedefs</Message>
-      <Command>echo chdir ..\util
-chdir ..\util
-chdir
-echo makedefs.exe -v
-makedefs.exe -v
-echo makedefs.exe -o
-makedefs.exe  -o
-echo makedefs.exe -p
-makedefs.exe -p
-echo makedefs.exe -m
-makedefs.exe -m
-echo makedefs.exe -z
-makedefs.exe -z
-echo chdir ..\dat
-chdir ..\dat
-chdir
-echo Generating NetHack database
-echo ..\util\makedefs.exe -d
-..\util\makedefs.exe -d
-echo Generating rumors
-echo ..\util\makedefs.exe -r
-..\util\makedefs.exe -r
-echo Generating quests
-echo ..\util\makedefs.exe -q
-..\util\makedefs.exe -q
-echo Generating oracles
-echo ..\util\makedefs.exe -h
-..\util\makedefs.exe -h
-echo Generating dungeon.pdf
-echo ..\util\makedefs.exe -e
-..\util\makedefs.exe -e
-echo chdir ..\build
-chdir ..\build
-copy ..\win\share\tilemap.c ..\win\share\tiletxt.c
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Midl>
-      <TypeLibraryName>.\..\util/makedefs.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>.;..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/makedefs.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x0409</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\..\util/makedefs.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/makedefs.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Running makedefs</Message>
-      <Command>echo chdir ..\util
-chdir ..\util
-chdir
-echo makedefs.exe -v
-makedefs.exe -v
-echo makedefs.exe -o
-makedefs.exe  -o
-echo makedefs.exe -p
-makedefs.exe -p
-echo makedefs.exe -m
-makedefs.exe -m
-echo makedefs.exe -z
-makedefs.exe -z
-echo chdir ..\dat
-chdir ..\dat
-chdir
-echo Generating NetHack database
-echo ..\util\makedefs.exe -d
-..\util\makedefs.exe -d
-echo Generating rumors
-echo ..\util\makedefs.exe -r
-..\util\makedefs.exe -r
-echo Generating quests
-echo ..\util\makedefs.exe -q
-..\util\makedefs.exe -q
-echo Generating oracles
-echo ..\util\makedefs.exe -h
-..\util\makedefs.exe -h
-echo Generating dungeon.pdf
-echo ..\util\makedefs.exe -e
-..\util\makedefs.exe -e
-echo chdir ..\build
-chdir ..\build
-copy ..\win\share\tilemap.c ..\win\share\tiletxt.c
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <Midl>
-      <TypeLibraryName>.\..\util/makedefs.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>.;..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/makedefs.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x0409</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\..\util/makedefs.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\..\util/makedefs.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Running makedefs</Message>
-      <Command>echo chdir ..\util
-chdir ..\util
-chdir
-echo makedefs.exe -v
-makedefs.exe -v
-echo makedefs.exe -o
-makedefs.exe  -o
-echo makedefs.exe -p
-makedefs.exe -p
-echo makedefs.exe -m
-makedefs.exe -m
-echo makedefs.exe -z
-makedefs.exe -z
-echo chdir ..\dat
-chdir ..\dat
-chdir
-echo Generating NetHack database
-echo ..\util\makedefs.exe -d
-..\util\makedefs.exe -d
-echo Generating rumors
-echo ..\util\makedefs.exe -r
-..\util\makedefs.exe -r
-echo Generating quests
-echo ..\util\makedefs.exe -q
-..\util\makedefs.exe -q
-echo Generating oracles
-echo ..\util\makedefs.exe -h
-..\util\makedefs.exe -h
-echo Generating dungeon.pdf
-echo ..\util\makedefs.exe -e
-..\util\makedefs.exe -e
-echo chdir ..\build
-chdir ..\build
-copy ..\win\share\tilemap.c ..\win\share\tiletxt.c
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\util\makedefs.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\monst.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\objects.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\include\config.h" />
-    <ClInclude Include="..\include\config1.h" />
-    <ClInclude Include="..\include\context.h" />
-    <ClInclude Include="..\include\coord.h" />
-    <ClInclude Include="..\include\global.h" />
-    <ClInclude Include="..\include\monattk.h" />
-    <ClInclude Include="..\include\monflag.h" />
-    <ClInclude Include="..\include\monsym.h" />
-    <ClInclude Include="..\include\nhlan.h" />
-    <ClInclude Include="..\include\ntconf.h" />
-    <ClInclude Include="..\include\objclass.h" />
-    <ClInclude Include="..\include\patchlevel.h" />
-    <ClInclude Include="..\include\qtext.h" />
-    <ClInclude Include="..\include\tradstdc.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2010/recover.vcxproj b/win/win32/vs2010/recover.vcxproj
deleted file mode 100644 (file)
index d053ec3..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}</ProjectGuid>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Midl>
-      <TypeLibraryName>.\Debug/recover.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/recover.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Debug/recover.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Debug/recover.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>install exe</Message>
-      <Command>copy $(OutDir)recover.exe ..\binary
-if exist ..\doc\recover.txt copy ..\doc\recover.txt ..\binary\recover.txt
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <Midl>
-      <TypeLibraryName>.\Debug/recover.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/recover.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Debug/recover.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Debug/recover.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>install exe</Message>
-      <Command>copy $(OutDir)recover.exe ..\binary
-if exist ..\doc\recover.txt copy ..\doc\recover.txt ..\binary\recover.txt
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Midl>
-      <TypeLibraryName>.\Release/recover.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/recover.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\Release/recover.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Release/recover.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Command>copy $(OutDir)recover.exe ..\binary
-if exist ..\doc\recover.txt copy ..\doc\recover.txt ..\binary\recover.txt
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <Midl>
-      <TypeLibraryName>.\Release/recover.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/recover.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\Release/recover.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Release/recover.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Command>copy $(OutDir)recover.exe ..\binary
-if exist ..\doc\recover.txt copy ..\doc\recover.txt ..\binary\recover.txt
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\util\recover.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\include\config.h" />
-    <ClInclude Include="..\include\config1.h" />
-    <ClInclude Include="..\include\coord.h" />
-    <ClInclude Include="..\include\global.h" />
-    <ClInclude Include="..\include\nhlan.h" />
-    <ClInclude Include="..\include\ntconf.h" />
-    <ClInclude Include="..\include\tradstdc.h" />
-    <ClInclude Include="..\sys\winnt\win32api.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="dlb_main.vcxproj">
-      <Project>{0303a585-3f83-4bb7-af6b-1e12c8fb54ac}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-    <ProjectReference Include="makedefs.vcxproj">
-      <Project>{ba3dd34c-04b7-40d0-b373-9329aa9e8945}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2010/tile2bmp.vcxproj b/win/win32/vs2010/tile2bmp.vcxproj
deleted file mode 100644 (file)
index e7e432e..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{642BC75D-ABAF-403E-8224-7C725FD4CB42}</ProjectGuid>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Midl>
-      <TypeLibraryName>.\Debug/tile2bmp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/tile2bmp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Debug/tile2bmp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Debug/tile2bmp.bsc</OutputFile>
-    </Bscmake>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <Midl>
-      <TypeLibraryName>.\Debug/tile2bmp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/tile2bmp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Debug/tile2bmp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Debug/tile2bmp.bsc</OutputFile>
-    </Bscmake>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Midl>
-      <TypeLibraryName>.\Release/tile2bmp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/tile2bmp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\Release/tile2bmp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Release/tile2bmp.bsc</OutputFile>
-    </Bscmake>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <Midl>
-      <TypeLibraryName>.\Release/tile2bmp.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/tile2bmp.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\Release/tile2bmp.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Release/tile2bmp.bsc</OutputFile>
-    </Bscmake>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\src\decl.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\drawing.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\monst.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\src\objects.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\share\tile2bmp.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">PACKED_FILE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">PACKED_FILE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\share\tiletext.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <ClCompile Include="..\win\share\tiletxt.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">TILETEXT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">TILETEXT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">TILETEXT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">TILETEXT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2010/tilemap.vcxproj b/win/win32/vs2010/tilemap.vcxproj
deleted file mode 100644 (file)
index ea20257..0000000
+++ /dev/null
@@ -1,333 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{93F10526-209E-41D7-BBEA-775787876895}</ProjectGuid>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Midl>
-      <TypeLibraryName>.\Debug/tilemap.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt\include;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/tilemap.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Debug/tilemap.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Debug/tilemap.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Generating src\tile.c</Message>
-      <Command>echo chdir ..\src
-chdir ..\src
-..\util\tilemap.exe
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <Midl>
-      <TypeLibraryName>.\Debug/tilemap.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt\include;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/tilemap.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Debug/tilemap.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Debug/tilemap.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Generating src\tile.c</Message>
-      <Command>echo chdir ..\src
-chdir ..\src
-..\util\tilemap.exe
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Midl>
-      <TypeLibraryName>.\Release/tilemap.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt\include;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/tilemap.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\Release/tilemap.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Release/tilemap.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Generating src\tile.c</Message>
-      <Command>echo chdir ..\src
-chdir ..\src
-..\util\tilemap.exe
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <Midl>
-      <TypeLibraryName>.\Release/tilemap.tlb</TypeLibraryName>
-      <HeaderFileName>
-      </HeaderFileName>
-    </Midl>
-    <ClCompile>
-      <Optimization>MaxSpeed</Optimization>
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt\include;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>true</StringPooling>
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/tilemap.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-    </ClCompile>
-    <ResourceCompile>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <Culture>0x1009</Culture>
-    </ResourceCompile>
-    <Link>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\Release/tilemap.pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
-    </Link>
-    <Bscmake>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <OutputFile>.\Release/tilemap.bsc</OutputFile>
-    </Bscmake>
-    <PostBuildEvent>
-      <Message>Generating src\tile.c</Message>
-      <Command>echo chdir ..\src
-chdir ..\src
-..\util\tilemap.exe
-echo chdir ..\build
-chdir ..\build
-</Command>
-    </PostBuildEvent>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="..\win\share\tilemap.c">
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\include\align.h" />
-    <ClInclude Include="..\include\attrib.h" />
-    <ClInclude Include="..\include\color.h" />
-    <ClInclude Include="..\include\config.h" />
-    <ClInclude Include="..\include\config1.h" />
-    <ClInclude Include="..\include\context.h" />
-    <ClInclude Include="..\include\coord.h" />
-    <ClInclude Include="..\include\decl.h" />
-    <ClInclude Include="..\include\dgn_comp.h" />
-    <ClInclude Include="..\include\dgn_file.h" />
-    <ClInclude Include="..\include\display.h" />
-    <ClInclude Include="..\include\dungeon.h" />
-    <ClInclude Include="..\include\engrave.h" />
-    <ClInclude Include="..\include\flag.h" />
-    <ClInclude Include="..\include\global.h" />
-    <ClInclude Include="..\include\mkroom.h" />
-    <ClInclude Include="..\include\monattk.h" />
-    <ClInclude Include="..\include\monst.h" />
-    <ClInclude Include="..\include\monsym.h" />
-    <ClInclude Include="..\include\nhlan.h" />
-    <ClInclude Include="..\include\ntconf.h" />
-    <ClInclude Include="..\include\obj.h" />
-    <ClInclude Include="..\include\objclass.h" />
-    <ClInclude Include="..\include\onames.h" />
-    <ClInclude Include="..\include\permonst.h" />
-    <ClInclude Include="..\include\pm.h" />
-    <ClInclude Include="..\include\prop.h" />
-    <ClInclude Include="..\include\quest.h" />
-    <ClInclude Include="..\include\rect.h" />
-    <ClInclude Include="..\include\region.h" />
-    <ClInclude Include="..\include\rm.h" />
-    <ClInclude Include="..\include\skills.h" />
-    <ClInclude Include="..\include\spell.h" />
-    <ClInclude Include="..\include\timeout.h" />
-    <ClInclude Include="..\include\tradstdc.h" />
-    <ClInclude Include="..\include\trampoli.h" />
-    <ClInclude Include="..\include\trap.h" />
-    <ClInclude Include="..\include\vision.h" />
-    <ClInclude Include="..\include\winprocs.h" />
-    <ClInclude Include="..\include\wintty.h" />
-    <ClInclude Include="..\include\wintype.h" />
-    <ClInclude Include="..\include\you.h" />
-    <ClInclude Include="..\include\youprop.h" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2010/uudecode.vcxproj b/win/win32/vs2010/uudecode.vcxproj
deleted file mode 100644 (file)
index d3206a3..0000000
+++ /dev/null
@@ -1,332 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{63F9B82B-F589-4082-ABE5-D4F0682050AB}</ProjectGuid>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>Windows7.1SDK</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/uudecode.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/uudecode.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>\r
-      <ObjectFileName>.\Release/</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/uudecode.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/uudecode.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Command>echo chdir ..\win\win32\r
-chdir ..\win\win32\r
-echo decoding icon (nhico.uu to NetHack.ico)\r
-..\..\util\uudecode.exe ../../sys/winnt/nhico.uu\r
-echo decoding mnsel (mnsel.uu to mnsel.bmp)\r
-..\..\util\uudecode.exe mnsel.uu\r
-echo decoding mnselcnt (mnselcnt.uu to mnselcnt.bmp)\r
-..\..\util\uudecode.exe mnselcnt.uu\r
-echo decoding mnunsel (mnunsel.uu to mnunsel.bmp)\r
-..\..\util\uudecode.exe mnunsel.uu\r
-echo decoding petmark (petmark.uu to petmark.bmp)\r
-..\..\util\uudecode.exe petmark.uu\r
-echo decoding pilemark (pilemark.uu to pilemark.bmp)\r
-..\..\util\uudecode.exe pilemark.uu\r
-echo decoding splash (splash.uu to splash.bmp)\r
-..\..\util\uudecode.exe splash.uu\r
-echo decoding tombstone (rip.uu to rip.bmp)\r
-..\..\util\uudecode.exe rip.uu\r
-chdir ..\..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/uudecode.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/uudecode.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>\r
-      <ObjectFileName>.\Release/</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/uudecode.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/uudecode.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Command>echo chdir ..\win\win32\r
-chdir ..\win\win32\r
-echo decoding icon (nhico.uu to NetHack.ico)\r
-..\..\util\uudecode.exe ../../sys/winnt/nhico.uu\r
-echo decoding mnsel (mnsel.uu to mnsel.bmp)\r
-..\..\util\uudecode.exe mnsel.uu\r
-echo decoding mnselcnt (mnselcnt.uu to mnselcnt.bmp)\r
-..\..\util\uudecode.exe mnselcnt.uu\r
-echo decoding mnunsel (mnunsel.uu to mnunsel.bmp)\r
-..\..\util\uudecode.exe mnunsel.uu\r
-echo decoding petmark (petmark.uu to petmark.bmp)\r
-..\..\util\uudecode.exe petmark.uu\r
-echo decoding pilemark (pilemark.uu to pilemark.bmp)\r
-..\..\util\uudecode.exe pilemark.uu\r
-echo decoding splash (splash.uu to splash.bmp)\r
-..\..\util\uudecode.exe splash.uu\r
-echo decoding tombstone (rip.uu to rip.bmp)\r
-..\..\util\uudecode.exe rip.uu\r
-chdir ..\..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/uudecode.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/uudecode.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>\r
-      <ObjectFileName>.\Debug/</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\Debug/uudecode.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/uudecode.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Command>echo chdir ..\win\win32\r
-chdir ..\win\win32\r
-echo decoding icon (nhico.uu to NetHack.ico)\r
-..\..\util\uudecode.exe ../../sys/winnt/nhico.uu\r
-echo decoding mnsel (mnsel.uu to mnsel.bmp)\r
-..\..\util\uudecode.exe mnsel.uu\r
-echo decoding mnselcnt (mnselcnt.uu to mnselcnt.bmp)\r
-..\..\util\uudecode.exe mnselcnt.uu\r
-echo decoding mnunsel (mnunsel.uu to mnunsel.bmp)\r
-..\..\util\uudecode.exe mnunsel.uu\r
-echo decoding petmark (petmark.uu to petmark.bmp)\r
-..\..\util\uudecode.exe petmark.uu\r
-echo decoding pilemark (pilemark.uu to pilemark.bmp)\r
-..\..\util\uudecode.exe pilemark.uu\r
-echo decoding splash (splash.uu to splash.bmp)\r
-..\..\util\uudecode.exe splash.uu\r
-echo decoding tombstone (rip.uu to rip.bmp)\r
-..\..\util\uudecode.exe rip.uu\r
-chdir ..\..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/uudecode.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/uudecode.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>\r
-      <ObjectFileName>.\Debug/</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\Debug/uudecode.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/uudecode.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Command>echo chdir ..\win\win32\r
-chdir ..\win\win32\r
-echo decoding icon (nhico.uu to NetHack.ico)\r
-..\..\util\uudecode.exe ../../sys/winnt/nhico.uu\r
-echo decoding mnsel (mnsel.uu to mnsel.bmp)\r
-..\..\util\uudecode.exe mnsel.uu\r
-echo decoding mnselcnt (mnselcnt.uu to mnselcnt.bmp)\r
-..\..\util\uudecode.exe mnselcnt.uu\r
-echo decoding mnunsel (mnunsel.uu to mnunsel.bmp)\r
-..\..\util\uudecode.exe mnunsel.uu\r
-echo decoding petmark (petmark.uu to petmark.bmp)\r
-..\..\util\uudecode.exe petmark.uu\r
-echo decoding pilemark (pilemark.uu to pilemark.bmp)\r
-..\..\util\uudecode.exe pilemark.uu\r
-echo decoding splash (splash.uu to splash.bmp)\r
-..\..\util\uudecode.exe splash.uu\r
-echo decoding tombstone (rip.uu to rip.bmp)\r
-..\..\util\uudecode.exe rip.uu\r
-chdir ..\..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\sys\share\uudecode.c">\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>\r
diff --git a/win/win32/vs2013/NetHack.sln b/win/win32/vs2013/NetHack.sln
deleted file mode 100644 (file)
index 3b335b6..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-\r
-Microsoft Visual Studio Solution File, Format Version 12.00\r
-# Visual Studio Express 2013 for Windows Desktop\r
-VisualStudioVersion = 12.0.31101.0\r
-MinimumVisualStudioVersion = 10.0.40219.1\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetHackW", "build\NetHackW.vcxproj", "{CEC5D360-8804-454F-8591-002184C23499}"\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dgncomp", "build\dgncomp.vcxproj", "{8A3F81C7-2968-49A8-86BF-2669412AD7DE}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42} = {642BC75D-ABAF-403E-8224-7C725FD4CB42}\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dgnstuff", "build\dgnstuff.vcxproj", "{B9E02F2C-8851-442B-BF2A-3581802B78D4}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-               {FF144DFB-83A5-4D26-A598-715A2B354782} = {FF144DFB-83A5-4D26-A598-715A2B354782}\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dlb_main", "build\dlb_main.vcxproj", "{0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}"\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "levcomp", "build\levcomp.vcxproj", "{9DD9C52E-E8C9-4533-BD22-83C055C0AABA}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4} = {B9E02F2C-8851-442B-BF2A-3581802B78D4}\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "levstuff", "build\levstuff.vcxproj", "{FF144DFB-83A5-4D26-A598-715A2B354782}"\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makedefs", "build\makedefs.vcxproj", "{BA3DD34C-04B7-40D0-B373-9329AA9E8945}"\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "recover", "build\recover.vcxproj", "{2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}"\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tile2bmp", "build\tile2bmp.vcxproj", "{642BC75D-ABAF-403E-8224-7C725FD4CB42}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tilemap", "build\tilemap.vcxproj", "{93F10526-209E-41D7-BBEA-775787876895}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE} = {8A3F81C7-2968-49A8-86BF-2669412AD7DE}\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tiles", "build\tiles.vcxproj", "{55946465-FC65-47B3-BB48-742C7694C0D6}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-               {93F10526-209E-41D7-BBEA-775787876895} = {93F10526-209E-41D7-BBEA-775787876895}\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uudecode", "build\uudecode.vcxproj", "{63F9B82B-F589-4082-ABE5-D4F0682050AB}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945}\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetHack", "build\NetHack.vcxproj", "{609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB} = {63F9B82B-F589-4082-ABE5-D4F0682050AB}\r
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945}\r
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} = {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}\r
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE} = {8A3F81C7-2968-49A8-86BF-2669412AD7DE}\r
-       EndProjectSection\r
-EndProject\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nhdefkey", "build\nhdefkey.vcxproj", "{6813477F-64B6-4B97-B230-438D0D233385}"\r
-       ProjectSection(ProjectDependencies) = postProject\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945}\r
-       EndProjectSection\r
-EndProject\r
-Global\r
-       GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
-               Debug|Win32 = Debug|Win32\r
-               Debug|x64 = Debug|x64\r
-               Release|Win32 = Release|Win32\r
-               Release|x64 = Release|x64\r
-       EndGlobalSection\r
-       GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
-               {CEC5D360-8804-454F-8591-002184C23499}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {CEC5D360-8804-454F-8591-002184C23499}.Debug|Win32.Build.0 = Debug|Win32\r
-               {CEC5D360-8804-454F-8591-002184C23499}.Debug|x64.ActiveCfg = Debug|x64\r
-               {CEC5D360-8804-454F-8591-002184C23499}.Debug|x64.Build.0 = Debug|x64\r
-               {CEC5D360-8804-454F-8591-002184C23499}.Release|Win32.ActiveCfg = Release|Win32\r
-               {CEC5D360-8804-454F-8591-002184C23499}.Release|Win32.Build.0 = Release|Win32\r
-               {CEC5D360-8804-454F-8591-002184C23499}.Release|x64.ActiveCfg = Release|x64\r
-               {CEC5D360-8804-454F-8591-002184C23499}.Release|x64.Build.0 = Release|x64\r
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Debug|Win32.Build.0 = Debug|Win32\r
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Debug|x64.ActiveCfg = Debug|x64\r
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Debug|x64.Build.0 = Debug|x64\r
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Release|Win32.ActiveCfg = Release|Win32\r
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Release|Win32.Build.0 = Release|Win32\r
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Release|x64.ActiveCfg = Release|x64\r
-               {8A3F81C7-2968-49A8-86BF-2669412AD7DE}.Release|x64.Build.0 = Release|x64\r
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Debug|Win32.Build.0 = Debug|Win32\r
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Debug|x64.ActiveCfg = Debug|x64\r
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Debug|x64.Build.0 = Debug|x64\r
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Release|Win32.ActiveCfg = Release|Win32\r
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Release|Win32.Build.0 = Release|Win32\r
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Release|x64.ActiveCfg = Release|x64\r
-               {B9E02F2C-8851-442B-BF2A-3581802B78D4}.Release|x64.Build.0 = Release|x64\r
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Debug|Win32.Build.0 = Debug|Win32\r
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Debug|x64.ActiveCfg = Debug|x64\r
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Debug|x64.Build.0 = Debug|x64\r
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Release|Win32.ActiveCfg = Release|Win32\r
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Release|Win32.Build.0 = Release|Win32\r
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Release|x64.ActiveCfg = Release|x64\r
-               {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}.Release|x64.Build.0 = Release|x64\r
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Debug|Win32.Build.0 = Debug|Win32\r
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Debug|x64.ActiveCfg = Debug|x64\r
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Debug|x64.Build.0 = Debug|x64\r
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Release|Win32.ActiveCfg = Release|Win32\r
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Release|Win32.Build.0 = Release|Win32\r
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Release|x64.ActiveCfg = Release|x64\r
-               {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}.Release|x64.Build.0 = Release|x64\r
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Debug|Win32.Build.0 = Debug|Win32\r
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Debug|x64.ActiveCfg = Debug|x64\r
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Debug|x64.Build.0 = Debug|x64\r
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Release|Win32.ActiveCfg = Release|Win32\r
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Release|Win32.Build.0 = Release|Win32\r
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Release|x64.ActiveCfg = Release|x64\r
-               {FF144DFB-83A5-4D26-A598-715A2B354782}.Release|x64.Build.0 = Release|x64\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Debug|Win32.Build.0 = Debug|Win32\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Debug|x64.ActiveCfg = Debug|x64\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Debug|x64.Build.0 = Debug|x64\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Release|Win32.ActiveCfg = Release|Win32\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Release|Win32.Build.0 = Release|Win32\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Release|x64.ActiveCfg = Release|x64\r
-               {BA3DD34C-04B7-40D0-B373-9329AA9E8945}.Release|x64.Build.0 = Release|x64\r
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Debug|Win32.Build.0 = Debug|Win32\r
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Debug|x64.ActiveCfg = Debug|x64\r
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Debug|x64.Build.0 = Debug|x64\r
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Release|Win32.ActiveCfg = Release|Win32\r
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Release|Win32.Build.0 = Release|Win32\r
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Release|x64.ActiveCfg = Release|x64\r
-               {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}.Release|x64.Build.0 = Release|x64\r
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Debug|Win32.Build.0 = Debug|Win32\r
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Debug|x64.ActiveCfg = Debug|x64\r
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Debug|x64.Build.0 = Debug|x64\r
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Release|Win32.ActiveCfg = Release|Win32\r
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Release|Win32.Build.0 = Release|Win32\r
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Release|x64.ActiveCfg = Release|x64\r
-               {642BC75D-ABAF-403E-8224-7C725FD4CB42}.Release|x64.Build.0 = Release|x64\r
-               {93F10526-209E-41D7-BBEA-775787876895}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {93F10526-209E-41D7-BBEA-775787876895}.Debug|Win32.Build.0 = Debug|Win32\r
-               {93F10526-209E-41D7-BBEA-775787876895}.Debug|x64.ActiveCfg = Debug|x64\r
-               {93F10526-209E-41D7-BBEA-775787876895}.Debug|x64.Build.0 = Debug|x64\r
-               {93F10526-209E-41D7-BBEA-775787876895}.Release|Win32.ActiveCfg = Release|Win32\r
-               {93F10526-209E-41D7-BBEA-775787876895}.Release|Win32.Build.0 = Release|Win32\r
-               {93F10526-209E-41D7-BBEA-775787876895}.Release|x64.ActiveCfg = Release|x64\r
-               {93F10526-209E-41D7-BBEA-775787876895}.Release|x64.Build.0 = Release|x64\r
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Debug|Win32.Build.0 = Debug|Win32\r
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Debug|x64.ActiveCfg = Debug|x64\r
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Debug|x64.Build.0 = Debug|x64\r
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Release|Win32.ActiveCfg = Release|Win32\r
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Release|Win32.Build.0 = Release|Win32\r
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Release|x64.ActiveCfg = Release|x64\r
-               {55946465-FC65-47B3-BB48-742C7694C0D6}.Release|x64.Build.0 = Release|x64\r
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Debug|Win32.Build.0 = Debug|Win32\r
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Debug|x64.ActiveCfg = Debug|x64\r
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Debug|x64.Build.0 = Debug|x64\r
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Release|Win32.ActiveCfg = Release|Win32\r
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Release|Win32.Build.0 = Release|Win32\r
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Release|x64.ActiveCfg = Release|x64\r
-               {63F9B82B-F589-4082-ABE5-D4F0682050AB}.Release|x64.Build.0 = Release|x64\r
-               {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|Win32.Build.0 = Debug|Win32\r
-               {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|x64.ActiveCfg = Debug|Win32\r
-               {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|Win32.ActiveCfg = Release|Win32\r
-               {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|Win32.Build.0 = Release|Win32\r
-               {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|x64.ActiveCfg = Release|Win32\r
-               {6813477F-64B6-4B97-B230-438D0D233385}.Debug|Win32.ActiveCfg = Debug|Win32\r
-               {6813477F-64B6-4B97-B230-438D0D233385}.Debug|Win32.Build.0 = Debug|Win32\r
-               {6813477F-64B6-4B97-B230-438D0D233385}.Debug|x64.ActiveCfg = Debug|x64\r
-               {6813477F-64B6-4B97-B230-438D0D233385}.Debug|x64.Build.0 = Debug|x64\r
-               {6813477F-64B6-4B97-B230-438D0D233385}.Release|Win32.ActiveCfg = Release|Win32\r
-               {6813477F-64B6-4B97-B230-438D0D233385}.Release|Win32.Build.0 = Release|Win32\r
-               {6813477F-64B6-4B97-B230-438D0D233385}.Release|x64.ActiveCfg = Release|x64\r
-               {6813477F-64B6-4B97-B230-438D0D233385}.Release|x64.Build.0 = Release|x64\r
-       EndGlobalSection\r
-       GlobalSection(SolutionProperties) = preSolution\r
-               HideSolutionNode = FALSE\r
-       EndGlobalSection\r
-EndGlobal\r
diff --git a/win/win32/vs2013/NetHack.vcxproj b/win/win32/vs2013/NetHack.vcxproj
deleted file mode 100644 (file)
index 3721b37..0000000
+++ /dev/null
@@ -1,492 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}</ProjectGuid>\r
-    <Keyword>Win32Proj</Keyword>\r
-    <RootNamespace>NetHack</RootNamespace>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseDebugLibraries>true</UseDebugLibraries>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseDebugLibraries>false</UseDebugLibraries>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-    <WholeProgramOptimization>true</WholeProgramOptimization>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <ClCompile>\r
-      <AdditionalOptions>/Gs /Oi-  /FS %(AdditionalOptions)</AdditionalOptions>\r
-      <Optimization>Disabled</Optimization>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\r
-      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
-      <OmitFramePointers>true</OmitFramePointers>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <IntrinsicFunctions>false</IntrinsicFunctions>\r
-      <PreprocessorDefinitions>TILES;MSWIN_GRAPHICS;WIN32;WIN32CON;DLB;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <SDLCheck>true</SDLCheck>\r
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/NetHack.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-    </ClCompile>\r
-    <Link>\r
-      <SubSystem>Console</SubSystem>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
-      <OptimizeReferences>true</OptimizeReferences>\r
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winmm.lib;Winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\Release/NetHack.pdb</ProgramDatabaseFile>\r
-      <GenerateMapFile>true</GenerateMapFile>\r
-      <MapFileName>.\Release/NetHack.map</MapFileName>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-      <MapExports>true</MapExports>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/NetHack.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Install exe</Message>\r
-      <Command>\r
-        copy $(OutDir)NetHack.exe ..\binary\r
-        copy ..\dat\nhdat ..\binary\r
-        copy ..\dat\license ..\binary\r
-        if exist tiles.bmp copy tiles.bmp ..\binary\r
-        if NOT exist ..\binary\sysconf copy ..\sys\winnt\sysconf ..\binary\sysconf\r
-        if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt\r
-        if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt\r
-        copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh\r
-      </Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <ClCompile>\r
-      <AdditionalOptions>/Gs /Oi-  /FS %(AdditionalOptions)</AdditionalOptions>\r
-      <Optimization>Disabled</Optimization>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\r
-      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
-      <OmitFramePointers>true</OmitFramePointers>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <IntrinsicFunctions>false</IntrinsicFunctions>\r
-      <PreprocessorDefinitions>TILES;MSWIN_GRAPHICS;WIN32;WIN32CON;DLB;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <SDLCheck>true</SDLCheck>\r
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/NetHack.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-    </ClCompile>\r
-    <Link>\r
-      <SubSystem>Console</SubSystem>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
-      <OptimizeReferences>true</OptimizeReferences>\r
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\Release/NetHack.pdb</ProgramDatabaseFile>\r
-      <GenerateMapFile>true</GenerateMapFile>\r
-      <MapFileName>.\Release/NetHack.map</MapFileName>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/NetHack.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Install exe</Message>\r
-      <Command>\r
-          copy $(OutDir)NetHack.exe ..\binary\r
-          copy ..\dat\nhdat ..\binary\r
-          copy ..\dat\license ..\binary\r
-          if exist tiles.bmp copy tiles.bmp ..\binary\r
-          if NOT exist ..\binary\sysconf copy ..\sys\winnt\sysconf ..\binary\sysconf\r
-          if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt\r
-          if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt\r
-          copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh\r
-        </Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <ClCompile>\r
-      <AdditionalOptions>/Gs /Oi-  /FS %(AdditionalOptions)</AdditionalOptions>\r
-      <Optimization>Disabled</Optimization>\r
-      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\r
-      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
-      <OmitFramePointers>true</OmitFramePointers>\r
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>TILES;MSWIN_GRAPHICS;NDEBUG;WIN32;WIN32CON;DLB;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <SDLCheck>true</SDLCheck>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Debug/NetHack.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-    </ClCompile>\r
-    <Link>\r
-      <ProgramDatabaseFile>.\Release/NetHack.pdb</ProgramDatabaseFile>\r
-      <GenerateMapFile>true</GenerateMapFile>\r
-      <MapFileName>.\Release/NetHack.map</MapFileName>\r
-      <SubSystem>Console</SubSystem>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/NetHack.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Install exe</Message>\r
-      <Command>\r
-          if NOT exist ..\binary\*.* mkdir ..\binary\r
-          copy $(OutDir)NetHack.exe ..\binary\r
-          copy ..\dat\nhdat ..\binary\r
-          copy ..\dat\license ..\binary\r
-          copy ..\dat\symbols ..\binary\r
-          if exist tiles.bmp copy tiles.bmp ..\binary\r
-          if NOT exist ..\binary\sysconf copy ..\sys\winnt\sysconf ..\binary\sysconf\r
-          if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt\r
-          if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt\r
-          copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh\r
-        </Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <ClCompile>\r
-      <AdditionalOptions>/Gs /Oi-  /FS %(AdditionalOptions)</AdditionalOptions>\r
-      <Optimization>Disabled</Optimization>\r
-      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\r
-      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
-      <OmitFramePointers>true</OmitFramePointers>\r
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>TILES;MSWIN_GRAPHICS;WIN32;WIN32CON;DLB;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <SDLCheck>true</SDLCheck>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Debug/NetHack.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-    </ClCompile>\r
-    <Link>\r
-      <ProgramDatabaseFile>.\Release/NetHack.pdb</ProgramDatabaseFile>\r
-      <GenerateMapFile>true</GenerateMapFile>\r
-      <MapFileName>.\Release/NetHack.map</MapFileName>\r
-      <SubSystem>Console</SubSystem>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winmm.lib;Winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/NetHack.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Install exe</Message>\r
-      <Command>\r
-          if NOT exist ..\binary\*.* mkdir ..\binary\r
-          copy $(OutDir)NetHack.exe ..\binary\r
-          copy ..\dat\nhdat ..\binary\r
-          copy ..\dat\license ..\binary\r
-          copy ..\dat\symbols ..\binary\r
-          if exist tiles.bmp copy tiles.bmp ..\binary\r
-          if NOT exist ..\binary\sysconf copy ..\sys\winnt\sysconf ..\binary\sysconf\r
-          if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt\r
-          if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt\r
-          copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh\r
-        </Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\src\allmain.c" />\r
-    <ClCompile Include="..\src\alloc.c" />\r
-    <ClCompile Include="..\src\apply.c" />\r
-    <ClCompile Include="..\src\artifact.c" />\r
-    <ClCompile Include="..\src\attrib.c" />\r
-    <ClCompile Include="..\src\ball.c" />\r
-    <ClCompile Include="..\src\bones.c" />\r
-    <ClCompile Include="..\src\botl.c" />\r
-    <ClCompile Include="..\src\cmd.c" />\r
-    <ClCompile Include="..\src\dbridge.c" />\r
-    <ClCompile Include="..\src\decl.c" />\r
-    <ClCompile Include="..\src\detect.c" />\r
-    <ClCompile Include="..\src\dig.c" />\r
-    <ClCompile Include="..\src\display.c" />\r
-    <ClCompile Include="..\src\dlb.c" />\r
-    <ClCompile Include="..\src\do.c" />\r
-    <ClCompile Include="..\src\dog.c" />\r
-    <ClCompile Include="..\src\dogmove.c" />\r
-    <ClCompile Include="..\src\dokick.c" />\r
-    <ClCompile Include="..\src\dothrow.c" />\r
-    <ClCompile Include="..\src\do_name.c" />\r
-    <ClCompile Include="..\src\do_wear.c" />\r
-    <ClCompile Include="..\src\drawing.c" />\r
-    <ClCompile Include="..\src\dungeon.c" />\r
-    <ClCompile Include="..\src\eat.c" />\r
-    <ClCompile Include="..\src\end.c" />\r
-    <ClCompile Include="..\src\engrave.c" />\r
-    <ClCompile Include="..\src\exper.c" />\r
-    <ClCompile Include="..\src\explode.c" />\r
-    <ClCompile Include="..\src\extralev.c" />\r
-    <ClCompile Include="..\src\files.c" />\r
-    <ClCompile Include="..\src\fountain.c" />\r
-    <ClCompile Include="..\src\hack.c" />\r
-    <ClCompile Include="..\src\hacklib.c" />\r
-    <ClCompile Include="..\src\invent.c" />\r
-    <ClCompile Include="..\src\light.c" />\r
-    <ClCompile Include="..\src\lock.c" />\r
-    <ClCompile Include="..\src\mail.c" />\r
-    <ClCompile Include="..\src\makemon.c" />\r
-    <ClCompile Include="..\src\mapglyph.c" />\r
-    <ClCompile Include="..\src\mcastu.c" />\r
-    <ClCompile Include="..\src\mhitm.c" />\r
-    <ClCompile Include="..\src\mhitu.c" />\r
-    <ClCompile Include="..\src\minion.c" />\r
-    <ClCompile Include="..\src\mklev.c" />\r
-    <ClCompile Include="..\src\mkmap.c" />\r
-    <ClCompile Include="..\src\mkmaze.c" />\r
-    <ClCompile Include="..\src\mkobj.c" />\r
-    <ClCompile Include="..\src\mkroom.c" />\r
-    <ClCompile Include="..\src\mon.c" />\r
-    <ClCompile Include="..\src\mondata.c" />\r
-    <ClCompile Include="..\src\monmove.c" />\r
-    <ClCompile Include="..\src\monst.c" />\r
-    <ClCompile Include="..\src\monstr.c" />\r
-    <ClCompile Include="..\src\mplayer.c" />\r
-    <ClCompile Include="..\src\mthrowu.c" />\r
-    <ClCompile Include="..\src\muse.c" />\r
-    <ClCompile Include="..\src\music.c" />\r
-    <ClCompile Include="..\src\objects.c" />\r
-    <ClCompile Include="..\src\objnam.c" />\r
-    <ClCompile Include="..\src\options.c" />\r
-    <ClCompile Include="..\src\o_init.c" />\r
-    <ClCompile Include="..\src\pager.c" />\r
-    <ClCompile Include="..\src\pickup.c" />\r
-    <ClCompile Include="..\src\pline.c" />\r
-    <ClCompile Include="..\src\polyself.c" />\r
-    <ClCompile Include="..\src\potion.c" />\r
-    <ClCompile Include="..\src\pray.c" />\r
-    <ClCompile Include="..\src\priest.c" />\r
-    <ClCompile Include="..\src\quest.c" />\r
-    <ClCompile Include="..\src\questpgr.c" />\r
-    <ClCompile Include="..\src\read.c" />\r
-    <ClCompile Include="..\src\rect.c" />\r
-    <ClCompile Include="..\src\region.c" />\r
-    <ClCompile Include="..\src\restore.c" />\r
-    <ClCompile Include="..\src\rip.c" />\r
-    <ClCompile Include="..\src\rnd.c" />\r
-    <ClCompile Include="..\src\role.c" />\r
-    <ClCompile Include="..\src\rumors.c" />\r
-    <ClCompile Include="..\src\save.c" />\r
-    <ClCompile Include="..\src\shk.c" />\r
-    <ClCompile Include="..\src\shknam.c" />\r
-    <ClCompile Include="..\src\sit.c" />\r
-    <ClCompile Include="..\src\sounds.c" />\r
-    <ClCompile Include="..\src\spell.c" />\r
-    <ClCompile Include="..\src\sp_lev.c" />\r
-    <ClCompile Include="..\src\steal.c" />\r
-    <ClCompile Include="..\src\steed.c" />\r
-    <ClCompile Include="..\src\sys.c" />\r
-    <ClCompile Include="..\src\teleport.c" />\r
-    <ClCompile Include="..\src\tile.c" />\r
-    <ClCompile Include="..\src\timeout.c" />\r
-    <ClCompile Include="..\src\topten.c" />\r
-    <ClCompile Include="..\src\track.c" />\r
-    <ClCompile Include="..\src\trap.c" />\r
-    <ClCompile Include="..\src\uhitm.c" />\r
-    <ClCompile Include="..\src\u_init.c" />\r
-    <ClCompile Include="..\src\vault.c" />\r
-    <ClCompile Include="..\src\version.c" />\r
-    <ClCompile Include="..\src\vision.c" />\r
-    <ClCompile Include="..\src\weapon.c" />\r
-    <ClCompile Include="..\src\were.c" />\r
-    <ClCompile Include="..\src\wield.c" />\r
-    <ClCompile Include="..\src\windows.c" />\r
-    <ClCompile Include="..\src\wizard.c" />\r
-    <ClCompile Include="..\src\worm.c" />\r
-    <ClCompile Include="..\src\worn.c" />\r
-    <ClCompile Include="..\src\write.c" />\r
-    <ClCompile Include="..\src\zap.c" />\r
-    <ClCompile Include="..\sys\share\cppregex.cpp" />\r
-    <ClCompile Include="..\sys\share\nhlan.c" />\r
-    <ClCompile Include="..\sys\share\pcmain.c" />\r
-    <ClCompile Include="..\sys\share\pcsys.c" />\r
-    <ClCompile Include="..\sys\share\pcunix.c" />\r
-    <ClCompile Include="..\sys\share\random.c" />\r
-    <ClCompile Include="..\sys\winnt\ntsound.c" />\r
-    <ClCompile Include="..\sys\winnt\nttty.c" />\r
-    <ClCompile Include="..\sys\winnt\stubs.c">\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">GUISTUB;NDEBUG;WIN32;WIN32CON;DLB;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">GUISTUB;WIN32;WIN32CON;DLB;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">GUISTUB;WIN32;WIN32CON;DLB;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">GUISTUB;WIN32;WIN32CON;DLB;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\sys\winnt\winnt.c" />\r
-    <ClCompile Include="..\win\tty\getline.c" />\r
-    <ClCompile Include="..\win\tty\topl.c" />\r
-    <ClCompile Include="..\win\tty\wintty.c" />\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ClInclude Include="..\include\align.h" />\r
-    <ClInclude Include="..\include\artifact.h" />\r
-    <ClInclude Include="..\include\artilist.h" />\r
-    <ClInclude Include="..\include\attrib.h" />\r
-    <ClInclude Include="..\include\botl.h" />\r
-    <ClInclude Include="..\include\color.h" />\r
-    <ClInclude Include="..\include\config.h" />\r
-    <ClInclude Include="..\include\config1.h" />\r
-    <ClInclude Include="..\include\context.h" />\r
-    <ClInclude Include="..\include\coord.h" />\r
-    <ClInclude Include="..\include\date.h" />\r
-    <ClInclude Include="..\include\decl.h" />\r
-    <ClInclude Include="..\include\display.h" />\r
-    <ClInclude Include="..\include\dlb.h" />\r
-    <ClInclude Include="..\include\dungeon.h" />\r
-    <ClInclude Include="..\include\engrave.h" />\r
-    <ClInclude Include="..\include\extern.h" />\r
-    <ClInclude Include="..\include\flag.h" />\r
-    <ClInclude Include="..\include\func_tab.h" />\r
-    <ClInclude Include="..\include\global.h" />\r
-    <ClInclude Include="..\include\hack.h" />\r
-    <ClInclude Include="..\include\lev.h" />\r
-    <ClInclude Include="..\include\mextra.h" />\r
-    <ClInclude Include="..\include\mfndpos.h" />\r
-    <ClInclude Include="..\include\mkroom.h" />\r
-    <ClInclude Include="..\include\monattk.h" />\r
-    <ClInclude Include="..\include\mondata.h" />\r
-    <ClInclude Include="..\include\monflag.h" />\r
-    <ClInclude Include="..\include\monst.h" />\r
-    <ClInclude Include="..\include\monsym.h" />\r
-    <ClInclude Include="..\include\ntconf.h" />\r
-    <ClInclude Include="..\include\obj.h" />\r
-    <ClInclude Include="..\include\objclass.h" />\r
-    <ClInclude Include="..\include\onames.h" />\r
-    <ClInclude Include="..\include\patchlevel.h" />\r
-    <ClInclude Include="..\include\permonst.h" />\r
-    <ClInclude Include="..\include\pm.h" />\r
-    <ClInclude Include="..\include\prop.h" />\r
-    <ClInclude Include="..\include\qtext.h" />\r
-    <ClInclude Include="..\include\quest.h" />\r
-    <ClInclude Include="..\include\rect.h" />\r
-    <ClInclude Include="..\include\region.h" />\r
-    <ClInclude Include="..\include\rm.h" />\r
-    <ClInclude Include="..\include\skills.h" />\r
-    <ClInclude Include="..\include\spell.h" />\r
-    <ClInclude Include="..\include\sp_lev.h" />\r
-    <ClInclude Include="..\include\timeout.h" />\r
-    <ClInclude Include="..\include\tradstdc.h" />\r
-    <ClInclude Include="..\include\trap.h" />\r
-    <ClInclude Include="..\include\vision.h" />\r
-    <ClInclude Include="..\include\winprocs.h" />\r
-    <ClInclude Include="..\include\wintty.h" />\r
-    <ClInclude Include="..\include\wintype.h" />\r
-    <ClInclude Include="..\include\you.h" />\r
-    <ClInclude Include="..\include\youprop.h" />\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2013/NetHackW.vcxproj b/win/win32/vs2013/NetHackW.vcxproj
deleted file mode 100644 (file)
index 7cded70..0000000
+++ /dev/null
@@ -1,508 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{CEC5D360-8804-454F-8591-002184C23499}</ProjectGuid>\r
-    <RootNamespace>NetHackW</RootNamespace>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Midl>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MkTypLibCompatible>true</MkTypLibCompatible>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <TargetEnvironment>Win32</TargetEnvironment>\r
-      <TypeLibraryName>.\Release/NetHackW.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <AdditionalOptions>/Gs /Oi-  /FS %(AdditionalOptions)</AdditionalOptions>\r
-      <Optimization>Disabled</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
-      <OmitFramePointers>true</OmitFramePointers>\r
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>TILES;MSWIN_GRAPHICS;WIN32CONNDEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/NetHackW.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <AdditionalOptions>/MAPINFO:EXPORTS %(AdditionalOptions)</AdditionalOptions>\r
-      <AdditionalDependencies>comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\Release/NetHackW.pdb</ProgramDatabaseFile>\r
-      <GenerateMapFile>true</GenerateMapFile>\r
-      <MapFileName>.\Release/NetHackW.map</MapFileName>\r
-      <SubSystem>Windows</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/NetHackW.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Install exe</Message>\r
-      <Command>copy $(OutDir)NetHackW.exe ..\binary\r
-copy ..\dat\nhdat ..\binary\r
-copy ..\dat\license ..\binary\r
-if NOT exist ..\binary\sysconf copy ..\sys\winnt\sysconf ..\binary\sysconf\r
-if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt\r
-if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt\r
-copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Midl>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MkTypLibCompatible>true</MkTypLibCompatible>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <TypeLibraryName>.\Release/NetHackW.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <AdditionalOptions>/Gs /Oi-  /FS %(AdditionalOptions)</AdditionalOptions>\r
-      <Optimization>Disabled</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
-      <OmitFramePointers>true</OmitFramePointers>\r
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>TILES;MSWIN_GRAPHICS;WIN32CONNDEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/NetHackW.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <AdditionalOptions>/MAPINFO:EXPORTS %(AdditionalOptions)</AdditionalOptions>\r
-      <AdditionalDependencies>comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\Release/NetHackW.pdb</ProgramDatabaseFile>\r
-      <GenerateMapFile>true</GenerateMapFile>\r
-      <MapFileName>.\Release/NetHackW.map</MapFileName>\r
-      <SubSystem>Windows</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/NetHackW.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Install exe</Message>\r
-      <Command>copy $(OutDir)NetHackW.exe ..\binary\r
-copy ..\dat\nhdat ..\binary\r
-copy ..\dat\license ..\binary\r
-if NOT exist ..\binary\sysconf copy ..\sys\winnt\sysconf ..\binary\sysconf\r
-if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt\r
-if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt\r
-copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Midl>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MkTypLibCompatible>true</MkTypLibCompatible>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <TargetEnvironment>Win32</TargetEnvironment>\r
-      <TypeLibraryName>.\Debug/NetHackW.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>TILES;MSWIN_GRAPHICS;WIN32CON_DEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/NetHackW.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/Gs /Oi-  /FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <AdditionalDependencies>comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Windows</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/NetHackW.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Install exe</Message>\r
-      <Command>if NOT exist ..\binary\*.* mkdir ..\binary\r
-copy $(OutDir)NetHackW.exe ..\binary\r
-copy ..\dat\nhdat ..\binary\r
-copy ..\dat\license ..\binary\r
-copy ..\dat\symbols ..\binary\r
-if NOT exist ..\binary\sysconf copy ..\sys\winnt\sysconf ..\binary\sysconf\r
-if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt\r
-if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt\r
-copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Midl>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MkTypLibCompatible>true</MkTypLibCompatible>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <TypeLibraryName>.\Debug/NetHackW.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>TILES;MSWIN_GRAPHICS;WIN32CON_DEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/NetHackW.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/Gs /Oi-  /FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <AdditionalDependencies>comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Windows</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/NetHackW.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Install exe</Message>\r
-      <Command>if NOT exist ..\binary\*.* mkdir ..\binary\r
-copy $(OutDir)NetHackW.exe ..\binary\r
-copy ..\dat\nhdat ..\binary\r
-copy ..\dat\license ..\binary\r
-copy ..\dat\symbols ..\binary\r
-if NOT exist ..\binary\sysconf copy ..\sys\winnt\sysconf ..\binary\sysconf\r
-if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt\r
-if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt\r
-copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\src\allmain.c" />\r
-    <ClCompile Include="..\src\alloc.c" />\r
-    <ClCompile Include="..\src\apply.c" />\r
-    <ClCompile Include="..\src\artifact.c" />\r
-    <ClCompile Include="..\src\attrib.c" />\r
-    <ClCompile Include="..\src\ball.c" />\r
-    <ClCompile Include="..\src\bones.c" />\r
-    <ClCompile Include="..\src\botl.c" />\r
-    <ClCompile Include="..\src\cmd.c" />\r
-    <ClCompile Include="..\src\dbridge.c" />\r
-    <ClCompile Include="..\src\decl.c" />\r
-    <ClCompile Include="..\src\detect.c" />\r
-    <ClCompile Include="..\src\dig.c" />\r
-    <ClCompile Include="..\src\display.c" />\r
-    <ClCompile Include="..\src\dlb.c" />\r
-    <ClCompile Include="..\src\do.c" />\r
-    <ClCompile Include="..\src\dog.c" />\r
-    <ClCompile Include="..\src\dogmove.c" />\r
-    <ClCompile Include="..\src\dokick.c" />\r
-    <ClCompile Include="..\src\dothrow.c" />\r
-    <ClCompile Include="..\src\do_name.c" />\r
-    <ClCompile Include="..\src\do_wear.c" />\r
-    <ClCompile Include="..\src\drawing.c" />\r
-    <ClCompile Include="..\src\dungeon.c" />\r
-    <ClCompile Include="..\src\eat.c" />\r
-    <ClCompile Include="..\src\end.c" />\r
-    <ClCompile Include="..\src\engrave.c" />\r
-    <ClCompile Include="..\src\exper.c" />\r
-    <ClCompile Include="..\src\explode.c" />\r
-    <ClCompile Include="..\src\extralev.c" />\r
-    <ClCompile Include="..\src\files.c" />\r
-    <ClCompile Include="..\src\fountain.c" />\r
-    <ClCompile Include="..\src\hack.c" />\r
-    <ClCompile Include="..\src\hacklib.c" />\r
-    <ClCompile Include="..\src\invent.c" />\r
-    <ClCompile Include="..\src\light.c" />\r
-    <ClCompile Include="..\src\lock.c" />\r
-    <ClCompile Include="..\src\mail.c" />\r
-    <ClCompile Include="..\src\makemon.c" />\r
-    <ClCompile Include="..\src\mapglyph.c" />\r
-    <ClCompile Include="..\src\mcastu.c" />\r
-    <ClCompile Include="..\src\mhitm.c" />\r
-    <ClCompile Include="..\src\mhitu.c" />\r
-    <ClCompile Include="..\src\minion.c" />\r
-    <ClCompile Include="..\src\mklev.c" />\r
-    <ClCompile Include="..\src\mkmap.c" />\r
-    <ClCompile Include="..\src\mkmaze.c" />\r
-    <ClCompile Include="..\src\mkobj.c" />\r
-    <ClCompile Include="..\src\mkroom.c" />\r
-    <ClCompile Include="..\src\mon.c" />\r
-    <ClCompile Include="..\src\mondata.c" />\r
-    <ClCompile Include="..\src\monmove.c" />\r
-    <ClCompile Include="..\src\monst.c" />\r
-    <ClCompile Include="..\src\monstr.c" />\r
-    <ClCompile Include="..\src\mplayer.c" />\r
-    <ClCompile Include="..\src\mthrowu.c" />\r
-    <ClCompile Include="..\src\muse.c" />\r
-    <ClCompile Include="..\src\music.c" />\r
-    <ClCompile Include="..\src\objects.c" />\r
-    <ClCompile Include="..\src\objnam.c" />\r
-    <ClCompile Include="..\src\options.c" />\r
-    <ClCompile Include="..\src\o_init.c" />\r
-    <ClCompile Include="..\src\pager.c" />\r
-    <ClCompile Include="..\src\pickup.c" />\r
-    <ClCompile Include="..\src\pline.c" />\r
-    <ClCompile Include="..\src\polyself.c" />\r
-    <ClCompile Include="..\src\potion.c" />\r
-    <ClCompile Include="..\src\pray.c" />\r
-    <ClCompile Include="..\src\priest.c" />\r
-    <ClCompile Include="..\src\quest.c" />\r
-    <ClCompile Include="..\src\questpgr.c" />\r
-    <ClCompile Include="..\src\read.c" />\r
-    <ClCompile Include="..\src\rect.c" />\r
-    <ClCompile Include="..\src\region.c" />\r
-    <ClCompile Include="..\src\restore.c" />\r
-    <ClCompile Include="..\src\rip.c" />\r
-    <ClCompile Include="..\src\rnd.c" />\r
-    <ClCompile Include="..\src\role.c" />\r
-    <ClCompile Include="..\src\rumors.c" />\r
-    <ClCompile Include="..\src\save.c" />\r
-    <ClCompile Include="..\src\shk.c" />\r
-    <ClCompile Include="..\src\shknam.c" />\r
-    <ClCompile Include="..\src\sit.c" />\r
-    <ClCompile Include="..\src\sounds.c" />\r
-    <ClCompile Include="..\src\spell.c" />\r
-    <ClCompile Include="..\src\sp_lev.c" />\r
-    <ClCompile Include="..\src\steal.c" />\r
-    <ClCompile Include="..\src\steed.c" />\r
-    <ClCompile Include="..\src\sys.c" />\r
-    <ClCompile Include="..\src\teleport.c" />\r
-    <ClCompile Include="..\src\tile.c" />\r
-    <ClCompile Include="..\src\timeout.c" />\r
-    <ClCompile Include="..\src\topten.c" />\r
-    <ClCompile Include="..\src\track.c" />\r
-    <ClCompile Include="..\src\trap.c" />\r
-    <ClCompile Include="..\src\uhitm.c" />\r
-    <ClCompile Include="..\src\u_init.c" />\r
-    <ClCompile Include="..\src\vault.c" />\r
-    <ClCompile Include="..\src\version.c" />\r
-    <ClCompile Include="..\src\vision.c" />\r
-    <ClCompile Include="..\src\vis_tab.c" />\r
-    <ClCompile Include="..\src\weapon.c" />\r
-    <ClCompile Include="..\src\were.c" />\r
-    <ClCompile Include="..\src\wield.c" />\r
-    <ClCompile Include="..\src\windows.c" />\r
-    <ClCompile Include="..\src\wizard.c" />\r
-    <ClCompile Include="..\src\worm.c" />\r
-    <ClCompile Include="..\src\worn.c" />\r
-    <ClCompile Include="..\src\write.c" />\r
-    <ClCompile Include="..\src\zap.c" />\r
-    <ClCompile Include="..\sys\share\cppregex.cpp" />\r
-    <ClCompile Include="..\sys\share\nhlan.c" />\r
-    <ClCompile Include="..\sys\share\pcmain.c" />\r
-    <ClCompile Include="..\sys\share\pcsys.c" />\r
-    <ClCompile Include="..\sys\share\pcunix.c" />\r
-    <ClCompile Include="..\sys\share\random.c" />\r
-    <ClCompile Include="..\sys\winnt\ntsound.c" />\r
-    <ClCompile Include="..\sys\winnt\stubs.c">\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">TTYSTUB; _DEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">TTYSTUB;NDEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">TTYSTUB; _DEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">TTYSTUB;NDEBUG;WIN32;_WINDOWS;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\sys\winnt\winnt.c" />\r
-    <ClCompile Include="..\win\win32\mhaskyn.c" />\r
-    <ClCompile Include="..\win\win32\mhdlg.c" />\r
-    <ClCompile Include="..\win\win32\mhfont.c" />\r
-    <ClCompile Include="..\win\win32\mhinput.c" />\r
-    <ClCompile Include="..\win\win32\mhmain.c" />\r
-    <ClCompile Include="..\win\win32\mhmap.c" />\r
-    <ClCompile Include="..\win\win32\mhmenu.c" />\r
-    <ClCompile Include="..\win\win32\mhmsgwnd.c" />\r
-    <ClCompile Include="..\win\win32\mhrip.c" />\r
-    <ClCompile Include="..\win\win32\mhsplash.c" />\r
-    <ClCompile Include="..\win\win32\mhstatus.c" />\r
-    <ClCompile Include="..\win\win32\mhtext.c" />\r
-    <ClCompile Include="..\win\win32\mswproc.c" />\r
-    <ClCompile Include="..\win\win32\winhack.c" />\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ProjectReference Include="dgncomp.vcxproj">\r
-      <Project>{8a3f81c7-2968-49a8-86bf-2669412ad7de}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-    <ProjectReference Include="dlb_main.vcxproj">\r
-      <Project>{0303a585-3f83-4bb7-af6b-1e12c8fb54ac}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-    <ProjectReference Include="levcomp.vcxproj">\r
-      <Project>{9dd9c52e-e8c9-4533-bd22-83c055c0aaba}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-    <ProjectReference Include="makedefs.vcxproj">\r
-      <Project>{ba3dd34c-04b7-40d0-b373-9329aa9e8945}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-    <ProjectReference Include="tilemap.vcxproj">\r
-      <Project>{93f10526-209e-41d7-bbea-775787876895}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-    <ProjectReference Include="tiles.vcxproj">\r
-      <Project>{55946465-fc65-47b3-bb48-742c7694c0d6}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-      <Private>false</Private>\r
-      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>\r
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>\r
-      <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>\r
-    </ProjectReference>\r
-    <ProjectReference Include="uudecode.vcxproj">\r
-      <Project>{63f9b82b-f589-4082-abe5-d4f0682050ab}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ResourceCompile Include="..\win\win32\winhack.rc" />\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2013/dgncomp.vcxproj b/win/win32/vs2013/dgncomp.vcxproj
deleted file mode 100644 (file)
index 85a3655..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{8A3F81C7-2968-49A8-86BF-2669412AD7DE}</ProjectGuid>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/dgncomp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/dgncomp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\..\util/dgncomp.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/dgncomp.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>dgncomp</Message>\r
-      <Command>echo Building dungeon
-echo chdir ..\dat
-chdir ..\dat
-echo ..\util\dgncomp.exe dungeon.pdf
-..\util\dgncomp.exe dungeon.pdf
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/dgncomp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/dgncomp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\..\util/dgncomp.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/dgncomp.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>dgncomp</Message>\r
-      <Command>echo Building dungeon
-echo chdir ..\dat
-chdir ..\dat
-echo ..\util\dgncomp.exe dungeon.pdf
-..\util\dgncomp.exe dungeon.pdf
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/dgncomp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/dgncomp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/dgncomp.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>dgncomp</Message>\r
-      <Command>echo Building dungeon
-echo chdir ..\dat
-chdir ..\dat
-echo ..\util\dgncomp.exe dungeon.pdf
-..\util\dgncomp.exe dungeon.pdf
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/dgncomp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/dgncomp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/dgncomp.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>dgncomp</Message>\r
-      <Command>echo Building dungeon
-echo chdir ..\dat
-chdir ..\dat
-echo ..\util\dgncomp.exe dungeon.pdf
-..\util\dgncomp.exe dungeon.pdf
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\src\alloc.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\util\dgn_lex.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\util\dgn_main.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\util\dgn_yacc.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\util\panic.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ClInclude Include="..\include\align.h" />\r
-    <ClInclude Include="..\include\attrib.h" />\r
-    <ClInclude Include="..\include\color.h" />\r
-    <ClInclude Include="..\include\config.h" />\r
-    <ClInclude Include="..\include\config1.h" />\r
-    <ClInclude Include="..\include\context.h" />\r
-    <ClInclude Include="..\include\coord.h" />\r
-    <ClInclude Include="..\include\decl.h" />\r
-    <ClInclude Include="..\include\dgn_comp.h" />\r
-    <ClInclude Include="..\include\dgn_file.h" />\r
-    <ClInclude Include="..\include\display.h" />\r
-    <ClInclude Include="..\include\dungeon.h" />\r
-    <ClInclude Include="..\include\engrave.h" />\r
-    <ClInclude Include="..\include\flag.h" />\r
-    <ClInclude Include="..\include\global.h" />\r
-    <ClInclude Include="..\include\mkroom.h" />\r
-    <ClInclude Include="..\include\monattk.h" />\r
-    <ClInclude Include="..\include\monst.h" />\r
-    <ClInclude Include="..\include\monsym.h" />\r
-    <ClInclude Include="..\include\nhlan.h" />\r
-    <ClInclude Include="..\include\ntconf.h" />\r
-    <ClInclude Include="..\include\obj.h" />\r
-    <ClInclude Include="..\include\objclass.h" />\r
-    <ClInclude Include="..\include\onames.h" />\r
-    <ClInclude Include="..\include\permonst.h" />\r
-    <ClInclude Include="..\include\pm.h" />\r
-    <ClInclude Include="..\include\prop.h" />\r
-    <ClInclude Include="..\include\quest.h" />\r
-    <ClInclude Include="..\include\rect.h" />\r
-    <ClInclude Include="..\include\region.h" />\r
-    <ClInclude Include="..\include\rm.h" />\r
-    <ClInclude Include="..\include\skills.h" />\r
-    <ClInclude Include="..\include\spell.h" />\r
-    <ClInclude Include="..\include\timeout.h" />\r
-    <ClInclude Include="..\include\tradstdc.h" />\r
-    <ClInclude Include="..\include\trampoli.h" />\r
-    <ClInclude Include="..\include\trap.h" />\r
-    <ClInclude Include="..\include\vision.h" />\r
-    <ClInclude Include="..\include\winprocs.h" />\r
-    <ClInclude Include="..\include\wintty.h" />\r
-    <ClInclude Include="..\include\wintype.h" />\r
-    <ClInclude Include="..\include\you.h" />\r
-    <ClInclude Include="..\include\youprop.h" />\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ProjectReference Include="dgnstuff.vcxproj">\r
-      <Project>{b9e02f2c-8851-442b-bf2a-3581802b78d4}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2013/dgnstuff.vcxproj b/win/win32/vs2013/dgnstuff.vcxproj
deleted file mode 100644 (file)
index 48d3378..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{B9E02F2C-8851-442B-BF2A-3581802B78D4}</ProjectGuid>
-    <Keyword>MakeFileProj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\dgnstuff___Win32_Debug\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\dgnstuff___Win32_Debug\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">nmake /f "dgnstuff.mak"</NMakeBuildCommandLine>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">nmake /f "dgnstuff.mak"</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">nmake /f "dgnstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">nmake /f "dgnstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\util\dgncomp.exe</NMakeOutput>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\util\dgncomp.exe</NMakeOutput>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">nmake /f "dgnstuff.mak"</NMakeBuildCommandLine>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">nmake /f "dgnstuff.mak"</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">nmake /f "dgnstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">nmake /f "dgnstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\util\dgncomp.exe</NMakeOutput>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\util\dgncomp.exe</NMakeOutput>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ProjectReference Include="makedefs.vcxproj">
-      <Project>{ba3dd34c-04b7-40d0-b373-9329aa9e8945}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
diff --git a/win/win32/vs2013/dlb_main.vcxproj b/win/win32/vs2013/dlb_main.vcxproj
deleted file mode 100644 (file)
index 3d52cae..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}</ProjectGuid>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/dlb_main.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;DLB;WIN32CON;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/dlb_main.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/dlb_main.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/dlb_main.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Packaging via DLB</Message>\r
-      <Command>echo chdir ..\dat\r
-chdir ..\dat\r
-chdir\r
-echo data &gt;dlb.lst\r
-echo oracles &gt;&gt;dlb.lst\r
-if exist options echo options &gt;&gt;dlb.lst\r
-if exist ttyoptions echo ttyoptions &gt;&gt;dlb.lst\r
-if exist guioptions echo guioptions &gt;&gt;dlb.lst\r
-if NOT exist porthelp copy ..\sys\winnt\porthelp porthelp\r
-if exist porthelp echo porthelp &gt;&gt;dlb.lst\r
-echo quest.dat &gt;&gt;dlb.lst\r
-echo rumors &gt;&gt;dlb.lst\r
-echo tribute &gt;&gt;dlb.lst\r
-echo help &gt;&gt;dlb.lst\r
-echo hh &gt;&gt;dlb.lst\r
-echo cmdhelp &gt;&gt;dlb.lst\r
-echo history &gt;&gt;dlb.lst\r
-echo opthelp &gt;&gt;dlb.lst\r
-echo wizhelp &gt;&gt;dlb.lst\r
-echo dungeon &gt;&gt;dlb.lst\r
-echo license &gt;&gt;dlb.lst\r
-for %%N in (*.lev) do echo %%N &gt;&gt;dlb.lst\r
-..\util\dlb_main.exe cIf dlb.lst nhdat\r
-echo chdir ..\build\r
-chdir ..\build\r
-echo if NOT exist ..\binary\*.* mkdir ..\binary\r
-if NOT exist ..\binary\*.* mkdir ..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/dlb_main.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;DLB;WIN32CON;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/dlb_main.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/dlb_main.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/dlb_main.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Packaging via DLB</Message>\r
-      <Command>echo chdir ..\dat\r
-chdir ..\dat\r
-chdir\r
-echo data &gt;dlb.lst\r
-echo oracles &gt;&gt;dlb.lst\r
-if exist options echo options &gt;&gt;dlb.lst\r
-if exist ttyoptions echo ttyoptions &gt;&gt;dlb.lst\r
-if exist guioptions echo guioptions &gt;&gt;dlb.lst\r
-if NOT exist porthelp copy ..\sys\winnt\porthelp porthelp\r
-if exist porthelp echo porthelp &gt;&gt;dlb.lst\r
-echo quest.dat &gt;&gt;dlb.lst\r
-echo rumors &gt;&gt;dlb.lst\r
-echo tribute &gt;&gt;dlb.lst\r
-echo help &gt;&gt;dlb.lst\r
-echo hh &gt;&gt;dlb.lst\r
-echo cmdhelp &gt;&gt;dlb.lst\r
-echo history &gt;&gt;dlb.lst\r
-echo opthelp &gt;&gt;dlb.lst\r
-echo wizhelp &gt;&gt;dlb.lst\r
-echo dungeon &gt;&gt;dlb.lst\r
-echo license &gt;&gt;dlb.lst\r
-for %%N in (*.lev) do echo %%N &gt;&gt;dlb.lst\r
-..\util\dlb_main.exe cIf dlb.lst nhdat\r
-echo chdir ..\build\r
-chdir ..\build\r
-echo if NOT exist ..\binary\*.* mkdir ..\binary\r
-if NOT exist ..\binary\*.* mkdir ..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/dlb_main.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;DLB;WIN32CON;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/dlb_main.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/dlb_main.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Packaging via dlb</Message>\r
-      <Command>echo chdir ..\dat\r
-chdir ..\dat\r
-chdir\r
-echo data &gt;dlb.lst\r
-echo oracles &gt;&gt;dlb.lst\r
-if exist options echo options &gt;&gt;dlb.lst\r
-if exist ttyoptions echo ttyoptions &gt;&gt;dlb.lst\r
-if exist guioptions echo guioptions &gt;&gt;dlb.lst\r
-if NOT exist porthelp copy ..\sys\winnt\porthelp porthelp\r
-if exist porthelp echo porthelp &gt;&gt;dlb.lst\r
-echo quest.dat &gt;&gt;dlb.lst\r
-echo rumors &gt;&gt;dlb.lst\r
-echo tribute &gt;&gt;dlb.lst\r
-echo help &gt;&gt;dlb.lst\r
-echo hh &gt;&gt;dlb.lst\r
-echo cmdhelp &gt;&gt;dlb.lst\r
-echo history &gt;&gt;dlb.lst\r
-echo opthelp &gt;&gt;dlb.lst\r
-echo wizhelp &gt;&gt;dlb.lst\r
-echo dungeon &gt;&gt;dlb.lst\r
-echo license &gt;&gt;dlb.lst\r
-for %%N in (*.lev) do echo %%N &gt;&gt;dlb.lst\r
-..\util\dlb_main.exe cIf dlb.lst nhdat\r
-echo chdir ..\build\r
-chdir ..\build\r
-echo if NOT exist ..\binary\*.* mkdir ..\binary\r
-if NOT exist ..\binary\*.* mkdir ..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/dlb_main.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;DLB;WIN32CON;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/dlb_main.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/dlb_main.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Packaging via dlb</Message>\r
-      <Command>echo chdir ..\dat\r
-chdir ..\dat\r
-chdir\r
-echo data &gt;dlb.lst\r
-echo oracles &gt;&gt;dlb.lst\r
-if exist options echo options &gt;&gt;dlb.lst\r
-if exist ttyoptions echo ttyoptions &gt;&gt;dlb.lst\r
-if exist guioptions echo guioptions &gt;&gt;dlb.lst\r
-if NOT exist porthelp copy ..\sys\winnt\porthelp porthelp\r
-if exist porthelp echo porthelp &gt;&gt;dlb.lst\r
-echo quest.dat &gt;&gt;dlb.lst\r
-echo rumors &gt;&gt;dlb.lst\r
-echo tribute &gt;&gt;dlb.lst\r
-echo help &gt;&gt;dlb.lst\r
-echo hh &gt;&gt;dlb.lst\r
-echo cmdhelp &gt;&gt;dlb.lst\r
-echo history &gt;&gt;dlb.lst\r
-echo opthelp &gt;&gt;dlb.lst\r
-echo wizhelp &gt;&gt;dlb.lst\r
-echo dungeon &gt;&gt;dlb.lst\r
-echo license &gt;&gt;dlb.lst\r
-for %%N in (*.lev) do echo %%N &gt;&gt;dlb.lst\r
-..\util\dlb_main.exe cIf dlb.lst nhdat\r
-echo chdir ..\build\r
-chdir ..\build\r
-echo if NOT exist ..\binary\*.* mkdir ..\binary\r
-if NOT exist ..\binary\*.* mkdir ..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\src\alloc.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\src\dlb.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\util\dlb_main.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\util\panic.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ClInclude Include="..\include\dlb.h" />\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ProjectReference Include="dgncomp.vcxproj">\r
-      <Project>{8a3f81c7-2968-49a8-86bf-2669412ad7de}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-    <ProjectReference Include="levcomp.vcxproj">\r
-      <Project>{9dd9c52e-e8c9-4533-bd22-83c055c0aaba}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-    <ProjectReference Include="makedefs.vcxproj">\r
-      <Project>{ba3dd34c-04b7-40d0-b373-9329aa9e8945}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2013/levcomp.vcxproj b/win/win32/vs2013/levcomp.vcxproj
deleted file mode 100644 (file)
index 4ea5417..0000000
+++ /dev/null
@@ -1,581 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{9DD9C52E-E8C9-4533-BD22-83C055C0AABA}</ProjectGuid>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/levcomp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/levcomp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\..\util/levcomp.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/levcomp.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>levcomp</Message>\r
-      <Command>echo Building special levels
-echo chdir ..\dat
-chdir ..\dat
-echo arch.des
-..\util\levcomp.exe arch.des
-echo barb.des
-..\util\levcomp.exe barb.des
-echo bigroom.des
-..\util\levcomp.exe bigroom.des
-echo castle.des
-..\util\levcomp.exe castle.des
-echo caveman.des
-..\util\levcomp.exe caveman.des
-echo endgame.des
-..\util\levcomp.exe endgame.des
-echo gehennom.des
-..\util\levcomp.exe gehennom.des
-echo healer.des
-..\util\levcomp.exe healer.des
-echo knight.des
-..\util\levcomp.exe knight.des
-echo knox.des
-..\util\levcomp.exe knox.des
-echo medusa.des
-..\util\levcomp.exe medusa.des
-echo mines.des
-..\util\levcomp.exe mines.des
-echo monk.des
-..\util\levcomp.exe monk.des
-echo oracle.des
-..\util\levcomp.exe oracle.des
-echo priest.des
-..\util\levcomp.exe priest.des
-echo ranger.des
-..\util\levcomp.exe ranger.des
-echo rogue.des
-..\util\levcomp.exe rogue.des
-echo samurai.des
-..\util\levcomp.exe samurai.des
-echo sokoban.des
-..\util\levcomp.exe sokoban.des
-echo tourist.des
-..\util\levcomp.exe tourist.des
-echo tower.des
-..\util\levcomp.exe tower.des
-echo valkyrie.des
-..\util\levcomp.exe valkyrie.des
-echo wizard .des
-..\util\levcomp.exe wizard.des
-echo yendor.des
-..\util\levcomp.exe yendor.des
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/levcomp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/levcomp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\..\util/levcomp.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/levcomp.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>levcomp</Message>\r
-      <Command>echo Building special levels
-echo chdir ..\dat
-chdir ..\dat
-echo arch.des
-..\util\levcomp.exe arch.des
-echo barb.des
-..\util\levcomp.exe barb.des
-echo bigroom.des
-..\util\levcomp.exe bigroom.des
-echo castle.des
-..\util\levcomp.exe castle.des
-echo caveman.des
-..\util\levcomp.exe caveman.des
-echo endgame.des
-..\util\levcomp.exe endgame.des
-echo gehennom.des
-..\util\levcomp.exe gehennom.des
-echo healer.des
-..\util\levcomp.exe healer.des
-echo knight.des
-..\util\levcomp.exe knight.des
-echo knox.des
-..\util\levcomp.exe knox.des
-echo medusa.des
-..\util\levcomp.exe medusa.des
-echo mines.des
-..\util\levcomp.exe mines.des
-echo monk.des
-..\util\levcomp.exe monk.des
-echo oracle.des
-..\util\levcomp.exe oracle.des
-echo priest.des
-..\util\levcomp.exe priest.des
-echo ranger.des
-..\util\levcomp.exe ranger.des
-echo rogue.des
-..\util\levcomp.exe rogue.des
-echo samurai.des
-..\util\levcomp.exe samurai.des
-echo sokoban.des
-..\util\levcomp.exe sokoban.des
-echo tourist.des
-..\util\levcomp.exe tourist.des
-echo tower.des
-..\util\levcomp.exe tower.des
-echo valkyrie.des
-..\util\levcomp.exe valkyrie.des
-echo wizard .des
-..\util\levcomp.exe wizard.des
-echo yendor.des
-..\util\levcomp.exe yendor.des
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/levcomp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/levcomp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/levcomp.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>levcomp</Message>\r
-      <Command>echo Building special levels
-echo chdir ..\dat
-chdir ..\dat
-echo arch.des
-..\util\levcomp.exe arch.des
-echo barb.des
-..\util\levcomp.exe barb.des
-echo bigroom.des
-..\util\levcomp.exe bigroom.des
-echo castle.des
-..\util\levcomp.exe castle.des
-echo caveman.des
-..\util\levcomp.exe caveman.des
-echo endgame.des
-..\util\levcomp.exe endgame.des
-echo gehennom.des
-..\util\levcomp.exe gehennom.des
-echo healer.des
-..\util\levcomp.exe healer.des
-echo knight.des
-..\util\levcomp.exe knight.des
-echo knox.des
-..\util\levcomp.exe knox.des
-echo medusa.des
-..\util\levcomp.exe medusa.des
-echo mines.des
-..\util\levcomp.exe mines.des
-echo monk.des
-..\util\levcomp.exe monk.des
-echo oracle.des
-..\util\levcomp.exe oracle.des
-echo priest.des
-..\util\levcomp.exe priest.des
-echo ranger.des
-..\util\levcomp.exe ranger.des
-echo rogue.des
-..\util\levcomp.exe rogue.des
-echo samurai.des
-..\util\levcomp.exe samurai.des
-echo sokoban.des
-..\util\levcomp.exe sokoban.des
-echo tourist.des
-..\util\levcomp.exe tourist.des
-echo tower.des
-..\util\levcomp.exe tower.des
-echo valkyrie.des
-..\util\levcomp.exe valkyrie.des
-echo wizard .des
-..\util\levcomp.exe wizard.des
-echo yendor.des
-..\util\levcomp.exe yendor.des
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/levcomp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/levcomp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/levcomp.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>levcomp</Message>\r
-      <Command>echo Building special levels
-echo chdir ..\dat
-chdir ..\dat
-echo arch.des
-..\util\levcomp.exe arch.des
-echo barb.des
-..\util\levcomp.exe barb.des
-echo bigroom.des
-..\util\levcomp.exe bigroom.des
-echo castle.des
-..\util\levcomp.exe castle.des
-echo caveman.des
-..\util\levcomp.exe caveman.des
-echo endgame.des
-..\util\levcomp.exe endgame.des
-echo gehennom.des
-..\util\levcomp.exe gehennom.des
-echo healer.des
-..\util\levcomp.exe healer.des
-echo knight.des
-..\util\levcomp.exe knight.des
-echo knox.des
-..\util\levcomp.exe knox.des
-echo medusa.des
-..\util\levcomp.exe medusa.des
-echo mines.des
-..\util\levcomp.exe mines.des
-echo monk.des
-..\util\levcomp.exe monk.des
-echo oracle.des
-..\util\levcomp.exe oracle.des
-echo priest.des
-..\util\levcomp.exe priest.des
-echo ranger.des
-..\util\levcomp.exe ranger.des
-echo rogue.des
-..\util\levcomp.exe rogue.des
-echo samurai.des
-..\util\levcomp.exe samurai.des
-echo sokoban.des
-..\util\levcomp.exe sokoban.des
-echo tourist.des
-..\util\levcomp.exe tourist.des
-echo tower.des
-..\util\levcomp.exe tower.des
-echo valkyrie.des
-..\util\levcomp.exe valkyrie.des
-echo wizard .des
-..\util\levcomp.exe wizard.des
-echo yendor.des
-..\util\levcomp.exe yendor.des
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\src\alloc.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\src\decl.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\src\drawing.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\util\lev_lex.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\util\lev_main.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\util\lev_yacc.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\src\monst.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\src\objects.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\util\panic.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ClInclude Include="..\include\lev_comp.h" />\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ProjectReference Include="levstuff.vcxproj">\r
-      <Project>{ff144dfb-83a5-4d26-a598-715a2b354782}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>
diff --git a/win/win32/vs2013/levstuff.vcxproj b/win/win32/vs2013/levstuff.vcxproj
deleted file mode 100644 (file)
index f7bb276..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{FF144DFB-83A5-4D26-A598-715A2B354782}</ProjectGuid>
-    <Keyword>MakeFileProj</Keyword>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Makefile</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\Release\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">nmake /f "levstuff.mak"</NMakeBuildCommandLine>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">nmake /f "levstuff.mak"</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">nmake /f "levstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'">nmake /f "levstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\util\lev_lex.c</NMakeOutput>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\util\lev_lex.c</NMakeOutput>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\levstuff___Win32_Debug0\</OutDir>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\levstuff___Win32_Debug0\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\levstuff___Win32_Debug0\</IntDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\levstuff___Win32_Debug0\</IntDir>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">nmake /f "levstuff.mak"</NMakeBuildCommandLine>
-    <NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">nmake /f "levstuff.mak"</NMakeBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">nmake /f "levstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">nmake /f "levstuff.mak" /a</NMakeReBuildCommandLine>
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
-    <NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\util\lev_lex.c</NMakeOutput>
-    <NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\util\lev_lex.c</NMakeOutput>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeForcedIncludes)</NMakeForcedIncludes>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-    <NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies>
-  </PropertyGroup>
-  <ItemDefinitionGroup>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ProjectReference Include="makedefs.vcxproj">
-      <Project>{ba3dd34c-04b7-40d0-b373-9329aa9e8945}</Project>
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
-    </ProjectReference>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
diff --git a/win/win32/vs2013/makedefs.vcxproj b/win/win32/vs2013/makedefs.vcxproj
deleted file mode 100644 (file)
index b977ec5..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{BA3DD34C-04B7-40D0-B373-9329AA9E8945}</ProjectGuid>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/makedefs.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>.;..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/makedefs.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\..\util/makedefs.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/makedefs.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Running makedefs</Message>\r
-      <Command>echo chdir ..\util
-chdir ..\util
-chdir
-echo makedefs.exe -v
-makedefs.exe -v
-echo makedefs.exe -o
-makedefs.exe  -o
-echo makedefs.exe -p
-makedefs.exe -p
-echo makedefs.exe -m
-makedefs.exe -m
-echo makedefs.exe -z
-makedefs.exe -z
-echo chdir ..\dat
-chdir ..\dat
-chdir
-echo Generating NetHack database
-echo ..\util\makedefs.exe -d
-..\util\makedefs.exe -d
-echo Generating rumors
-echo ..\util\makedefs.exe -r
-..\util\makedefs.exe -r
-echo Generating quests
-echo ..\util\makedefs.exe -q
-..\util\makedefs.exe -q
-echo Generating oracles
-echo ..\util\makedefs.exe -h
-..\util\makedefs.exe -h
-echo Generating dungeon.pdf
-echo ..\util\makedefs.exe -e
-..\util\makedefs.exe -e
-echo chdir ..\build
-chdir ..\build
-copy ..\win\share\tilemap.c ..\win\share\tiletxt.c
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/makedefs.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>.;..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/makedefs.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\..\util/makedefs.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/makedefs.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Running makedefs</Message>\r
-      <Command>echo chdir ..\util
-chdir ..\util
-chdir
-echo makedefs.exe -v
-makedefs.exe -v
-echo makedefs.exe -o
-makedefs.exe  -o
-echo makedefs.exe -p
-makedefs.exe -p
-echo makedefs.exe -m
-makedefs.exe -m
-echo makedefs.exe -z
-makedefs.exe -z
-echo chdir ..\dat
-chdir ..\dat
-chdir
-echo Generating NetHack database
-echo ..\util\makedefs.exe -d
-..\util\makedefs.exe -d
-echo Generating rumors
-echo ..\util\makedefs.exe -r
-..\util\makedefs.exe -r
-echo Generating quests
-echo ..\util\makedefs.exe -q
-..\util\makedefs.exe -q
-echo Generating oracles
-echo ..\util\makedefs.exe -h
-..\util\makedefs.exe -h
-echo Generating dungeon.pdf
-echo ..\util\makedefs.exe -e
-..\util\makedefs.exe -e
-echo chdir ..\build
-chdir ..\build
-copy ..\win\share\tilemap.c ..\win\share\tiletxt.c
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/makedefs.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>.;..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/makedefs.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/makedefs.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Running makedefs</Message>\r
-      <Command>echo chdir ..\util
-chdir ..\util
-chdir
-echo makedefs.exe -v
-makedefs.exe -v
-echo makedefs.exe -o
-makedefs.exe  -o
-echo makedefs.exe -p
-makedefs.exe -p
-echo makedefs.exe -m
-makedefs.exe -m
-echo makedefs.exe -z
-makedefs.exe -z
-echo chdir ..\dat
-chdir ..\dat
-chdir
-echo Generating NetHack database
-echo ..\util\makedefs.exe -d
-..\util\makedefs.exe -d
-echo Generating rumors
-echo ..\util\makedefs.exe -r
-..\util\makedefs.exe -r
-echo Generating quests
-echo ..\util\makedefs.exe -q
-..\util\makedefs.exe -q
-echo Generating oracles
-echo ..\util\makedefs.exe -h
-..\util\makedefs.exe -h
-echo Generating dungeon.pdf
-echo ..\util\makedefs.exe -e
-..\util\makedefs.exe -e
-echo chdir ..\build
-chdir ..\build
-copy ..\win\share\tilemap.c ..\win\share\tiletxt.c
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\..\util/makedefs.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>.;..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/makedefs.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\..\util/makedefs.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Running makedefs</Message>\r
-      <Command>echo chdir ..\util
-chdir ..\util
-chdir
-echo makedefs.exe -v
-makedefs.exe -v
-echo makedefs.exe -o
-makedefs.exe  -o
-echo makedefs.exe -p
-makedefs.exe -p
-echo makedefs.exe -m
-makedefs.exe -m
-echo makedefs.exe -z
-makedefs.exe -z
-echo chdir ..\dat
-chdir ..\dat
-chdir
-echo Generating NetHack database
-echo ..\util\makedefs.exe -d
-..\util\makedefs.exe -d
-echo Generating rumors
-echo ..\util\makedefs.exe -r
-..\util\makedefs.exe -r
-echo Generating quests
-echo ..\util\makedefs.exe -q
-..\util\makedefs.exe -q
-echo Generating oracles
-echo ..\util\makedefs.exe -h
-..\util\makedefs.exe -h
-echo Generating dungeon.pdf
-echo ..\util\makedefs.exe -e
-..\util\makedefs.exe -e
-echo chdir ..\build
-chdir ..\build
-copy ..\win\share\tilemap.c ..\win\share\tiletxt.c
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\util\makedefs.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\src\monst.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\src\objects.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ClInclude Include="..\include\config.h" />\r
-    <ClInclude Include="..\include\config1.h" />\r
-    <ClInclude Include="..\include\context.h" />\r
-    <ClInclude Include="..\include\coord.h" />\r
-    <ClInclude Include="..\include\global.h" />\r
-    <ClInclude Include="..\include\monattk.h" />\r
-    <ClInclude Include="..\include\monflag.h" />\r
-    <ClInclude Include="..\include\monsym.h" />\r
-    <ClInclude Include="..\include\nhlan.h" />\r
-    <ClInclude Include="..\include\ntconf.h" />\r
-    <ClInclude Include="..\include\objclass.h" />\r
-    <ClInclude Include="..\include\patchlevel.h" />\r
-    <ClInclude Include="..\include\qtext.h" />\r
-    <ClInclude Include="..\include\tradstdc.h" />\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2013/nhdefkey.vcxproj b/win/win32/vs2013/nhdefkey.vcxproj
deleted file mode 100644 (file)
index 9d5d016..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{6813477F-64B6-4B97-B230-438D0D233385}</ProjectGuid>\r
-    <Keyword>Win32Proj</Keyword>\r
-    <RootNamespace>nhdefkey</RootNamespace>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>DynamicLibrary</ConfigurationType>\r
-    <UseDebugLibraries>true</UseDebugLibraries>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-    <CharacterSet>NotSet</CharacterSet>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>DynamicLibrary</ConfigurationType>\r
-    <UseDebugLibraries>true</UseDebugLibraries>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-    <CharacterSet>NotSet</CharacterSet>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>DynamicLibrary</ConfigurationType>\r
-    <UseDebugLibraries>false</UseDebugLibraries>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-    <WholeProgramOptimization>true</WholeProgramOptimization>\r
-    <CharacterSet>NotSet</CharacterSet>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>DynamicLibrary</ConfigurationType>\r
-    <UseDebugLibraries>false</UseDebugLibraries>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-    <WholeProgramOptimization>true</WholeProgramOptimization>\r
-    <CharacterSet>NotSet</CharacterSet>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-  </ImportGroup>\r
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <LinkIncremental>true</LinkIncremental>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <LinkIncremental>true</LinkIncremental>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <LinkIncremental>false</LinkIncremental>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <LinkIncremental>false</LinkIncremental>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <ClCompile>\r
-      <PrecompiledHeader>\r
-      </PrecompiledHeader>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <Optimization>Disabled</Optimization>\r
-      <PreprocessorDefinitions>WIN32;WIN32CON;_DEBUG;_WINDOWS;_USRDLL;NHDEFKEY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-    </ClCompile>\r
-    <Link>\r
-      <SubSystem>Windows</SubSystem>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ModuleDefinitionFile>$(ProjectDir)..\build\nhdefkey.def</ModuleDefinitionFile>\r
-      <MapExports>true</MapExports>\r
-      <GenerateMapFile>true</GenerateMapFile>\r
-    </Link>\r
-    <PostBuildEvent>\r
-      <Command>copy $(TargetPath) ..\binary &amp; if exist $(TargetDir)$(TargetName).PDB copy $(TargetDir)$(TargetName).PDB ..\binary</Command>\r
-    </PostBuildEvent>\r
-    <PreLinkEvent>\r
-      <Command>\r
-      </Command>\r
-    </PreLinkEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <ClCompile>\r
-      <PrecompiledHeader>\r
-      </PrecompiledHeader>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <Optimization>Disabled</Optimization>\r
-      <PreprocessorDefinitions>WIN32;WIN32CON;_DEBUG;_WINDOWS;_USRDLL;NHDEFKEY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-    </ClCompile>\r
-    <Link>\r
-      <SubSystem>Windows</SubSystem>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ModuleDefinitionFile>$(ProjectDir)..\build\nhdefkey64.def</ModuleDefinitionFile>\r
-    </Link>\r
-    <PostBuildEvent>\r
-      <Command>copy $(TargetPath) ..\binary &amp; if exist $(TargetDir)$(TargetName).PDB copy $(TargetDir)$(TargetName).PDB ..\binary</Command>\r
-    </PostBuildEvent>\r
-    <PreLinkEvent>\r
-      <Command>\r
-      </Command>\r
-    </PreLinkEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <ClCompile>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <PrecompiledHeader>\r
-      </PrecompiledHeader>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <IntrinsicFunctions>true</IntrinsicFunctions>\r
-      <PreprocessorDefinitions>WIN32;WIN32CON;NDEBUG;_WINDOWS;_USRDLL;NHDEFKEY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-    </ClCompile>\r
-    <Link>\r
-      <SubSystem>Windows</SubSystem>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
-      <OptimizeReferences>true</OptimizeReferences>\r
-      <ModuleDefinitionFile>$(ProjectDir)..\build\nhdefkey.def</ModuleDefinitionFile>\r
-      <MapExports>true</MapExports>\r
-      <GenerateMapFile>true</GenerateMapFile>\r
-    </Link>\r
-    <PostBuildEvent>\r
-      <Command>copy $(TargetPath) ..\binary &amp; if exist $(TargetDir)$(TargetName).PDB copy $(TargetDir)$(TargetName).PDB ..\binary</Command>\r
-    </PostBuildEvent>\r
-    <PreLinkEvent>\r
-      <Command>\r
-      </Command>\r
-    </PreLinkEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <ClCompile>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <PrecompiledHeader>\r
-      </PrecompiledHeader>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <IntrinsicFunctions>true</IntrinsicFunctions>\r
-      <PreprocessorDefinitions>WIN32;WIN32CON;NDEBUG;_WINDOWS;_USRDLL;NHDEFKEY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-    </ClCompile>\r
-    <Link>\r
-      <SubSystem>Windows</SubSystem>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>\r
-      <OptimizeReferences>true</OptimizeReferences>\r
-      <ModuleDefinitionFile>$(ProjectDir)..\build\nhdefkey64.def</ModuleDefinitionFile>\r
-    </Link>\r
-    <PostBuildEvent>\r
-      <Command>copy $(TargetPath) ..\binary &amp; if exist $(TargetDir)$(TargetName).PDB copy $(TargetDir)$(TargetName).PDB ..\binary</Command>\r
-    </PostBuildEvent>\r
-    <PreLinkEvent>\r
-      <Command>\r
-      </Command>\r
-    </PreLinkEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\sys\winnt\nhdefkey.c" />\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ClInclude Include="..\include\hack.h" />\r
-    <ClInclude Include="..\include\ntconf.h" />\r
-    <ClInclude Include="..\include\wintty.h" />\r
-    <ClInclude Include="..\sys\winnt\win32api.h" />\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2013/recover.vcxproj b/win/win32/vs2013/recover.vcxproj
deleted file mode 100644 (file)
index 6320fea..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}</ProjectGuid>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/recover.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/recover.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/recover.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>install exe</Message>\r
-      <Command>copy $(OutDir)recover.exe ..\binary
-if exist ..\doc\recover.txt copy ..\doc\recover.txt ..\binary\recover.txt
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/recover.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/recover.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/recover.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>install exe</Message>\r
-      <Command>copy $(OutDir)recover.exe ..\binary
-if exist ..\doc\recover.txt copy ..\doc\recover.txt ..\binary\recover.txt
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/recover.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/recover.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/recover.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/recover.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Command>copy $(OutDir)recover.exe ..\binary
-if exist ..\doc\recover.txt copy ..\doc\recover.txt ..\binary\recover.txt
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/recover.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/recover.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/recover.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/recover.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Command>copy $(OutDir)recover.exe ..\binary
-if exist ..\doc\recover.txt copy ..\doc\recover.txt ..\binary\recover.txt
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\util\recover.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ClInclude Include="..\include\config.h" />\r
-    <ClInclude Include="..\include\config1.h" />\r
-    <ClInclude Include="..\include\coord.h" />\r
-    <ClInclude Include="..\include\global.h" />\r
-    <ClInclude Include="..\include\nhlan.h" />\r
-    <ClInclude Include="..\include\ntconf.h" />\r
-    <ClInclude Include="..\include\tradstdc.h" />\r
-    <ClInclude Include="..\sys\winnt\win32api.h" />\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ProjectReference Include="dlb_main.vcxproj">\r
-      <Project>{0303a585-3f83-4bb7-af6b-1e12c8fb54ac}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-    <ProjectReference Include="makedefs.vcxproj">\r
-      <Project>{ba3dd34c-04b7-40d0-b373-9329aa9e8945}</Project>\r
-      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\r
-    </ProjectReference>\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2013/tile2bmp.vcxproj b/win/win32/vs2013/tile2bmp.vcxproj
deleted file mode 100644 (file)
index 710d7be..0000000
+++ /dev/null
@@ -1,324 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{642BC75D-ABAF-403E-8224-7C725FD4CB42}</ProjectGuid>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/tile2bmp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/tile2bmp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/tile2bmp.bsc</OutputFile>\r
-    </Bscmake>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/tile2bmp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/tile2bmp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/tile2bmp.bsc</OutputFile>\r
-    </Bscmake>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/tile2bmp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/tile2bmp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/tile2bmp.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/tile2bmp.bsc</OutputFile>\r
-    </Bscmake>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/tile2bmp.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/tile2bmp.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/tile2bmp.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/tile2bmp.bsc</OutputFile>\r
-    </Bscmake>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\src\decl.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\src\drawing.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\src\monst.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\src\objects.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\win\share\tile2bmp.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">PACKED_FILE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">PACKED_FILE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\win\share\tiletext.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-    <ClCompile Include="..\win\share\tiletxt.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">TILETEXT;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">TILETEXT;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">TILETEXT;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">TILETEXT;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2013/tilemap.vcxproj b/win/win32/vs2013/tilemap.vcxproj
deleted file mode 100644 (file)
index f381613..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{93F10526-209E-41D7-BBEA-775787876895}</ProjectGuid>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/tilemap.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt\include;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/tilemap.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/tilemap.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Generating src\tile.c</Message>\r
-      <Command>echo chdir ..\src
-chdir ..\src
-..\util\tilemap.exe
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/tilemap.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt\include;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/tilemap.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/tilemap.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Generating src\tile.c</Message>\r
-      <Command>echo chdir ..\src
-chdir ..\src
-..\util\tilemap.exe
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/tilemap.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt\include;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/tilemap.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/tilemap.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/tilemap.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Generating src\tile.c</Message>\r
-      <Command>echo chdir ..\src
-chdir ..\src
-..\util\tilemap.exe
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/tilemap.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <AdditionalIncludeDirectories>..\include;..\sys\winnt\include;..\win\share;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/tilemap.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x1009</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/tilemap.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/tilemap.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Message>Generating src\tile.c</Message>\r
-      <Command>echo chdir ..\src
-chdir ..\src
-..\util\tilemap.exe
-echo chdir ..\build
-chdir ..\build
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\win\share\tilemap.c">\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-  </ItemGroup>\r
-  <ItemGroup>\r
-    <ClInclude Include="..\include\align.h" />\r
-    <ClInclude Include="..\include\attrib.h" />\r
-    <ClInclude Include="..\include\color.h" />\r
-    <ClInclude Include="..\include\config.h" />\r
-    <ClInclude Include="..\include\config1.h" />\r
-    <ClInclude Include="..\include\context.h" />\r
-    <ClInclude Include="..\include\coord.h" />\r
-    <ClInclude Include="..\include\decl.h" />\r
-    <ClInclude Include="..\include\dgn_comp.h" />\r
-    <ClInclude Include="..\include\dgn_file.h" />\r
-    <ClInclude Include="..\include\display.h" />\r
-    <ClInclude Include="..\include\dungeon.h" />\r
-    <ClInclude Include="..\include\engrave.h" />\r
-    <ClInclude Include="..\include\flag.h" />\r
-    <ClInclude Include="..\include\global.h" />\r
-    <ClInclude Include="..\include\mkroom.h" />\r
-    <ClInclude Include="..\include\monattk.h" />\r
-    <ClInclude Include="..\include\monst.h" />\r
-    <ClInclude Include="..\include\monsym.h" />\r
-    <ClInclude Include="..\include\nhlan.h" />\r
-    <ClInclude Include="..\include\ntconf.h" />\r
-    <ClInclude Include="..\include\obj.h" />\r
-    <ClInclude Include="..\include\objclass.h" />\r
-    <ClInclude Include="..\include\onames.h" />\r
-    <ClInclude Include="..\include\permonst.h" />\r
-    <ClInclude Include="..\include\pm.h" />\r
-    <ClInclude Include="..\include\prop.h" />\r
-    <ClInclude Include="..\include\quest.h" />\r
-    <ClInclude Include="..\include\rect.h" />\r
-    <ClInclude Include="..\include\region.h" />\r
-    <ClInclude Include="..\include\rm.h" />\r
-    <ClInclude Include="..\include\skills.h" />\r
-    <ClInclude Include="..\include\spell.h" />\r
-    <ClInclude Include="..\include\timeout.h" />\r
-    <ClInclude Include="..\include\tradstdc.h" />\r
-    <ClInclude Include="..\include\trampoli.h" />\r
-    <ClInclude Include="..\include\trap.h" />\r
-    <ClInclude Include="..\include\vision.h" />\r
-    <ClInclude Include="..\include\winprocs.h" />\r
-    <ClInclude Include="..\include\wintty.h" />\r
-    <ClInclude Include="..\include\wintype.h" />\r
-    <ClInclude Include="..\include\you.h" />\r
-    <ClInclude Include="..\include\youprop.h" />\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>
\ No newline at end of file
diff --git a/win/win32/vs2013/uudecode.vcxproj b/win/win32/vs2013/uudecode.vcxproj
deleted file mode 100644 (file)
index 4139753..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
-  <ItemGroup Label="ProjectConfigurations">\r
-    <ProjectConfiguration Include="Debug|Win32">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Debug|x64">\r
-      <Configuration>Debug</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|Win32">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>Win32</Platform>\r
-    </ProjectConfiguration>\r
-    <ProjectConfiguration Include="Release|x64">\r
-      <Configuration>Release</Configuration>\r
-      <Platform>x64</Platform>\r
-    </ProjectConfiguration>\r
-  </ItemGroup>\r
-  <PropertyGroup Label="Globals">\r
-    <ProjectGuid>{63F9B82B-F589-4082-ABE5-D4F0682050AB}</ProjectGuid>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
-    <ConfigurationType>Application</ConfigurationType>\r
-    <UseOfMfc>false</UseOfMfc>\r
-    <CharacterSet>MultiByte</CharacterSet>\r
-    <PlatformToolset>v120</PlatformToolset>\r
-  </PropertyGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
-  <ImportGroup Label="ExtensionSettings">\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">\r
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
-    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
-  </ImportGroup>\r
-  <PropertyGroup Label="UserMacros" />\r
-  <PropertyGroup>\r
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\..\util\</OutDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\$(ConfigurationName)\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\$(ProjectName)\</IntDir>\r
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\Debug\$(ProjectName)\</IntDir>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\..\util\</OutDir>\r
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\..\util\</OutDir>\r
-  </PropertyGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/uudecode.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/uudecode.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/uudecode.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/uudecode.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Command>echo chdir ..\win\win32\r
-chdir ..\win\win32\r
-echo decoding icon (nhico.uu to NetHack.ico)\r
-..\..\util\uudecode.exe ../../sys/winnt/nhico.uu\r
-echo decoding mnsel (mnsel.uu to mnsel.bmp)\r
-..\..\util\uudecode.exe mnsel.uu\r
-echo decoding mnselcnt (mnselcnt.uu to mnselcnt.bmp)\r
-..\..\util\uudecode.exe mnselcnt.uu\r
-echo decoding mnunsel (mnunsel.uu to mnunsel.bmp)\r
-..\..\util\uudecode.exe mnunsel.uu\r
-echo decoding petmark (petmark.uu to petmark.bmp)\r
-..\..\util\uudecode.exe petmark.uu\r
-echo decoding pilemark (pilemark.uu to pilemark.bmp)\r
-..\..\util\uudecode.exe pilemark.uu\r
-echo decoding splash (splash.uu to splash.bmp)\r
-..\..\util\uudecode.exe splash.uu\r
-echo decoding tombstone (rip.uu to rip.bmp)\r
-..\..\util\uudecode.exe rip.uu\r
-chdir ..\..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Release/uudecode.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>MaxSpeed</Optimization>\r
-      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <StringPooling>true</StringPooling>\r
-      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
-      <FunctionLevelLinking>true</FunctionLevelLinking>\r
-      <PrecompiledHeaderOutputFile>.\Release/uudecode.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <ProgramDatabaseFile>.\Release/uudecode.pdb</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Release/uudecode.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Command>echo chdir ..\win\win32\r
-chdir ..\win\win32\r
-echo decoding icon (nhico.uu to NetHack.ico)\r
-..\..\util\uudecode.exe ../../sys/winnt/nhico.uu\r
-echo decoding mnsel (mnsel.uu to mnsel.bmp)\r
-..\..\util\uudecode.exe mnsel.uu\r
-echo decoding mnselcnt (mnselcnt.uu to mnselcnt.bmp)\r
-..\..\util\uudecode.exe mnselcnt.uu\r
-echo decoding mnunsel (mnunsel.uu to mnunsel.bmp)\r
-..\..\util\uudecode.exe mnunsel.uu\r
-echo decoding petmark (petmark.uu to petmark.bmp)\r
-..\..\util\uudecode.exe petmark.uu\r
-echo decoding pilemark (pilemark.uu to pilemark.bmp)\r
-..\..\util\uudecode.exe pilemark.uu\r
-echo decoding splash (splash.uu to splash.bmp)\r
-..\..\util\uudecode.exe splash.uu\r
-echo decoding tombstone (rip.uu to rip.bmp)\r
-..\..\util\uudecode.exe rip.uu\r
-chdir ..\..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/uudecode.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/uudecode.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <TargetMachine>MachineX86</TargetMachine>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/uudecode.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Command>echo chdir ..\win\win32\r
-chdir ..\win\win32\r
-echo decoding icon (nhico.uu to NetHack.ico)\r
-..\..\util\uudecode.exe ../../sys/winnt/nhico.uu\r
-echo decoding mnsel (mnsel.uu to mnsel.bmp)\r
-..\..\util\uudecode.exe mnsel.uu\r
-echo decoding mnselcnt (mnselcnt.uu to mnselcnt.bmp)\r
-..\..\util\uudecode.exe mnselcnt.uu\r
-echo decoding mnunsel (mnunsel.uu to mnunsel.bmp)\r
-..\..\util\uudecode.exe mnunsel.uu\r
-echo decoding petmark (petmark.uu to petmark.bmp)\r
-..\..\util\uudecode.exe petmark.uu\r
-echo decoding pilemark (pilemark.uu to pilemark.bmp)\r
-..\..\util\uudecode.exe pilemark.uu\r
-echo decoding splash (splash.uu to splash.bmp)\r
-..\..\util\uudecode.exe splash.uu\r
-echo decoding tombstone (rip.uu to rip.bmp)\r
-..\..\util\uudecode.exe rip.uu\r
-chdir ..\..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
-    <Midl>\r
-      <TypeLibraryName>.\Debug/uudecode.tlb</TypeLibraryName>\r
-      <HeaderFileName>\r
-      </HeaderFileName>\r
-    </Midl>\r
-    <ClCompile>\r
-      <Optimization>Disabled</Optimization>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
-      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
-      <PrecompiledHeaderOutputFile>.\Debug/uudecode.pch</PrecompiledHeaderOutputFile>\r
-      <AssemblerListingLocation>.\$(ConfigurationName)\$(ProjectName)\</AssemblerListingLocation>\r
-      <ObjectFileName>.\$(ConfigurationName)\$(ProjectName)\</ObjectFileName>\r
-      <ProgramDataBaseFileName>.\$(ConfigurationName)\$(ProjectName)\</ProgramDataBaseFileName>\r
-      <WarningLevel>Level3</WarningLevel>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
-      <MultiProcessorCompilation>false</MultiProcessorCompilation>\r
-      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\r
-    </ClCompile>\r
-    <ResourceCompile>\r
-      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <Culture>0x0409</Culture>\r
-    </ResourceCompile>\r
-    <Link>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <GenerateDebugInformation>true</GenerateDebugInformation>\r
-      <ProgramDatabaseFile>.\$(ConfigurationName)\$(ProjectName)\</ProgramDatabaseFile>\r
-      <SubSystem>Console</SubSystem>\r
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>\r
-      <DataExecutionPrevention>\r
-      </DataExecutionPrevention>\r
-      <AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>\r
-    </Link>\r
-    <Bscmake>\r
-      <SuppressStartupBanner>true</SuppressStartupBanner>\r
-      <OutputFile>.\Debug/uudecode.bsc</OutputFile>\r
-    </Bscmake>\r
-    <PostBuildEvent>\r
-      <Command>echo chdir ..\win\win32\r
-chdir ..\win\win32\r
-echo decoding icon (nhico.uu to NetHack.ico)\r
-..\..\util\uudecode.exe ../../sys/winnt/nhico.uu\r
-echo decoding mnsel (mnsel.uu to mnsel.bmp)\r
-..\..\util\uudecode.exe mnsel.uu\r
-echo decoding mnselcnt (mnselcnt.uu to mnselcnt.bmp)\r
-..\..\util\uudecode.exe mnselcnt.uu\r
-echo decoding mnunsel (mnunsel.uu to mnunsel.bmp)\r
-..\..\util\uudecode.exe mnunsel.uu\r
-echo decoding petmark (petmark.uu to petmark.bmp)\r
-..\..\util\uudecode.exe petmark.uu\r
-echo decoding pilemark (pilemark.uu to pilemark.bmp)\r
-..\..\util\uudecode.exe pilemark.uu\r
-echo decoding splash (splash.uu to splash.bmp)\r
-..\..\util\uudecode.exe splash.uu\r
-echo decoding tombstone (rip.uu to rip.bmp)\r
-..\..\util\uudecode.exe rip.uu\r
-chdir ..\..\binary\r
-</Command>\r
-    </PostBuildEvent>\r
-  </ItemDefinitionGroup>\r
-  <ItemGroup>\r
-    <ClCompile Include="..\sys\share\uudecode.c">\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
-    </ClCompile>\r
-  </ItemGroup>\r
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
-  <ImportGroup Label="ExtensionTargets">\r
-  </ImportGroup>\r
-</Project>\r
diff --git a/win/win32/vs2015/NetHack.vcxproj b/win/win32/vs2015/NetHack.vcxproj
new file mode 100644 (file)
index 0000000..3c0ce99
--- /dev/null
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}</ProjectGuid>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <RootNamespace>NetHack</RootNamespace>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>\r
+      <AdditionalOptions>/Gs /Oi- %(AdditionalOptions)</AdditionalOptions>
+      <Optimization>Disabled</Optimization>\r
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\r
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <AdditionalIncludeDirectories>$(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>TILES;WIN32CON;DLB;MSWIN_GRAPHICS;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>\r
+    <Link>\r
+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winmm.lib;Winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+    </Link>\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="$(SrcDir)allmain.c" />
+    <ClCompile Include="$(SrcDir)alloc.c" />
+    <ClCompile Include="$(SrcDir)apply.c" />
+    <ClCompile Include="$(SrcDir)artifact.c" />
+    <ClCompile Include="$(SrcDir)attrib.c" />
+    <ClCompile Include="$(SrcDir)ball.c" />
+    <ClCompile Include="$(SrcDir)bones.c" />
+    <ClCompile Include="$(SrcDir)botl.c" />
+    <ClCompile Include="$(SrcDir)cmd.c" />
+    <ClCompile Include="$(SrcDir)dbridge.c" />
+    <ClCompile Include="$(SrcDir)decl.c" />
+    <ClCompile Include="$(SrcDir)detect.c" />
+    <ClCompile Include="$(SrcDir)dig.c" />
+    <ClCompile Include="$(SrcDir)display.c" />
+    <ClCompile Include="$(SrcDir)dlb.c" />
+    <ClCompile Include="$(SrcDir)do.c" />
+    <ClCompile Include="$(SrcDir)dog.c" />
+    <ClCompile Include="$(SrcDir)dogmove.c" />
+    <ClCompile Include="$(SrcDir)dokick.c" />
+    <ClCompile Include="$(SrcDir)dothrow.c" />
+    <ClCompile Include="$(SrcDir)do_name.c" />
+    <ClCompile Include="$(SrcDir)do_wear.c" />
+    <ClCompile Include="$(SrcDir)drawing.c" />
+    <ClCompile Include="$(SrcDir)dungeon.c" />
+    <ClCompile Include="$(SrcDir)eat.c" />
+    <ClCompile Include="$(SrcDir)end.c" />
+    <ClCompile Include="$(SrcDir)engrave.c" />
+    <ClCompile Include="$(SrcDir)exper.c" />
+    <ClCompile Include="$(SrcDir)explode.c" />
+    <ClCompile Include="$(SrcDir)extralev.c" />
+    <ClCompile Include="$(SrcDir)files.c" />
+    <ClCompile Include="$(SrcDir)fountain.c" />
+    <ClCompile Include="$(SrcDir)hack.c" />
+    <ClCompile Include="$(SrcDir)hacklib.c" />
+    <ClCompile Include="$(SrcDir)invent.c" />
+    <ClCompile Include="$(SrcDir)light.c" />
+    <ClCompile Include="$(SrcDir)lock.c" />
+    <ClCompile Include="$(SrcDir)mail.c" />
+    <ClCompile Include="$(SrcDir)makemon.c" />
+    <ClCompile Include="$(SrcDir)mapglyph.c" />
+    <ClCompile Include="$(SrcDir)mcastu.c" />
+    <ClCompile Include="$(SrcDir)mhitm.c" />
+    <ClCompile Include="$(SrcDir)mhitu.c" />
+    <ClCompile Include="$(SrcDir)minion.c" />
+    <ClCompile Include="$(SrcDir)mklev.c" />
+    <ClCompile Include="$(SrcDir)mkmap.c" />
+    <ClCompile Include="$(SrcDir)mkmaze.c" />
+    <ClCompile Include="$(SrcDir)mkobj.c" />
+    <ClCompile Include="$(SrcDir)mkroom.c" />
+    <ClCompile Include="$(SrcDir)mon.c" />
+    <ClCompile Include="$(SrcDir)mondata.c" />
+    <ClCompile Include="$(SrcDir)monmove.c" />
+    <ClCompile Include="$(SrcDir)monst.c" />
+    <ClCompile Include="$(SrcDir)monstr.c" />
+    <ClCompile Include="$(SrcDir)mplayer.c" />
+    <ClCompile Include="$(SrcDir)mthrowu.c" />
+    <ClCompile Include="$(SrcDir)muse.c" />
+    <ClCompile Include="$(SrcDir)music.c" />
+    <ClCompile Include="$(SrcDir)objects.c" />
+    <ClCompile Include="$(SrcDir)objnam.c" />
+    <ClCompile Include="$(SrcDir)options.c" />
+    <ClCompile Include="$(SrcDir)o_init.c" />
+    <ClCompile Include="$(SrcDir)pager.c" />
+    <ClCompile Include="$(SrcDir)pickup.c" />
+    <ClCompile Include="$(SrcDir)pline.c" />
+    <ClCompile Include="$(SrcDir)polyself.c" />
+    <ClCompile Include="$(SrcDir)potion.c" />
+    <ClCompile Include="$(SrcDir)pray.c" />
+    <ClCompile Include="$(SrcDir)priest.c" />
+    <ClCompile Include="$(SrcDir)quest.c" />
+    <ClCompile Include="$(SrcDir)questpgr.c" />
+    <ClCompile Include="$(SrcDir)read.c" />
+    <ClCompile Include="$(SrcDir)rect.c" />
+    <ClCompile Include="$(SrcDir)region.c" />
+    <ClCompile Include="$(SrcDir)restore.c" />
+    <ClCompile Include="$(SrcDir)rip.c" />
+    <ClCompile Include="$(SrcDir)rnd.c" />
+    <ClCompile Include="$(SrcDir)role.c" />
+    <ClCompile Include="$(SrcDir)rumors.c" />
+    <ClCompile Include="$(SrcDir)save.c" />
+    <ClCompile Include="$(SrcDir)shk.c" />
+    <ClCompile Include="$(SrcDir)shknam.c" />
+    <ClCompile Include="$(SrcDir)sit.c" />
+    <ClCompile Include="$(SrcDir)sounds.c" />
+    <ClCompile Include="$(SrcDir)spell.c" />
+    <ClCompile Include="$(SrcDir)sp_lev.c" />
+    <ClCompile Include="$(SrcDir)steal.c" />
+    <ClCompile Include="$(SrcDir)steed.c" />
+    <ClCompile Include="$(SrcDir)sys.c" />
+    <ClCompile Include="$(SrcDir)teleport.c" />
+    <ClCompile Include="$(SrcDir)tile.c" />
+    <ClCompile Include="$(SrcDir)timeout.c" />
+    <ClCompile Include="$(SrcDir)topten.c" />
+    <ClCompile Include="$(SrcDir)track.c" />
+    <ClCompile Include="$(SrcDir)trap.c" />
+    <ClCompile Include="$(SrcDir)uhitm.c" />
+    <ClCompile Include="$(SrcDir)u_init.c" />
+    <ClCompile Include="$(SrcDir)vault.c" />
+    <ClCompile Include="$(SrcDir)version.c" />
+    <ClCompile Include="$(SrcDir)vision.c" />
+    <ClCompile Include="$(SrcDir)weapon.c" />
+    <ClCompile Include="$(SrcDir)were.c" />
+    <ClCompile Include="$(SrcDir)wield.c" />
+    <ClCompile Include="$(SrcDir)windows.c" />
+    <ClCompile Include="$(SrcDir)wizard.c" />
+    <ClCompile Include="$(SrcDir)worm.c" />
+    <ClCompile Include="$(SrcDir)worn.c" />
+    <ClCompile Include="$(SrcDir)write.c" />
+    <ClCompile Include="$(SrcDir)zap.c" />
+    <ClCompile Include="$(SysShareDir)cppregex.cpp" />
+    <ClCompile Include="$(SysShareDir)nhlan.c" />
+    <ClCompile Include="$(SysShareDir)pcmain.c" />
+    <ClCompile Include="$(SysShareDir)pcsys.c" />
+    <ClCompile Include="$(SysShareDir)pcunix.c" />
+    <ClCompile Include="$(SysShareDir)random.c" />
+    <ClCompile Include="$(SysWinntDir)ntsound.c" />
+    <ClCompile Include="$(SysWinntDir)nttty.c" />
+    <ClCompile Include="$(SysWinntDir)stubs.c">
+      <PreprocessorDefinitions>GUISTUB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>\r
+    <ClCompile Include="$(SysWinntDir)winnt.c" />
+    <ClCompile Include="$(WinTtyDir)getline.c" />
+    <ClCompile Include="$(WinTtyDir)topl.c" />
+    <ClCompile Include="$(WinTtyDir)wintty.c" />
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="$(IncDir)align.h" />
+    <ClInclude Include="$(IncDir)artifact.h" />
+    <ClInclude Include="$(IncDir)artilist.h" />
+    <ClInclude Include="$(IncDir)attrib.h" />
+    <ClInclude Include="$(IncDir)botl.h" />
+    <ClInclude Include="$(IncDir)color.h" />
+    <ClInclude Include="$(IncDir)config.h" />
+    <ClInclude Include="$(IncDir)config1.h" />
+    <ClInclude Include="$(IncDir)context.h" />
+    <ClInclude Include="$(IncDir)coord.h" />
+    <ClInclude Include="$(IncDir)date.h" />
+    <ClInclude Include="$(IncDir)decl.h" />
+    <ClInclude Include="$(IncDir)display.h" />
+    <ClInclude Include="$(IncDir)dlb.h" />
+    <ClInclude Include="$(IncDir)dungeon.h" />
+    <ClInclude Include="$(IncDir)engrave.h" />
+    <ClInclude Include="$(IncDir)extern.h" />
+    <ClInclude Include="$(IncDir)flag.h" />
+    <ClInclude Include="$(IncDir)func_tab.h" />
+    <ClInclude Include="$(IncDir)global.h" />
+    <ClInclude Include="$(IncDir)hack.h" />
+    <ClInclude Include="$(IncDir)lev.h" />
+    <ClInclude Include="$(IncDir)mextra.h" />
+    <ClInclude Include="$(IncDir)mfndpos.h" />
+    <ClInclude Include="$(IncDir)mkroom.h" />
+    <ClInclude Include="$(IncDir)monattk.h" />
+    <ClInclude Include="$(IncDir)mondata.h" />
+    <ClInclude Include="$(IncDir)monflag.h" />
+    <ClInclude Include="$(IncDir)monst.h" />
+    <ClInclude Include="$(IncDir)monsym.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)obj.h" />
+    <ClInclude Include="$(IncDir)objclass.h" />
+    <ClInclude Include="$(IncDir)onames.h" />
+    <ClInclude Include="$(IncDir)patchlevel.h" />
+    <ClInclude Include="$(IncDir)permonst.h" />
+    <ClInclude Include="$(IncDir)pm.h" />
+    <ClInclude Include="$(IncDir)prop.h" />
+    <ClInclude Include="$(IncDir)qtext.h" />
+    <ClInclude Include="$(IncDir)quest.h" />
+    <ClInclude Include="$(IncDir)rect.h" />
+    <ClInclude Include="$(IncDir)region.h" />
+    <ClInclude Include="$(IncDir)rm.h" />
+    <ClInclude Include="$(IncDir)skills.h" />
+    <ClInclude Include="$(IncDir)spell.h" />
+    <ClInclude Include="$(IncDir)sp_lev.h" />
+    <ClInclude Include="$(IncDir)timeout.h" />
+    <ClInclude Include="$(IncDir)tradstdc.h" />
+    <ClInclude Include="$(IncDir)trap.h" />
+    <ClInclude Include="$(IncDir)vision.h" />
+    <ClInclude Include="$(IncDir)winprocs.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(IncDir)wintype.h" />
+    <ClInclude Include="$(IncDir)you.h" />
+    <ClInclude Include="$(IncDir)youprop.h" />
+    <ClInclude Include="$(WinWin32Dir)nhresource.h" />
+  </ItemGroup>\r
+  <ItemGroup>
+    <ResourceCompile Include="$(WinWin32Dir)NetHack.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="$(WinWin32Dir)nethack.ico" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afternethack.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/NetHackW.vcxproj b/win/win32/vs2015/NetHackW.vcxproj
new file mode 100644 (file)
index 0000000..52403bb
--- /dev/null
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="config.props" />
+
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{CEC5D360-8804-454F-8591-002184C23499}</ProjectGuid>\r
+    <RootNamespace>NetHackW</RootNamespace>\r
+  </PropertyGroup>\r
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+
+  <ItemDefinitionGroup>
+    <ClCompile>\r
+      <AdditionalOptions>/Gs /Oi- %(AdditionalOptions)</AdditionalOptions>
+      <Optimization>Disabled</Optimization>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
+      <AdditionalIncludeDirectories>$(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>TILES;_WINDOWS;DLB;MSWIN_GRAPHICS;WIN32CONNDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>\r
+    <ResourceCompile>\r
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <Culture>0x0409</Culture>\r
+    </ResourceCompile>\r
+    <Link>\r
+       <!-- TODO common.props has SubSystem Console -->
+      <SubSystem>Windows</SubSystem>\r
+      <AdditionalDependencies>comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+    </Link>\r
+  </ItemDefinitionGroup>\r
+
+
+  <ItemGroup>\r
+    <ClCompile Include="$(SrcDir)allmain.c" />
+    <ClCompile Include="$(SrcDir)alloc.c" />
+    <ClCompile Include="$(SrcDir)apply.c" />
+    <ClCompile Include="$(SrcDir)artifact.c" />
+    <ClCompile Include="$(SrcDir)attrib.c" />
+    <ClCompile Include="$(SrcDir)ball.c" />
+    <ClCompile Include="$(SrcDir)bones.c" />
+    <ClCompile Include="$(SrcDir)botl.c" />
+    <ClCompile Include="$(SrcDir)cmd.c" />
+    <ClCompile Include="$(SrcDir)dbridge.c" />
+    <ClCompile Include="$(SrcDir)decl.c" />
+    <ClCompile Include="$(SrcDir)detect.c" />
+    <ClCompile Include="$(SrcDir)dig.c" />
+    <ClCompile Include="$(SrcDir)display.c" />
+    <ClCompile Include="$(SrcDir)dlb.c" />
+    <ClCompile Include="$(SrcDir)do.c" />
+    <ClCompile Include="$(SrcDir)dog.c" />
+    <ClCompile Include="$(SrcDir)dogmove.c" />
+    <ClCompile Include="$(SrcDir)dokick.c" />
+    <ClCompile Include="$(SrcDir)dothrow.c" />
+    <ClCompile Include="$(SrcDir)do_name.c" />
+    <ClCompile Include="$(SrcDir)do_wear.c" />
+    <ClCompile Include="$(SrcDir)drawing.c" />
+    <ClCompile Include="$(SrcDir)dungeon.c" />
+    <ClCompile Include="$(SrcDir)eat.c" />
+    <ClCompile Include="$(SrcDir)end.c" />
+    <ClCompile Include="$(SrcDir)engrave.c" />
+    <ClCompile Include="$(SrcDir)exper.c" />
+    <ClCompile Include="$(SrcDir)explode.c" />
+    <ClCompile Include="$(SrcDir)extralev.c" />
+    <ClCompile Include="$(SrcDir)files.c" />
+    <ClCompile Include="$(SrcDir)fountain.c" />
+    <ClCompile Include="$(SrcDir)hack.c" />
+    <ClCompile Include="$(SrcDir)hacklib.c" />
+    <ClCompile Include="$(SrcDir)invent.c" />
+    <ClCompile Include="$(SrcDir)light.c" />
+    <ClCompile Include="$(SrcDir)lock.c" />
+    <ClCompile Include="$(SrcDir)mail.c" />
+    <ClCompile Include="$(SrcDir)makemon.c" />
+    <ClCompile Include="$(SrcDir)mapglyph.c" />
+    <ClCompile Include="$(SrcDir)mcastu.c" />
+    <ClCompile Include="$(SrcDir)mhitm.c" />
+    <ClCompile Include="$(SrcDir)mhitu.c" />
+    <ClCompile Include="$(SrcDir)minion.c" />
+    <ClCompile Include="$(SrcDir)mklev.c" />
+    <ClCompile Include="$(SrcDir)mkmap.c" />
+    <ClCompile Include="$(SrcDir)mkmaze.c" />
+    <ClCompile Include="$(SrcDir)mkobj.c" />
+    <ClCompile Include="$(SrcDir)mkroom.c" />
+    <ClCompile Include="$(SrcDir)mon.c" />
+    <ClCompile Include="$(SrcDir)mondata.c" />
+    <ClCompile Include="$(SrcDir)monmove.c" />
+    <ClCompile Include="$(SrcDir)monst.c" />
+    <ClCompile Include="$(SrcDir)monstr.c" />
+    <ClCompile Include="$(SrcDir)mplayer.c" />
+    <ClCompile Include="$(SrcDir)mthrowu.c" />
+    <ClCompile Include="$(SrcDir)muse.c" />
+    <ClCompile Include="$(SrcDir)music.c" />
+    <ClCompile Include="$(SrcDir)objects.c" />
+    <ClCompile Include="$(SrcDir)objnam.c" />
+    <ClCompile Include="$(SrcDir)options.c" />
+    <ClCompile Include="$(SrcDir)o_init.c" />
+    <ClCompile Include="$(SrcDir)pager.c" />
+    <ClCompile Include="$(SrcDir)pickup.c" />
+    <ClCompile Include="$(SrcDir)pline.c" />
+    <ClCompile Include="$(SrcDir)polyself.c" />
+    <ClCompile Include="$(SrcDir)potion.c" />
+    <ClCompile Include="$(SrcDir)pray.c" />
+    <ClCompile Include="$(SrcDir)priest.c" />
+    <ClCompile Include="$(SrcDir)quest.c" />
+    <ClCompile Include="$(SrcDir)questpgr.c" />
+    <ClCompile Include="$(SrcDir)read.c" />
+    <ClCompile Include="$(SrcDir)rect.c" />
+    <ClCompile Include="$(SrcDir)region.c" />
+    <ClCompile Include="$(SrcDir)restore.c" />
+    <ClCompile Include="$(SrcDir)rip.c" />
+    <ClCompile Include="$(SrcDir)rnd.c" />
+    <ClCompile Include="$(SrcDir)role.c" />
+    <ClCompile Include="$(SrcDir)rumors.c" />
+    <ClCompile Include="$(SrcDir)save.c" />
+    <ClCompile Include="$(SrcDir)shk.c" />
+    <ClCompile Include="$(SrcDir)shknam.c" />
+    <ClCompile Include="$(SrcDir)sit.c" />
+    <ClCompile Include="$(SrcDir)sounds.c" />
+    <ClCompile Include="$(SrcDir)spell.c" />
+    <ClCompile Include="$(SrcDir)sp_lev.c" />
+    <ClCompile Include="$(SrcDir)steal.c" />
+    <ClCompile Include="$(SrcDir)steed.c" />
+    <ClCompile Include="$(SrcDir)sys.c" />
+    <ClCompile Include="$(SrcDir)teleport.c" />
+    <ClCompile Include="$(SrcDir)tile.c" />
+    <ClCompile Include="$(SrcDir)timeout.c" />
+    <ClCompile Include="$(SrcDir)topten.c" />
+    <ClCompile Include="$(SrcDir)track.c" />
+    <ClCompile Include="$(SrcDir)trap.c" />
+    <ClCompile Include="$(SrcDir)uhitm.c" />
+    <ClCompile Include="$(SrcDir)u_init.c" />
+    <ClCompile Include="$(SrcDir)vault.c" />
+    <ClCompile Include="$(SrcDir)version.c" />
+    <ClCompile Include="$(SrcDir)vision.c" />
+    <ClCompile Include="$(SrcDir)vis_tab.c" />
+    <ClCompile Include="$(SrcDir)weapon.c" />
+    <ClCompile Include="$(SrcDir)were.c" />
+    <ClCompile Include="$(SrcDir)wield.c" />
+    <ClCompile Include="$(SrcDir)windows.c" />
+    <ClCompile Include="$(SrcDir)wizard.c" />
+    <ClCompile Include="$(SrcDir)worm.c" />
+    <ClCompile Include="$(SrcDir)worn.c" />
+    <ClCompile Include="$(SrcDir)write.c" />
+    <ClCompile Include="$(SrcDir)zap.c" />
+    <ClCompile Include="$(SysShareDir)cppregex.cpp" />
+    <ClCompile Include="$(SysShareDir)nhlan.c" />
+    <ClCompile Include="$(SysShareDir)pcmain.c" />
+    <ClCompile Include="$(SysShareDir)pcsys.c" />
+    <ClCompile Include="$(SysShareDir)pcunix.c" />
+    <ClCompile Include="$(SysShareDir)random.c" />
+    <ClCompile Include="$(SysWinntDir)ntsound.c" />
+    <ClCompile Include="$(SysWinntDir)stubs.c">
+      <PreprocessorDefinitions>TTYSTUB;</PreprocessorDefinitions>
+    </ClCompile>\r
+    <ClCompile Include="$(SysWinntDir)winnt.c" />
+    <ClCompile Include="$(WinWin32Dir)mhaskyn.c" />
+    <ClCompile Include="$(WinWin32Dir)mhdlg.c" />
+    <ClCompile Include="$(WinWin32Dir)mhfont.c" />
+    <ClCompile Include="$(WinWin32Dir)mhinput.c" />
+    <ClCompile Include="$(WinWin32Dir)mhmain.c" />
+    <ClCompile Include="$(WinWin32Dir)mhmap.c" />
+    <ClCompile Include="$(WinWin32Dir)mhmenu.c" />
+    <ClCompile Include="$(WinWin32Dir)mhmsgwnd.c" />
+    <ClCompile Include="$(WinWin32Dir)mhrip.c" />
+    <ClCompile Include="$(WinWin32Dir)mhsplash.c" />
+    <ClCompile Include="$(WinWin32Dir)mhstatus.c" />
+    <ClCompile Include="$(WinWin32Dir)mhtext.c" />
+    <ClCompile Include="$(WinWin32Dir)mswproc.c" />
+    <ClCompile Include="$(WinWin32Dir)winhack.c" />
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ResourceCompile Include="$(WinWin32Dir)winhack.rc" />
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+ <Target Name="AfterBuild">
+    <MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afternethack.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+
+ </Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/afterdgncomp.proj b/win/win32/vs2015/afterdgncomp.proj
new file mode 100644 (file)
index 0000000..7aebee7
--- /dev/null
@@ -0,0 +1,12 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build" 
+     Inputs="$(ToolsDir)dgncomp.exe;$(DatDir)dungeon.pdf"
+        Outputs="$(DatDir)dungeon">
+       <Exec Command="$(ToolsDir)dgncomp.exe dungeon.pdf" WorkingDirectory="$(DatDir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="$(DatDir)dungeon"/>
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/afterdlb.proj b/win/win32/vs2015/afterdlb.proj
new file mode 100644 (file)
index 0000000..ed68ba3
--- /dev/null
@@ -0,0 +1,17 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build" 
+       Inputs="$(ToolsDir)dlb.exe;@(DlbList);$(SysWinntDir)porthelp"
+       Outputs="$(BinDir)nhdat">
+
+       <Copy SourceFiles="$(SysWinntDir)porthelp" DestinationFolder="$(DatDir)"/>
+       <WriteLinesToFile File="$(DatDir)dlb.lst" Lines="@(DlbList->'%(filename)%(extension)')" Overwrite="true"/>
+       <Exec Command="$(ToolsDir)dlb.exe cIf $(DatDir)dlb.lst $(BinDir)nhdat" WorkingDirectory="$(DatDir)"/>
+       <Delete Files="$(DatDir)porthelp"/>
+
+       </Target>
+  <Target Name="Clean">
+       <Delete Files="$(BinDir)nhdat"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2015/afterlevcomp.proj b/win/win32/vs2015/afterlevcomp.proj
new file mode 100644 (file)
index 0000000..924f66c
--- /dev/null
@@ -0,0 +1,12 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build" 
+     Inputs="@(Desfiles->'$(DatDir)%(filename)%(extension)');$(BinDir)levcomp.exe"
+        Outputs="@(Levfiles->'$(DatDir)%(filename)%(extension)')">
+       <Exec Command="$(ToolsDir)levcomp.exe @(Desfiles, ' ')" WorkingDirectory="$(DatDir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="@(Levfiles->'$(DatDir)%(filename)%(extension)')"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2015/aftermakedefs.proj b/win/win32/vs2015/aftermakedefs.proj
new file mode 100644 (file)
index 0000000..20adf1b
--- /dev/null
@@ -0,0 +1,22 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build" 
+     Inputs="$(ToolsDir)makedefs.exe"
+        Outputs="@(Defs)">
+       <Exec Command="$(ToolsDir)makedefs.exe -v" WorkingDirectory="$(UtilDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -o" WorkingDirectory="$(UtilDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -p" WorkingDirectory="$(UtilDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -m" WorkingDirectory="$(UtilDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -z" WorkingDirectory="$(UtilDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -d" WorkingDirectory="$(DatDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -r" WorkingDirectory="$(DatDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -s" WorkingDirectory="$(DatDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -q" WorkingDirectory="$(DatDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -h" WorkingDirectory="$(DatDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -e" WorkingDirectory="$(DatDir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="@(Defs)"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2015/afternethack.proj b/win/win32/vs2015/afternethack.proj
new file mode 100644 (file)
index 0000000..3b76932
--- /dev/null
@@ -0,0 +1,15 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <!-- TODO not copying record -->
+  <Target Name="Build" 
+       Inputs="$(SysWinntDir)defaults.nh;$(DocDir)Guidebook.txt;$(DatDir)license;$(SysWinntDir)sysconf;$(DocDir)nethack.txt;$(DatDir)symbols;$(WinWin32Dir)record;$(DatDir)opthelp"
+       Outputs="$(BinDir)defaults.nh;$(BinDir)Guidebook.txt;$(BinDir)license;$(BinDir)sysconf;$(BinDir)symbols;$(BinDir)record;$(BinDir)opthelp">
+
+       <Copy SourceFiles="$(SysWinntDir)defaults.nh;$(DocDir)Guidebook.txt;$(DatDir)license;$(SysWinntDir)sysconf;$(DocDir)nethack.txt;$(DatDir)symbols;$(WinWin32Dir)record;$(DatDir)opthelp" DestinationFolder="$(BinDir)"/>
+
+       </Target>
+  <Target Name="Clean">
+       <Delete Files="$(BinDir)defaults.nh;$(BinDir)Guidebook.txt;$(BinDir)license;$(BinDir)sysconf;$(BinDir)nethack.txt;$(BinDir)symbols;$(BinDir)record;$(BinDir)opthelp"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2015/afterrecover.proj b/win/win32/vs2015/afterrecover.proj
new file mode 100644 (file)
index 0000000..0652e78
--- /dev/null
@@ -0,0 +1,12 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build" 
+     Inputs="$(DocDir)recover.txt"
+        Outputs="$(BinDir)recover.txt">
+       <Copy SourceFiles="$(DocDir)recover.txt" DestinationFiles="$(BinDir)recover.txt"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="$(BinDir)recover.txt"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2015/aftertile2bmp.proj b/win/win32/vs2015/aftertile2bmp.proj
new file mode 100644 (file)
index 0000000..28d2b2e
--- /dev/null
@@ -0,0 +1,13 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build" 
+     Inputs="$(ToolsDir)tile2bmp.exe;$(WinShareDir)monsters.txt;$(WinShareDir)objects.txt"
+        Outputs="$(WinWin32Dir)tiles.bmp">
+       <Exec Command="$(ToolsDir)tile2bmp.exe tiles.bmp" WorkingDirectory="$(SrcDir)"/>
+       <Move SourceFiles="$(SrcDir)tiles.bmp" DestinationFolder="$(WinWin32Dir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="$(WinWin32Dir)tiles.bmp"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2015/aftertilemap.proj b/win/win32/vs2015/aftertilemap.proj
new file mode 100644 (file)
index 0000000..bfdb48f
--- /dev/null
@@ -0,0 +1,12 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build" 
+     Inputs="$(ToolsDir)tilemap.exe"
+        Outputs="$(SrcDir)tile.c">
+       <Exec Command="$(ToolsDir)tilemap.exe" WorkingDirectory="$(SrcDir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="$(SrcDir)tile.c"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2015/afteruudecode.proj b/win/win32/vs2015/afteruudecode.proj
new file mode 100644 (file)
index 0000000..b33e3c4
--- /dev/null
@@ -0,0 +1,20 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build" 
+     Inputs="$(ToolsDir)uudecode.exe;@(UUFiles)"
+        Outputs="@(IconFiles);@(BmpFiles);@(RecordFiles)">
+       <Exec Command="$(ToolsDir)uudecode.exe $(SysWinntDir)nhico.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)mnsel.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)mnselcnt.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)mnunsel.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)petmark.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)pilemark.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)splash.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)rip.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)record.uu" WorkingDirectory="$(WinWin32Dir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="@(IconFiles);@(BmpFiles);@(RecordFiles)"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2015/build.bat b/win/win32/vs2015/build.bat
new file mode 100644 (file)
index 0000000..78b7356
--- /dev/null
@@ -0,0 +1,44 @@
+@echo off
+
+if "%VisualStudioVersion%"=="" (
+       echo MSBuild environment not set ... attempting to setup build environment.
+       call :setup_environment
+)
+
+if "%VisualStudioVersion%"=="" (
+       echo Unable to setup build environment.  Exiting.
+       goto :EOF
+)
+
+msbuild NetHack.sln /t:Clean;Build /p:Configuration=Debug;Platform=Win32
+msbuild NetHack.sln /t:Clean;Build /p:Configuration=Debug;Platform=x64
+msbuild NetHack.sln /t:Clean;Build /p:Configuration=Release;Platform=Win32
+msbuild NetHack.sln /t:Clean;Build /p:Configuration=Release;Platform=x64
+
+goto :EOF
+
+:setup_environment
+
+
+if "%VS140COMNTOOLS%"=="" (
+       call :set_vs14comntools
+)
+
+if "%VS140COMNTOOLS%"=="" (
+       echo Can not find Visual Studio 2015 Common Tools path.
+       echo Set VS140COMNTOOLS appropriately.
+       goto :EOF
+)
+
+call "%VS140COMNTOOLS%VsMSBuildCmd.bat"
+cd %~dp0
+
+goto :EOF
+
+:set_vs14comntools
+
+if exist "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\Common7\Tools" (
+       set "VS140COMNTOOLS=%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\Common7\Tools\"
+)
+
+goto :EOF
diff --git a/win/win32/vs2015/common.props b/win/win32/vs2015/common.props
new file mode 100644 (file)
index 0000000..5889dbb
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PreprocessorDefinitions>WIN32;CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <ProgramDatabaseFile>$(SymbolsDir)$(TargetName).pdb</ProgramDatabaseFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+    </Link>
+  </ItemDefinitionGroup>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/config.props b/win/win32/vs2015/config.props
new file mode 100644 (file)
index 0000000..84ef04d
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/console.props b/win/win32/vs2015/console.props
new file mode 100644 (file)
index 0000000..8fdca9d
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/default.props b/win/win32/vs2015/default.props
new file mode 100644 (file)
index 0000000..8261906
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ConfigurationType>Application</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
+    <LocalDebuggerWorkingDirectory>$(BinDir)</LocalDebuggerWorkingDirectory>
+  </PropertyGroup> 
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" >
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" >
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/default_dll.props b/win/win32/vs2015/default_dll.props
new file mode 100644 (file)
index 0000000..94a07f4
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup> 
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" >
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" >
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/dgncomp.vcxproj b/win/win32/vs2015/dgncomp.vcxproj
new file mode 100644 (file)
index 0000000..a44735d
--- /dev/null
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="config.props" />
+
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{8A3F81C7-2968-49A8-86BF-2669412AD7DE}</ProjectGuid>\r
+  </PropertyGroup>\r
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+
+  <ItemDefinitionGroup>
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>\r
+  </ItemDefinitionGroup>\r
+
+
+  <ItemGroup>\r
+    <ClCompile Include="$(SrcDir)alloc.c" />
+    <ClCompile Include="$(SysShareDir)\dgn_lex.c" />
+    <ClCompile Include="$(UtilDir)dgn_main.c" />
+    <ClCompile Include="$(SysShareDir)dgn_yacc.c" />
+    <ClCompile Include="$(UtilDir)panic.c" />
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="$(IncDir)align.h" />
+    <ClInclude Include="$(IncDir)attrib.h" />
+    <ClInclude Include="$(IncDir)color.h" />
+    <ClInclude Include="$(IncDir)config.h" />
+    <ClInclude Include="$(IncDir)config1.h" />
+    <ClInclude Include="$(IncDir)context.h" />
+    <ClInclude Include="$(IncDir)coord.h" />
+    <ClInclude Include="$(IncDir)decl.h" />
+    <ClInclude Include="$(IncDir)dgn_comp.h" />
+    <ClInclude Include="$(IncDir)dgn_file.h" />
+    <ClInclude Include="$(IncDir)display.h" />
+    <ClInclude Include="$(IncDir)dungeon.h" />
+    <ClInclude Include="$(IncDir)engrave.h" />
+    <ClInclude Include="$(IncDir)flag.h" />
+    <ClInclude Include="$(IncDir)global.h" />
+    <ClInclude Include="$(IncDir)mkroom.h" />
+    <ClInclude Include="$(IncDir)monattk.h" />
+    <ClInclude Include="$(IncDir)monst.h" />
+    <ClInclude Include="$(IncDir)monsym.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)obj.h" />
+    <ClInclude Include="$(IncDir)objclass.h" />
+    <ClInclude Include="$(IncDir)onames.h" />
+    <ClInclude Include="$(IncDir)permonst.h" />
+    <ClInclude Include="$(IncDir)pm.h" />
+    <ClInclude Include="$(IncDir)prop.h" />
+    <ClInclude Include="$(IncDir)quest.h" />
+    <ClInclude Include="$(IncDir)rect.h" />
+    <ClInclude Include="$(IncDir)region.h" />
+    <ClInclude Include="$(IncDir)rm.h" />
+    <ClInclude Include="$(IncDir)skills.h" />
+    <ClInclude Include="$(IncDir)spell.h" />
+    <ClInclude Include="$(IncDir)timeout.h" />
+    <ClInclude Include="$(IncDir)tradstdc.h" />
+    <ClInclude Include="$(IncDir)trampoli.h" />
+    <ClInclude Include="$(IncDir)trap.h" />
+    <ClInclude Include="$(IncDir)vision.h" />
+    <ClInclude Include="$(IncDir)winprocs.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(IncDir)wintype.h" />
+    <ClInclude Include="$(IncDir)you.h" />
+    <ClInclude Include="$(IncDir)youprop.h" />
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <Choose>
+    <When Condition=" '$(YACC)'!='' "> 
+      <PropertyGroup>
+        <BuildDependsOn>
+          Lex;
+          Yacc;
+          $(BuildDependsOn);
+        </BuildDependsOn>
+      </PropertyGroup>
+       </When>
+       <Otherwise>
+      <PropertyGroup>
+        <BuildDependsOn>
+          NoLex;
+          NoYacc;
+          $(BuildDependsOn);
+        </BuildDependsOn>
+      </PropertyGroup>
+       </Otherwise>
+  </Choose>  
+  <Target Name="Yacc" Inputs="$(UtilDir)dgn_comp.y" Outputs="$(UtilDir)dgn_yacc.c;$(IncDir)dgn_comp.h">
+    <Message Text="Running Yacc" Importance="high" />
+    <Exec Command="$(YACC) -d dgn_comp.y" WorkingDirectory="$(UtilDir)" />
+       <Move SourceFiles="$(UtilDir)y.tab.c;$(UtilDir)y.tab.h" DestinationFiles="$(UtilDir)dgn_yacc.c;$(IncDir)dgn_comp.h" />  
+  </Target>
+  <Target Name="Lex" Inputs="$(UtilDir)lev_comp.l" Outputs="$(UtilDir)dgn_lex.c">
+    <Message Text="Running Lex" Importance="high" />
+    <Exec Command="$(LEX) dgn_comp.l" WorkingDirectory="$(UtilDir)" />
+       <Move SourceFiles="$(UtilDir)lex.yy.c" DestinationFiles="$(UtilDir)dgn_lex.c" />        
+  </Target>
+  <Target Name="NoYacc" Inputs="$(SysShareDir)dgn_yacc.c;$(SysShareDir)dgn_comp.h" Outputs="$(UtilDir)dgn_yacc.c;$(IncDir)dgn_comp.h">
+    <Message Text="No Yacc using pre-built files" Importance="high" />
+       <Copy SourceFiles="$(SysShareDir)dgn_yacc.c;$(SysShareDir)dgn_comp.h" DestinationFiles="$(UtilDir)dgn_yacc.c;$(IncDir)dgn_comp.h" />    
+  </Target>
+  <Target Name="NoLex" Inputs="$(SysShareDir)dgn_lex.c" Outputs="$(UtilDir)dgn_lex.c">
+    <Message Text="No Lex using pre-built files" Importance="high" />
+       <Copy SourceFiles="$(SysShareDir)dgn_lex.c" DestinationFiles="$(UtilDir)dgn_lex.c" />   
+  </Target>
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afterdgncomp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afterdgncomp.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+       <Delete Files="$(UtilDir)dgn_yacc.c;$(IncDir)dgn_comp.h;$(UtilDir)dgn_lex.c" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afterdgncomp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/dirs.props b/win/win32/vs2015/dirs.props
new file mode 100644 (file)
index 0000000..8cdcf60
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <RootDir>$(MSBuildProjectDirectory)\..\..\..\</RootDir>
+    <BinDir>$(RootDir)bin\$(Configuration)\$(Platform)\</BinDir>
+    <ObjDir>$(ProjectDir)obj\$(Configuration)\$(Platform)\$(TargetName)\</ObjDir>
+    <SymbolsDir>$(ProjectDir)symbols\$(Configuration)\$(Platform)\$(TargetName)\</SymbolsDir>
+    <ToolsDir>$(RootDir)tools\$(Configuration)\$(Platform)\</ToolsDir>
+    <UtilDir>$(RootDir)util\</UtilDir>
+    <DatDir>$(RootDir)dat\</DatDir>
+    <DocDir>$(RootDir)doc\</DocDir>
+    <IncDir>$(RootDir)include\</IncDir>
+    <SrcDir>$(RootDir)src\</SrcDir>
+       <SysDir>$(RootDir)sys\</SysDir>
+    <UtilDir>$(RootDir)util\</UtilDir>
+       <SysShareDir>$(RootDir)sys\share\</SysShareDir>
+    <SysWinntDir>$(RootDir)sys\winnt\</SysWinntDir>
+    <WinShareDir>$(RootDir)win\share\</WinShareDir>
+    <WinTtyDir>$(RootDir)win\tty\</WinTtyDir>
+    <WinWin32Dir>$(RootDir)win\win32\</WinWin32Dir>
+    <OutDir>$(ToolsDir)</OutDir>
+       <IntDir>$(ObjDir)</IntDir>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/dlb.vcxproj b/win/win32/vs2015/dlb.vcxproj
new file mode 100644 (file)
index 0000000..06424d4
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}</ProjectGuid>
+  </PropertyGroup>
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SrcDir)alloc.c" />
+    <ClCompile Include="$(SrcDir)dlb.c" />
+    <ClCompile Include="$(UtilDir)dlb_main.c" />
+    <ClCompile Include="$(UtilDir)panic.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)dlb.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afterdlb.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afterdlb.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afterdlb.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/dll.props b/win/win32/vs2015/dll.props
new file mode 100644 (file)
index 0000000..3b37e2e
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32CON;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/files.props b/win/win32/vs2015/files.props
new file mode 100644 (file)
index 0000000..d905edb
--- /dev/null
@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <!-- -v -->
+    <Defs Include = "$(DatDir)options"/>
+    <Defs Include = "$(IncDir)date.h"/>
+       <!-- -o -->
+    <Defs Include = "$(IncDir)onames.h"/>
+       <!-- -p -->
+    <Defs Include = "$(IncDir)pm.h"/>
+       <!-- -m -->
+    <Defs Include = "$(SrcDir)monstr.c"/>
+       <!-- -z -->
+    <Defs Include = "$(IncDir)vis_tab.h"/>
+    <Defs Include = "$(SrcDir)vis_tab.c"/>
+       <!-- -d -->
+    <Defs Include = "$(DatDir)data"/>
+       <!-- -r -->
+    <Defs Include = "$(DatDir)rumors"/>
+       <!-- -s -->
+    <Defs Include = "$(DatDir)engrave"/>
+    <Defs Include = "$(DatDir)epitaph"/>
+    <Defs Include = "$(DatDir)bogusmon"/>
+       <!-- -q -->
+    <Defs Include = "$(DatDir)quest.dat"/>
+       <!-- -h -->
+    <Defs Include = "$(DatDir)oracles"/>
+       <!-- -e -->
+    <Defs Include = "$(DatDir)dungeon.pdf"/>
+  </ItemGroup>
+  <ItemGroup>
+    <Desfiles Include = "arch.des"/>
+    <Desfiles Include = "barb.des"/>
+    <Desfiles Include = "bigroom.des"/>
+    <Desfiles Include = "castle.des"/>
+    <Desfiles Include = "caveman.des"/>
+    <Desfiles Include = "endgame.des"/>
+    <Desfiles Include = "gehennom.des"/>
+    <Desfiles Include = "healer.des"/>
+    <Desfiles Include = "knight.des"/>
+    <Desfiles Include = "knox.des"/>
+    <Desfiles Include = "medusa.des"/>
+    <Desfiles Include = "mines.des"/>
+    <Desfiles Include = "monk.des"/>
+    <Desfiles Include = "oracle.des"/>
+    <Desfiles Include = "priest.des"/>
+    <Desfiles Include = "ranger.des"/>
+    <Desfiles Include = "rogue.des"/>
+    <Desfiles Include = "samurai.des"/>
+    <Desfiles Include = "sokoban.des"/>
+    <Desfiles Include = "tourist.des"/>
+    <Desfiles Include = "tower.des"/>
+    <Desfiles Include = "valkyrie.des"/>
+    <Desfiles Include = "wizard.des"/> 
+    <Desfiles Include = "yendor.des"/>
+  </ItemGroup>
+  <ItemGroup>
+    <Levfiles Include = "bigrm-1.lev"/>
+    <Levfiles Include = "bigrm-2.lev"/>
+    <Levfiles Include = "bigrm-3.lev"/>
+    <Levfiles Include = "bigrm-4.lev"/>
+    <Levfiles Include = "bigrm-5.lev"/>
+    <Levfiles Include = "bigrm-6.lev"/>
+    <Levfiles Include = "bigrm-7.lev"/>
+    <Levfiles Include = "bigrm-8.lev"/>
+    <Levfiles Include = "bigrm-9.lev"/>
+    <Levfiles Include = "bigrm-10.lev"/>
+    <Levfiles Include = "castle.lev"/>
+    <Levfiles Include = "air.lev"/>
+    <Levfiles Include = "astral.lev"/>
+    <Levfiles Include = "earth.lev"/>
+    <Levfiles Include = "fire.lev"/>
+    <Levfiles Include = "water.lev"/>
+    <Levfiles Include = "asmodeus.lev"/>
+    <Levfiles Include = "baalz.lev"/>
+    <Levfiles Include = "juiblex.lev"/>
+    <Levfiles Include = "orcus.lev"/>
+    <Levfiles Include = "sanctum.lev"/>
+    <Levfiles Include = "valley.lev"/>
+    <Levfiles Include = "knox.lev"/>
+    <Levfiles Include = "minefill.lev"/>
+    <Levfiles Include = "minend-1.lev"/>
+    <Levfiles Include = "minend-2.lev"/>
+    <Levfiles Include = "minend-3.lev"/>
+    <Levfiles Include = "minetn-1.lev"/>
+    <Levfiles Include = "minetn-2.lev"/>
+    <Levfiles Include = "minetn-3.lev"/>
+    <Levfiles Include = "minetn-4.lev"/>
+    <Levfiles Include = "minetn-5.lev"/>
+    <Levfiles Include = "minetn-6.lev"/>
+    <Levfiles Include = "minetn-7.lev"/>
+    <Levfiles Include = "medusa-1.lev"/>
+    <Levfiles Include = "medusa-2.lev"/>
+    <Levfiles Include = "medusa-3.lev"/>
+    <Levfiles Include = "medusa-4.lev"/>
+    <Levfiles Include = "oracle.lev"/>
+    <Levfiles Include = "soko1-1.lev"/>
+    <Levfiles Include = "soko1-2.lev"/>
+    <Levfiles Include = "soko2-1.lev"/>
+    <Levfiles Include = "soko2-2.lev"/>
+    <Levfiles Include = "soko3-1.lev"/>
+    <Levfiles Include = "soko3-2.lev"/>
+    <Levfiles Include = "soko4-1.lev"/>
+    <Levfiles Include = "soko4-2.lev"/>
+    <Levfiles Include = "tower1.lev"/>
+    <Levfiles Include = "tower2.lev"/>
+    <Levfiles Include = "tower3.lev"/>
+    <Levfiles Include = "fakewiz1.lev"/>
+    <Levfiles Include = "fakewiz2.lev"/>
+    <Levfiles Include = "wizard1.lev"/>
+    <Levfiles Include = "wizard2.lev"/>
+    <Levfiles Include = "wizard3.lev"/>
+    <Levfiles Include = "arc-fila.lev"/>
+    <Levfiles Include = "arc-filb.lev"/>
+    <Levfiles Include = "arc-goal.lev"/>
+    <Levfiles Include = "arc-loca.lev"/>
+    <Levfiles Include = "arc-strt.lev"/>
+    <Levfiles Include = "bar-fila.lev"/>
+    <Levfiles Include = "bar-filb.lev"/>
+    <Levfiles Include = "bar-goal.lev"/>
+    <Levfiles Include = "bar-loca.lev"/>
+    <Levfiles Include = "bar-strt.lev"/>
+    <Levfiles Include = "cav-fila.lev"/>
+    <Levfiles Include = "cav-filb.lev"/>
+    <Levfiles Include = "cav-goal.lev"/>
+    <Levfiles Include = "cav-loca.lev"/>
+    <Levfiles Include = "cav-strt.lev"/>
+    <Levfiles Include = "hea-fila.lev"/>
+    <Levfiles Include = "hea-filb.lev"/>
+    <Levfiles Include = "hea-goal.lev"/>
+    <Levfiles Include = "hea-loca.lev"/>
+    <Levfiles Include = "hea-strt.lev"/>
+    <Levfiles Include = "kni-fila.lev"/>
+    <Levfiles Include = "kni-filb.lev"/>
+    <Levfiles Include = "kni-goal.lev"/>
+    <Levfiles Include = "kni-loca.lev"/>
+    <Levfiles Include = "kni-strt.lev"/>
+    <Levfiles Include = "mon-fila.lev"/>
+    <Levfiles Include = "mon-filb.lev"/>
+    <Levfiles Include = "mon-goal.lev"/>
+    <Levfiles Include = "mon-loca.lev"/>
+    <Levfiles Include = "mon-strt.lev"/>
+    <Levfiles Include = "pri-fila.lev"/>
+    <Levfiles Include = "pri-filb.lev"/>
+    <Levfiles Include = "pri-goal.lev"/>
+    <Levfiles Include = "pri-loca.lev"/>
+    <Levfiles Include = "pri-strt.lev"/>
+    <Levfiles Include = "ran-fila.lev"/>
+    <Levfiles Include = "ran-filb.lev"/>
+    <Levfiles Include = "ran-goal.lev"/>
+    <Levfiles Include = "ran-loca.lev"/>
+    <Levfiles Include = "ran-strt.lev"/>
+    <Levfiles Include = "rog-fila.lev"/>
+    <Levfiles Include = "rog-filb.lev"/>
+    <Levfiles Include = "rog-goal.lev"/>
+    <Levfiles Include = "rog-loca.lev"/>
+    <Levfiles Include = "rog-strt.lev"/>
+    <Levfiles Include = "sam-fila.lev"/>
+    <Levfiles Include = "sam-filb.lev"/>
+    <Levfiles Include = "sam-goal.lev"/>
+    <Levfiles Include = "sam-loca.lev"/>
+    <Levfiles Include = "sam-strt.lev"/>
+    <Levfiles Include = "tou-fila.lev"/>
+    <Levfiles Include = "tou-filb.lev"/>
+    <Levfiles Include = "tou-goal.lev"/>
+    <Levfiles Include = "tou-loca.lev"/>
+    <Levfiles Include = "tou-strt.lev"/>
+    <Levfiles Include = "val-fila.lev"/>
+    <Levfiles Include = "val-filb.lev"/>
+    <Levfiles Include = "val-goal.lev"/>
+    <Levfiles Include = "val-loca.lev"/>
+    <Levfiles Include = "val-strt.lev"/>
+    <Levfiles Include = "wiz-fila.lev"/>
+    <Levfiles Include = "wiz-filb.lev"/>
+    <Levfiles Include = "wiz-goal.lev"/>
+    <Levfiles Include = "wiz-loca.lev"/>
+    <Levfiles Include = "wiz-strt.lev"/>
+  </ItemGroup>
+  <ItemGroup>
+    <UUFiles Include = "$(SysWinntDir)nhico.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)mnsel.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)mnselcnt.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)mnunsel.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)petmark.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)pilemark.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)splash.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)rip.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)record.uu"/>
+  </ItemGroup>
+  <ItemGroup>
+    <IconFiles Include = "$(WinWin32Dir)nethack.ico"/>
+  </ItemGroup>
+  <ItemGroup>
+    <RecordFiles Include = "$(WinWin32Dir)record"/>
+  </ItemGroup>
+  <ItemGroup>
+    <BmpFiles Include = "$(WinWin32Dir)mnsel.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)mnselcnt.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)mnunsel.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)petmark.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)pilemark.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)rip.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)splash.bmp"/>
+  </ItemGroup>
+  <ItemGroup>
+    <DlbList Include = "$(DatDir)data"/>
+    <DlbList Include = "$(DatDir)oracles"/>
+    <DlbList Include = "$(DatDir)options" Condition="Exists('$(DatDir)options')"/>
+    <DlbList Include = "$(DatDir)ttyoptions" Condition="Exists('$(DatDir)ttyoptions')"/>
+    <DlbList Include = "$(DatDir)guioptions" Condition="Exists('$(DatDir)guioptions')"/>
+    <DlbList Include = "$(DatDir)quest.dat"/>
+    <DlbList Include = "$(DatDir)rumors"/>
+    <DlbList Include = "$(DatDir)engrave"/>
+    <DlbList Include = "$(DatDir)epitaph"/>
+    <DlbList Include = "$(DatDir)bogusmon"/>
+    <DlbList Include = "$(DatDir)tribute"/>
+    <DlbList Include = "$(DatDir)help"/>
+    <DlbList Include = "$(DatDir)porthelp"/>
+    <DlbList Include = "$(DatDir)hh"/>
+    <DlbList Include = "$(DatDir)cmdhelp"/>
+    <DlbList Include = "$(DatDir)history"/>
+    <DlbList Include = "$(DatDir)opthelp"/>
+    <DlbList Include = "$(DatDir)wizhelp"/>
+    <DlbList Include = "$(DatDir)dungeon"/>
+    <DlbList Include = "$(DatDir)license"/>
+    <DlbList Include = "$(DatDir)*.lev"/>
+  </ItemGroup>
+ </Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/levcomp.vcxproj b/win/win32/vs2015/levcomp.vcxproj
new file mode 100644 (file)
index 0000000..1d01ffa
--- /dev/null
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="config.props" />
+
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{9DD9C52E-E8C9-4533-BD22-83C055C0AABA}</ProjectGuid>\r
+  </PropertyGroup>\r
+  
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <ItemDefinitionGroup>
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>\r
+  </ItemDefinitionGroup>\r
+
+  <ItemGroup>\r
+    <ClCompile Include="$(SrcDir)alloc.c" />
+    <ClCompile Include="$(SrcDir)decl.c" />
+    <ClCompile Include="$(SrcDir)drawing.c" />
+    <ClCompile Include="$(UtilDir)lev_lex.c" />
+    <ClCompile Include="$(UtilDir)lev_main.c" />
+    <ClCompile Include="$(UtilDir)lev_yacc.c" />
+    <ClCompile Include="$(SrcDir)monst.c" />
+    <ClCompile Include="$(SrcDir)objects.c" />
+    <ClCompile Include="$(UtilDir)panic.c" />  
+  </ItemGroup>\r
+  
+  <ItemGroup>\r
+    <ClInclude Include="$(IncDir)lev_comp.h" />
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <Choose>
+    <When Condition=" '$(YACC)'!='' "> 
+      <PropertyGroup>
+        <BuildDependsOn>
+          Lex;
+          Yacc;
+          $(BuildDependsOn);
+        </BuildDependsOn>
+      </PropertyGroup>
+       </When>
+       <Otherwise>
+      <PropertyGroup>
+        <BuildDependsOn>
+          NoLex;
+          NoYacc;
+          $(BuildDependsOn);
+        </BuildDependsOn>
+      </PropertyGroup>
+       </Otherwise>
+  </Choose>
+  <Target Name="Yacc" Inputs="$(UtilDir)lev_comp.y" Outputs="$(UtilDir)lev_yacc.c;$(IncDir)lev_comp.h">
+    <Message Text="Running Yacc" Importance="high" />
+    <Exec Command="$(YACC) -d lev_comp.y" WorkingDirectory="$(UtilDir)" />
+       <Move SourceFiles="$(UtilDir)y.tab.c;$(UtilDir)y.tab.h" DestinationFiles="$(UtilDir)lev_yacc.c;$(IncDir)lev_comp.h" />  
+  </Target>
+  <Target Name="Lex" Inputs="$(UtilDir)lev_comp.l" Outputs="$(UtilDir)lev_lex.c">
+    <Message Text="Running Lex" Importance="high" />
+    <Exec Command="$(LEX) lev_comp.l" WorkingDirectory="$(UtilDir)" />
+       <Move SourceFiles="$(UtilDir)lex.yy.c" DestinationFiles="$(UtilDir)lev_lex.c" />        
+  </Target>
+  <Target Name="NoYacc" Inputs="$(SysShareDir)lev_yacc.c;$(SysShareDir)lev_comp.h" Outputs="$(UtilDir)lev_yacc.c;$(IncDir)lev_comp.h">
+    <Message Text="No Yacc using pre-built files" Importance="high" />
+       <Copy SourceFiles="$(SysShareDir)lev_yacc.c;$(SysShareDir)lev_comp.h" DestinationFiles="$(UtilDir)lev_yacc.c;$(IncDir)lev_comp.h" />    
+  </Target>
+  <Target Name="NoLex" Inputs="$(SysShareDir)lev_lex.c" Outputs="$(UtilDir)lev_lex.c">
+    <Message Text="No Lex using pre-built files" Importance="high" />
+       <Copy SourceFiles="$(SysShareDir)lev_lex.c" DestinationFiles="$(UtilDir)lev_lex.c" />   
+  </Target>
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afterlevcomp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afterlevcomp.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+       <Delete Files="$(UtilDir)lev_yacc.c;$(IncDir)lev_comp.h;$(UtilDir)lev_lex.c" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afterlevcomp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/makedefs.vcxproj b/win/win32/vs2015/makedefs.vcxproj
new file mode 100644 (file)
index 0000000..cedd412
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">       
+  <Import Project="config.props" />
+
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{BA3DD34C-04B7-40D0-B373-9329AA9E8945}</ProjectGuid>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+
+
+  <ItemDefinitionGroup>
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>\r
+  </ItemDefinitionGroup>\r
+  
+
+  <ItemGroup>\r
+    <ClCompile Include="..\..\..\util\makedefs.c" />
+    <ClCompile Include="..\..\..\src\monst.c" />
+    <ClCompile Include="..\..\..\src\objects.c" />
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="..\..\..\include\config.h" />
+    <ClInclude Include="..\..\..\include\config1.h" />
+    <ClInclude Include="..\..\..\include\context.h" />
+    <ClInclude Include="..\..\..\include\coord.h" />
+    <ClInclude Include="..\..\..\include\global.h" />
+    <ClInclude Include="..\..\..\include\monattk.h" />
+    <ClInclude Include="..\..\..\include\monflag.h" />
+    <ClInclude Include="..\..\..\include\monsym.h" />
+    <ClInclude Include="..\..\..\include\ntconf.h" />
+    <ClInclude Include="..\..\..\include\objclass.h" />
+    <ClInclude Include="..\..\..\include\patchlevel.h" />
+    <ClInclude Include="..\..\..\include\qtext.h" />
+    <ClInclude Include="..\..\..\include\tradstdc.h" />
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <Target Name="AfterBuild">
+    <MSBuild Projects="aftermakedefs.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="aftermakedefs.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="aftermakedefs.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/nh340key.def b/win/win32/vs2015/nh340key.def
new file mode 100644 (file)
index 0000000..f484a53
--- /dev/null
@@ -0,0 +1,8 @@
+LIBRARY nh340key
+EXPORTS
+ProcessKeystroke
+NHkbhit
+CheckInput
+SourceWhere
+SourceAuthor
+KeyHandlerName
diff --git a/win/win32/vs2015/nh340key.vcxproj b/win/win32/vs2015/nh340key.vcxproj
new file mode 100644 (file)
index 0000000..8b20686
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{be04e242-a1e9-4593-b95b-057f37330b76}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>nh340key</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default_dll.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="dll.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <ImportLibrary>$(ToolsDir)$(TargetName).lib</ImportLibrary>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+    <Link>
+      <ModuleDefinitionFile>nh340key.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SysWinntDir)nh340key.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)hack.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(SysWinntDir)win32api.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/nhdefkey.def b/win/win32/vs2015/nhdefkey.def
new file mode 100644 (file)
index 0000000..2950904
--- /dev/null
@@ -0,0 +1,8 @@
+LIBRARY nhdefkey
+EXPORTS
+ProcessKeystroke
+NHkbhit
+CheckInput
+SourceWhere
+SourceAuthor
+KeyHandlerName
diff --git a/win/win32/vs2015/nhdefkey.vcxproj b/win/win32/vs2015/nhdefkey.vcxproj
new file mode 100644 (file)
index 0000000..84fdf2f
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{6813477F-64B6-4B97-B230-438D0D233385}</ProjectGuid>\r
+    <Keyword>Win32Proj</Keyword>\r
+    <RootNamespace>nhdefkey</RootNamespace>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <Import Project="default_dll.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="dll.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>\r
+    <Link>\r
+      <ImportLibrary>$(ToolsDir)$(TargetName).lib</ImportLibrary>
+    </Link>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+    <Link>
+      <ModuleDefinitionFile>nhdefkey.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>\r
+    <ClCompile Include="$(SysWinntDir)nhdefkey.c" />
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="$(IncDir)hack.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(SysWinntDir)win32api.h" />
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/nhraykey.def b/win/win32/vs2015/nhraykey.def
new file mode 100644 (file)
index 0000000..5432a1a
--- /dev/null
@@ -0,0 +1,8 @@
+LIBRARY nhraykey
+EXPORTS
+ProcessKeystroke
+NHkbhit
+CheckInput
+SourceWhere
+SourceAuthor
+KeyHandlerName
diff --git a/win/win32/vs2015/nhraykey.vcxproj b/win/win32/vs2015/nhraykey.vcxproj
new file mode 100644 (file)
index 0000000..0017f4a
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{2e1f4bb3-3bd7-43ad-8e64-d3b8a2f5d7b2}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>nhraykey</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default_dll.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="dll.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <ImportLibrary>$(ToolsDir)$(TargetName).lib</ImportLibrary>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+    <Link>
+      <ModuleDefinitionFile>nhraykey.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SysWinntDir)nhraykey.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)hack.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(SysWinntDir)win32api.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/notes.txt b/win/win32/vs2015/notes.txt
new file mode 100644 (file)
index 0000000..5a7d933
--- /dev/null
@@ -0,0 +1,45 @@
+Changes made to vs2015 build
+
+To Do
+
+Questions
+
+1. Why is /Gs used?  This initiates stack probes for every function call (not just functions that use more then 4k)?
+2. Why is /Oi- used?  This turns off compiler intrinsics.
+3. Why is /FS used?  This forces serialization of writes to PDB.  This really isn't needed.
+4. Why are we disabling optimizations for release builds?
+5. Why are we omitting frame pointers?  Makes debugging harder.  Crash dumps less usefull.
+6. Why are we forcing function level linking?
+7. Why are we turning off intrinsics (again)?
+8. Why are we enabling additional security checks? (SDLCheck)
+9. Why are we using string pooling?
+10. Why do we turn off multi-processor compilation?
+
+Nethack Compiler Settings - Release
+/Gs
+/Oi-
+/FS
+Optimizations:Disabled
+WarningLevel:Level3
+InlineFunctionExpansion:Default
+FavorSizeOrSpeed:Speed
+OmitFramePointers:true
+Optimization:MaxSpeed
+FunctionLevelLinking:true
+IntrinsicFunctions:false
+PreprocessorDefinitions:TILES;MSWIN_GRAPHICS;WIN32;WIN32CON;DLB;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;_CONSOLE;_LIB;
+SDLCheck:true
+AdditionalIncludeDirectories:..\win\win32;..\include;..\sys\winnt;..\sys\share;..\win\share;
+StringPooling:true
+RuntimeLibrary:MultiThreaded
+SuppressStartupBanner:true
+MultiProcessorCompilation:false
+
+Nethack Link Settings - Release
+SubSystem:Console
+GenetateDebugInformation:true
+EnableCOMDATFolding:true
+OptimizeReferenes:true
+AdditionalDependencies:kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winmm.lib;Winmm.lib;
+SuppressStartupBanner:true
+TargetMachine:MachineX86
diff --git a/win/win32/vs2015/recover.vcxproj b/win/win32/vs2015/recover.vcxproj
new file mode 100644 (file)
index 0000000..7abba07
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}</ProjectGuid>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="$(UtilDir)recover.c" />
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="$(IncDir)config.h" />
+    <ClInclude Include="$(IncDir)config1.h" />
+    <ClInclude Include="$(IncDir)coord.h" />
+    <ClInclude Include="$(IncDir)global.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)tradstdc.h" />
+    <ClInclude Include="$(SysWinntDir)win32api.h" />
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afterrecover.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afterrecover.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afterrecover.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/tile2bmp.vcxproj b/win/win32/vs2015/tile2bmp.vcxproj
new file mode 100644 (file)
index 0000000..9b72b98
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="config.props" />
+
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{642BC75D-ABAF-403E-8224-7C725FD4CB42}</ProjectGuid>\r
+  </PropertyGroup>\r
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  
+  <ItemDefinitionGroup>
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>\r
+  </ItemDefinitionGroup>\r
+  
+  <ItemGroup>\r
+    <ClCompile Include="$(SrcDir)decl.c" />
+    <ClCompile Include="$(SrcDir)drawing.c" />
+    <ClCompile Include="$(SrcDir)monst.c" />
+    <ClCompile Include="$(SrcDir)objects.c" />
+    <ClCompile Include="$(WinShareDir)tile2bmp.c" />
+    <ClCompile Include="$(WinShareDir)tiletext.c" />
+    <ClCompile Include="$(WinShareDir)tilemap.c">
+       <PreprocessorDefinitions>TILETEXT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+       </ClCompile>
+  </ItemGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+
+ <Target Name="AfterBuild">
+    <MSBuild Projects="aftertile2bmp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="aftertile2bmp.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="aftertile2bmp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/tilemap.vcxproj b/win/win32/vs2015/tilemap.vcxproj
new file mode 100644 (file)
index 0000000..a970b2a
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="config.props" />
+
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{93F10526-209E-41D7-BBEA-775787876895}</ProjectGuid>\r
+  </PropertyGroup>\r
+  
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+
+  <ItemDefinitionGroup>
+    <ClCompile>\r
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>\r
+  </ItemDefinitionGroup>\r
+
+  <ItemGroup>\r
+    <ClCompile Include="$(WinShareDir)tilemap.c" />
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="$(IncDir)align.h" />
+    <ClInclude Include="$(IncDir)attrib.h" />
+    <ClInclude Include="$(IncDir)color.h" />
+    <ClInclude Include="$(IncDir)config.h" />
+    <ClInclude Include="$(IncDir)config1.h" />
+    <ClInclude Include="$(IncDir)context.h" />
+    <ClInclude Include="$(IncDir)coord.h" />
+    <ClInclude Include="$(IncDir)decl.h" />
+    <ClInclude Include="$(IncDir)dgn_comp.h" />
+    <ClInclude Include="$(IncDir)dgn_file.h" />
+    <ClInclude Include="$(IncDir)display.h" />
+    <ClInclude Include="$(IncDir)dungeon.h" />
+    <ClInclude Include="$(IncDir)engrave.h" />
+    <ClInclude Include="$(IncDir)flag.h" />
+    <ClInclude Include="$(IncDir)global.h" />
+    <ClInclude Include="$(IncDir)mkroom.h" />
+    <ClInclude Include="$(IncDir)monattk.h" />
+    <ClInclude Include="$(IncDir)monst.h" />
+    <ClInclude Include="$(IncDir)monsym.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)obj.h" />
+    <ClInclude Include="$(IncDir)objclass.h" />
+    <ClInclude Include="$(IncDir)onames.h" />
+    <ClInclude Include="$(IncDir)permonst.h" />
+    <ClInclude Include="$(IncDir)pm.h" />
+    <ClInclude Include="$(IncDir)prop.h" />
+    <ClInclude Include="$(IncDir)quest.h" />
+    <ClInclude Include="$(IncDir)rect.h" />
+    <ClInclude Include="$(IncDir)region.h" />
+    <ClInclude Include="$(IncDir)rm.h" />
+    <ClInclude Include="$(IncDir)skills.h" />
+    <ClInclude Include="$(IncDir)spell.h" />
+    <ClInclude Include="$(IncDir)timeout.h" />
+    <ClInclude Include="$(IncDir)tradstdc.h" />
+    <ClInclude Include="$(IncDir)trampoli.h" />
+    <ClInclude Include="$(IncDir)trap.h" />
+    <ClInclude Include="$(IncDir)vision.h" />
+    <ClInclude Include="$(IncDir)winprocs.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(IncDir)wintype.h" />
+    <ClInclude Include="$(IncDir)you.h" />
+    <ClInclude Include="$(IncDir)youprop.h" />
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <Target Name="AfterBuild">
+    <MSBuild Projects="aftertilemap.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="aftertilemap.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="aftertilemap.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2015/uudecode.vcxproj b/win/win32/vs2015/uudecode.vcxproj
new file mode 100644 (file)
index 0000000..d37115e
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <Import Project="config.props" />
+
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{63F9B82B-F589-4082-ABE5-D4F0682050AB}</ProjectGuid>\r
+  </PropertyGroup>\r
+
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <ItemGroup>\r
+    <ClCompile Include="$(SysShareDir)uudecode.c" />
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afteruudecode.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afteruudecode.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afteruudecode.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/NetHack.vcxproj b/win/win32/vs2017/NetHack.vcxproj
new file mode 100644 (file)
index 0000000..dfa15c3
--- /dev/null
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>NetHack</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalOptions>/Gs /Oi- %(AdditionalOptions)</AdditionalOptions>
+      <Optimization>Disabled</Optimization>
+      <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <OmitFramePointers>true</OmitFramePointers>
+      <AdditionalIncludeDirectories>$(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>TILES;WIN32CON;DLB;MSWIN_GRAPHICS;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winmm.lib;Winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SrcDir)allmain.c" />
+    <ClCompile Include="$(SrcDir)alloc.c" />
+    <ClCompile Include="$(SrcDir)apply.c" />
+    <ClCompile Include="$(SrcDir)artifact.c" />
+    <ClCompile Include="$(SrcDir)attrib.c" />
+    <ClCompile Include="$(SrcDir)ball.c" />
+    <ClCompile Include="$(SrcDir)bones.c" />
+    <ClCompile Include="$(SrcDir)botl.c" />
+    <ClCompile Include="$(SrcDir)cmd.c" />
+    <ClCompile Include="$(SrcDir)dbridge.c" />
+    <ClCompile Include="$(SrcDir)decl.c" />
+    <ClCompile Include="$(SrcDir)detect.c" />
+    <ClCompile Include="$(SrcDir)dig.c" />
+    <ClCompile Include="$(SrcDir)display.c" />
+    <ClCompile Include="$(SrcDir)dlb.c" />
+    <ClCompile Include="$(SrcDir)do.c" />
+    <ClCompile Include="$(SrcDir)dog.c" />
+    <ClCompile Include="$(SrcDir)dogmove.c" />
+    <ClCompile Include="$(SrcDir)dokick.c" />
+    <ClCompile Include="$(SrcDir)dothrow.c" />
+    <ClCompile Include="$(SrcDir)do_name.c" />
+    <ClCompile Include="$(SrcDir)do_wear.c" />
+    <ClCompile Include="$(SrcDir)drawing.c" />
+    <ClCompile Include="$(SrcDir)dungeon.c" />
+    <ClCompile Include="$(SrcDir)eat.c" />
+    <ClCompile Include="$(SrcDir)end.c" />
+    <ClCompile Include="$(SrcDir)engrave.c" />
+    <ClCompile Include="$(SrcDir)exper.c" />
+    <ClCompile Include="$(SrcDir)explode.c" />
+    <ClCompile Include="$(SrcDir)extralev.c" />
+    <ClCompile Include="$(SrcDir)files.c" />
+    <ClCompile Include="$(SrcDir)fountain.c" />
+    <ClCompile Include="$(SrcDir)hack.c" />
+    <ClCompile Include="$(SrcDir)hacklib.c" />
+    <ClCompile Include="$(SrcDir)invent.c" />
+    <ClCompile Include="$(SrcDir)light.c" />
+    <ClCompile Include="$(SrcDir)lock.c" />
+    <ClCompile Include="$(SrcDir)mail.c" />
+    <ClCompile Include="$(SrcDir)makemon.c" />
+    <ClCompile Include="$(SrcDir)mapglyph.c" />
+    <ClCompile Include="$(SrcDir)mcastu.c" />
+    <ClCompile Include="$(SrcDir)mhitm.c" />
+    <ClCompile Include="$(SrcDir)mhitu.c" />
+    <ClCompile Include="$(SrcDir)minion.c" />
+    <ClCompile Include="$(SrcDir)mklev.c" />
+    <ClCompile Include="$(SrcDir)mkmap.c" />
+    <ClCompile Include="$(SrcDir)mkmaze.c" />
+    <ClCompile Include="$(SrcDir)mkobj.c" />
+    <ClCompile Include="$(SrcDir)mkroom.c" />
+    <ClCompile Include="$(SrcDir)mon.c" />
+    <ClCompile Include="$(SrcDir)mondata.c" />
+    <ClCompile Include="$(SrcDir)monmove.c" />
+    <ClCompile Include="$(SrcDir)monst.c" />
+    <ClCompile Include="$(SrcDir)monstr.c" />
+    <ClCompile Include="$(SrcDir)mplayer.c" />
+    <ClCompile Include="$(SrcDir)mthrowu.c" />
+    <ClCompile Include="$(SrcDir)muse.c" />
+    <ClCompile Include="$(SrcDir)music.c" />
+    <ClCompile Include="$(SrcDir)objects.c" />
+    <ClCompile Include="$(SrcDir)objnam.c" />
+    <ClCompile Include="$(SrcDir)options.c" />
+    <ClCompile Include="$(SrcDir)o_init.c" />
+    <ClCompile Include="$(SrcDir)pager.c" />
+    <ClCompile Include="$(SrcDir)pickup.c" />
+    <ClCompile Include="$(SrcDir)pline.c" />
+    <ClCompile Include="$(SrcDir)polyself.c" />
+    <ClCompile Include="$(SrcDir)potion.c" />
+    <ClCompile Include="$(SrcDir)pray.c" />
+    <ClCompile Include="$(SrcDir)priest.c" />
+    <ClCompile Include="$(SrcDir)quest.c" />
+    <ClCompile Include="$(SrcDir)questpgr.c" />
+    <ClCompile Include="$(SrcDir)read.c" />
+    <ClCompile Include="$(SrcDir)rect.c" />
+    <ClCompile Include="$(SrcDir)region.c" />
+    <ClCompile Include="$(SrcDir)restore.c" />
+    <ClCompile Include="$(SrcDir)rip.c" />
+    <ClCompile Include="$(SrcDir)rnd.c" />
+    <ClCompile Include="$(SrcDir)role.c" />
+    <ClCompile Include="$(SrcDir)rumors.c" />
+    <ClCompile Include="$(SrcDir)save.c" />
+    <ClCompile Include="$(SrcDir)shk.c" />
+    <ClCompile Include="$(SrcDir)shknam.c" />
+    <ClCompile Include="$(SrcDir)sit.c" />
+    <ClCompile Include="$(SrcDir)sounds.c" />
+    <ClCompile Include="$(SrcDir)spell.c" />
+    <ClCompile Include="$(SrcDir)sp_lev.c" />
+    <ClCompile Include="$(SrcDir)steal.c" />
+    <ClCompile Include="$(SrcDir)steed.c" />
+    <ClCompile Include="$(SrcDir)sys.c" />
+    <ClCompile Include="$(SrcDir)teleport.c" />
+    <ClCompile Include="$(SrcDir)tile.c" />
+    <ClCompile Include="$(SrcDir)timeout.c" />
+    <ClCompile Include="$(SrcDir)topten.c" />
+    <ClCompile Include="$(SrcDir)track.c" />
+    <ClCompile Include="$(SrcDir)trap.c" />
+    <ClCompile Include="$(SrcDir)uhitm.c" />
+    <ClCompile Include="$(SrcDir)u_init.c" />
+    <ClCompile Include="$(SrcDir)vault.c" />
+    <ClCompile Include="$(SrcDir)version.c" />
+    <ClCompile Include="$(SrcDir)vision.c" />
+    <ClCompile Include="$(SrcDir)weapon.c" />
+    <ClCompile Include="$(SrcDir)were.c" />
+    <ClCompile Include="$(SrcDir)wield.c" />
+    <ClCompile Include="$(SrcDir)windows.c" />
+    <ClCompile Include="$(SrcDir)wizard.c" />
+    <ClCompile Include="$(SrcDir)worm.c" />
+    <ClCompile Include="$(SrcDir)worn.c" />
+    <ClCompile Include="$(SrcDir)write.c" />
+    <ClCompile Include="$(SrcDir)zap.c" />
+    <ClCompile Include="$(SysShareDir)cppregex.cpp" />
+    <ClCompile Include="$(SysShareDir)nhlan.c" />
+    <ClCompile Include="$(SysShareDir)pcmain.c" />
+    <ClCompile Include="$(SysShareDir)pcsys.c" />
+    <ClCompile Include="$(SysShareDir)pcunix.c" />
+    <ClCompile Include="$(SysShareDir)random.c" />
+    <ClCompile Include="$(SysWinntDir)ntsound.c" />
+    <ClCompile Include="$(SysWinntDir)nttty.c" />
+    <ClCompile Include="$(SysWinntDir)stubs.c">
+      <PreprocessorDefinitions>GUISTUB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <ClCompile Include="$(SysWinntDir)winnt.c" />
+    <ClCompile Include="$(WinTtyDir)getline.c" />
+    <ClCompile Include="$(WinTtyDir)topl.c" />
+    <ClCompile Include="$(WinTtyDir)wintty.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)align.h" />
+    <ClInclude Include="$(IncDir)artifact.h" />
+    <ClInclude Include="$(IncDir)artilist.h" />
+    <ClInclude Include="$(IncDir)attrib.h" />
+    <ClInclude Include="$(IncDir)botl.h" />
+    <ClInclude Include="$(IncDir)color.h" />
+    <ClInclude Include="$(IncDir)config.h" />
+    <ClInclude Include="$(IncDir)config1.h" />
+    <ClInclude Include="$(IncDir)context.h" />
+    <ClInclude Include="$(IncDir)coord.h" />
+    <ClInclude Include="$(IncDir)date.h" />
+    <ClInclude Include="$(IncDir)decl.h" />
+    <ClInclude Include="$(IncDir)display.h" />
+    <ClInclude Include="$(IncDir)dlb.h" />
+    <ClInclude Include="$(IncDir)dungeon.h" />
+    <ClInclude Include="$(IncDir)engrave.h" />
+    <ClInclude Include="$(IncDir)extern.h" />
+    <ClInclude Include="$(IncDir)flag.h" />
+    <ClInclude Include="$(IncDir)func_tab.h" />
+    <ClInclude Include="$(IncDir)global.h" />
+    <ClInclude Include="$(IncDir)hack.h" />
+    <ClInclude Include="$(IncDir)lev.h" />
+    <ClInclude Include="$(IncDir)mextra.h" />
+    <ClInclude Include="$(IncDir)mfndpos.h" />
+    <ClInclude Include="$(IncDir)mkroom.h" />
+    <ClInclude Include="$(IncDir)monattk.h" />
+    <ClInclude Include="$(IncDir)mondata.h" />
+    <ClInclude Include="$(IncDir)monflag.h" />
+    <ClInclude Include="$(IncDir)monst.h" />
+    <ClInclude Include="$(IncDir)monsym.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)obj.h" />
+    <ClInclude Include="$(IncDir)objclass.h" />
+    <ClInclude Include="$(IncDir)onames.h" />
+    <ClInclude Include="$(IncDir)patchlevel.h" />
+    <ClInclude Include="$(IncDir)permonst.h" />
+    <ClInclude Include="$(IncDir)pm.h" />
+    <ClInclude Include="$(IncDir)prop.h" />
+    <ClInclude Include="$(IncDir)qtext.h" />
+    <ClInclude Include="$(IncDir)quest.h" />
+    <ClInclude Include="$(IncDir)rect.h" />
+    <ClInclude Include="$(IncDir)region.h" />
+    <ClInclude Include="$(IncDir)rm.h" />
+    <ClInclude Include="$(IncDir)skills.h" />
+    <ClInclude Include="$(IncDir)spell.h" />
+    <ClInclude Include="$(IncDir)sp_lev.h" />
+    <ClInclude Include="$(IncDir)timeout.h" />
+    <ClInclude Include="$(IncDir)tradstdc.h" />
+    <ClInclude Include="$(IncDir)trap.h" />
+    <ClInclude Include="$(IncDir)vision.h" />
+    <ClInclude Include="$(IncDir)winprocs.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(IncDir)wintype.h" />
+    <ClInclude Include="$(IncDir)you.h" />
+    <ClInclude Include="$(IncDir)youprop.h" />
+    <ClInclude Include="$(WinWin32Dir)nhresource.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="$(WinWin32Dir)NetHack.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="$(WinWin32Dir)nethack.ico" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afternethack.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/NetHackW.vcxproj b/win/win32/vs2017/NetHackW.vcxproj
new file mode 100644 (file)
index 0000000..d1cd0bb
--- /dev/null
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{CEC5D360-8804-454F-8591-002184C23499}</ProjectGuid>
+    <RootNamespace>NetHackW</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalOptions>/Gs /Oi- %(AdditionalOptions)</AdditionalOptions>
+      <Optimization>Disabled</Optimization>
+      <OmitFramePointers>true</OmitFramePointers>
+      <AdditionalIncludeDirectories>$(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>TILES;_WINDOWS;DLB;MSWIN_GRAPHICS;WIN32CONNDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0409</Culture>
+    </ResourceCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <AdditionalDependencies>comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SrcDir)allmain.c" />
+    <ClCompile Include="$(SrcDir)alloc.c" />
+    <ClCompile Include="$(SrcDir)apply.c" />
+    <ClCompile Include="$(SrcDir)artifact.c" />
+    <ClCompile Include="$(SrcDir)attrib.c" />
+    <ClCompile Include="$(SrcDir)ball.c" />
+    <ClCompile Include="$(SrcDir)bones.c" />
+    <ClCompile Include="$(SrcDir)botl.c" />
+    <ClCompile Include="$(SrcDir)cmd.c" />
+    <ClCompile Include="$(SrcDir)dbridge.c" />
+    <ClCompile Include="$(SrcDir)decl.c" />
+    <ClCompile Include="$(SrcDir)detect.c" />
+    <ClCompile Include="$(SrcDir)dig.c" />
+    <ClCompile Include="$(SrcDir)display.c" />
+    <ClCompile Include="$(SrcDir)dlb.c" />
+    <ClCompile Include="$(SrcDir)do.c" />
+    <ClCompile Include="$(SrcDir)dog.c" />
+    <ClCompile Include="$(SrcDir)dogmove.c" />
+    <ClCompile Include="$(SrcDir)dokick.c" />
+    <ClCompile Include="$(SrcDir)dothrow.c" />
+    <ClCompile Include="$(SrcDir)do_name.c" />
+    <ClCompile Include="$(SrcDir)do_wear.c" />
+    <ClCompile Include="$(SrcDir)drawing.c" />
+    <ClCompile Include="$(SrcDir)dungeon.c" />
+    <ClCompile Include="$(SrcDir)eat.c" />
+    <ClCompile Include="$(SrcDir)end.c" />
+    <ClCompile Include="$(SrcDir)engrave.c" />
+    <ClCompile Include="$(SrcDir)exper.c" />
+    <ClCompile Include="$(SrcDir)explode.c" />
+    <ClCompile Include="$(SrcDir)extralev.c" />
+    <ClCompile Include="$(SrcDir)files.c" />
+    <ClCompile Include="$(SrcDir)fountain.c" />
+    <ClCompile Include="$(SrcDir)hack.c" />
+    <ClCompile Include="$(SrcDir)hacklib.c" />
+    <ClCompile Include="$(SrcDir)invent.c" />
+    <ClCompile Include="$(SrcDir)light.c" />
+    <ClCompile Include="$(SrcDir)lock.c" />
+    <ClCompile Include="$(SrcDir)mail.c" />
+    <ClCompile Include="$(SrcDir)makemon.c" />
+    <ClCompile Include="$(SrcDir)mapglyph.c" />
+    <ClCompile Include="$(SrcDir)mcastu.c" />
+    <ClCompile Include="$(SrcDir)mhitm.c" />
+    <ClCompile Include="$(SrcDir)mhitu.c" />
+    <ClCompile Include="$(SrcDir)minion.c" />
+    <ClCompile Include="$(SrcDir)mklev.c" />
+    <ClCompile Include="$(SrcDir)mkmap.c" />
+    <ClCompile Include="$(SrcDir)mkmaze.c" />
+    <ClCompile Include="$(SrcDir)mkobj.c" />
+    <ClCompile Include="$(SrcDir)mkroom.c" />
+    <ClCompile Include="$(SrcDir)mon.c" />
+    <ClCompile Include="$(SrcDir)mondata.c" />
+    <ClCompile Include="$(SrcDir)monmove.c" />
+    <ClCompile Include="$(SrcDir)monst.c" />
+    <ClCompile Include="$(SrcDir)monstr.c" />
+    <ClCompile Include="$(SrcDir)mplayer.c" />
+    <ClCompile Include="$(SrcDir)mthrowu.c" />
+    <ClCompile Include="$(SrcDir)muse.c" />
+    <ClCompile Include="$(SrcDir)music.c" />
+    <ClCompile Include="$(SrcDir)objects.c" />
+    <ClCompile Include="$(SrcDir)objnam.c" />
+    <ClCompile Include="$(SrcDir)options.c" />
+    <ClCompile Include="$(SrcDir)o_init.c" />
+    <ClCompile Include="$(SrcDir)pager.c" />
+    <ClCompile Include="$(SrcDir)pickup.c" />
+    <ClCompile Include="$(SrcDir)pline.c" />
+    <ClCompile Include="$(SrcDir)polyself.c" />
+    <ClCompile Include="$(SrcDir)potion.c" />
+    <ClCompile Include="$(SrcDir)pray.c" />
+    <ClCompile Include="$(SrcDir)priest.c" />
+    <ClCompile Include="$(SrcDir)quest.c" />
+    <ClCompile Include="$(SrcDir)questpgr.c" />
+    <ClCompile Include="$(SrcDir)read.c" />
+    <ClCompile Include="$(SrcDir)rect.c" />
+    <ClCompile Include="$(SrcDir)region.c" />
+    <ClCompile Include="$(SrcDir)restore.c" />
+    <ClCompile Include="$(SrcDir)rip.c" />
+    <ClCompile Include="$(SrcDir)rnd.c" />
+    <ClCompile Include="$(SrcDir)role.c" />
+    <ClCompile Include="$(SrcDir)rumors.c" />
+    <ClCompile Include="$(SrcDir)save.c" />
+    <ClCompile Include="$(SrcDir)shk.c" />
+    <ClCompile Include="$(SrcDir)shknam.c" />
+    <ClCompile Include="$(SrcDir)sit.c" />
+    <ClCompile Include="$(SrcDir)sounds.c" />
+    <ClCompile Include="$(SrcDir)spell.c" />
+    <ClCompile Include="$(SrcDir)sp_lev.c" />
+    <ClCompile Include="$(SrcDir)steal.c" />
+    <ClCompile Include="$(SrcDir)steed.c" />
+    <ClCompile Include="$(SrcDir)sys.c" />
+    <ClCompile Include="$(SrcDir)teleport.c" />
+    <ClCompile Include="$(SrcDir)tile.c" />
+    <ClCompile Include="$(SrcDir)timeout.c" />
+    <ClCompile Include="$(SrcDir)topten.c" />
+    <ClCompile Include="$(SrcDir)track.c" />
+    <ClCompile Include="$(SrcDir)trap.c" />
+    <ClCompile Include="$(SrcDir)uhitm.c" />
+    <ClCompile Include="$(SrcDir)u_init.c" />
+    <ClCompile Include="$(SrcDir)vault.c" />
+    <ClCompile Include="$(SrcDir)version.c" />
+    <ClCompile Include="$(SrcDir)vision.c" />
+    <ClCompile Include="$(SrcDir)vis_tab.c" />
+    <ClCompile Include="$(SrcDir)weapon.c" />
+    <ClCompile Include="$(SrcDir)were.c" />
+    <ClCompile Include="$(SrcDir)wield.c" />
+    <ClCompile Include="$(SrcDir)windows.c" />
+    <ClCompile Include="$(SrcDir)wizard.c" />
+    <ClCompile Include="$(SrcDir)worm.c" />
+    <ClCompile Include="$(SrcDir)worn.c" />
+    <ClCompile Include="$(SrcDir)write.c" />
+    <ClCompile Include="$(SrcDir)zap.c" />
+    <ClCompile Include="$(SysShareDir)cppregex.cpp" />
+    <ClCompile Include="$(SysShareDir)nhlan.c" />
+    <ClCompile Include="$(SysShareDir)pcmain.c" />
+    <ClCompile Include="$(SysShareDir)pcsys.c" />
+    <ClCompile Include="$(SysShareDir)pcunix.c" />
+    <ClCompile Include="$(SysShareDir)random.c" />
+    <ClCompile Include="$(SysWinntDir)ntsound.c" />
+    <ClCompile Include="$(SysWinntDir)stubs.c">
+      <PreprocessorDefinitions>TTYSTUB;</PreprocessorDefinitions>
+    </ClCompile>
+    <ClCompile Include="$(SysWinntDir)winnt.c" />
+    <ClCompile Include="$(WinWin32Dir)mhaskyn.c" />
+    <ClCompile Include="$(WinWin32Dir)mhdlg.c" />
+    <ClCompile Include="$(WinWin32Dir)mhfont.c" />
+    <ClCompile Include="$(WinWin32Dir)mhinput.c" />
+    <ClCompile Include="$(WinWin32Dir)mhmain.c" />
+    <ClCompile Include="$(WinWin32Dir)mhmap.c" />
+    <ClCompile Include="$(WinWin32Dir)mhmenu.c" />
+    <ClCompile Include="$(WinWin32Dir)mhmsgwnd.c" />
+    <ClCompile Include="$(WinWin32Dir)mhrip.c" />
+    <ClCompile Include="$(WinWin32Dir)mhsplash.c" />
+    <ClCompile Include="$(WinWin32Dir)mhstatus.c" />
+    <ClCompile Include="$(WinWin32Dir)mhtext.c" />
+    <ClCompile Include="$(WinWin32Dir)mswproc.c" />
+    <ClCompile Include="$(WinWin32Dir)winhack.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="$(WinWin32Dir)winhack.rc" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afternethack.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/afterdgncomp.proj b/win/win32/vs2017/afterdgncomp.proj
new file mode 100644 (file)
index 0000000..38aee32
--- /dev/null
@@ -0,0 +1,12 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build"
+     Inputs="$(ToolsDir)dgncomp.exe;$(DatDir)dungeon.pdf"
+        Outputs="$(DatDir)dungeon">
+       <Exec Command="$(ToolsDir)dgncomp.exe dungeon.pdf" WorkingDirectory="$(DatDir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="$(DatDir)dungeon"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2017/afterdlb.proj b/win/win32/vs2017/afterdlb.proj
new file mode 100644 (file)
index 0000000..eff6311
--- /dev/null
@@ -0,0 +1,17 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build"
+       Inputs="$(ToolsDir)dlb.exe;@(DlbList);$(SysWinntDir)porthelp"
+       Outputs="$(BinDir)nhdat">
+
+       <Copy SourceFiles="$(SysWinntDir)porthelp" DestinationFolder="$(DatDir)"/>
+       <WriteLinesToFile File="$(DatDir)dlb.lst" Lines="@(DlbList->'%(filename)%(extension)')" Overwrite="true"/>
+       <Exec Command="$(ToolsDir)dlb.exe cIf $(DatDir)dlb.lst $(BinDir)nhdat" WorkingDirectory="$(DatDir)"/>
+       <Delete Files="$(DatDir)porthelp"/>
+
+       </Target>
+  <Target Name="Clean">
+       <Delete Files="$(BinDir)nhdat"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2017/afterlevcomp.proj b/win/win32/vs2017/afterlevcomp.proj
new file mode 100644 (file)
index 0000000..c0d8dd4
--- /dev/null
@@ -0,0 +1,12 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build"
+     Inputs="@(Desfiles->'$(DatDir)%(filename)%(extension)');$(BinDir)levcomp.exe"
+        Outputs="@(Levfiles->'$(DatDir)%(filename)%(extension)')">
+       <Exec Command="$(ToolsDir)levcomp.exe @(Desfiles, ' ')" WorkingDirectory="$(DatDir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="@(Levfiles->'$(DatDir)%(filename)%(extension)')"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2017/aftermakedefs.proj b/win/win32/vs2017/aftermakedefs.proj
new file mode 100644 (file)
index 0000000..7448066
--- /dev/null
@@ -0,0 +1,22 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build"
+     Inputs="$(ToolsDir)makedefs.exe"
+        Outputs="@(Defs)">
+       <Exec Command="$(ToolsDir)makedefs.exe -v" WorkingDirectory="$(UtilDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -o" WorkingDirectory="$(UtilDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -p" WorkingDirectory="$(UtilDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -m" WorkingDirectory="$(UtilDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -z" WorkingDirectory="$(UtilDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -d" WorkingDirectory="$(DatDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -r" WorkingDirectory="$(DatDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -s" WorkingDirectory="$(DatDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -q" WorkingDirectory="$(DatDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -h" WorkingDirectory="$(DatDir)"/>
+       <Exec Command="$(ToolsDir)makedefs.exe -e" WorkingDirectory="$(DatDir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="@(Defs)"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2017/afternethack.proj b/win/win32/vs2017/afternethack.proj
new file mode 100644 (file)
index 0000000..912d75e
--- /dev/null
@@ -0,0 +1,15 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <!-- TODO not copying record -->
+  <Target Name="Build"
+       Inputs="$(SysWinntDir)defaults.nh;$(DocDir)Guidebook.txt;$(DatDir)license;$(SysWinntDir)sysconf;$(DocDir)nethack.txt;$(DatDir)symbols;$(WinWin32Dir)record;$(DatDir)opthelp"
+       Outputs="$(BinDir)defaults.nh;$(BinDir)Guidebook.txt;$(BinDir)license;$(BinDir)sysconf;$(BinDir)symbols;$(BinDir)record;$(BinDir)opthelp">
+
+       <Copy SourceFiles="$(SysWinntDir)defaults.nh;$(DocDir)Guidebook.txt;$(DatDir)license;$(SysWinntDir)sysconf;$(DocDir)nethack.txt;$(DatDir)symbols;$(WinWin32Dir)record;$(DatDir)opthelp" DestinationFolder="$(BinDir)"/>
+
+       </Target>
+  <Target Name="Clean">
+       <Delete Files="$(BinDir)defaults.nh;$(BinDir)Guidebook.txt;$(BinDir)license;$(BinDir)sysconf;$(BinDir)nethack.txt;$(BinDir)symbols;$(BinDir)record;$(BinDir)opthelp"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2017/afterrecover.proj b/win/win32/vs2017/afterrecover.proj
new file mode 100644 (file)
index 0000000..46ab13a
--- /dev/null
@@ -0,0 +1,12 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build"
+     Inputs="$(DocDir)recover.txt"
+        Outputs="$(BinDir)recover.txt">
+       <Copy SourceFiles="$(DocDir)recover.txt" DestinationFiles="$(BinDir)recover.txt"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="$(BinDir)recover.txt"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2017/aftertile2bmp.proj b/win/win32/vs2017/aftertile2bmp.proj
new file mode 100644 (file)
index 0000000..44e0312
--- /dev/null
@@ -0,0 +1,13 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build"
+     Inputs="$(ToolsDir)tile2bmp.exe;$(WinShareDir)monsters.txt;$(WinShareDir)objects.txt"
+        Outputs="$(WinWin32Dir)tiles.bmp">
+       <Exec Command="$(ToolsDir)tile2bmp.exe tiles.bmp" WorkingDirectory="$(SrcDir)"/>
+       <Move SourceFiles="$(SrcDir)tiles.bmp" DestinationFolder="$(WinWin32Dir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="$(WinWin32Dir)tiles.bmp"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2017/aftertilemap.proj b/win/win32/vs2017/aftertilemap.proj
new file mode 100644 (file)
index 0000000..d68eaba
--- /dev/null
@@ -0,0 +1,12 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build"
+     Inputs="$(ToolsDir)tilemap.exe"
+        Outputs="$(SrcDir)tile.c">
+       <Exec Command="$(ToolsDir)tilemap.exe" WorkingDirectory="$(SrcDir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="$(SrcDir)tile.c"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2017/afteruudecode.proj b/win/win32/vs2017/afteruudecode.proj
new file mode 100644 (file)
index 0000000..fd0370b
--- /dev/null
@@ -0,0 +1,20 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="dirs.props"/>
+  <Import Project="files.props"/>
+  <Target Name="Build"
+     Inputs="$(ToolsDir)uudecode.exe;@(UUFiles)"
+        Outputs="@(IconFiles);@(BmpFiles);@(RecordFiles)">
+       <Exec Command="$(ToolsDir)uudecode.exe $(SysWinntDir)nhico.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)mnsel.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)mnselcnt.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)mnunsel.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)petmark.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)pilemark.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)splash.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)rip.uu" WorkingDirectory="$(WinWin32Dir)"/>
+       <Exec Command="$(ToolsDir)uudecode.exe $(WinWin32Dir)record.uu" WorkingDirectory="$(WinWin32Dir)"/>
+  </Target>
+  <Target Name="Clean">
+       <Delete Files="@(IconFiles);@(BmpFiles);@(RecordFiles)"/>
+  </Target>
+</Project>
diff --git a/win/win32/vs2017/build.bat b/win/win32/vs2017/build.bat
new file mode 100644 (file)
index 0000000..2a10d62
--- /dev/null
@@ -0,0 +1,44 @@
+@echo off
+
+if "%VSCMD_VER%"=="" (
+       echo MSBuild environment not set ... attempting to setup build environment.
+       call :setup_environment
+)
+
+if "%VSCMD_VER%"=="" (
+       echo Unable to setup build environment.  Exiting.
+       goto :EOF
+)
+
+msbuild NetHack.sln /t:Clean;Build /p:Configuration=Debug;Platform=Win32
+msbuild NetHack.sln /t:Clean;Build /p:Configuration=Debug;Platform=x64
+msbuild NetHack.sln /t:Clean;Build /p:Configuration=Release;Platform=Win32
+msbuild NetHack.sln /t:Clean;Build /p:Configuration=Release;Platform=x64
+
+goto :EOF
+
+:setup_environment
+
+
+if "%VS150COMNTOOLS%"=="" (
+       call :set_vs15comntools
+)
+
+if "%VS150COMNTOOLS%"=="" (
+       echo Can not find Visual Studio 2017 Common Tools path.
+       echo Set VS150COMNTOOLS appropriately.
+       goto :EOF
+)
+
+call "%VS150COMNTOOLS%VsMSBuildCmd.bat"
+cd %~dp0
+
+goto :EOF
+
+:set_vs15comntools
+
+if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Professional\Common7\Tools" (
+       set "VS150COMNTOOLS=%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Professional\Common7\Tools\"
+)
+
+goto :EOF
diff --git a/win/win32/vs2017/common.props b/win/win32/vs2017/common.props
new file mode 100644 (file)
index 0000000..8f5d2a4
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PreprocessorDefinitions>WIN32;CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <ProgramDatabaseFile>$(SymbolsDir)$(TargetName).pdb</ProgramDatabaseFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+    </Link>
+  </ItemDefinitionGroup>
+</Project>
diff --git a/win/win32/vs2017/config.props b/win/win32/vs2017/config.props
new file mode 100644 (file)
index 0000000..3d435b5
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'==''">
+    <LatestTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</LatestTargetPlatformVersion>
+    <WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+</Project>
diff --git a/win/win32/vs2017/console.props b/win/win32/vs2017/console.props
new file mode 100644 (file)
index 0000000..f91d9da
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+</Project>
diff --git a/win/win32/vs2017/default.props b/win/win32/vs2017/default.props
new file mode 100644 (file)
index 0000000..e0bc581
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ConfigurationType>Application</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v141</PlatformToolset>
+    <LocalDebuggerWorkingDirectory>$(BinDir)</LocalDebuggerWorkingDirectory>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" >
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" >
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+
+</Project>
diff --git a/win/win32/vs2017/default_dll.props b/win/win32/vs2017/default_dll.props
new file mode 100644 (file)
index 0000000..51d90a3
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v141</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" >
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" >
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+
+</Project>
diff --git a/win/win32/vs2017/dgncomp.vcxproj b/win/win32/vs2017/dgncomp.vcxproj
new file mode 100644 (file)
index 0000000..5ef5aec
--- /dev/null
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{8A3F81C7-2968-49A8-86BF-2669412AD7DE}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SrcDir)alloc.c" />
+    <ClCompile Include="$(SysShareDir)\dgn_lex.c" />
+    <ClCompile Include="$(UtilDir)dgn_main.c" />
+    <ClCompile Include="$(SysShareDir)dgn_yacc.c" />
+    <ClCompile Include="$(UtilDir)panic.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)align.h" />
+    <ClInclude Include="$(IncDir)attrib.h" />
+    <ClInclude Include="$(IncDir)color.h" />
+    <ClInclude Include="$(IncDir)config.h" />
+    <ClInclude Include="$(IncDir)config1.h" />
+    <ClInclude Include="$(IncDir)context.h" />
+    <ClInclude Include="$(IncDir)coord.h" />
+    <ClInclude Include="$(IncDir)decl.h" />
+    <ClInclude Include="$(IncDir)dgn_comp.h" />
+    <ClInclude Include="$(IncDir)dgn_file.h" />
+    <ClInclude Include="$(IncDir)display.h" />
+    <ClInclude Include="$(IncDir)dungeon.h" />
+    <ClInclude Include="$(IncDir)engrave.h" />
+    <ClInclude Include="$(IncDir)flag.h" />
+    <ClInclude Include="$(IncDir)global.h" />
+    <ClInclude Include="$(IncDir)mkroom.h" />
+    <ClInclude Include="$(IncDir)monattk.h" />
+    <ClInclude Include="$(IncDir)monst.h" />
+    <ClInclude Include="$(IncDir)monsym.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)obj.h" />
+    <ClInclude Include="$(IncDir)objclass.h" />
+    <ClInclude Include="$(IncDir)onames.h" />
+    <ClInclude Include="$(IncDir)permonst.h" />
+    <ClInclude Include="$(IncDir)pm.h" />
+    <ClInclude Include="$(IncDir)prop.h" />
+    <ClInclude Include="$(IncDir)quest.h" />
+    <ClInclude Include="$(IncDir)rect.h" />
+    <ClInclude Include="$(IncDir)region.h" />
+    <ClInclude Include="$(IncDir)rm.h" />
+    <ClInclude Include="$(IncDir)skills.h" />
+    <ClInclude Include="$(IncDir)spell.h" />
+    <ClInclude Include="$(IncDir)timeout.h" />
+    <ClInclude Include="$(IncDir)tradstdc.h" />
+    <ClInclude Include="$(IncDir)trampoli.h" />
+    <ClInclude Include="$(IncDir)trap.h" />
+    <ClInclude Include="$(IncDir)vision.h" />
+    <ClInclude Include="$(IncDir)winprocs.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(IncDir)wintype.h" />
+    <ClInclude Include="$(IncDir)you.h" />
+    <ClInclude Include="$(IncDir)youprop.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Choose>
+    <When Condition=" '$(YACC)'!='' ">
+      <PropertyGroup>
+        <BuildDependsOn>
+          Lex;
+          Yacc;
+          $(BuildDependsOn);
+        </BuildDependsOn>
+      </PropertyGroup>
+    </When>
+    <Otherwise>
+      <PropertyGroup>
+        <BuildDependsOn>
+          NoLex;
+          NoYacc;
+          $(BuildDependsOn);
+        </BuildDependsOn>
+      </PropertyGroup>
+    </Otherwise>
+  </Choose>
+  <Target Name="Yacc" Inputs="$(UtilDir)dgn_comp.y" Outputs="$(UtilDir)dgn_yacc.c;$(IncDir)dgn_comp.h">
+    <Message Text="Running Yacc" Importance="high" />
+    <Exec Command="$(YACC) -d dgn_comp.y" WorkingDirectory="$(UtilDir)" />
+    <Move SourceFiles="$(UtilDir)y.tab.c;$(UtilDir)y.tab.h" DestinationFiles="$(UtilDir)dgn_yacc.c;$(IncDir)dgn_comp.h" />
+  </Target>
+  <Target Name="Lex" Inputs="$(UtilDir)lev_comp.l" Outputs="$(UtilDir)dgn_lex.c">
+    <Message Text="Running Lex" Importance="high" />
+    <Exec Command="$(LEX) dgn_comp.l" WorkingDirectory="$(UtilDir)" />
+    <Move SourceFiles="$(UtilDir)lex.yy.c" DestinationFiles="$(UtilDir)dgn_lex.c" />
+  </Target>
+  <Target Name="NoYacc" Inputs="$(SysShareDir)dgn_yacc.c;$(SysShareDir)dgn_comp.h" Outputs="$(UtilDir)dgn_yacc.c;$(IncDir)dgn_comp.h">
+    <Message Text="No Yacc using pre-built files" Importance="high" />
+    <Copy SourceFiles="$(SysShareDir)dgn_yacc.c;$(SysShareDir)dgn_comp.h" DestinationFiles="$(UtilDir)dgn_yacc.c;$(IncDir)dgn_comp.h" />
+  </Target>
+  <Target Name="NoLex" Inputs="$(SysShareDir)dgn_lex.c" Outputs="$(UtilDir)dgn_lex.c">
+    <Message Text="No Lex using pre-built files" Importance="high" />
+    <Copy SourceFiles="$(SysShareDir)dgn_lex.c" DestinationFiles="$(UtilDir)dgn_lex.c" />
+  </Target>
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afterdgncomp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afterdgncomp.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+    <Delete Files="$(UtilDir)dgn_yacc.c;$(IncDir)dgn_comp.h;$(UtilDir)dgn_lex.c" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afterdgncomp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/dirs.props b/win/win32/vs2017/dirs.props
new file mode 100644 (file)
index 0000000..9d4ed49
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <RootDir>$(MSBuildProjectDirectory)\..\..\..\</RootDir>
+    <BinDir>$(RootDir)bin\$(Configuration)\$(Platform)\</BinDir>
+    <ObjDir>$(ProjectDir)obj\$(Configuration)\$(Platform)\$(TargetName)\</ObjDir>
+    <SymbolsDir>$(ProjectDir)symbols\$(Configuration)\$(Platform)\$(TargetName)\</SymbolsDir>
+    <ToolsDir>$(RootDir)tools\$(Configuration)\$(Platform)\</ToolsDir>
+    <UtilDir>$(RootDir)util\</UtilDir>
+    <DatDir>$(RootDir)dat\</DatDir>
+    <DocDir>$(RootDir)doc\</DocDir>
+    <IncDir>$(RootDir)include\</IncDir>
+    <SrcDir>$(RootDir)src\</SrcDir>
+       <SysDir>$(RootDir)sys\</SysDir>
+    <UtilDir>$(RootDir)util\</UtilDir>
+       <SysShareDir>$(RootDir)sys\share\</SysShareDir>
+    <SysWinntDir>$(RootDir)sys\winnt\</SysWinntDir>
+    <WinShareDir>$(RootDir)win\share\</WinShareDir>
+    <WinTtyDir>$(RootDir)win\tty\</WinTtyDir>
+    <WinWin32Dir>$(RootDir)win\win32\</WinWin32Dir>
+    <OutDir>$(ToolsDir)</OutDir>
+       <IntDir>$(ObjDir)</IntDir>
+  </PropertyGroup>
+</Project>
diff --git a/win/win32/vs2017/dlb.vcxproj b/win/win32/vs2017/dlb.vcxproj
new file mode 100644 (file)
index 0000000..03b56b8
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SrcDir)alloc.c" />
+    <ClCompile Include="$(SrcDir)dlb.c" />
+    <ClCompile Include="$(UtilDir)dlb_main.c" />
+    <ClCompile Include="$(UtilDir)panic.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)dlb.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afterdlb.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afterdlb.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afterdlb.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/dll.props b/win/win32/vs2017/dll.props
new file mode 100644 (file)
index 0000000..bd90844
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32CON;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+</Project>
diff --git a/win/win32/vs2017/files.props b/win/win32/vs2017/files.props
new file mode 100644 (file)
index 0000000..7a93b0d
--- /dev/null
@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <!-- -v -->
+    <Defs Include = "$(DatDir)options"/>
+    <Defs Include = "$(IncDir)date.h"/>
+       <!-- -o -->
+    <Defs Include = "$(IncDir)onames.h"/>
+       <!-- -p -->
+    <Defs Include = "$(IncDir)pm.h"/>
+       <!-- -m -->
+    <Defs Include = "$(SrcDir)monstr.c"/>
+       <!-- -z -->
+    <Defs Include = "$(IncDir)vis_tab.h"/>
+    <Defs Include = "$(SrcDir)vis_tab.c"/>
+       <!-- -d -->
+    <Defs Include = "$(DatDir)data"/>
+       <!-- -r -->
+    <Defs Include = "$(DatDir)rumors"/>
+       <!-- -s -->
+    <Defs Include = "$(DatDir)engrave"/>
+    <Defs Include = "$(DatDir)epitaph"/>
+    <Defs Include = "$(DatDir)bogusmon"/>
+       <!-- -q -->
+    <Defs Include = "$(DatDir)quest.dat"/>
+       <!-- -h -->
+    <Defs Include = "$(DatDir)oracles"/>
+       <!-- -e -->
+    <Defs Include = "$(DatDir)dungeon.pdf"/>
+  </ItemGroup>
+  <ItemGroup>
+    <Desfiles Include = "arch.des"/>
+    <Desfiles Include = "barb.des"/>
+    <Desfiles Include = "bigroom.des"/>
+    <Desfiles Include = "castle.des"/>
+    <Desfiles Include = "caveman.des"/>
+    <Desfiles Include = "endgame.des"/>
+    <Desfiles Include = "gehennom.des"/>
+    <Desfiles Include = "healer.des"/>
+    <Desfiles Include = "knight.des"/>
+    <Desfiles Include = "knox.des"/>
+    <Desfiles Include = "medusa.des"/>
+    <Desfiles Include = "mines.des"/>
+    <Desfiles Include = "monk.des"/>
+    <Desfiles Include = "oracle.des"/>
+    <Desfiles Include = "priest.des"/>
+    <Desfiles Include = "ranger.des"/>
+    <Desfiles Include = "rogue.des"/>
+    <Desfiles Include = "samurai.des"/>
+    <Desfiles Include = "sokoban.des"/>
+    <Desfiles Include = "tourist.des"/>
+    <Desfiles Include = "tower.des"/>
+    <Desfiles Include = "valkyrie.des"/>
+    <Desfiles Include = "wizard.des"/> 
+    <Desfiles Include = "yendor.des"/>
+  </ItemGroup>
+  <ItemGroup>
+    <Levfiles Include = "bigrm-1.lev"/>
+    <Levfiles Include = "bigrm-2.lev"/>
+    <Levfiles Include = "bigrm-3.lev"/>
+    <Levfiles Include = "bigrm-4.lev"/>
+    <Levfiles Include = "bigrm-5.lev"/>
+    <Levfiles Include = "bigrm-6.lev"/>
+    <Levfiles Include = "bigrm-7.lev"/>
+    <Levfiles Include = "bigrm-8.lev"/>
+    <Levfiles Include = "bigrm-9.lev"/>
+    <Levfiles Include = "bigrm-10.lev"/>
+    <Levfiles Include = "castle.lev"/>
+    <Levfiles Include = "air.lev"/>
+    <Levfiles Include = "astral.lev"/>
+    <Levfiles Include = "earth.lev"/>
+    <Levfiles Include = "fire.lev"/>
+    <Levfiles Include = "water.lev"/>
+    <Levfiles Include = "asmodeus.lev"/>
+    <Levfiles Include = "baalz.lev"/>
+    <Levfiles Include = "juiblex.lev"/>
+    <Levfiles Include = "orcus.lev"/>
+    <Levfiles Include = "sanctum.lev"/>
+    <Levfiles Include = "valley.lev"/>
+    <Levfiles Include = "knox.lev"/>
+    <Levfiles Include = "minefill.lev"/>
+    <Levfiles Include = "minend-1.lev"/>
+    <Levfiles Include = "minend-2.lev"/>
+    <Levfiles Include = "minend-3.lev"/>
+    <Levfiles Include = "minetn-1.lev"/>
+    <Levfiles Include = "minetn-2.lev"/>
+    <Levfiles Include = "minetn-3.lev"/>
+    <Levfiles Include = "minetn-4.lev"/>
+    <Levfiles Include = "minetn-5.lev"/>
+    <Levfiles Include = "minetn-6.lev"/>
+    <Levfiles Include = "minetn-7.lev"/>
+    <Levfiles Include = "medusa-1.lev"/>
+    <Levfiles Include = "medusa-2.lev"/>
+    <Levfiles Include = "medusa-3.lev"/>
+    <Levfiles Include = "medusa-4.lev"/>
+    <Levfiles Include = "oracle.lev"/>
+    <Levfiles Include = "soko1-1.lev"/>
+    <Levfiles Include = "soko1-2.lev"/>
+    <Levfiles Include = "soko2-1.lev"/>
+    <Levfiles Include = "soko2-2.lev"/>
+    <Levfiles Include = "soko3-1.lev"/>
+    <Levfiles Include = "soko3-2.lev"/>
+    <Levfiles Include = "soko4-1.lev"/>
+    <Levfiles Include = "soko4-2.lev"/>
+    <Levfiles Include = "tower1.lev"/>
+    <Levfiles Include = "tower2.lev"/>
+    <Levfiles Include = "tower3.lev"/>
+    <Levfiles Include = "fakewiz1.lev"/>
+    <Levfiles Include = "fakewiz2.lev"/>
+    <Levfiles Include = "wizard1.lev"/>
+    <Levfiles Include = "wizard2.lev"/>
+    <Levfiles Include = "wizard3.lev"/>
+    <Levfiles Include = "arc-fila.lev"/>
+    <Levfiles Include = "arc-filb.lev"/>
+    <Levfiles Include = "arc-goal.lev"/>
+    <Levfiles Include = "arc-loca.lev"/>
+    <Levfiles Include = "arc-strt.lev"/>
+    <Levfiles Include = "bar-fila.lev"/>
+    <Levfiles Include = "bar-filb.lev"/>
+    <Levfiles Include = "bar-goal.lev"/>
+    <Levfiles Include = "bar-loca.lev"/>
+    <Levfiles Include = "bar-strt.lev"/>
+    <Levfiles Include = "cav-fila.lev"/>
+    <Levfiles Include = "cav-filb.lev"/>
+    <Levfiles Include = "cav-goal.lev"/>
+    <Levfiles Include = "cav-loca.lev"/>
+    <Levfiles Include = "cav-strt.lev"/>
+    <Levfiles Include = "hea-fila.lev"/>
+    <Levfiles Include = "hea-filb.lev"/>
+    <Levfiles Include = "hea-goal.lev"/>
+    <Levfiles Include = "hea-loca.lev"/>
+    <Levfiles Include = "hea-strt.lev"/>
+    <Levfiles Include = "kni-fila.lev"/>
+    <Levfiles Include = "kni-filb.lev"/>
+    <Levfiles Include = "kni-goal.lev"/>
+    <Levfiles Include = "kni-loca.lev"/>
+    <Levfiles Include = "kni-strt.lev"/>
+    <Levfiles Include = "mon-fila.lev"/>
+    <Levfiles Include = "mon-filb.lev"/>
+    <Levfiles Include = "mon-goal.lev"/>
+    <Levfiles Include = "mon-loca.lev"/>
+    <Levfiles Include = "mon-strt.lev"/>
+    <Levfiles Include = "pri-fila.lev"/>
+    <Levfiles Include = "pri-filb.lev"/>
+    <Levfiles Include = "pri-goal.lev"/>
+    <Levfiles Include = "pri-loca.lev"/>
+    <Levfiles Include = "pri-strt.lev"/>
+    <Levfiles Include = "ran-fila.lev"/>
+    <Levfiles Include = "ran-filb.lev"/>
+    <Levfiles Include = "ran-goal.lev"/>
+    <Levfiles Include = "ran-loca.lev"/>
+    <Levfiles Include = "ran-strt.lev"/>
+    <Levfiles Include = "rog-fila.lev"/>
+    <Levfiles Include = "rog-filb.lev"/>
+    <Levfiles Include = "rog-goal.lev"/>
+    <Levfiles Include = "rog-loca.lev"/>
+    <Levfiles Include = "rog-strt.lev"/>
+    <Levfiles Include = "sam-fila.lev"/>
+    <Levfiles Include = "sam-filb.lev"/>
+    <Levfiles Include = "sam-goal.lev"/>
+    <Levfiles Include = "sam-loca.lev"/>
+    <Levfiles Include = "sam-strt.lev"/>
+    <Levfiles Include = "tou-fila.lev"/>
+    <Levfiles Include = "tou-filb.lev"/>
+    <Levfiles Include = "tou-goal.lev"/>
+    <Levfiles Include = "tou-loca.lev"/>
+    <Levfiles Include = "tou-strt.lev"/>
+    <Levfiles Include = "val-fila.lev"/>
+    <Levfiles Include = "val-filb.lev"/>
+    <Levfiles Include = "val-goal.lev"/>
+    <Levfiles Include = "val-loca.lev"/>
+    <Levfiles Include = "val-strt.lev"/>
+    <Levfiles Include = "wiz-fila.lev"/>
+    <Levfiles Include = "wiz-filb.lev"/>
+    <Levfiles Include = "wiz-goal.lev"/>
+    <Levfiles Include = "wiz-loca.lev"/>
+    <Levfiles Include = "wiz-strt.lev"/>
+  </ItemGroup>
+  <ItemGroup>
+    <UUFiles Include = "$(SysWinntDir)nhico.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)mnsel.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)mnselcnt.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)mnunsel.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)petmark.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)pilemark.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)splash.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)rip.uu"/>
+    <UUFiles Include = "$(WinWin32Dir)record.uu"/>
+  </ItemGroup>
+  <ItemGroup>
+    <IconFiles Include = "$(WinWin32Dir)nethack.ico"/>
+  </ItemGroup>
+  <ItemGroup>
+    <RecordFiles Include = "$(WinWin32Dir)record"/>
+  </ItemGroup>
+  <ItemGroup>
+    <BmpFiles Include = "$(WinWin32Dir)mnsel.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)mnselcnt.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)mnunsel.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)petmark.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)pilemark.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)rip.bmp"/>
+    <BmpFiles Include = "$(WinWin32Dir)splash.bmp"/>
+  </ItemGroup>
+  <ItemGroup>
+    <DlbList Include = "$(DatDir)data"/>
+    <DlbList Include = "$(DatDir)oracles"/>
+    <DlbList Include = "$(DatDir)options" Condition="Exists('$(DatDir)options')"/>
+    <DlbList Include = "$(DatDir)ttyoptions" Condition="Exists('$(DatDir)ttyoptions')"/>
+    <DlbList Include = "$(DatDir)guioptions" Condition="Exists('$(DatDir)guioptions')"/>
+    <DlbList Include = "$(DatDir)quest.dat"/>
+    <DlbList Include = "$(DatDir)rumors"/>
+    <DlbList Include = "$(DatDir)engrave"/>
+    <DlbList Include = "$(DatDir)epitaph"/>
+    <DlbList Include = "$(DatDir)bogusmon"/>
+    <DlbList Include = "$(DatDir)tribute"/>
+    <DlbList Include = "$(DatDir)help"/>
+    <DlbList Include = "$(DatDir)porthelp"/>
+    <DlbList Include = "$(DatDir)hh"/>
+    <DlbList Include = "$(DatDir)cmdhelp"/>
+    <DlbList Include = "$(DatDir)history"/>
+    <DlbList Include = "$(DatDir)opthelp"/>
+    <DlbList Include = "$(DatDir)wizhelp"/>
+    <DlbList Include = "$(DatDir)dungeon"/>
+    <DlbList Include = "$(DatDir)license"/>
+    <DlbList Include = "$(DatDir)*.lev"/>
+  </ItemGroup>
+ </Project>
diff --git a/win/win32/vs2017/levcomp.vcxproj b/win/win32/vs2017/levcomp.vcxproj
new file mode 100644 (file)
index 0000000..3fbcffe
--- /dev/null
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{9DD9C52E-E8C9-4533-BD22-83C055C0AABA}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SrcDir)alloc.c" />
+    <ClCompile Include="$(SrcDir)decl.c" />
+    <ClCompile Include="$(SrcDir)drawing.c" />
+    <ClCompile Include="$(UtilDir)lev_lex.c" />
+    <ClCompile Include="$(UtilDir)lev_main.c" />
+    <ClCompile Include="$(UtilDir)lev_yacc.c" />
+    <ClCompile Include="$(SrcDir)monst.c" />
+    <ClCompile Include="$(SrcDir)objects.c" />
+    <ClCompile Include="$(UtilDir)panic.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)lev_comp.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Choose>
+    <When Condition=" '$(YACC)'!='' ">
+      <PropertyGroup>
+        <BuildDependsOn>
+          Lex;
+          Yacc;
+          $(BuildDependsOn);
+        </BuildDependsOn>
+      </PropertyGroup>
+    </When>
+    <Otherwise>
+      <PropertyGroup>
+        <BuildDependsOn>
+          NoLex;
+          NoYacc;
+          $(BuildDependsOn);
+        </BuildDependsOn>
+      </PropertyGroup>
+    </Otherwise>
+  </Choose>
+  <Target Name="Yacc" Inputs="$(UtilDir)lev_comp.y" Outputs="$(UtilDir)lev_yacc.c;$(IncDir)lev_comp.h">
+    <Message Text="Running Yacc" Importance="high" />
+    <Exec Command="$(YACC) -d lev_comp.y" WorkingDirectory="$(UtilDir)" />
+    <Move SourceFiles="$(UtilDir)y.tab.c;$(UtilDir)y.tab.h" DestinationFiles="$(UtilDir)lev_yacc.c;$(IncDir)lev_comp.h" />
+  </Target>
+  <Target Name="Lex" Inputs="$(UtilDir)lev_comp.l" Outputs="$(UtilDir)lev_lex.c">
+    <Message Text="Running Lex" Importance="high" />
+    <Exec Command="$(LEX) lev_comp.l" WorkingDirectory="$(UtilDir)" />
+    <Move SourceFiles="$(UtilDir)lex.yy.c" DestinationFiles="$(UtilDir)lev_lex.c" />
+  </Target>
+  <Target Name="NoYacc" Inputs="$(SysShareDir)lev_yacc.c;$(SysShareDir)lev_comp.h" Outputs="$(UtilDir)lev_yacc.c;$(IncDir)lev_comp.h">
+    <Message Text="No Yacc using pre-built files" Importance="high" />
+    <Copy SourceFiles="$(SysShareDir)lev_yacc.c;$(SysShareDir)lev_comp.h" DestinationFiles="$(UtilDir)lev_yacc.c;$(IncDir)lev_comp.h" />
+  </Target>
+  <Target Name="NoLex" Inputs="$(SysShareDir)lev_lex.c" Outputs="$(UtilDir)lev_lex.c">
+    <Message Text="No Lex using pre-built files" Importance="high" />
+    <Copy SourceFiles="$(SysShareDir)lev_lex.c" DestinationFiles="$(UtilDir)lev_lex.c" />
+  </Target>
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afterlevcomp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afterlevcomp.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+    <Delete Files="$(UtilDir)lev_yacc.c;$(IncDir)lev_comp.h;$(UtilDir)lev_lex.c" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afterlevcomp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/makedefs.vcxproj b/win/win32/vs2017/makedefs.vcxproj
new file mode 100644 (file)
index 0000000..46cc21b
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{BA3DD34C-04B7-40D0-B373-9329AA9E8945}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\util\makedefs.c" />
+    <ClCompile Include="..\..\..\src\monst.c" />
+    <ClCompile Include="..\..\..\src\objects.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\include\config.h" />
+    <ClInclude Include="..\..\..\include\config1.h" />
+    <ClInclude Include="..\..\..\include\context.h" />
+    <ClInclude Include="..\..\..\include\coord.h" />
+    <ClInclude Include="..\..\..\include\global.h" />
+    <ClInclude Include="..\..\..\include\monattk.h" />
+    <ClInclude Include="..\..\..\include\monflag.h" />
+    <ClInclude Include="..\..\..\include\monsym.h" />
+    <ClInclude Include="..\..\..\include\ntconf.h" />
+    <ClInclude Include="..\..\..\include\objclass.h" />
+    <ClInclude Include="..\..\..\include\patchlevel.h" />
+    <ClInclude Include="..\..\..\include\qtext.h" />
+    <ClInclude Include="..\..\..\include\tradstdc.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Target Name="AfterBuild">
+    <MSBuild Projects="aftermakedefs.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="aftermakedefs.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="aftermakedefs.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/nh340key.def b/win/win32/vs2017/nh340key.def
new file mode 100644 (file)
index 0000000..f484a53
--- /dev/null
@@ -0,0 +1,8 @@
+LIBRARY nh340key
+EXPORTS
+ProcessKeystroke
+NHkbhit
+CheckInput
+SourceWhere
+SourceAuthor
+KeyHandlerName
diff --git a/win/win32/vs2017/nh340key.vcxproj b/win/win32/vs2017/nh340key.vcxproj
new file mode 100644 (file)
index 0000000..4c01d59
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{BE04E242-A1E9-4593-B95B-057F37330B76}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>nh340key</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default_dll.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="dll.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <ImportLibrary>$(ToolsDir)$(TargetName).lib</ImportLibrary>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+    <Link>
+      <ModuleDefinitionFile>nh340key.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SysWinntDir)nh340key.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)hack.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(SysWinntDir)win32api.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/nhdefkey.def b/win/win32/vs2017/nhdefkey.def
new file mode 100644 (file)
index 0000000..2950904
--- /dev/null
@@ -0,0 +1,8 @@
+LIBRARY nhdefkey
+EXPORTS
+ProcessKeystroke
+NHkbhit
+CheckInput
+SourceWhere
+SourceAuthor
+KeyHandlerName
diff --git a/win/win32/vs2017/nhdefkey.vcxproj b/win/win32/vs2017/nhdefkey.vcxproj
new file mode 100644 (file)
index 0000000..37a36e0
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{6813477F-64B6-4B97-B230-438D0D233385}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>nhdefkey</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default_dll.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="dll.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <ImportLibrary>$(ToolsDir)$(TargetName).lib</ImportLibrary>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+    <Link>
+      <ModuleDefinitionFile>nhdefkey.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SysWinntDir)nhdefkey.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)hack.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(SysWinntDir)win32api.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/nhraykey.def b/win/win32/vs2017/nhraykey.def
new file mode 100644 (file)
index 0000000..5432a1a
--- /dev/null
@@ -0,0 +1,8 @@
+LIBRARY nhraykey
+EXPORTS
+ProcessKeystroke
+NHkbhit
+CheckInput
+SourceWhere
+SourceAuthor
+KeyHandlerName
diff --git a/win/win32/vs2017/nhraykey.vcxproj b/win/win32/vs2017/nhraykey.vcxproj
new file mode 100644 (file)
index 0000000..fd6c415
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>nhraykey</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default_dll.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="dll.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <ImportLibrary>$(ToolsDir)$(TargetName).lib</ImportLibrary>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+    <Link>
+      <ModuleDefinitionFile>nhraykey.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SysWinntDir)nhraykey.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)hack.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(SysWinntDir)win32api.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/recover.vcxproj b/win/win32/vs2017/recover.vcxproj
new file mode 100644 (file)
index 0000000..75fe4db
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <PropertyGroup>
+    <OutDir>$(BinDir)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(UtilDir)recover.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)config.h" />
+    <ClInclude Include="$(IncDir)config1.h" />
+    <ClInclude Include="$(IncDir)coord.h" />
+    <ClInclude Include="$(IncDir)global.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)tradstdc.h" />
+    <ClInclude Include="$(SysWinntDir)win32api.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afterrecover.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afterrecover.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afterrecover.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/tile2bmp.vcxproj b/win/win32/vs2017/tile2bmp.vcxproj
new file mode 100644 (file)
index 0000000..0c2db97
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{642BC75D-ABAF-403E-8224-7C725FD4CB42}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(SrcDir)decl.c" />
+    <ClCompile Include="$(SrcDir)drawing.c" />
+    <ClCompile Include="$(SrcDir)monst.c" />
+    <ClCompile Include="$(SrcDir)objects.c" />
+    <ClCompile Include="$(WinShareDir)tile2bmp.c" />
+    <ClCompile Include="$(WinShareDir)tiletext.c" />
+    <ClCompile Include="$(WinShareDir)tilemap.c">
+      <PreprocessorDefinitions>TILETEXT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Target Name="AfterBuild">
+    <MSBuild Projects="aftertile2bmp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="aftertile2bmp.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="aftertile2bmp.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/win/win32/vs2017/tilemap.vcxproj b/win/win32/vs2017/tilemap.vcxproj
new file mode 100644 (file)
index 0000000..d9edb8f
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{93F10526-209E-41D7-BBEA-775787876895}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="$(WinShareDir)tilemap.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="$(IncDir)align.h" />
+    <ClInclude Include="$(IncDir)attrib.h" />
+    <ClInclude Include="$(IncDir)color.h" />
+    <ClInclude Include="$(IncDir)config.h" />
+    <ClInclude Include="$(IncDir)config1.h" />
+    <ClInclude Include="$(IncDir)context.h" />
+    <ClInclude Include="$(IncDir)coord.h" />
+    <ClInclude Include="$(IncDir)decl.h" />
+    <ClInclude Include="$(IncDir)dgn_comp.h" />
+    <ClInclude Include="$(IncDir)dgn_file.h" />
+    <ClInclude Include="$(IncDir)display.h" />
+    <ClInclude Include="$(IncDir)dungeon.h" />
+    <ClInclude Include="$(IncDir)engrave.h" />
+    <ClInclude Include="$(IncDir)flag.h" />
+    <ClInclude Include="$(IncDir)global.h" />
+    <ClInclude Include="$(IncDir)mkroom.h" />
+    <ClInclude Include="$(IncDir)monattk.h" />
+    <ClInclude Include="$(IncDir)monst.h" />
+    <ClInclude Include="$(IncDir)monsym.h" />
+    <ClInclude Include="$(IncDir)ntconf.h" />
+    <ClInclude Include="$(IncDir)obj.h" />
+    <ClInclude Include="$(IncDir)objclass.h" />
+    <ClInclude Include="$(IncDir)onames.h" />
+    <ClInclude Include="$(IncDir)permonst.h" />
+    <ClInclude Include="$(IncDir)pm.h" />
+    <ClInclude Include="$(IncDir)prop.h" />
+    <ClInclude Include="$(IncDir)quest.h" />
+    <ClInclude Include="$(IncDir)rect.h" />
+    <ClInclude Include="$(IncDir)region.h" />
+    <ClInclude Include="$(IncDir)rm.h" />
+    <ClInclude Include="$(IncDir)skills.h" />
+    <ClInclude Include="$(IncDir)spell.h" />
+    <ClInclude Include="$(IncDir)timeout.h" />
+    <ClInclude Include="$(IncDir)tradstdc.h" />
+    <ClInclude Include="$(IncDir)trampoli.h" />
+    <ClInclude Include="$(IncDir)trap.h" />
+    <ClInclude Include="$(IncDir)vision.h" />
+    <ClInclude Include="$(IncDir)winprocs.h" />
+    <ClInclude Include="$(IncDir)wintty.h" />
+    <ClInclude Include="$(IncDir)wintype.h" />
+    <ClInclude Include="$(IncDir)you.h" />
+    <ClInclude Include="$(IncDir)youprop.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Target Name="AfterBuild">
+    <MSBuild Projects="aftertilemap.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="aftertilemap.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="aftertilemap.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
similarity index 96%
rename from win/win32/vs2010/tiles.vcxproj
rename to win/win32/vs2017/tiles.vcxproj
index bc8385a..f17bd02 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
       <Configuration>Debug</Configuration>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Makefile</ConfigurationType>
     <UseOfMfc>false</UseOfMfc>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
     <ConfigurationType>Makefile</ConfigurationType>
     <UseOfMfc>false</UseOfMfc>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Makefile</ConfigurationType>
     <UseOfMfc>false</UseOfMfc>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
     <ConfigurationType>Makefile</ConfigurationType>
     <UseOfMfc>false</UseOfMfc>
+    <PlatformToolset>v120</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/win/win32/vs2017/uudecode.vcxproj b/win/win32/vs2017/uudecode.vcxproj
new file mode 100644 (file)
index 0000000..bb03d7f
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="config.props" />
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{63F9B82B-F589-4082-ABE5-D4F0682050AB}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <Import Project="default.props" />
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <Import Project="console.props" />
+  <Import Project="common.props" />
+  <Import Project="dirs.props" />
+  <Import Project="files.props" />
+  <ItemGroup>
+    <ClCompile Include="$(SysShareDir)uudecode.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <Target Name="AfterBuild">
+    <MSBuild Projects="afteruudecode.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterClean">
+    <MSBuild Projects="afteruudecode.proj" Targets="Clean" Properties="Configuration=$(Configuration)" />
+  </Target>
+  <Target Name="AfterRebuild">
+    <MSBuild Projects="afteruudecode.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
+  </Target>
+</Project>
\ No newline at end of file
index efa1551..9b9a40b 100644 (file)
 #endif
 #endif
 
+#undef Protection /* We have a global name space collision.  No source file
+                     using win32api.h should be using the Protection macro
+                     from youprop.h.
+                     A better fix would be to ensure we include all window
+                     header files before we start clobbering the global name
+                     space with NetHack specific macros. */
+
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
+#include <windowsx.h>
 #include <commctrl.h>
 #include <tchar.h>
 #include "hack.h"
+#include "color.h"
 
 /* Create an array to keep track of the various windows */
 
@@ -97,6 +106,8 @@ typedef struct mswin_nhwindow_app {
         regNetHackMode; /* NetHack mode means no Windows keys in some places
                            */
 
+    COLORREF regMapColors[CLR_MAX];
+
     LONG regMainMinX;
     LONG regMainMinY;
     LONG regMainMaxX;
@@ -157,6 +168,7 @@ void mswin_cliparound(int x, int y);
 void mswin_print_glyph(winid wid, XCHAR_P x, XCHAR_P y, int glyph, int bkglyph);
 void mswin_raw_print(const char *str);
 void mswin_raw_print_bold(const char *str);
+void mswin_raw_print_flush();
 int mswin_nhgetch(void);
 int mswin_nh_poskey(int *x, int *y, int *mod);
 void mswin_nhbell(void);
@@ -175,18 +187,11 @@ void mswin_preference_update(const char *pref);
 char *mswin_getmsghistory(BOOLEAN_P init);
 void mswin_putmsghistory(const char *msg, BOOLEAN_P);
 
-#ifdef STATUS_VIA_WINDOWPORT
 void mswin_status_init(void);
 void mswin_status_finish(void);
 void mswin_status_enablefield(int fieldidx, const char *nm, const char *fmt,
                               boolean enable);
-void mswin_status_update(int idx, genericptr_t ptr, int chg, int percent);
-
-#ifdef STATUS_HILITES
-void mswin_status_threshold(int fldidx, int thresholdtype, anything threshold,
-                            int behavior, int under, int over);
-#endif /* STATUS_HILITES */
-#endif /*STATUS_VIA_WINDOWPORT*/
+void mswin_status_update(int idx, genericptr_t ptr, int chg, int percent, int color, unsigned long *colormasks);
 
 /* helper function */
 HWND mswin_hwnd_from_winid(winid wid);
@@ -204,6 +209,7 @@ void mswin_write_reg(void);
 
 void mswin_get_window_placement(int type, LPRECT rt);
 void mswin_update_window_placement(int type, LPRECT rt);
+void mswin_apply_window_style(HWND hwnd);
 
 int NHMessageBox(HWND hWnd, LPCTSTR text, UINT type);
 
@@ -225,7 +231,7 @@ extern COLORREF status_fg_color;
 extern COLORREF message_bg_color;
 extern COLORREF message_fg_color;
 
-#define SYSCLR_TO_BRUSH(x) ((HBRUSH)((x) + 1))
+#define SYSCLR_TO_BRUSH(x) ((HBRUSH)(((intptr_t) x) + 1))
 
 /* unicode stuff */
 #define NH_CODEPAGE (SYMHANDLING(H_IBM) ? GetOEMCP() : GetACP())
index fd9b821..558a958 100644 (file)
@@ -1,4 +1,4 @@
-//Microsoft Developer Studio generated resource script.
+// Microsoft Visual C++ generated resource script.
 //
 #include "resource.h"
 
@@ -19,10 +19,9 @@ LANGUAGE LANG_ENGLISH,SUBLANG_ENGLISH_US
 #undef APSTUDIO_READONLY_SYMBOLS
 
 /////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
+// English (United States) resources
 
 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
 /*JP
 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 */
@@ -31,7 +30,6 @@ LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
 #pragma code_page(1252)
 */
 #pragma code_page(932)
-#endif //_WIN32
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -40,14 +38,15 @@ LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
 
 // Icon with lowest ID value placed first to ensure application icon
 // remains consistent on all systems.
-IDI_NETHACKW            ICON    DISCARDABLE     "NETHACK.ICO"
+IDI_NETHACKW            ICON                    "NETHACK.ICO"
+
 
 /////////////////////////////////////////////////////////////////////////////
 //
 // Menu
 //
 
-IDC_NETHACKW MENU DISCARDABLE 
+IDC_NETHACKW MENU
 BEGIN
 /*JP
     POPUP "&File"
@@ -161,7 +160,7 @@ END
 // Accelerator
 //
 
-IDC_NETHACKW ACCELERATORS MOVEABLE PURE 
+IDC_NETHACKW ACCELERATORS
 BEGIN
     "?",            IDM_ABOUT,              ASCII,  ALT
     "/",            IDM_ABOUT,              ASCII,  ALT
@@ -173,8 +172,8 @@ END
 // Dialog
 //
 
-IDD_ABOUTBOX DIALOG DISCARDABLE  22, 17, 230, 75
-STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+IDD_ABOUTBOX DIALOG 22, 17, 230, 75
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
 CAPTION "About"
 /*JP
 FONT 8, "System"
@@ -187,35 +186,33 @@ BEGIN
 END
 
 IDD_NHTEXT DIALOGEX 0, 0, 172, 178
-STYLE WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME
+STYLE DS_SETFONT | WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME
 EXSTYLE WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT
 /*JP
-FONT 8, "MS Sans Serif", 0, 0
+FONT 8, "MS Sans Serif", 0, 0, 0x1
 */
-FONT 10, "\82l\82\82o\83S\83V\83b\83N", 0, 0
+FONT 10, "\82l\82\82o\83S\83V\83b\83N", 0, 0, 0x1
 BEGIN
-    EDITTEXT        IDC_TEXT_CONTROL,0,0,172,160,ES_MULTILINE | 
-                    ES_OEMCONVERT | ES_READONLY | WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP
+    EDITTEXT        IDC_TEXT_CONTROL,0,0,172,160,ES_MULTILINE | ES_OEMCONVERT | ES_READONLY | WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP
     DEFPUSHBUTTON   "OK",IDOK,54,163,50,14,BS_FLAT | NOT WS_TABSTOP
 END
 
 IDD_MENU DIALOGEX 0, 0, 187, 153
-STYLE WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME
+STYLE DS_SETFONT | WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME
 EXSTYLE WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT
 /*JP
-FONT 8, "MS Sans Serif", 0, 0
+FONT 8, "MS Sans Serif", 0, 0, 0x1
 */
-FONT 10, "\82l\82\82o\83S\83V\83b\83N", 0, 0
+FONT 10, "\82l\82\82o\83S\83V\83b\83N", 0, 0, 0x1
 BEGIN
-    LISTBOX         IDC_MENU_LIST,10,10,170,55,LBS_SORT
-    EDITTEXT        IDC_MENU_TEXT,10,70,170,60,ES_MULTILINE | ES_OEMCONVERT | 
-                    ES_READONLY | WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP
+    LISTBOX         IDC_MENU_LIST,10,10,170,55,LBS_SORT | NOT WS_BORDER
+    EDITTEXT        IDC_MENU_TEXT,10,70,170,60,ES_MULTILINE | ES_OEMCONVERT | ES_READONLY | NOT WS_BORDER | WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP
     DEFPUSHBUTTON   "OK",IDOK,7,132,50,14,BS_FLAT | NOT WS_TABSTOP
     PUSHBUTTON      "Cancel",IDCANCEL,130,132,50,14,BS_FLAT | NOT WS_TABSTOP
 END
 
-IDD_GETLIN DIALOG DISCARDABLE  0, 0, 131, 29
-STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_GETLIN DIALOG 0, 0, 131, 29
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Question?"
 /*JP
 FONT 8, "MS Sans Serif"
@@ -227,8 +224,8 @@ BEGIN
     EDITTEXT        IDC_GETLIN_EDIT,0,0,130,13,ES_AUTOHSCROLL
 END
 
-IDD_EXTCMD DIALOG DISCARDABLE  0, 0, 137, 117
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_EXTCMD DIALOG 0, 0, 137, 117
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Extended Commands"
 /*JP
 FONT 8, "MS Sans Serif"
@@ -237,88 +234,84 @@ FONT 10, "
 BEGIN
     DEFPUSHBUTTON   "OK",IDOK,80,7,50,14
     PUSHBUTTON      "Cancel",IDCANCEL,80,24,50,14
-    LISTBOX         IDC_EXTCMD_LIST,7,7,65,103,LBS_NOINTEGRALHEIGHT | 
-                    WS_VSCROLL | WS_TABSTOP
+    LISTBOX         IDC_EXTCMD_LIST,7,7,65,103,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
 END
 
-IDD_PLAYER_SELECTOR DIALOG DISCARDABLE  0, 0, 152, 169
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_PLAYER_SELECTOR DIALOGEX 0, 0, 225, 212
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "What are you?"
 /*JP
-FONT 8, "MS Sans Serif"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
 */
-FONT 10, "\82l\82\82o\83S\83V\83b\83N"
+FONT 10, "\82l\82\82o\83S\83V\83b\83N", 0, 0, 0x0
 BEGIN
 /*JP
-    DEFPUSHBUTTON   "Play",IDOK,7,148,66,14
+    DEFPUSHBUTTON   "Play",IDOK,12,192,54,14,WS_GROUP
+*/
+    DEFPUSHBUTTON   "OK",IDOK,12,192,54,14,WS_GROUP
+    PUSHBUTTON      "Quit",IDCANCEL,162,192,54,14,WS_GROUP
+    EDITTEXT        IDC_PLSEL_NAME,12,12,105,12,ES_AUTOHSCROLL | ES_READONLY | WS_GROUP | NOT WS_TABSTOP
+/*JP
+    CONTROL         "Neutral",IDC_PLSEL_ALIGN_NEUTRAL,"Button",BS_AUTORADIOBUTTON,168,60,37,10
 */
-    DEFPUSHBUTTON   "OK",IDOK,7,148,66,14
-    PUSHBUTTON      "Quit",IDCANCEL,79,148,66,14
+    CONTROL         "\92\86\97§",IDC_PLSEL_ALIGN_NEUTRAL,"Button",BS_AUTORADIOBUTTON,168,60,37,10
 /*JP
-    LTEXT           "Name:",IDC_STATIC,7,8,25,10
+    CONTROL         "Lawful",IDC_PLSEL_ALIGN_LAWFUL,"Button",BS_AUTORADIOBUTTON | WS_GROUP,168,48,35,10
 */
-    LTEXT           "\96¼\91O:",IDC_STATIC,7,8,25,10
-    EDITTEXT        IDC_PLSEL_NAME,40,7,105,12,ES_AUTOHSCROLL | ES_READONLY | 
-                    NOT WS_TABSTOP
+    CONTROL         "\92\81\8f\98",IDC_PLSEL_ALIGN_LAWFUL,"Button",BS_AUTORADIOBUTTON | WS_GROUP,168,48,35,10
 /*JP
-    GROUPBOX        "Role",IDC_STATIC,7,21,138,30
+    CONTROL         "Chaotic",IDC_PLSEL_ALIGN_CHAOTIC,"Button",BS_AUTORADIOBUTTON,168,72,38,10
 */
-    GROUPBOX        "\90E\8bÆ",IDC_STATIC,7,21,138,30
+    CONTROL         "\8d¬\93×",IDC_PLSEL_ALIGN_CHAOTIC,"Button",BS_AUTORADIOBUTTON,168,72,38,10
 /*JP
-    CONTROL         "Random",IDC_PLSEL_ROLE_RANDOM,"Button",BS_AUTOCHECKBOX | 
+    CONTROL         "Male",IDC_PLSEL_GENDER_MALE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,168,108,30,10
 */
-    CONTROL         "\83\89\83\93\83_\83\80",IDC_PLSEL_ROLE_RANDOM,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,14,34,40,10
-    COMBOBOX        IDC_PLSEL_ROLE_LIST,63,33,75,50,CBS_DROPDOWNLIST | 
-                    WS_VSCROLL | WS_TABSTOP
+    CONTROL         "\92j\90«",IDC_PLSEL_GENDER_MALE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,168,108,30,10
 /*JP
-    GROUPBOX        "Race",IDC_STATIC,7,51,138,30
+    CONTROL         "Female",IDC_PLSEL_GENDER_FEMALE,"Button",BS_AUTORADIOBUTTON,168,120,38,10
 */
-    GROUPBOX        "\8eí\91°",IDC_STATIC,7,51,138,30
+    CONTROL         "\8f\97\90«",IDC_PLSEL_GENDER_FEMALE,"Button",BS_AUTORADIOBUTTON,168,120,38,10
 /*JP
-    CONTROL         "Random",IDC_PLSEL_RACE_RANDOM,"Button",BS_AUTOCHECKBOX | 
+    GROUPBOX        "Alignment",IDC_STATIC,162,36,48,54
 */
-    CONTROL         "\83\89\83\93\83_\83\80",IDC_PLSEL_RACE_RANDOM,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,14,63,40,10
-    COMBOBOX        IDC_PLSEL_RACE_LIST,63,62,75,45,CBS_DROPDOWNLIST | 
-                    WS_VSCROLL | WS_TABSTOP
+    GROUPBOX        "\91®\90«",IDC_STATIC,162,36,48,54
 /*JP
-    GROUPBOX        "Gender",IDC_STATIC,7,81,138,30
+    GROUPBOX        "Gender",IDC_STATIC,162,96,48,42
 */
-    GROUPBOX        "\90«\95Ê",IDC_STATIC,7,81,138,30
+    GROUPBOX        "\90«\95Ê",IDC_STATIC,162,96,48,42
 /*JP
-    CONTROL         "Random",IDC_PLSEL_GENDER_RANDOM,"Button",
+    GROUPBOX        "Role",IDC_STATIC,6,36,72,150
 */
-    CONTROL         "\83\89\83\93\83_\83\80",IDC_PLSEL_GENDER_RANDOM,"Button",
-                    BS_AUTOCHECKBOX | WS_TABSTOP,14,93,40,10
-    COMBOBOX        IDC_PLSEL_GENDER_LIST,63,92,75,40,CBS_DROPDOWNLIST | 
-                    WS_VSCROLL | WS_TABSTOP
+    GROUPBOX        "\90E\8bÆ",IDC_STATIC,6,36,72,150
 /*JP
-    GROUPBOX        "Alignment",IDC_STATIC,7,111,138,30
+    GROUPBOX        "Race",IDC_STATIC,84,36,72,72
 */
-    GROUPBOX        "\91®\90«",IDC_STATIC,7,111,138,30
+    GROUPBOX        "\8eí\91°",IDC_STATIC,84,36,72,72
 /*JP
-    CONTROL         "Random",IDC_PLSEL_ALIGN_RANDOM,"Button",BS_AUTOCHECKBOX | 
+    PUSHBUTTON      "Random",IDC_PLSEL_RANDOM,90,192,54,14,WS_GROUP
 */
-    CONTROL         "\83\89\83\93\83_\83\80",IDC_PLSEL_ALIGN_RANDOM,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,13,123,40,10
-    COMBOBOX        IDC_PLSEL_ALIGN_LIST,63,122,75,45,CBS_DROPDOWNLIST | 
-                    WS_VSCROLL | WS_TABSTOP
+    PUSHBUTTON      "\83\89\83\93\83_\83\80",IDC_PLSEL_RANDOM,90,192,54,14,WS_GROUP
+/*JP
+    GROUPBOX        "Name",IDC_STATIC,6,0,120,30
+*/
+    GROUPBOX        "\96¼\91O",IDC_STATIC,6,0,120,30
+    CONTROL         "",IDC_PLSEL_ROLE_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_OWNERDRAWFIXED | LVS_ALIGNLEFT | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_GROUP | WS_TABSTOP,12,48,60,130
+    CONTROL         "",IDC_PLSEL_RACE_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_OWNERDRAWFIXED | LVS_ALIGNLEFT | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_GROUP | WS_TABSTOP,90,48,60,51
 END
 
 IDD_NHRIP DIALOGEX 0, 0, 281, 209
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Here lies..."
 /*JP
-FONT 8, "MS Sans Serif", 0, 0
+FONT 8, "MS Sans Serif", 0, 0, 0x1
 */
 FONT 10, "\82l\82\82o\83S\83V\83b\83N", 0, 0
 BEGIN
     DEFPUSHBUTTON   "OK",IDOK,82,188,50,14
 END
 
-IDD_SPLASH DIALOG DISCARDABLE  0, 0, 281, 257
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_SPLASH DIALOG 0, 0, 281, 257
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Welcome to NetHack"
 /*JP
 FONT 8, "MS Sans Serif"
@@ -326,8 +319,7 @@ FONT 8, "MS Sans Serif"
 FONT 10, "\82l\82\82o\83S\83V\83b\83N"
 BEGIN
     DEFPUSHBUTTON   "OK",IDOK,224,236,50,14
-    EDITTEXT        IDC_EXTRAINFO,7,176,267,52,ES_MULTILINE | ES_READONLY | 
-                    WS_VSCROLL
+    EDITTEXT        IDC_EXTRAINFO,7,176,267,52,ES_MULTILINE | ES_READONLY | WS_VSCROLL
 END
 
 
@@ -337,7 +329,7 @@ END
 // TEXTINCLUDE
 //
 
-2 TEXTINCLUDE DISCARDABLE 
+2 TEXTINCLUDE 
 BEGIN
     "#if defined(__BORLANDC__)\r\n"
     "LANGUAGE LANG_ENGLISH,SUBLANG_ENGLISH_US\r\n"
@@ -349,13 +341,13 @@ BEGIN
     "\0"
 END
 
-3 TEXTINCLUDE DISCARDABLE 
+3 TEXTINCLUDE 
 BEGIN
     "\r\n"
     "\0"
 END
 
-1 TEXTINCLUDE DISCARDABLE 
+1 TEXTINCLUDE 
 BEGIN
     "resource.h\0"
 END
@@ -368,14 +360,22 @@ END
 // Bitmap
 //
 
-IDB_TILES               BITMAP  DISCARDABLE     "tiles.bmp"
-IDB_MENU_SEL            BITMAP  DISCARDABLE     "mnsel.bmp"
-IDB_MENU_UNSEL          BITMAP  DISCARDABLE     "mnunsel.bmp"
-IDB_PETMARK             BITMAP  DISCARDABLE     "petmark.bmp"
-IDB_PILEMARK            BITMAP  DISCARDABLE     "pilemark.bmp"
-IDB_MENU_SEL_COUNT      BITMAP  DISCARDABLE     "mnselcnt.bmp"
-IDB_RIP                 BITMAP  DISCARDABLE     "rip.bmp"
-IDB_SPLASH              BITMAP  DISCARDABLE     "splash.bmp"
+IDB_TILES               BITMAP                  "tiles.bmp"
+
+IDB_MENU_SEL            BITMAP                  "mnsel.bmp"
+
+IDB_MENU_UNSEL          BITMAP                  "mnunsel.bmp"
+
+IDB_PETMARK             BITMAP                  "petmark.bmp"
+
+IDB_PILEMARK            BITMAP                  "pilemark.bmp"
+
+IDB_MENU_SEL_COUNT      BITMAP                  "mnselcnt.bmp"
+
+IDB_RIP                 BITMAP                  "rip.bmp"
+
+IDB_SPLASH              BITMAP                  "splash.bmp"
+
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -383,7 +383,7 @@ IDB_SPLASH              BITMAP  DISCARDABLE     "splash.bmp"
 //
 
 #ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO DISCARDABLE 
+GUIDELINES DESIGNINFO
 BEGIN
     IDD_NHTEXT, DIALOG
     BEGIN
@@ -414,9 +414,9 @@ BEGIN
     IDD_PLAYER_SELECTOR, DIALOG
     BEGIN
         LEFTMARGIN, 7
-        RIGHTMARGIN, 145
+        RIGHTMARGIN, 218
         TOPMARGIN, 7
-        BOTTOMMARGIN, 162
+        BOTTOMMARGIN, 205
     END
 
     IDD_NHRIP, DIALOG
@@ -443,8 +443,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 3,5,0,0
- PRODUCTVERSION 3,5,0,0
+ FILEVERSION 3,6,1,0
+ PRODUCTVERSION 3,6,1,0
  FILEFLAGSMASK 0x1fL
 #ifdef _DEBUG
  FILEFLAGS 0x9L
@@ -459,14 +459,14 @@ BEGIN
     BEGIN
         BLOCK "040904b0"
         BEGIN
-            VALUE "FileDescription", "NetHack for Windows - Graphical Interface\0"
-            VALUE "FileVersion", "3.5.0\0"
-            VALUE "InternalName", "NetHackW\0"
-            VALUE "LegalCopyright", "Copyright (C) 1985 - 2006.  By Stichting Mathematisch Centrum and M. Stephenson.  See license for details.\0"
-            VALUE "OriginalFilename", "NetHackW.exe\0"
-            VALUE "PrivateBuild", "140606\0"
-            VALUE "ProductName", "NetHack\0"
-            VALUE "ProductVersion", "3.5.0\0"
+            VALUE "FileDescription", "NetHack for Windows - Graphical Interface"
+            VALUE "FileVersion", "3.6.1"
+            VALUE "InternalName", "NetHackW"
+            VALUE "LegalCopyright", "Copyright (C) 1985 - 2018.  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.1"
         END
     END
     BLOCK "VarFileInfo"
@@ -475,12 +475,24 @@ BEGIN
     END
 END
 
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// AFX_DIALOG_LAYOUT
+//
+
+IDD_PLAYER_SELECTOR AFX_DIALOG_LAYOUT
+BEGIN
+    0
+END
+
+
 /////////////////////////////////////////////////////////////////////////////
 //
 // String Table
 //
 
-STRINGTABLE DISCARDABLE 
+STRINGTABLE
 BEGIN
 /*JP
     IDS_APP_TITLE           "JNetHack for Windows - Graphical Interface"
@@ -490,7 +502,7 @@ BEGIN
     IDS_APP_TITLE_SHORT     "NetHack for Windows"
 END
 
-#endif    // English (U.S.) resources
+#endif    // English (United States) resources
 /////////////////////////////////////////////////////////////////////////////