diff --git a/dat/history b/dat/history index 7dcaaca18..9e5979862 100644 --- a/dat/history +++ b/dat/history @@ -223,7 +223,7 @@ for decades, joined the NetHack Development Team in late May 2019. NetHack 3.6.3 was released on December 5, 2019 containing over 190 bug fixes to NetHack 3.6.2. -NetHack 3.6.4 was released on December 17, 2019 containing a security +NetHack 3.6.4 was released on December 18, 2019 containing a security fix and a few bug fixes. The official NetHack web site is maintained by Ken Lorber at diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index be4279bbe..c85238f4d 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -24,7 +24,7 @@ .ds vr "NetHack 3.7 .ds f0 "\*(vr .ds f1 -.ds f2 "December 17, 2019 +.ds f2 "December 18, 2019 . .\" A note on some special characters: .\" \(lq = left double quote @@ -4800,6 +4800,13 @@ 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 +ACCESSIBILITY\ =\ 0 or 1 to disable or enable, respectively, the ability for players +to set S_pet_override and S_hero_override symbols in their configuration file. +.lp +PORTABLE_DEVICE_PATHS\ =\ 0 or 1 Windows OS only, the game will look +for all of its external files, and write to all of its output files in one place +rather than at the standard locations. +.lp 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: @@ -5162,7 +5169,7 @@ participant for decades, joined the NetHack Development Team in late May 2019. NetHack 3.6.3 was released on December 5, 2019 containing over 190 bug fixes to NetHack 3.6.2. .pg -NetHack 3.6.4 was released on December 17, 2019 containing a security fix +NetHack 3.6.4 was released on December 18, 2019 containing a security fix and a few bug fixes. .pg The official NetHack web site is maintained by \fBKen Lorber\fP diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 05fa7ae6c..4e36344af 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -45,7 +45,7 @@ %.au \author{Original version - Eric S. Raymond\\ (Edited and expanded for 3.6 by Mike Stephenson and others)} -\date{December 17, 2019} +\date{December 18, 2019} \maketitle @@ -5309,6 +5309,16 @@ Minimum number of points to get an entry in the score file. 0 or 1 to use user names or numeric userids, respectively, to identify unique people for the score file %.lp +\item[\ib{ACCESSIBILITY}] +0 or 1 to disable or enable, respectively, the ability for players +to set S\verb+_+pet\verb+_+override and S\verb+_+hero\verb+_+override +symbols in their configuration file. +%.lp +\item[\ib{PORTABLE\verb+_+DEVICE\verb+_+PATHS}] +0 or 1 Windows OS only, the game will look for all of its external +files, and write to all of its output files in one place +rather than at the standard locations. +%.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 @@ -5767,7 +5777,7 @@ fixes to NetHack 3.6.2. %.pg \medskip -NetHack 3.6.4 was released on December 17, 2019 containing a security fix and +NetHack 3.6.4 was released on December 18, 2019 containing a security fix and a few bug fixes. %.pg diff --git a/doc/Guidebook.txt b/doc/Guidebook.txt index df6454bbb..e6d62d1d3 100644 --- a/doc/Guidebook.txt +++ b/doc/Guidebook.txt @@ -15,7 +15,7 @@ Original version - Eric S. Raymond (Edited and expanded for 3.6 by Mike Stephenson and others) - December 17, 2019 + December 18, 2019 @@ -5634,6 +5634,15 @@ MAX_STATUENAME_RANK = Maximum number of score file entries to use for random statue names (default is 10). + ACCESSIBILITY = 0 or 1 to disable or enable, respectively, the + ability for players to set S_pet_override and S_hero_override + symbols in their configuration file. + + PORTABLE_DEVICE_PATHS = 0 or 1 Windows OS only, the game will + look for all of its external files, and write to all of its + output files in one place rather than at the standard loca- + tions. + DUMPLOGFILE = A filename where the end-of-game dumplog is saved. Not defining this will prevent dumplog from being cre- ated. Only available if your game is compiled with DUMPLOG. Al- @@ -5685,6 +5694,15 @@ If you just want to see what the current top players/games list is, you can type nethack -s all on most versions. + + NetHack is an intricate and difficult game. Novices might + "discovery" mode that enables you to keep old save files and + cheat death, at the paltry cost of not getting on the high score + + 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" + NetHack 3.6 December 18, 2019 11. Explore mode NetHack is an intricate and difficult game. Novices might @@ -5751,16 +5769,21 @@ Andries Brouwer did a major re-write, transforming Hack into a very different game, and published (at least) three versions - (1.0.1, 1.0.2, and 1.0.3) for UNIX machines to the Usenet. Don G. Kneller ported Hack 1.0.3 to Microsoft C and MS-DOS, producing PC HACK 1.01e, added support for DEC Rainbow graphics in version 1.03g, and went on to produce at least four more ver- - sions (3.0, 3.2, 3.51, and 3.6). R. Black ported PC HACK 3.51 to Lattice C and the Atari - 520/1040ST, producing ST Hack 1.03. + incorporating many of the added features, and produced NetHack + NetHack Guidebook 88 + Don G. Kneller ported Hack 1.0.3 to Microsoft C and MS-DOS, + producing PC HACK 1.01e, added support for DEC Rainbow graphics + in version 1.03g, and went on to produce at least four more ver- + sions (3.0, 3.2, 3.51, and 3.6). + R. Black ported PC HACK 3.51 to Lattice C and the Atari + 520/1040ST, producing ST Hack 1.03. Mike Stephenson merged these various versions back together, incorporating many of the added features, and produced NetHack 1.4. He then coordinated a cast of thousands in enhancing and @@ -5815,9 +5838,18 @@ Jon W{tte and Hao-yang Wang, with help from Ross Brown, Mike Engber, David Hairston, Michael Hamel, Jonathan Handler, Johnny Lee, Tim Lennan, Rob Menke, and Andy Swanson, developed NetHack - 3.1 for the Macintosh, porting it for MPW. Building on their de- - velopment, Bart House added a Think C port. + 3.1 for the Macintosh, porting it for MPW. Building on their + ed NetHack 3.1 to the Atari. Pat Rankin, with help from Joshua + Delahunty, was responsible for the VMS version of NetHack 3.1. + + Dean Luick, with help from David Cohrs, developed NetHack + 3.1 for X11. Warwick Allison wrote a tiled version of NetHack + for the Atari; he later contributed the tiles to the NetHack De- + velopment Team and tile support was then added to other plat- + + NetHack Guidebook 89 + development, Bart House added a Think C port. Timo Hakulinen ported NetHack 3.1 to OS/2. Eric Smith port- ed NetHack 3.1 to the Atari. Pat Rankin, with help from Joshua Delahunty, was responsible for the VMS version of NetHack 3.1. @@ -5828,7 +5860,6 @@ for the Atari; he later contributed the tiles to the NetHack De- velopment Team and tile support was then added to other plat- forms. - The 3.2 NetHack Development Team, comprised of Michael Alli- son, Ken Arromdee, David Cohrs, Jessie Collet, Steve Creps, Kevin Darcy, Timo Hakulinen, Steve Linhart, Dean Luick, Pat Rankin, Er- @@ -5882,6 +5913,18 @@ lison, Ken Arromdee, David Cohrs, Jessie Collet, Steve Creps, Kevin Darcy, Timo Hakulinen, Kevin Hugo, Steve Linhart, Ken Lor- ber, Dean Luick, Pat Rankin, Eric Smith, Mike Stephenson, Janet + + + NetHack 3.6 December 18, 2019 + + + + + + NetHack Guidebook 90 + + + Walz, and Paul Winner, released 3.3.0 in December 1999 and 3.3.1 in August of 2000. @@ -5949,6 +5992,18 @@ The release of NetHack 3.4.3 in December 2003 marked the be- ginning of a long release hiatus. 3.4.3 proved to be a remarkably + + + NetHack 3.6 December 18, 2019 + + + + + + NetHack Guidebook 91 + + + stable version that provided continued enjoyment by the community for more than a decade. The NetHack Development Team slowly and quietly continued to work on the game behind the scenes during @@ -6014,6 +6069,19 @@ Alex Kompel, Dion Nicolaas, Derek S. Ray and Yitzhak Sapir main- tained the port of NetHack 3.6 for Microsoft Windows. + + + + NetHack 3.6 December 18, 2019 + + + + + + NetHack Guidebook 92 + + + Pat Rankin attempted to keep the VMS port running for NetHack 3.6, hindered by limited access. Kevin Smolkowski has up- dated and tested it for the most recent version of OpenVMS (V8.4 @@ -6042,7 +6110,7 @@ NetHack 3.6.3 was released on December 5, 2019 containing over 190 bug fixes to NetHack 3.6.2. - NetHack 3.6.4 was released on December 17, 2019 containing a + NetHack 3.6.4 was released on December 18, 2019 containing a security fix and a few bug fixes. The official NetHack web site is maintained by Ken Lorber at @@ -6079,6 +6147,19 @@ of Dungeoneers: Adam Aronow J. Ali Harlow Mikko Juola Alex Kompel Janet Walz Nathan Eady + + + + NetHack 3.6 December 18, 2019 + + + + + + NetHack Guidebook 93 + + + Alex Smith Janne Salmijarvi Norm Meluch Andreas Dorn Jean-Christophe Collet Olaf Seibert Andy Church Jeff Bailey Pasi Kallinen diff --git a/doc/fixes36.4 b/doc/fixes36.4 index 441dd7770..c199560c4 100644 --- a/doc/fixes36.4 +++ b/doc/fixes36.4 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.4 $ $NHDT-Date: 1576287569 2019/12/14 01:39:29 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.12 $ $NHDT-Date: 1576638499 2019/12/18 03:08:19 $ fixes36.4 contains a terse summary of changes made to 3.6.3 in order to produce 3.6.4. @@ -16,12 +16,19 @@ message "your knapsack can't accomodate any more items" when picking stuff up pending; vary the message rather than add more convoluted pickup code dozen-ish assorted spelling/typo fixes in messages and source comments fix potential buffer overflow when parsing run-time configuration file +wizard mode wishing for terrain would leave it unmapped if done while blind +wizard mode terrain wish could leave hero in water (severe vision limits) or + in lava (trapped, sinking) which wasn't there any more +flying hero can go down (via '>') holes or trap doors instead of escaping trap +polymorphed hero hiding on the ceiling can now use '>' to unhide instead of + being told "you can't go down here" Platform- and/or Interface-Specific Fixes or Features ----------------------------------------------------- fix compilation on platforms that split the ncurses and tinfo libraries -allow run-from-removable-device on Windows +Windows: allow all game files to be on a portable device via the sysconf + option 'portable_device_paths' General New Features diff --git a/include/mondata.h b/include/mondata.h index e35601ae4..e84a09272 100644 --- a/include/mondata.h +++ b/include/mondata.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 mondata.h $NHDT-Date: 1550524558 2019/02/18 21:15:58 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.37 $ */ +/* NetHack 3.6 mondata.h $NHDT-Date: 1576626512 2019/12/17 23:48:32 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.39 $ */ /* Copyright (c) 1989 Mike Threepoint */ /* NetHack may be freely redistributed. See license for details. */ @@ -31,6 +31,7 @@ (is_minion((mon)->data) && mon_aligntyp(mon) == A_LAWFUL) #define is_flyer(ptr) (((ptr)->mflags1 & M1_FLY) != 0L) #define is_floater(ptr) ((ptr)->mlet == S_EYE || (ptr)->mlet == S_LIGHT) +/* clinger: piercers, mimics, wumpus -- generally don't fall down holes */ #define is_clinger(ptr) (((ptr)->mflags1 & M1_CLING) != 0L) #define is_swimmer(ptr) (((ptr)->mflags1 & M1_SWIM) != 0L) #define breathless(ptr) (((ptr)->mflags1 & M1_BREATHLESS) != 0L) @@ -41,14 +42,24 @@ #define noncorporeal(ptr) ((ptr)->mlet == S_GHOST) #define tunnels(ptr) (((ptr)->mflags1 & M1_TUNNEL) != 0L) #define needspick(ptr) (((ptr)->mflags1 & M1_NEEDPICK) != 0L) +/* hides_under() requires an object at the location in order to hide */ #define hides_under(ptr) (((ptr)->mflags1 & M1_CONCEAL) != 0L) +/* is_hider() is True for mimics but when hiding they appear as something + else rather than become mon->mundetected, so use is_hider() with care */ #define is_hider(ptr) (((ptr)->mflags1 & M1_HIDE) != 0L) +/* piercers cling to the ceiling; lurkers above are hiders but they fly + so aren't classified as clingers; unfortunately mimics are classified + as both hiders and clingers but have nothing to do with ceilings; + wumpuses (not wumpi :-) cling but aren't hiders */ +#define ceiling_hider(ptr) \ + (is_hider(ptr) && ((is_clinger(ptr) && (ptr)->mlet != S_MIMIC) \ + || is_flyer(ptr))) /* lurker above */ #define haseyes(ptr) (((ptr)->mflags1 & M1_NOEYES) == 0L) -#define eyecount(ptr) \ - (!haseyes(ptr) ? 0 : ((ptr) == &mons[PM_CYCLOPS] \ - || (ptr) == &mons[PM_FLOATING_EYE]) \ - ? 1 \ - : 2) +/* used to decide whether plural applies so no need for 'more than 2' */ +#define eyecount(ptr) \ + (!haseyes(ptr) ? 0 \ + : ((ptr) == &mons[PM_CYCLOPS] || (ptr) == &mons[PM_FLOATING_EYE]) ? 1 \ + : 2) #define nohands(ptr) (((ptr)->mflags1 & M1_NOHANDS) != 0L) #define nolimbs(ptr) (((ptr)->mflags1 & M1_NOLIMBS) == M1_NOLIMBS) #define notake(ptr) (((ptr)->mflags1 & M1_NOTAKE) != 0L) diff --git a/include/patchlevel.h b/include/patchlevel.h index 47de7c295..3d272ed14 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -44,13 +44,30 @@ /****************************************************************************/ /* Version 3.6.x */ -/* Patch 4, December 17, 2019 +/* Patch 4, December 18, 2019 + * + * fix potential buffer overflow when parsing run-time configuration file * GDBPATH and GREPPATH from sysconf or -D... on compilation command line were * being processed even if PANICTRACE was disabled but only being freed * at end of game when that was enabled - * fix the article used in the message when your steed encounters a polymorph trap + * fix the article used in the message when your steed encounters a polymorph + * trap + * allow teleporting onto the vibrating square + * message "your knapsack can't accomodate any more items" when picking stuff + * up or removing such from container was inaccurate if there was some + * gold pending; vary the message rather than add more convoluted pickup + * code * dozen-ish assorted spelling/typo fixes in messages and source comments - * fix potential buffer overflow when parsing run-time configuration file + * wizard mode wishing for terrain would leave it unmapped if done while blind + * wizard mode terrain wish could leave hero in water (severe vision limits) + * or in lava (trapped, sinking) which wasn't there any more + * flying hero can go down (via '>') holes or trap doors instead of escaping + * trap + * polymorphed hero hiding on the ceiling can now use '>' to unhide instead of + * being told "you can't go down here" + * fix compilation on platforms that split the ncurses and tinfo libraries + * Windows: allow all game files to be on a portable device via the sysconf + * option 'portable_device_paths' */ /* Patch 3, December 5, 2019 @@ -69,7 +86,7 @@ * Added several grammar corrections * Improved recognition of deafness for several situations including the * playing of musical instruments and bribing negotiations with demon lords - * Fixed ignoring of god's wrath when hero injured himself during altar kick + * Fixed ignoring of god's wrath when hero injured himself during altar kick * Fixed several cases where persistent inventory window was not updated * Fixed temple priests or shopkeepers moving over other monsters * Fixed a crash-causing bug when putting on levitation boots over a sink @@ -82,14 +99,14 @@ * the Windows platform * Improved the layout and display of the player selection dialog used on the * Windows graphical implementation - * Improved performance of some tty versions by reducing the number of + * Improved performance of some tty versions by reducing the number of * function calls made from mapglyph * Allowed the msdos implementation to build with curses and PDCurses * Included over 100 other fixes and improvements as outlined in doc/fixes36.3 */ /* Patch 2, May 7, 2019 - * + * * Over 320 bug fixes including a couple of crash bug fixes as outlined in * doc/fixes36.2 * More than 15 enhancements or improvements diff --git a/include/sys.h b/include/sys.h index 16382ef99..afb1fc865 100644 --- a/include/sys.h +++ b/include/sys.h @@ -17,9 +17,6 @@ struct sysopt { char *debugfiles; /* files to show debugplines in. '*' is all. */ #ifdef DUMPLOG char *dumplogfile; /* where the dump file is saved */ -#endif -#ifdef WIN32 - char *portable_device_top; /* nethack configuration for a portable drive */ #endif int env_dbgfl; /* 1: debugfiles comes from getenv("DEBUGFILES") * so sysconf's DEBUGFILES shouldn't override it; @@ -51,7 +48,9 @@ struct sysopt { /* enable accessibility options */ int accessibility; - +#ifdef WIN32 + int portable_device_paths; /* nethack configuration for a portable device */ +#endif }; extern struct sysopt sysopt; diff --git a/src/do.c b/src/do.c index 65913f1dc..98a8ff3f2 100644 --- a/src/do.c +++ b/src/do.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do.c $NHDT-Date: 1576181796 2019/12/12 20:16:36 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.197 $ */ +/* NetHack 3.6 do.c $NHDT-Date: 1576638499 2019/12/18 03:08:19 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.198 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -994,6 +994,24 @@ dodown() : surface(u.ux, u.uy)); return 0; /* didn't move */ } + + if (Upolyd && ceiling_hider(&mons[u.umonnum]) && u.uundetected) { + u.uundetected = 0; + if (Flying) { /* lurker above */ + You("fly out of hiding."); + } else { /* piercer */ + You("drop to the %s.", surface(u.ux, u.uy)); + if (is_pool_or_lava(u.ux, u.uy)) { + pooleffects(FALSE); + } else { + (void) pickup(1); + if ((trap = t_at(u.ux, u.uy)) != 0) + dotrap(trap, TOOKPLUNGE); + } + } + return 1; /* came out of hiding; might need '>' again to go down */ + } + if (!stairs_down && !ladder_down) { trap = t_at(u.ux, u.uy); if (trap && (uteetering_at_seen_pit(trap) || uescaped_shaft(trap))) { diff --git a/src/files.c b/src/files.c index ae4f497c4..82d6330df 100644 --- a/src/files.c +++ b/src/files.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 files.c $NHDT-Date: 1576096997 2019/12/11 20:43:17 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.301 $ */ +/* NetHack 3.7 files.c $NHDT-Date: 1576626110 2019/12/17 23:41:50 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.276 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2595,12 +2595,6 @@ char *origbuf; if (sysopt.dumplogfile) free((genericptr_t) sysopt.dumplogfile); sysopt.dumplogfile = dupstr(bufp); -#endif -#ifdef WIN32 - } else if (src == SET_IN_SYS && match_varname(buf, "portable_device_top", 8)) { - if (sysopt.portable_device_top) - free((genericptr_t) sysopt.portable_device_top); - sysopt.portable_device_top = dupstr(bufp); #endif } else if (src == SET_IN_SYS && match_varname(buf, "GENERICUSERS", 12)) { if (sysopt.genericusers) @@ -2741,6 +2735,16 @@ char *origbuf; return FALSE; } sysopt.accessibility = n; +#ifdef WIN32 + } else if (src == SET_IN_SYS + && match_varname(buf, "portable_device_paths", 8)) { + n = atoi(bufp); + if (n < 0 || n > 1) { + config_error_add("Illegal value in portable_device_paths (not 0,1)."); + return FALSE; + } + sysopt.portable_device_paths = n; +#endif #endif /* SYSCF */ } else if (match_varname(buf, "BOULDER", 3)) { @@ -3296,7 +3300,8 @@ boolean FDECL((*proc), (char *)); free(buf); } buf = strcat(tmpbuf, ep); - buf[sizeof inbuf - 1] = '\0'; + if (strlen(buf) >= sizeof inbuf) + buf[sizeof inbuf - 1] = '\0'; } if (morelines || (ignoreline && !oldline)) @@ -4338,11 +4343,10 @@ reveal_paths(VOID_ARGS) raw_printf("No end-of-game disclosure file (%s).", nodumpreason); #ifdef WIN32 - if (sysopt.portable_device_top) { + if (sysopt.portable_device_paths) { const char *pd = get_portable_device(); - raw_printf("Writable folder for portable device config (sysconf %s):", - "portable_device_top"); + raw_printf("portable_device_paths (set in sysconf):"); raw_printf(" \"%s\"", pd); } #endif diff --git a/src/hack.c b/src/hack.c index b38ae799c..9715c8285 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.c $NHDT-Date: 1568509227 2019/09/15 01:00:27 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.216 $ */ +/* NetHack 3.6 hack.c $NHDT-Date: 1576638500 2019/12/18 03:08:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.220 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2123,6 +2123,10 @@ boolean newspot; /* true if called by spoteffects */ } /* not mounted */ + /* if hiding on ceiling then don't automatically enter pool */ + if (Upolyd && ceiling_hider(&mons[u.umonnum]) && u.uundetected) + return FALSE; + /* drown(),lava_effects() return true if hero changes location while surviving the problem */ if (is_lava(u.ux, u.uy)) { diff --git a/src/objnam.c b/src/objnam.c index 16b41cb73..bae9e5974 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 objnam.c $NHDT-Date: 1575768412 2019/12/08 01:26:52 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.273 $ */ +/* NetHack 3.7 objnam.c $NHDT-Date: 1576638500 2019/12/18 03:08:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.257 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -3675,14 +3675,17 @@ struct obj *no_wish; goto typfnd; } } -/* Let wizards wish for traps and furniture. - * Must come after objects check so wizards can still wish for - * trap objects like beartraps. - * Disallow such topology tweaks for WIZKIT startup wishes. - */ + + /* + * Let wizards wish for traps and furniture. + * Must come after objects check so wizards can still wish for + * trap objects like beartraps. + * Disallow such topology tweaks for WIZKIT startup wishes. + */ wiztrap: if (wizard && !g.program_state.wizkit_wishing) { struct rm *lev; + boolean madeterrain = FALSE; int trap, x = u.ux, y = u.uy; for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) { @@ -3705,7 +3708,8 @@ struct obj *no_wish; return (struct obj *) &cg.zeroobj; } - /* furniture and terrain */ + /* furniture and terrain (use at your own risk; can clobber stairs + or place furniture on existing traps which shouldn't be allowed) */ lev = &levl[x][y]; p = eos(bp); if (!BSTRCMPI(bp, p - 8, "fountain")) { @@ -3714,43 +3718,36 @@ struct obj *no_wish; if (!strncmpi(bp, "magic ", 6)) lev->blessedftn = 1; pline("A %sfountain.", lev->blessedftn ? "magic " : ""); - newsym(x, y); - return (struct obj *) &cg.zeroobj; - } - if (!BSTRCMPI(bp, p - 6, "throne")) { + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 6, "throne")) { lev->typ = THRONE; pline("A throne."); - newsym(x, y); - return (struct obj *) &cg.zeroobj; - } - if (!BSTRCMPI(bp, p - 4, "sink")) { + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 4, "sink")) { lev->typ = SINK; g.level.flags.nsinks++; pline("A sink."); - newsym(x, y); - return (struct obj *) &cg.zeroobj; - } + madeterrain = TRUE; + /* ("water" matches "potion of water" rather than terrain) */ - if (!BSTRCMPI(bp, p - 4, "pool") || !BSTRCMPI(bp, p - 4, "moat")) { + } else if (!BSTRCMPI(bp, p - 4, "pool") + || !BSTRCMPI(bp, p - 4, "moat")) { lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL : MOAT; del_engr_at(x, y); pline("A %s.", (lev->typ == POOL) ? "pool" : "moat"); /* Must manually make kelp! */ water_damage_chain(g.level.objects[x][y], TRUE); - newsym(x, y); - return (struct obj *) &cg.zeroobj; - } - if (!BSTRCMPI(bp, p - 4, "lava")) { /* also matches "molten lava" */ + madeterrain = TRUE; + + /* also matches "molten lava" */ + } else if (!BSTRCMPI(bp, p - 4, "lava")) { lev->typ = LAVAPOOL; del_engr_at(x, y); pline("A pool of molten lava."); if (!(Levitation || Flying)) - (void) lava_effects(); - newsym(x, y); - return (struct obj *) &cg.zeroobj; - } - - if (!BSTRCMPI(bp, p - 5, "altar")) { + pooleffects(FALSE); + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 5, "altar")) { aligntyp al; lev->typ = ALTAR; @@ -3763,37 +3760,43 @@ struct obj *no_wish; else if (!strncmpi(bp, "unaligned ", 10)) al = A_NONE; else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */ - al = (!rn2(6)) ? A_NONE : rn2((int) A_LAWFUL + 2) - 1; + al = !rn2(6) ? A_NONE : (rn2((int) A_LAWFUL + 2) - 1); lev->altarmask = Align2amask(al); pline("%s altar.", An(align_str(al))); - newsym(x, y); - return (struct obj *) &cg.zeroobj; - } - - if (!BSTRCMPI(bp, p - 5, "grave") - || !BSTRCMPI(bp, p - 9, "headstone")) { + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 5, "grave") + || !BSTRCMPI(bp, p - 9, "headstone")) { make_grave(x, y, (char *) 0); pline("%s.", IS_GRAVE(lev->typ) ? "A grave" : "Can't place a grave here"); - newsym(x, y); - return (struct obj *) &cg.zeroobj; - } - - if (!BSTRCMPI(bp, p - 4, "tree")) { + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 4, "tree")) { lev->typ = TREE; pline("A tree."); - newsym(x, y); block_point(x, y); - return (struct obj *) &cg.zeroobj; - } - - if (!BSTRCMPI(bp, p - 4, "bars")) { + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 4, "bars")) { lev->typ = IRONBARS; pline("Iron bars."); - newsym(x, y); + madeterrain = TRUE; + } + + if (madeterrain) { + feel_newsym(x, y); /* map the spot where the wish occurred */ + /* hero started at but might not be there anymore (create + lava, decline to die, and get teleported away to safety) */ + if (u.uinwater && !is_pool(u.ux, u.uy)) { + u.uinwater = 0; /* leave the water */ + docrt(); + g.vision_full_recalc = 1; + } else if (u.utrap && u.utraptype == TT_LAVA + && !is_lava(u.ux, u.uy)) { + reset_utrap(FALSE); + } + /* cast 'const' away; caller won't modify this */ return (struct obj *) &cg.zeroobj; } - } + } /* end of wizard mode traps and terrain */ if (!oclass && !typ) { if (!strncmpi(bp, "polearm", 7)) { diff --git a/src/sys.c b/src/sys.c index 6f71b0bd2..63a48ab7d 100644 --- a/src/sys.c +++ b/src/sys.c @@ -34,9 +34,6 @@ sys_early_init() #endif #ifdef DUMPLOG sysopt.dumplogfile = (char *) 0; -#endif -#ifdef WIN32 - sysopt.portable_device_top = (char *) 0; #endif sysopt.env_dbgfl = 0; /* haven't checked getenv("DEBUGFILES") yet */ sysopt.shellers = (char *) 0; @@ -86,6 +83,9 @@ sys_early_init() /* default to little-endian in 3.7 */ sysopt.saveformat[0] = sysopt.bonesformat[0] = lendian; sysopt.accessibility = 0; +#ifdef WIN32 + sysopt.portable_device_paths = 0; +#endif return; } @@ -108,12 +108,6 @@ sysopt_release() #ifdef DUMPLOG if (sysopt.dumplogfile) free((genericptr_t)sysopt.dumplogfile), sysopt.dumplogfile=(char *)0; -#endif -#ifdef WIN32 - if (sysopt.portable_device_top) { - free((genericptr_t) sysopt.portable_device_top); - sysopt.portable_device_top = (char *) 0; - } #endif if (sysopt.genericusers) free((genericptr_t) sysopt.genericusers), diff --git a/src/trap.c b/src/trap.c index 568bcc811..0c8936fa3 100644 --- a/src/trap.c +++ b/src/trap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 trap.c $NHDT-Date: 1576274483 2019/12/13 22:01:23 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.325 $ */ +/* NetHack 3.6 trap.c $NHDT-Date: 1576638501 2019/12/18 03:08:21 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.329 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -486,8 +486,9 @@ unsigned ftflags; ; /* KMH -- You can't escape the Sokoban level traps */ else if (Levitation || u.ustuck || (!Can_fall_thru(&u.uz) && !levl[u.ux][u.uy].candig) - || ((Flying || is_clinger(g.youmonst.data)) - && !(ftflags & TOOKPLUNGE)) + || ((Flying || is_clinger(g.youmonst.data) + || (ceiling_hider(g.youmonst.data) && u.uundetected)) + && !(ftflags & TOOKPLUNGE)) || (Inhell && !u.uevent.invoked && newlevel == bottom)) { dont_fall = "don't fall in."; } else if (g.youmonst.data->msize >= MZ_HUGE) { @@ -3725,6 +3726,7 @@ drown() boolean inpool_ok = FALSE, crawl_ok; int i, x, y; + feel_newsym(u.ux, u.uy); /* in case Blind, map the water here */ /* happily wading in the same contiguous pool */ if (u.uinwater && is_pool(u.ux - u.dx, u.uy - u.dy) && (Swimming || Amphibious)) { @@ -5241,6 +5243,7 @@ lava_effects() int dmg = d(6, 6); /* only applicable for water walking */ boolean usurvive, boil_away; + feel_newsym(u.ux, u.uy); /* in case Blind, map the lava here */ burn_away_slime(); if (likes_lava(g.youmonst.data)) return FALSE; @@ -5365,7 +5368,10 @@ sink_into_lava() static const char sink_deeper[] = "You sink deeper into the lava."; if (!u.utrap || u.utraptype != TT_LAVA) { - ; /* do nothing; this shouldn't happen */ + ; /* do nothing; this usually won't happen but could after + * polymorphing from a flier into a ceiling hider and then hiding; + * allmain() only checks whether the hero is at a lava location, + * not whether he or she is currently sinking */ } else if (!is_lava(u.ux, u.uy)) { reset_utrap(FALSE); /* this shouldn't happen either */ } else if (!u.uinvulnerable) { diff --git a/sys/winnt/windmain.c b/sys/winnt/windmain.c index 3e9d6b721..908b0de88 100644 --- a/sys/winnt/windmain.c +++ b/sys/winnt/windmain.c @@ -167,25 +167,16 @@ folder_file_exists(const char * folder, const char * file_name) boolean test_portable_config( const char *executable_path, - char *portable_device_top_path, - size_t portable_device_top_path_size) + char *portable_device_path, + size_t portable_device_path_size) { + int lth = 0; + const char *sysconf = "sysconf"; + char tmppath[MAX_PATH]; boolean retval = FALSE, save_initoptions_noterminate = iflags.initoptions_noterminate; - char tmppath[MAX_PATH], *toppath, *sysconftop; -#ifdef UNICODE - TCHAR wdrive[_MAX_DRIVE]; - TCHAR wthisdir[_MAX_DIR]; - TCHAR wfname[_MAX_FNAME]; - TCHAR wext[_MAX_EXT]; -#endif - char drive[_MAX_DRIVE]; - char thisdir[_MAX_DIR]; - char fname[_MAX_FNAME]; - char ext[_MAX_EXT]; - errno_t err; - if (portable_device_top_path && folder_file_exists(executable_path, "sysconf")) { + if (portable_device_path && folder_file_exists(executable_path, "sysconf")) { /* There is a sysconf file (not just sysconf.template) present in the exe path, which is not the way NetHack is initially distributed, @@ -195,101 +186,38 @@ test_portable_config( delve into that... */ - *portable_device_top_path = '\0'; - (void) strncpy(tmppath, executable_path, sizeof tmppath - (1 + sizeof "sysconf")); - tmppath[sizeof tmppath - (1 + sizeof "sysconf")] = '\0'; - (void) strcat(tmppath, "sysconf"); - /* split the path up */ -#ifdef UNICODE - { - int sz, wchars_num = MultiByteToWideChar( CP_ACP, 0, tmppath, -1, NULL, 0); - wchar_t *wstr; - - if (wchars_num) { - wstr = (wchar_t *) alloc(wchars_num * sizeof(wchar_t)); - MultiByteToWideChar( CP_ACP, 0, tmppath, -1, wstr, wchars_num); - err = _wsplitpath_s(wstr, wdrive, _MAX_DRIVE, wthisdir, _MAX_DIR, - wfname, _MAX_FNAME, wext, _MAX_EXT); - free(wstr); - } - sz = WideCharToMultiByte(CP_ACP, 0, wdrive, -1, drive, - 0, NULL, NULL); - if (sz <= sizeof drive) - WideCharToMultiByte(CP_ACP, 0, wdrive, -1, drive, - sz, NULL, NULL); - - } -#else - err = _splitpath_s(tmppath, drive, _MAX_DRIVE, thisdir, _MAX_DIR, - fname, _MAX_FNAME, ext, _MAX_EXT); -#endif - if (err != 0) - goto done_test; - - toppath = (char *) alloc(portable_device_top_path_size); - *toppath = '\0'; - /* -2 because we need to append the path separator */ - (void) strncpy(toppath, drive, portable_device_top_path_size - 2); - toppath[portable_device_top_path_size - 2] = '\0'; - (void) strcat(toppath, "\\"); + *portable_device_path = '\0'; + lth = sizeof tmppath - strlen(sysconf); + (void) strncpy(tmppath, executable_path, lth - 1); + tmppath[lth - 1] = '\0'; + (void) strcat(tmppath, sysconf); iflags.initoptions_noterminate = 1; /* assure_syscf_file(); */ config_error_init(TRUE, tmppath, FALSE); /* ... and _must_ parse correctly. */ if (read_config_file(tmppath, SET_IN_SYS) - && sysopt.portable_device_top - && (strlen(sysopt.portable_device_top) + strlen(toppath) - < portable_device_top_path_size - 3)) { - sysconftop = sysopt.portable_device_top; - if (sysconftop[1] == ':') - sysconftop += 2; /* skip the device if specified */ - if (*sysconftop == '\\') - sysconftop += 1; /* skip the root folder if specified */ - (void) strcat(toppath, sysconftop); - append_slash(toppath); + && sysopt.portable_device_paths) retval = TRUE; - } else { - if (config_error_done()) - retval = FALSE; - } + (void) config_error_done(); iflags.initoptions_noterminate = save_initoptions_noterminate; - sysopt_release(); - if (retval) - Strcpy(portable_device_top_path, toppath); - free(toppath); + sysopt_release(); /* the real sysconf processing comes later */ + } + if (retval) { + lth = strlen(executable_path); + if (lth <= (int) portable_device_path_size - 1) + Strcpy(portable_device_path, executable_path); + else + retval = FALSE; } - done_test: - return retval; } -static char portable_device_top_path[MAX_PATH]; +static char portable_device_path[MAX_PATH]; const char *get_portable_device() { - return (const char *) portable_device_top_path; -} - -boolean illegal_dir(const char *d1, const char *d2) -{ - int i; - char tmpbuf[MAX_PATH]; - - if (!strcmpi(d1, d2)) { - (void) strncpy(tmpbuf, &portable_device_top_path[3], - sizeof tmpbuf - 1); - tmpbuf[sizeof tmpbuf - 1] = '\0'; - i = (int) strlen(tmpbuf) - 1; - if (tmpbuf[i] == '\\') - tmpbuf[i] = '\0'; - raw_printf("Illegal \"portable_device_top = %s\" in your sysconf file", - tmpbuf); - raw_printf("because the exe is running from that folder."); - raw_printf("Point 'portable_device_top' to a different folder."); - return TRUE; - } - return FALSE; + return (const char *) portable_device_path; } void @@ -308,19 +236,17 @@ set_default_prefix_locations(const char *programPath) strcpy(executable_path, get_executable_path()); append_slash(executable_path); - if (test_portable_config(executable_path, portable_device_top_path, - sizeof portable_device_top_path)) { - if (illegal_dir(portable_device_top_path, executable_path)) - windows_startup_state = 2; + if (test_portable_config(executable_path, + portable_device_path, sizeof portable_device_path)) { g.fqn_prefix[SYSCONFPREFIX] = executable_path; - g.fqn_prefix[CONFIGPREFIX] = portable_device_top_path; - g.fqn_prefix[HACKPREFIX] = portable_device_top_path; - g.fqn_prefix[SAVEPREFIX] = portable_device_top_path; - g.fqn_prefix[LEVELPREFIX] = portable_device_top_path; - g.fqn_prefix[BONESPREFIX] = portable_device_top_path; - g.fqn_prefix[SCOREPREFIX] = portable_device_top_path; - g.fqn_prefix[LOCKPREFIX] = portable_device_top_path; - g.fqn_prefix[TROUBLEPREFIX] = portable_device_top_path; + g.fqn_prefix[CONFIGPREFIX] = portable_device_path; + g.fqn_prefix[HACKPREFIX] = portable_device_path; + g.fqn_prefix[SAVEPREFIX] = portable_device_path; + g.fqn_prefix[LEVELPREFIX] = portable_device_path; + g.fqn_prefix[BONESPREFIX] = portable_device_path; + g.fqn_prefix[SCOREPREFIX] = portable_device_path; + g.fqn_prefix[LOCKPREFIX] = portable_device_path; + g.fqn_prefix[TROUBLEPREFIX] = portable_device_path; g.fqn_prefix[DATAPREFIX] = executable_path; } else { build_known_folder_path(&FOLDERID_Profile, profile_path,