diff --git a/dat/data.base b/dat/data.base index b18af14ef..9f2e6433a 100644 --- a/dat/data.base +++ b/dat/data.base @@ -426,8 +426,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 @@ -3179,6 +3179,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 diff --git a/dat/quest.txt b/dat/quest.txt index 58dc9d1cb..64bde2fe3 100644 --- a/dat/quest.txt +++ b/dat/quest.txt @@ -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. # @@ -27,9 +27,11 @@ # 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 # QT_OTHERNEMESIS 52 @@ -195,6 +197,12 @@ You realize the feeling must be the presence of %o. %Cp Arc 00041 The familiar presence of %o is in the ether. %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 +The have returned to %ns lair. +%E %Cc Arc 00050 "So, %p, you think that you can succeed in recovering %o, when your teacher, %l, has already failed. @@ -2463,6 +2471,9 @@ proudly again. Putting your kami in the hands of fate, you advance. As you arrive once again at the home of %n, your thoughts turn only to %o. %E +%Cp Sam 00042 +As you arrive once again at the home of %n. +%E %Cp Sam 00050 "Ah, so it is to be you, %p-san. I offer you seppuku. I will be your second if you wish." @@ -2713,6 +2724,9 @@ You sense the presence of %o. You gain confidence, knowing that you may soon be united with %o. %E +%Cp Tou 00042 +You have returned to %ns lair. +%E %Cc Tou 00050 "So, %p, %l thinks that you can wrest %o from me! @@ -3207,6 +3221,9 @@ You feel your mentor's presence; perhaps %o is nearby. %Cp Wiz 00041 The aura of %o tingles at the edge of your perception. %E +%Cp Wiz 00042 +You have returned to %ns lair. +%E %Cc Wiz 00050 "Ah, I recognize you, %p. So, %l has sent you to steal %o from me, hmmm? Well, %lh is a fool to send such diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 9805e32c0..5dd00e1e0 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -1,4 +1,4 @@ -.\" $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.224 $ $NHDT-Date: 1498078870 2017/06/21 21:01:10 $ +.\" $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.233 $ $NHDT-Date: 1505214878 2017/09/12 11:14:38 $ .ds h0 "NetHack Guidebook .ds h1 .ds h2 % @@ -608,9 +608,12 @@ 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 "" @@ -926,10 +929,16 @@ choosing the item to adjust, enter a count prior to its letter. .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 -``#overview'' command. Autocompletes. Default key is 'M-A', and '^N' if number_pad is on. +``#overview'' command. Autocompletes. Default key is 'M-A', and '^N' +if number_pad is on. .lp #apply Apply (use) a tool such as a pick-axe, a key, or a lamp. Default key is 'a'. -If the tool used acts on items on the floor, using the `m' prefix skips those items. +.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 @@ -1126,7 +1135,11 @@ 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. +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 away. Autocompletes. Default key is 'M-t'. .lp #twoweapon @@ -1427,8 +1440,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. @@ -1561,7 +1574,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 @@ -2199,6 +2212,12 @@ can be created with any text editor. 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 @@ -2263,6 +2282,19 @@ 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. @@ -2492,6 +2524,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 @@ -2703,7 +2738,7 @@ 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 @@ -2718,11 +2753,14 @@ 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; +.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. @@ -2793,7 +2831,7 @@ 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''); @@ -4121,7 +4159,7 @@ 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. .pg -\fBThe development team, as well as \fBSteve VanDevender\fP and +The development team, as well as \fBSteve VanDevender\fP and \fBKevin Smolkowski\fP ensured that NetHack 3.6 continued to operate on various Unix flavors and maintained the X11 interface. .pg @@ -4142,6 +4180,7 @@ released 3.6.1 as a bug fix release in January 2016. .pg The official NetHack web site is maintained by \fBKen Lorber\fP at http://www.nethack.org/. .pg +.hn 2 SHOUT-OUTS .pg The devteam would like to give a special "shout-out" to thank the generous diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index c09cc7d1e..edd7f9995 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -735,10 +735,13 @@ 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.\\ @@ -1112,9 +1115,12 @@ 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}'. +Default key is '{\tt a}'.\\ If the tool used acts on items on the floor, using the `{\tt m}' prefix -skips those items. +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}'.\\ @@ -1394,7 +1400,9 @@ The `{\tt m}' prefix makes the command use a menu. \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. +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 away. Autocompletes. Default key is '{\tt M-t}'. @@ -1674,6 +1682,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 \subsection*{Stairs (`{\tt <}', `{\tt >}')} %.pg @@ -1707,6 +1716,7 @@ 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 \subsection*{Ladders (`{\tt <}', `{\tt >}')} %.pg @@ -1792,8 +1802,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. @@ -1945,7 +1955,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 @@ -2682,7 +2692,14 @@ 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 ignore. +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 @@ -2772,6 +2789,24 @@ Example: \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. @@ -3054,6 +3089,10 @@ 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 @@ -3294,7 +3333,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}] @@ -3313,13 +3352,18 @@ 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. @@ -3395,7 +3439,7 @@ 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}] @@ -4571,7 +4615,7 @@ of moving 8 units at a time. \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 #attributes command. +seen via the {\tt \#attributes} command. \elist %.hn2 diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 72b2d2d81..b7b8ddc33 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -394,6 +394,8 @@ poor message when shape-shifted vampire reverts if cause of 'death' was 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 @@ -409,6 +411,41 @@ 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" +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 +fix mention_walls reporting secret doors as solid walls +corpses and other flammable items not subject to direct burning or fire-based + erosion which were thrown or dropped into lava remained intact Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository @@ -461,6 +498,10 @@ 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 Platform- and/or Interface-Specific Fixes @@ -503,6 +544,7 @@ 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 @@ -520,6 +562,8 @@ 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 General New Features @@ -610,6 +654,18 @@ 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 Platform- and/or Interface-Specific New Features diff --git a/include/config.h b/include/config.h index 11fb16e26..5f89126c3 100644 --- a/include/config.h +++ b/include/config.h @@ -449,6 +449,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 * diff --git a/include/decl.h b/include/decl.h index a418d20de..d161fae0f 100644 --- a/include/decl.h +++ b/include/decl.h @@ -421,7 +421,7 @@ struct plinemsg_type { E struct plinemsg_type *plinemsg_types; #ifdef PANICTRACE -E char *ARGV0; +E const char *ARGV0; #endif #ifdef DROPLEVEL diff --git a/include/extern.h b/include/extern.h index e7a941889..c35692979 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1502753404 2017/08/14 23:30:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.600 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1505170345 2017/09/11 22:52:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.604 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -142,6 +142,7 @@ 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 *)); @@ -198,7 +199,7 @@ 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 void FDECL(bind_key, (UCHAR_P, const char *)); +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)); @@ -607,6 +608,7 @@ 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 *)); @@ -666,7 +668,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 *)); @@ -767,6 +769,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); @@ -1682,7 +1687,7 @@ 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); @@ -1690,7 +1695,7 @@ 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 void FDECL(parsebindings, (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)); @@ -1957,6 +1962,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); @@ -2413,6 +2419,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)); diff --git a/include/flag.h b/include/flag.h index ac3844fc3..9cd6b3533 100644 --- a/include/flag.h +++ b/include/flag.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 flag.h $NHDT-Date: 1498078871 2017/06/21 21:01:11 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.119 $ */ +/* NetHack 3.6 flag.h $NHDT-Date: 1505214875 2017/09/12 11:14:35 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.123 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -60,15 +60,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]; @@ -190,6 +191,8 @@ struct instance_flags { * behaviour of various NetHack functions and probably warrant * a structure of their own elsewhere some day. */ + 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 */ @@ -226,6 +229,7 @@ struct instance_flags { boolean cbreak; /* in cbreak mode, rogue format */ boolean deferred_X; /* deferred entry into explore mode */ 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 */ @@ -441,6 +445,9 @@ enum runmode_types { #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 */ diff --git a/include/hack.h b/include/hack.h index c4691ae26..b3a05ca67 100644 --- a/include/hack.h +++ b/include/hack.h @@ -37,6 +37,12 @@ enum encumbrance_types { /* 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 */ enum hunger_state_types { SATIATED = 0, diff --git a/include/ntconf.h b/include/ntconf.h index 48b149bfa..a096a2ff1 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -28,6 +28,10 @@ #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 */ diff --git a/include/qtext.h b/include/qtext.h index 11b414dd6..752938423 100644 --- a/include/qtext.h +++ b/include/qtext.h @@ -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 diff --git a/include/sys.h b/include/sys.h index 91c5d3522..17bbadb85 100644 --- a/include/sys.h +++ b/include/sys.h @@ -27,6 +27,7 @@ struct sysopt { 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; diff --git a/src/apply.c b/src/apply.c index 6337eb49d..dd50f32fa 100644 --- a/src/apply.c +++ b/src/apply.c @@ -12,7 +12,7 @@ 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 *)); @@ -38,6 +38,8 @@ 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 @@ -571,6 +573,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; @@ -579,82 +585,102 @@ 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) { You("cannot leash any more pets."); - 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; goto got_target; } pline("Leash yourself? Very funny..."); - return; + return 0; } + /* + * From here on out, return value is 1 == a move is used. + */ + if (!(mtmp = m_at(cc.x, cc.y))) { There("is no creature there."); - return; + if (glyph_is_invisible(levl[cc.x][cc.y].glyph)) { + unmap_object(cc.x, cc.y); + newsym(cc.x, cc.y); + } + return 1; } spotmon = canspotmon(mtmp); -got_target: + got_target: - if (!mtmp->mtame) { - if (!spotmon) - There("is no creature there."); - else - pline("%s %s leashed!", Monnam(mtmp), - (!obj->leashmon) ? "cannot be" : "is not"); - return; - } - if (!obj->leashmon) { + 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) { + pline("%s %s leashed!", Monnam(mtmp), + (!obj->leashmon) ? "cannot be" : "is not"); + } else if (!obj->leashmon) { + /* applying a leash which isn't currently in use */ if (mtmp->mleashed) { pline("This %s is already leashed.", - spotmon ? l_monnam(mtmp) : "monster"); - return; - } - if (!leashable(mtmp)) { + spotmon ? l_monnam(mtmp) : "creature"); + } else if (!leashable(mtmp)) { pline("The leash won't fit onto %s%s.", spotmon ? "your " : "", l_monnam(mtmp)); - return; + } else { + You("slip the leash around %s%s.", spotmon ? "your " : "", + l_monnam(mtmp)); + mtmp->mleashed = 1; + obj->leashmon = (int) mtmp->m_id; + mtmp->msleeping = 0; } - - You("slip the leash around %s%s.", spotmon ? "your " : "", - l_monnam(mtmp)); - mtmp->mleashed = 1; - obj->leashmon = (int) mtmp->m_id; - mtmp->msleeping = 0; - return; - } - if (obj->leashmon != (int) mtmp->m_id) { - pline("This leash is not attached to that creature."); - return; } else { - if (obj->cursed) { + /* applying a leash which is currently in use */ + if (obj->leashmon != (int) mtmp->m_id) { + pline("This leash is not attached to that creature."); + } else if (obj->cursed) { pline_The("leash would not come off!"); - obj->bknown = TRUE; - return; + obj->bknown = 1; + } else { + mtmp->mleashed = 0; + obj->leashmon = 0; + You("remove the leash from %s%s.", + spotmon ? "your " : "", l_monnam(mtmp)); } - mtmp->mleashed = 0; - obj->leashmon = 0; - You("remove the leash from %s%s.", spotmon ? "your " : "", - l_monnam(mtmp)); } - return; + return 1; } /* assuming mtmp->mleashed has been checked */ @@ -1566,7 +1592,7 @@ boolean showmsg; static int jumping_is_magic; -boolean +STATIC_OVL boolean get_valid_jump_position(x,y) int x,y; { @@ -2860,7 +2886,7 @@ int min_range, max_range; static int polearm_range_min = -1; static int polearm_range_max = -1; -boolean +STATIC_OVL boolean get_valid_polearm_position(x,y) int x,y; { @@ -3553,7 +3579,7 @@ doapply() use_tinning_kit(obj); break; case LEASH: - use_leash(obj); + res = use_leash(obj); break; case SADDLE: res = use_saddle(obj); diff --git a/src/bones.c b/src/bones.c index 73fea3d2e..9f5dae173 100644 --- a/src/bones.c +++ b/src/bones.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 bones.c $NHDT-Date: 1450432756 2015/12/18 09:59:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.68 $ */ +/* NetHack 3.6 bones.c $NHDT-Date: 1503309019 2017/08/21 09:50:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */ /* NetHack may be freely redistributed. See license for details. */ @@ -552,7 +552,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; @@ -584,7 +584,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]; Sprintf(errbuf, "This is bones level '%s', not '%s'!", oldbonesid, diff --git a/src/botl.c b/src/botl.c index e28e8cc8b..d1d0a53e8 100644 --- a/src/botl.c +++ b/src/botl.c @@ -83,6 +83,16 @@ do_statusline1() return newbot1; } +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() { @@ -110,7 +120,8 @@ do_statusline2() 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 ? "$" : encglyph(objnum_to_glyph(GOLD_PIECE)), + (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 */ diff --git a/src/cmd.c b/src/cmd.c index cd7faedc8..6849f2ca4 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -381,8 +381,10 @@ doextlist(VOID_ARGS) #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. * @@ -399,9 +401,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'; @@ -416,10 +419,8 @@ extcmd_via_menu() 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( @@ -434,25 +435,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 ((extcmdlist[i].flags & AUTOCOMPLETE) - && !(!wizard && (extcmdlist[i].flags & WIZMODECMD)) - && !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); @@ -460,15 +469,17 @@ 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) { + Sprintf(prompt, "%s%s [%s]", wastoolong ? "or " : "", + choices[i]->ef_txt, choices[i]->ef_desc); } else if (acount == 1) { - Sprintf(prompt, "%s or %s", choices[i - 1]->ef_txt, - choices[i]->ef_txt); + Sprintf(prompt, "%s%s or %s", wastoolong ? "or " : "", + choices[i - 1]->ef_txt, choices[i]->ef_txt); } else { Strcat(prompt, " or "); Strcat(prompt, choices[i]->ef_txt); @@ -626,6 +637,7 @@ wiz_makemap(VOID_ARGS) if (wizard) { struct monst *mtmp; + rm_mapseen(ledger_no(&u.uz)); for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) if (mtmp->isshk) setpaid(mtmp); @@ -2857,7 +2869,7 @@ int final; struct ext_func_tab extcmdlist[] = { { '#', "#", "perform an extended command", doextcmd, IFBURIED | GENERALCMD }, - { M('?'), "?", "get this list of extended commands", + { M('?'), "?", "list all extended commands", doextlist, IFBURIED | AUTOCOMPLETE | GENERALCMD }, { M('a'), "adjust", "adjust inventory letters", doorganize, IFBURIED | AUTOCOMPLETE }, @@ -3056,7 +3068,7 @@ uchar key; return (char *) 0; } -void +boolean bind_key(key, command) uchar key; const char *command; @@ -3066,19 +3078,17 @@ const char *command; /* special case: "nothing" is reserved for unbinding */ if (!strcmp(command, "nothing")) { Cmd.commands[key] = (struct ext_func_tab *) 0; - return; + return TRUE; } for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) { if (strcmp(command, extcmd->ef_txt)) continue; Cmd.commands[key] = extcmd; - return; + return TRUE; } - pline( - "Bad command %s matched with key %c (ASCII %i). Ignoring command.\n", - command, key, key); + return FALSE; } /* initialize all keyboard commands */ @@ -3091,27 +3101,27 @@ commands_init() if (extcmd->key) Cmd.commands[extcmd->key] = extcmd; - bind_key(C('l'), "redraw"); /* if number_pad is set */ + (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 */ - bind_key('h', "help"); /* if number_pad is set */ - bind_key('j', "jump"); /* if number_pad is on */ + (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 */ - bind_key('k', "kick"); /* if number_pad is on */ - bind_key('l', "loot"); /* if number_pad is on */ - bind_key(C('n'), "annotate"); /* if number_pad is on */ - bind_key(M('n'), "name"); - bind_key(M('N'), "name"); - bind_key('u', "untrap"); /* if number_pad is on */ + (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: */ - bind_key(M('O'), "overview"); - bind_key(M('2'), "twoweapon"); + (void) bind_key(M('O'), "overview"); + (void) bind_key(M('2'), "twoweapon"); /* wait_on_space */ - bind_key(' ', "wait"); + (void) bind_key(' ', "wait"); } int @@ -4007,7 +4017,7 @@ boolean initial; } backed_dir_cmd = TRUE; for (i = 0; i < 8; i++) - bind_key(Cmd.dirchars[i], "nothing"); + (void) bind_key(Cmd.dirchars[i], "nothing"); } } @@ -4965,7 +4975,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; } diff --git a/src/dbridge.c b/src/dbridge.c index 0d0421862..bf03f8d4a 100644 --- a/src/dbridge.c +++ b/src/dbridge.c @@ -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. */ @@ -230,7 +230,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; @@ -375,7 +374,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; @@ -397,7 +395,6 @@ const char *verb; /* * Simple-minded "can it be here?" routine */ - STATIC_OVL boolean e_survives_at(etmp, x, y) struct entity *etmp; @@ -486,7 +483,6 @@ int xkill_flags, how; /* * These are never directly affected by a bridge or portcullis. */ - STATIC_OVL boolean automiss(etmp) struct entity *etmp; @@ -498,7 +494,6 @@ struct entity *etmp; /* * Does falling drawbridge or portcullis miss etmp? */ - STATIC_OVL boolean e_missed(etmp, chunks) struct entity *etmp; @@ -536,7 +531,6 @@ boolean chunks; /* * Can etmp jump from death? */ - STATIC_OVL boolean e_jumps(etmp) struct entity *etmp; @@ -604,6 +598,11 @@ 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"); + } pline("%s crushed underneath the drawbridge.", E_phrase(etmp, "are")); /* no jump */ e_died(etmp, @@ -639,11 +638,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; @@ -654,12 +652,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; @@ -763,10 +759,12 @@ struct entity *etmp; } } +/* 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; @@ -823,12 +821,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; @@ -870,12 +868,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; @@ -898,6 +896,7 @@ 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)) pline_The("portcullis of the drawbridge falls into the %s!", @@ -999,6 +998,7 @@ int x, y; do_entity(etmp1); } } + nokiller(); } /*dbridge.c*/ diff --git a/src/decl.c b/src/decl.c index 962367e7b..97020d5ae 100644 --- a/src/decl.c +++ b/src/decl.c @@ -333,7 +333,7 @@ NEARDATA struct savefile_info sfrestinfo, sfsaveinfo = { struct plinemsg_type *plinemsg_types = (struct plinemsg_type *) 0; #ifdef PANICTRACE -char *ARGV0; +const char *ARGV0; #endif /* XXX see comment in save.c */ diff --git a/src/detect.c b/src/detect.c index 86e3159bf..2ba4a968f 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1571,9 +1571,9 @@ boolean via_warning; Blind ? "to check nearby" : "look close by"); display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */ } - mtmp->mundetected = 0; - newsym(x, y); - goto find; + mtmp->mundetected = 0; + newsym(x, y); + goto find; } return 0; } diff --git a/src/dig.c b/src/dig.c index 4407c4c15..364d1cce6 100644 --- a/src/dig.c +++ b/src/dig.c @@ -404,7 +404,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); dmgtxt = "damage"; } if (level.flags.is_maze_lev) { @@ -424,7 +424,7 @@ dig(VOID_ARGS) } else if (closed_door(dpx, dpy)) { digtxt = "You break through the door."; if (shopedge) { - add_damage(dpx, dpy, 400L); + add_damage(dpx, dpy, SHOP_DOOR_COST); dmgtxt = "break"; } if (!(lev->doormask & D_TRAPPED)) @@ -1485,7 +1485,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) @@ -1502,7 +1502,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; @@ -1530,7 +1530,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); diff --git a/src/do.c b/src/do.c index 6f09b5bd2..d88dda4cf 100644 --- a/src/do.c +++ b/src/do.c @@ -190,7 +190,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 @@ -1254,6 +1254,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). */ diff --git a/src/do_name.c b/src/do_name.c index 7dec3fb7d..38b90fc45 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -10,6 +10,7 @@ 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 *)); diff --git a/src/dokick.c b/src/dokick.c index 2cb485472..a6a34898f 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -1278,7 +1278,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); pay_for_damage("break", FALSE); } if (in_town(x, y)) diff --git a/src/dungeon.c b/src/dungeon.c index 5b5e7c369..ca3f7c32d 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -57,6 +57,7 @@ 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)); @@ -247,7 +248,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); } } @@ -1794,6 +1795,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) @@ -1811,7 +1819,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, @@ -1885,7 +1895,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) @@ -2109,6 +2121,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; diff --git a/src/eat.c b/src/eat.c index 552ae147b..9bd6346b0 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1708,8 +1708,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); @@ -3125,9 +3129,15 @@ vomit() /* A good idea from David Neves */ Your("jaw gapes convulsively."); else make_sick(0L, (char *) 0, TRUE, SICK_VOMITABLE); - nomul(-2); - multi_reason = "vomiting"; - nomovemsg = You_can_move_again; + + /* 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); + multi_reason = "vomiting"; + nomovemsg = You_can_move_again; + } } int diff --git a/src/end.c b/src/end.c index 7cd3e4304..3344f5771 100644 --- a/src/end.c +++ b/src/end.c @@ -1373,7 +1373,7 @@ int how; if (!done_stopprint) artifact_score(invent, FALSE, endwin); /* list artifacts */ -#if DUMPLOG +#ifdef DUMPLOG dump_redirect(TRUE); artifact_score(invent, FALSE, 0); dump_redirect(FALSE); @@ -1457,7 +1457,7 @@ int how; raw_print(""); raw_print(""); } - terminate(EXIT_SUCCESS); + nh_terminate(EXIT_SUCCESS); } void @@ -1532,7 +1532,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 */ @@ -1549,7 +1549,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; diff --git a/src/explode.c b/src/explode.c index 74dfcdae2..50674f087 100644 --- a/src/explode.c +++ b/src/explode.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 explode.c $NHDT-Date: 1496103440 2017/05/30 00:17:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */ +/* NetHack 3.6 explode.c $NHDT-Date: 1503355817 2017/08/21 22:50:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.50 $ */ /* Copyright (C) 1990 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -90,7 +90,9 @@ int expltype; if (olet == MON_EXPLODE) { str = killer.name; - do_hallu = Hallucination && strstri(str, "'s explosion"); + do_hallu = (Hallucination + && (strstri(str, "'s explosion") + || strstri(str, "s' explosion"))); adtyp = AD_PHYS; } else switch (abs(type) % 10) { diff --git a/src/files.c b/src/files.c index b25539954..8ca16bab2 100644 --- a/src/files.c +++ b/src/files.c @@ -1,7 +1,9 @@ -/* NetHack 3.6 files.c $NHDT-Date: 1502581476 2017/08/12 23:44:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.211 $ */ +/* NetHack 3.6 files.c $NHDT-Date: 1503309020 2017/08/21 09:50:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.215 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ +#define NEED_VARARGS + #include "hack.h" #include "dlb.h" @@ -190,14 +192,22 @@ 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 @@ -205,6 +215,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() * @@ -697,17 +711,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 @@ -1205,7 +1249,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); } } @@ -1311,7 +1355,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); @@ -1643,8 +1687,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; @@ -2004,15 +2050,13 @@ int src; } /* - * 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 */ @@ -2058,13 +2102,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: @@ -2098,13 +2136,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; @@ -2112,25 +2248,23 @@ int src; #ifdef SYSCF int n; #endif - char *bufp, *altp, buf[4 * 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 == ' ') @@ -2144,21 +2278,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 (!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)) { - parsebindings(bufp); + 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); @@ -2278,6 +2412,14 @@ int src; 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); @@ -2298,8 +2440,8 @@ int src; 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); @@ -2307,45 +2449,45 @@ int src; n = atoi(bufp); /* XXX to get more than 25, need to rewrite all lock code */ if (n < 0 || n > 25) { - raw_printf("Illegal value in MAXPLAYERS (maximum is 25)."); - return 0; + 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; @@ -2355,8 +2497,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; @@ -2365,16 +2507,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) @@ -2383,8 +2525,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) @@ -2393,45 +2535,20 @@ 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, "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 */ - if (!parsesymbols(bufp)) { - raw_printf("Error in SYMBOLS definition '%s'.\n", bufp); - wait_synch(); - } - 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); @@ -2574,9 +2691,11 @@ int src; 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 @@ -2588,43 +2707,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]; 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 (!parse_config_line(fp, strip_newline(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; @@ -2728,47 +2952,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 */ @@ -2777,6 +3125,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 * @@ -2796,7 +3145,6 @@ int read_sym_file(which_set) int which_set; { - char buf[4 * BUFSZ]; FILE *fp; if (!(fp = fopen_sym_file())) @@ -2804,13 +3152,13 @@ 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_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 @@ -2820,17 +3168,26 @@ int which_set; " -_", 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) @@ -2844,8 +3201,7 @@ 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 (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, @@ -2867,6 +3223,7 @@ int which_set; chosen_symset_start = FALSE; return 1; } + config_error_add("No \"finish\""); return 0; } /* skip '=' and space which follows, if any */ @@ -2875,8 +3232,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 @@ -3111,7 +3470,7 @@ const char *dir UNUSED_if_not_OS2_CODEVIEW; #else fd = open(fq_record, O_CREAT | O_RDWR, S_IREAD | S_IWRITE); #endif - if (fd = < 0) { + if (fd <= 0) { raw_printf("Warning: cannot write record '%s'", tmp); wait_synch(); } else { diff --git a/src/hack.c b/src/hack.c index 8683fda77..11ff4275f 100644 --- a/src/hack.c +++ b/src/hack.c @@ -442,7 +442,7 @@ xchar x, y; } 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); dmgtxt = "damage"; } digtxt = "chew a hole in the wall."; @@ -472,7 +472,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); dmgtxt = "break"; } if (lev->doormask & D_TRAPPED) { @@ -722,9 +722,10 @@ int mode; && In_sokoban(&u.uz)) pline_The("Sokoban walls resist your ability."); else if (iflags.mention_walls) - pline("It's %s.", IS_WALL(tmpr->typ) ? "a wall" - : IS_TREE(tmpr->typ) ? "a tree" - : "solid stone"); + pline("It's %s.", + (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "a wall" + : IS_TREE(tmpr->typ) ? "a tree" + : "solid stone"); } return FALSE; } diff --git a/src/invent.c b/src/invent.c index b5ed81c6d..ab1ffc004 100644 --- a/src/invent.c +++ b/src/invent.c @@ -23,7 +23,7 @@ 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 *, const char *, - BOOLEAN_P, long *)); + const char *, BOOLEAN_P, long *)); STATIC_DCL char FDECL(display_used_invlets, (CHAR_P)); STATIC_DCL boolean FDECL(this_type_only, (struct obj *)); STATIC_DCL void NDECL(dounpaid); @@ -1080,6 +1080,8 @@ register const char *let, *word; xchar foox = 0; long cnt; boolean cntgiven = FALSE; + boolean msggiven = FALSE; + boolean oneloop = FALSE; long dummymask; if (*let == ALLOW_COUNT) @@ -1288,15 +1290,24 @@ register const char *let, *word; for (;;) { cnt = 0; cntgiven = FALSE; - if (!buf[0]) { - Sprintf(qbuf, "What do you want to %s? [*]", word); - } else { - Sprintf(qbuf, "What do you want to %s? [%s or ?*]", word, buf); - } + Sprintf(qbuf, "What do you want to %s?", word); 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)) { long tmpcnt = 0; @@ -1335,13 +1346,17 @@ 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]; - qbuf[0] = '\0'; + 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")) @@ -1357,6 +1372,7 @@ register const char *let, *word; if (ilet == '?' && !*lets && *altlets) allowed_choices = altlets; ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0, + menuquery, TRUE, allowcnt ? &ctmp : (long *) 0); if (!ilet) continue; @@ -1367,6 +1383,8 @@ register const char *let, *word; pline1(Never_mind); return (struct obj *) 0; } + if (ilet == '*') + goto redo_menu; if (allowcnt && ctmp >= 0) { cnt = ctmp; cntgiven = TRUE; @@ -2144,9 +2162,10 @@ free_pickinv_cache() * any count returned from the menu selection is placed here. */ STATIC_OVL char -display_pickinv(lets, xtra_choice, 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; { @@ -2204,7 +2223,7 @@ long *out_cnt; if (!flags.invlet_constant) reassign(); - if (n == 1) { + 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 */ @@ -2284,7 +2303,15 @@ nextclass: goto nextclass; } } - 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); + } + + end_menu(win, query && *query ? query : (char *) 0); n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected); if (n > 0) { @@ -2310,7 +2337,8 @@ display_inventory(lets, want_reply) const char *lets; boolean want_reply; { - return display_pickinv(lets, (char *) 0, want_reply, (long *) 0); + return display_pickinv(lets, (char *) 0, (char *) 0, + want_reply, (long *) 0); } /* diff --git a/src/lock.c b/src/lock.c index 121310630..94073f3ae 100644 --- a/src/lock.c +++ b/src/lock.c @@ -112,7 +112,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; @@ -659,7 +659,7 @@ int x, y; b_trapped("door", 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 */ diff --git a/src/mail.c b/src/mail.c index 946f81634..9d8986db9 100644 --- a/src/mail.c +++ b/src/mail.c @@ -641,7 +641,7 @@ struct obj *otmp UNUSED; if (child(1)) { (void) execl(mr, mr, (char *) 0); - terminate(EXIT_FAILURE); + nh_terminate(EXIT_FAILURE); } #else #ifndef AMS /* AMS mailboxes are directories */ diff --git a/src/mhitm.c b/src/mhitm.c index 3ab02f4a4..38668840c 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mhitm.c $NHDT-Date: 1496860757 2017/06/07 18:39:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.97 $ */ +/* NetHack 3.6 mhitm.c $NHDT-Date: 1504999944 2017/09/09 23:32:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1273,6 +1273,7 @@ register struct attack *mattk; | (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 && couldspot && !canspotmon(magr)) pline("%s suddenly disappears!", buf); @@ -1282,7 +1283,8 @@ register struct attack *mattk; break; case AD_DREN: if (!cancelled && !rn2(4)) - xdrainenergym(mdef, vis && canspotmon(mdef) && mattk->aatyp != AT_ENGL); + xdrainenergym(mdef, (boolean) (vis && canspotmon(mdef) + && mattk->aatyp != AT_ENGL)); tmp = 0; break; case AD_DRST: diff --git a/src/mhitu.c b/src/mhitu.c index df5541e19..50399899a 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mhitu.c $NHDT-Date: 1496619132 2017/06/04 23:32:12 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.146 $ */ +/* NetHack 3.6 mhitu.c $NHDT-Date: 1505001092 2017/09/09 23:51:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.147 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -26,8 +26,8 @@ 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; @@ -139,8 +139,8 @@ 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) */ @@ -225,17 +225,14 @@ boolean message; You("get regurgitated!"); } 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 { if (is_whirly(mdat)) { - switch (mdat->mattk[i].adtyp) { + switch (attk->adtyp) { case AD_ELEC: Strcpy(blast, " in a shower of sparks"); break; @@ -243,8 +240,9 @@ boolean message; Strcpy(blast, " in a blast of frost"); break; } - } else + } else { Strcpy(blast, " with a squelch"); + } You("get expelled from %s%s!", mon_nam(mtmp), blast); } } @@ -907,8 +905,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; @@ -972,6 +970,7 @@ register struct attack *mattk; } } else { /* hand to hand weapon */ struct obj *otmp = mon_currwep; + if (mattk->aatyp == AT_WEAP && otmp) { int tmp; @@ -1177,7 +1176,7 @@ 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; const char *sidestr = (side == RIGHT_SIDE) ? "right" : "left", *Monst_name = Monnam(mtmp), *leg = body_part(LEG); @@ -1718,13 +1717,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; @@ -1769,6 +1768,7 @@ register struct attack *mattk; i = number_leashed(); if (i > 0) { const char *s = (i > 1) ? "leashes" : "leash"; + pline_The("%s %s loose.", s, vtense(s, "snap")); unleash_all(); } @@ -1961,8 +1961,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; @@ -1976,8 +1976,8 @@ boolean ufound; levl[mtmp->mux][mtmp->muy].typ == WATER ? "empty water" : "thin air"); 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); @@ -2059,8 +2059,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[] = { "confused", /* [0] */ @@ -2275,8 +2275,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) { @@ -2299,7 +2299,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; @@ -2340,9 +2340,9 @@ 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 attr_tot, tried_gloves = 0; char qbuf[QBUFSZ]; @@ -2613,7 +2613,7 @@ register struct monst *mon; STATIC_OVL void mayberem(obj, str) -register struct obj *obj; +struct obj *obj; const char *str; { char qbuf[QBUFSZ]; @@ -2648,34 +2648,50 @@ 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)) { - pline("%s is splashed by your %s!", Monnam(mtmp), hliquid("acid")); + 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")); if (resists_acid(mtmp)) { pline("%s is not affected.", Monnam(mtmp)); tmp = 0; @@ -2729,9 +2745,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) { You("explode!"); /* KMH, balance patch -- this is okay with unchanging */ rehumanize(); @@ -2828,7 +2844,7 @@ assess_dmg: struct monst * cloneu() { - register struct monst *mon; + struct monst *mon; int mndx = monsndx(youmonst.data); if (u.mh <= 1) diff --git a/src/mon.c b/src/mon.c index 466de5c31..d01a79c95 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1502753408 2017/08/14 23:30:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.242 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1505266804 2017/09/13 01:40:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.244 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1994,6 +1994,8 @@ boolean was_swallowed; /* digestion */ Sprintf(killer.name, "%s explosion", s_suffix(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; } } @@ -3034,9 +3036,9 @@ decide_to_shapeshift(mon, shiftflags) struct monst *mon; int shiftflags; { - struct permonst *ptr; - unsigned was_female = mon->female; - boolean msg = FALSE; + struct permonst *ptr = 0; + unsigned mndx, was_female = mon->female; + boolean msg = FALSE, dochng = FALSE; if ((shiftflags & SHIFT_MSG) || ((shiftflags & SHIFT_SEENMSG) && sensemon(mon))) @@ -3045,28 +3047,48 @@ int shiftflags; if (!is_vampshifter(mon)) { /* regular shapeshifter */ if (!rn2(6)) - (void) newcham(mon, (struct permonst *) 0, FALSE, msg); + 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->data->mlet != S_VAMPIRE) { if ((mon->mhp <= (mon->mhpmax + 5) / 6) && rn2(4) - && mon->cham >= LOW_PM) - (void) newcham(mon, &mons[mon->cham], FALSE, msg); + && 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)) - (void) newcham(mon, (struct permonst *) 0, FALSE, msg); + 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; } } diff --git a/src/monmove.c b/src/monmove.c index 92cdac8dd..ab17709f4 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 monmove.c $NHDT-Date: 1496534703 2017/06/04 00:05:03 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.91 $ */ +/* NetHack 3.6 monmove.c $NHDT-Date: 1505265968 2017/09/13 01:26:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.93 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -134,8 +134,6 @@ 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 */ if (mtmp->iswiz || is_lminion(mtmp) || mtmp->data == &mons[PM_ANGEL] @@ -152,16 +150,18 @@ struct monst *mtmp; if (sobj_at(SCR_SCARE_MONSTER, x, y)) return TRUE; - /* creatures who don't (or can't) fear a written Elbereth: + /* + * Creatures who don't (or can't) fear a written Elbereth: * all the above plus shopkeepers, guards, blind or * peaceful monsters, humans, 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 @@ -752,6 +752,7 @@ 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 */ @@ -1249,7 +1250,7 @@ postmov: && (amorphous(ptr) || (can_fog(mtmp) && vamp_shift(mtmp, &mons[PM_FOG_CLOUD], - canspotmon(mtmp))))) { + sawmon)))) { /* update cached value for vamp_shift() case */ ptr = mtmp->data; if (flags.verbose && canseemon(mtmp)) diff --git a/src/monst.c b/src/monst.c index 5ae98c795..dd9ccfce8 100644 --- a/src/monst.c +++ b/src/monst.c @@ -39,6 +39,9 @@ void NDECL(monst_init); * 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) \ { \ @@ -253,7 +256,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), @@ -1211,8 +1214,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, @@ -2996,7 +3000,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), diff --git a/src/muse.c b/src/muse.c index f91a88b23..5745839b5 100644 --- a/src/muse.c +++ b/src/muse.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 muse.c $NHDT-Date: 1502753408 2017/08/14 23:30:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.79 $ */ +/* 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. */ @@ -1129,6 +1129,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; @@ -1233,6 +1251,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) @@ -1247,6 +1266,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); diff --git a/src/options.c b/src/options.c index 0bfacc09d..467a669ff 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1498078876 2017/06/21 21:01:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.288 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1505214875 2017/09/12 11:14:35 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.302 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -125,6 +125,7 @@ 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 }, @@ -485,7 +486,7 @@ static const menu_cmd_t default_menu_cmd_info[] = { { "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, "Insert selection" }, + { "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" }, @@ -506,17 +507,16 @@ static boolean initial, from_file; 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(badoptmsg, (const char *, 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(warning_opts, (char *, const char *)); +STATIC_DCL boolean FDECL(warning_opts, (char *, const char *)); STATIC_DCL int FDECL(feature_alert_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_DCL int FDECL(match_str2attr, (const char *)); STATIC_DCL const char *FDECL(attr2attrname, (int)); STATIC_DCL int NDECL(query_color); STATIC_DCL int FDECL(query_attr, (const char *)); @@ -525,6 +525,7 @@ 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); @@ -638,11 +639,14 @@ 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. @@ -788,18 +792,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 - read_config_file((char *) 0, SET_IN_FILE); + { + 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); /* @@ -937,43 +952,24 @@ const char *optname; #endif } -STATIC_OVL void -badoptmsg(opts, reason) -const char *opts; -const char *reason; /* "Bad syntax" or "Missing value" */ -{ - const char *linesplit = ""; +/* - if (!initial) { - if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1)) - option_help(); - else - pline("%s: %s. Enter \"?g\" for help.", reason, opts); - return; -#ifdef MAC - } else { - return; -#endif - } +# 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 -#ifdef WIN32 - linesplit = "\n"; -#endif - if (from_file) - raw_printf("%s in OPTIONS in %s: %s%s.\n", - reason, configfile, linesplit, opts); - else - raw_printf("%s in NETHACKOPTIONS: %s%s.\n", - reason, linesplit, opts); - wait_synch(); -} - -STATIC_OVL void -badoption(opts) -const char *opts; -{ - badoptmsg(opts, "Bad syntax"); -} +*/ STATIC_OVL char * string_for_opt(opts, val_optional) @@ -989,7 +985,7 @@ boolean val_optional; if (!colon || !*++colon) { if (!val_optional) - badoptmsg(opts, "Missing value"); + config_error_add("Missing parameter for '%s'", opts); return (char *) 0; } return colon; @@ -1032,22 +1028,35 @@ char *op; { int oc_sym, num; char *sp, buf[QBUFSZ]; + int retval = 1; num = 0; 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 /* not an object class char */ + 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 */ - || !index(flags.inv_order, oc_sym) || index(sp + 1, *sp)) - return 0; + 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'; @@ -1058,10 +1067,10 @@ char *op; 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; @@ -1070,7 +1079,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); @@ -1080,6 +1089,7 @@ const char *optype; : opts[i] ? (uchar) opts[i] : def_warnsyms[i].sym; assign_warnings(translate); + return TRUE; } void @@ -1099,26 +1109,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); @@ -1206,9 +1212,8 @@ int iscompound; /* 0 == boolean option, 1 == compound */ * For now just return. */ #else /* !MAC */ - raw_printf("\nWarning - %s option specified multiple times: %s.\n", + config_error_add("%s option specified multiple times: %s", iscompound ? "compound" : "boolean", opts); - wait_synch(); #endif /* ?MAC */ return; } @@ -1226,7 +1231,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, @@ -1237,12 +1245,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 */ @@ -1324,6 +1334,10 @@ char *str; } if (i == SIZE(colornames) && (*str >= '0' && *str <= '9')) c = atoi(str); + + if (c == CLR_MAX) + config_error_add("Unknown color '%s'", str); + return c; } @@ -1339,6 +1353,25 @@ int attr; return (char *) 0; } +STATIC_OVL int +match_str2attr(str) +const char *str; +{ + 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) + config_error_add("Unknown text attribute '%s'", str); + + return a; +} + STATIC_OVL int query_color() { @@ -1381,6 +1414,8 @@ 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); @@ -1464,11 +1499,7 @@ char *pattern; 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; @@ -1587,10 +1618,40 @@ 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; @@ -1604,11 +1665,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; @@ -1624,14 +1681,19 @@ 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); @@ -1644,17 +1706,9 @@ char *str; 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); + if (a == -1) + return FALSE; } /* the regexp portion here has not been condensed by mungspaces() */ @@ -1766,8 +1820,10 @@ char **opp; val_negated = !val_negated; } if (val_negated) { - if (!setrolefilter(op)) - badoption(opts); + 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); @@ -1784,18 +1840,22 @@ illegal_menu_cmd_key(c) char c; { if (c == 0 || c == '\r' || c == '\n' || c == '\033' - || c == ' ' || digit(c) || (letter(c) && c != '@')) + || c == ' ' || digit(c) || (letter(c) && c != '@')) { + config_error_add("Reserved menu command key '%s'", visctrl(c)); return TRUE; - else { /* reject default object class symbols */ + } else { /* reject default object class symbols */ int j; for (j = 1; j < MAXOCLASSES; j++) - if (c == def_oc_syms[j].sym) + if (c == def_oc_syms[j].sym) { + config_error_add("Menu command key '%s' is an object class", + visctrl(c)); return TRUE; + } } return FALSE; } -void +boolean parseoptions(opts, tinitial, tfrom_file) register char *opts; boolean tinitial, tfrom_file; @@ -1805,16 +1865,19 @@ boolean tinitial, tfrom_file; 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 */ @@ -1824,8 +1887,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 == '!') @@ -1845,28 +1910,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 */ @@ -1878,10 +1945,13 @@ boolean tinitial, tfrom_file; fullname = "align"; if (match_optname(opts, fullname, sizeof("align") - 1, TRUE)) { if (parse_role_opts(negated, fullname, opts, &op)) { - if ((flags.initalign = str2align(op)) == ROLE_NONE) - badoption(opts); - } - return; + if ((flags.initalign = str2align(op)) == ROLE_NONE) { + config_error_add("Unknown %s '%s'", fullname, op); + return FALSE; + } + } else + return FALSE; + return retval; } /* role:string or character:string */ @@ -1889,36 +1959,42 @@ boolean tinitial, tfrom_file; if (match_optname(opts, fullname, 4, TRUE) || match_optname(opts, (fullname = "character"), 4, TRUE)) { if (parse_role_opts(negated, fullname, opts, &op)) { - if ((flags.initrole = str2role(op)) == ROLE_NONE) - badoption(opts); - else /* Backwards compatibility */ + 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); - } - return; + } else + return FALSE; + return retval; } /* race:string */ fullname = "race"; if (match_optname(opts, fullname, 4, TRUE)) { if (parse_role_opts(negated, fullname, opts, &op)) { - if ((flags.initrace = str2race(op)) == ROLE_NONE) - badoption(opts); - else /* Backwards compatibility */ + if ((flags.initrace = str2race(op)) == ROLE_NONE) { + config_error_add("Unknown %s '%s'", fullname, op); + return FALSE; + } else /* Backwards compatibility */ pl_race = *op; - } - return; + } else + return FALSE; + return retval; } /* gender:string */ fullname = "gender"; if (match_optname(opts, fullname, 4, TRUE)) { if (parse_role_opts(negated, fullname, opts, &op)) { - if ((flags.initgend = str2gend(op)) == ROLE_NONE) - badoption(opts); - else + if ((flags.initgend = str2gend(op)) == ROLE_NONE) { + config_error_add("Unknown %s '%s'", fullname, op); + return FALSE; + } else flags.female = flags.initgend; - } - return; + } else + return FALSE; + return retval; } /* We always check for duplicates on the remaining compound options, @@ -1932,9 +2008,10 @@ boolean tinitial, tfrom_file; 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'; @@ -1956,48 +2033,58 @@ boolean tinitial, tfrom_file; preferred_pet = '\0'; break; default: - pline("Unrecognized pet type '%s'.", op); + config_error_add("Unrecognized pet type '%s'.", op); + 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"; @@ -2015,14 +2102,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 */ @@ -2040,7 +2127,7 @@ boolean tinitial, tfrom_file; } reset_commands(FALSE); number_pad(iflags.num_pad ? 1 : 0); - return; + return retval; } fullname = "roguesymset"; @@ -2049,20 +2136,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"; @@ -2071,19 +2160,21 @@ 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\".", + config_error_add("Unable to load symbol set \"%s\" from \"%s\"", op, SYMBOLS); - wait_synch(); + return FALSE; } else { switch_symbols(symset[PRIMARY].name != (char *) 0); need_redraw = TRUE; } - } - return; + } else + return FALSE; + return retval; } fullname = "runmode"; @@ -2101,21 +2192,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"; @@ -2125,9 +2222,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"; @@ -2144,7 +2243,7 @@ boolean tinitial, tfrom_file; } else { if (negated) { bad_negation(fullname, TRUE); - return; + return FALSE; } tmp = lowc(*op); } @@ -2161,11 +2260,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 @@ -2201,8 +2302,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); @@ -2226,19 +2327,22 @@ 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 @@ -2257,7 +2361,7 @@ 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; @@ -2266,15 +2370,17 @@ boolean tinitial, tfrom_file; { if (negated) { bad_negation("palette", FALSE); - return; + return FALSE; } color_number = 0; color_incr = 1; } #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; @@ -2320,7 +2426,7 @@ boolean tinitial, tfrom_file; if (!initial) { need_redraw = TRUE; } - return; + return retval; } #endif /* CHANGE_COLOR */ @@ -2334,13 +2440,13 @@ 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; @@ -2353,8 +2459,8 @@ boolean tinitial, tfrom_file; forig = fruit_from_name(pl_fruit, FALSE, (int *) 0); if (!forig && fnum >= 100) { - pline("Doing that so many times isn't very fruitful."); - return; + config_error_add("Doing that so many times isn't very fruitful."); + return retval; } } } @@ -2377,7 +2483,7 @@ 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"; @@ -2386,7 +2492,7 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { iflags.getpos_coords = GPCOORDS_NONE; - return; + return retval; } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { static char gpcoords[] = { GPCOORDS_NONE, GPCOORDS_COMPASS, GPCOORDS_COMFULL, GPCOORDS_MAP, @@ -2395,10 +2501,13 @@ boolean tinitial, tfrom_file; if (c && index(gpcoords, c)) iflags.getpos_coords = c; - else - badoption(opts); - } - return; + else { + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; + } + } else + return FALSE; + return retval; } fullname = "whatis_filter"; @@ -2407,7 +2516,7 @@ boolean tinitial, tfrom_file; complain_about_duplicate(opts, 1); if (negated) { iflags.getloc_filter = GFILTER_NONE; - return; + return retval; } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { char c = lowc(*op); @@ -2421,22 +2530,25 @@ boolean tinitial, tfrom_file; case 'a': iflags.getloc_filter = GFILTER_AREA; break; - default: - badoption(opts); + default: { + config_error_add("Unknown %s parameter '%s'", fullname, op); + return FALSE; } - } - return; + } + } 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 @@ -2448,12 +2560,12 @@ boolean tinitial, tfrom_file; 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; @@ -2462,7 +2574,7 @@ 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"); } else { @@ -2477,7 +2589,7 @@ boolean tinitial, tfrom_file; update_bouldersym(); need_redraw = TRUE; } - return; + return retval; } #endif @@ -2486,11 +2598,14 @@ boolean tinitial, tfrom_file; 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 */ @@ -2500,13 +2615,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 @@ -2523,11 +2640,15 @@ 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] */ @@ -2545,11 +2666,15 @@ 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 */ fullname = "packorder"; @@ -2558,13 +2683,13 @@ boolean tinitial, tfrom_file; 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), @@ -2611,8 +2736,9 @@ 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) @@ -2620,8 +2746,9 @@ boolean tinitial, tfrom_file; else break; /* no next token */ } /* for(;;) */ - } - return; + } else + return FALSE; + return retval; } /* accept deprecated boolean; superseded by paranoid_confirm:pray */ @@ -2631,7 +2758,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) */ @@ -2641,7 +2768,7 @@ 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 (lowc(*op)) { case 'u': /* Unencumbered */ @@ -2664,10 +2791,12 @@ boolean tinitial, tfrom_file; 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 */ @@ -2688,7 +2817,7 @@ 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; @@ -2712,7 +2841,7 @@ boolean tinitial, tfrom_file; } if (negated) { bad_negation("pickup_types", TRUE); - return; + return FALSE; } while (*op == ' ') op++; @@ -2729,10 +2858,12 @@ boolean tinitial, tfrom_file; badopt = TRUE; op++; } - if (badopt) - badoption(opts); + if (badopt) { + config_error_add("Unknown %s parameter '%s'", "pickup_types", op); + return FALSE; + } } - return; + return retval; } /* pile limit: when walking over objects, number which triggers @@ -2744,14 +2875,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 */ @@ -2762,10 +2894,10 @@ boolean tinitial, tfrom_file; if (negated) bad_negation(fullname, FALSE); if (duplicate || negated) - return; + return FALSE; op = string_for_opt(opts, FALSE); if (!op) - return; + return FALSE; if (!strncmpi(op, "normal", 6) || !strcmpi(op, "play")) { wizard = discover = FALSE; } else if (!strncmpi(op, "explore", 6) @@ -2774,9 +2906,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 @@ -2791,15 +2924,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, @@ -2821,15 +2959,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" */ @@ -2840,7 +2977,7 @@ boolean tinitial, tfrom_file; flags.end_disclose[num] = negated ? DISCLOSE_NO_WITHOUT_PROMPT : DISCLOSE_PROMPT_DEFAULT_YES; - return; + return retval; } num = 0; @@ -2881,25 +3018,26 @@ 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; } /* 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; @@ -2929,15 +3067,15 @@ 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"; @@ -2953,11 +3091,12 @@ boolean tinitial, tfrom_file; 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"; @@ -2965,11 +3104,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 @@ -2981,13 +3121,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"; @@ -2996,13 +3136,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 @@ -3014,13 +3154,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' */ @@ -3030,13 +3170,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 */ @@ -3074,11 +3214,15 @@ 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 */ @@ -3089,9 +3233,11 @@ boolean tinitial, tfrom_file; 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 */ @@ -3102,22 +3248,27 @@ boolean tinitial, tfrom_file; 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 */ @@ -3128,9 +3279,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 */ @@ -3142,8 +3295,9 @@ boolean tinitial, tfrom_file; if (iflags.wc_tile_file) free(iflags.wc_tile_file); iflags.wc_tile_file = dupstr(op); - } - return; + } else + return FALSE; + return retval; } /* WINCAP * tile_height:nn */ @@ -3154,9 +3308,11 @@ 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 */ @@ -3167,9 +3323,11 @@ 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; } fullname = "windowtype"; if (match_optname(opts, fullname, 3, TRUE)) { @@ -3177,26 +3335,28 @@ 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) { 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 @@ -3209,15 +3369,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); @@ -3225,7 +3386,7 @@ 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 = lowc(*op); @@ -3249,28 +3410,29 @@ boolean tinitial, tfrom_file; 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); + if (tmpattr == -1) + return FALSE; + else + iflags.menu_headings = tmpattr; + return retval; } /* check for menu command mapping */ @@ -3281,18 +3443,19 @@ boolean tinitial, tfrom_file; 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) { char c, op_buf[BUFSZ]; escapes(op, op_buf); c = *op_buf; - if (illegal_menu_cmd_key(c)) - 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) @@ -3303,15 +3466,14 @@ boolean tinitial, tfrom_file; op = string_for_opt(opts, TRUE); if (op && negated) { clear_status_hilites(tfrom_file); - return; + 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 (!set_status_hilites(op, tfrom_file)) /* TODO: error msg? */ + return FALSE; + return retval; } #endif @@ -3335,11 +3497,11 @@ 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; } fullname = "IBMgraphics"; if (match_optname(opts, fullname, 3, TRUE)) { @@ -3364,15 +3526,15 @@ 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; } #endif #ifdef MAC_GRAPHICS_ENV @@ -3393,15 +3555,15 @@ 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; } #endif @@ -3415,28 +3577,28 @@ boolean tinitial, tfrom_file; 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) { - badoption(opts); - return; + 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 { - badoption(opts); - return; + config_error_add("Illegal parameter for a boolean"); + return FALSE; } } @@ -3455,7 +3617,7 @@ boolean tinitial, tfrom_file; #endif /* only do processing below if setting with doset() */ if (initial) - return; + return retval; if (boolopt[i].addr == &flags.time #ifdef SCORE_ON_BOTL @@ -3501,69 +3663,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); - return; + check_gold_symbol(); + return retval; } /* out of valid options */ - badoption(opts); + config_error_add("Unknown option '%s'", opts); + return FALSE; } /* parse key:command */ -void +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; - parsebindings(bind); + ret |= parsebindings(bind); } /* parse a single binding: first split around : */ if (! (bind = index(bindings, ':'))) - return; /* it's not a binding */ + return FALSE; /* it's not a binding */ *bind++ = 0; /* read the key to be bound */ key = txt2key(bindings); if (!key) { - raw_printf("Bad binding %s.", bindings); - wait_synch(); - return; + 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; + 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)) { - char tmp[BUFSZ]; - Sprintf(tmp, "Bad menu key %s:%s", visctrl(key), bind); - badoption(tmp); + 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; + return TRUE; } } /* extended command? */ - bind_key(key, bind); + 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", @@ -4005,6 +4172,7 @@ doset() /* changing options via menu by Per Liboriussen */ destroy_nhwindow(tmpwin); if (need_redraw) { + check_gold_symbol(); reglyph_darkroom(); (void) doredraw(); } @@ -4497,6 +4665,7 @@ boolean setinitial, setfromfile; 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."); @@ -4558,6 +4727,7 @@ boolean setinitial, setfromfile; if (*mcbuf == '\033') return TRUE; if (*mcbuf + && test_regex_pattern(mcbuf, (const char *)0) && (mcclr = query_color()) != -1 && (mcattr = query_attr((char *) 0)) != -1 && !add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) { @@ -5069,20 +5239,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")) { Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat" @@ -5272,20 +5431,14 @@ const char *mapping; || (n == 2 && end == '#')) { grab = FALSE; } else { - if (!iflags.window_inited) - raw_print(APE_syntax_error); /* from options file */ - else - pline("%s", APE_syntax_error); /* via 'O' command */ + 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)) { - if (!iflags.window_inited) - raw_print(APE_regex_error); - else - pline("%s", APE_regex_error); + config_error_add("%s: %s", APE_regex_error, regex_error_desc(ape->regex)); regex_free(ape->regex); free((genericptr_t) ape); return 0; diff --git a/src/pager.c b/src/pager.c index c14a49bf1..d7fc456b8 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pager.c $NHDT-Date: 1471112245 2016/08/13 18:17:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.112 $ */ +/* NetHack 3.6 pager.c $NHDT-Date: 1505299155 2017/09/13 10:39:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.118 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -328,11 +328,20 @@ int x, y; Strcat(monbuf, ", "); } if (how_seen & MONSEEN_WARNMON) { - if (Hallucination) + if (Hallucination) { Strcat(monbuf, "paranoid delusion"); - else - Sprintf(eos(monbuf), "warned of %s", - makeplural(mtmp->data->mname)); + } 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); + + Sprintf(eos(monbuf), "warned of %s", makeplural(whom)); + } how_seen &= ~MONSEEN_WARNMON; if (how_seen) Strcat(monbuf, ", "); diff --git a/src/pickup.c b/src/pickup.c index 0b91a4bb4..56ff922f9 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -29,6 +29,7 @@ STATIC_DCL long FDECL(carry_count, (struct obj *, struct obj *, long, 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 *)); @@ -707,7 +708,7 @@ 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) @@ -840,7 +841,7 @@ 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, *olist = *olist_p; char *pack; @@ -859,7 +860,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 */ @@ -2019,6 +2019,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) @@ -2326,13 +2348,18 @@ explain_container_prompt(more_containers) boolean more_containers; { static const char *const explaintext[] = { - "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", "", - " n -- Next: loot next selected container", " q -- Quit: finished", - " ? -- Help: display this text.", "", 0 + " n -- Next: loot next selected container", + " q -- Quit: finished", + " ? -- Help: display this text.", + "", 0 }; const char *const *txtpp; winid win; @@ -2370,11 +2397,12 @@ 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'; @@ -2415,22 +2443,14 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */ 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) - You("owe %ld %s for lost merchandise.", loss, currency(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; + You("owe %ld %s for lost merchandise.", loss, currency(loss)); current_container->owt = weight(current_container); } inokay = (invent != 0 diff --git a/src/pline.c b/src/pline.c index 07e55e679..270272042 100644 --- a/src/pline.c +++ b/src/pline.c @@ -469,7 +469,7 @@ const char *line; (void) execv(args[0], (char *const *) args); perror((char *) 0); (void) fprintf(stderr, "Exec to message handler %s failed.\n", env); - terminate(EXIT_FAILURE); + nh_terminate(EXIT_FAILURE); } else if (f > 0) { int status; diff --git a/src/quest.c b/src/quest.c index f1222fc69..df4b83155 100644 --- a/src/quest.c +++ b/src/quest.c @@ -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. */ @@ -68,7 +68,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)++; } @@ -179,6 +192,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) diff --git a/src/questpgr.c b/src/questpgr.c index ed936d9e4..b96edbc3c 100644 --- a/src/questpgr.c +++ b/src/questpgr.c @@ -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. */ @@ -22,6 +22,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); @@ -196,6 +197,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() @@ -573,7 +626,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; } diff --git a/src/read.c b/src/read.c index 46f838426..9732fea96 100644 --- a/src/read.c +++ b/src/read.c @@ -29,6 +29,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 @@ -915,7 +916,7 @@ struct obj *sobj; return 0; } -boolean +STATIC_OVL boolean get_valid_stinking_cloud_pos(x,y) int x,y; { @@ -929,7 +930,7 @@ is_valid_stinking_cloud_pos(x, y, showmsg) int x, y; boolean showmsg; { - if (get_valid_stinking_cloud_pos(x,y)) { + if (!get_valid_stinking_cloud_pos(x,y)) { if (showmsg) You("smell rotten eggs."); return FALSE; @@ -1555,8 +1556,14 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */ pline("Thinking of Maud you forget everything else."); 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) @@ -1580,13 +1587,28 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */ if (Underwater) { pline_The("%s around you vaporizes violently!", hliquid("water")); } else { - pline_The("scroll erupts in a tower of flame!"); - iflags.last_msg = PLNMSG_TOWER_OF_FLAME; /* for explode() */ - burn_away_slime(); + 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) { + pline_The("scroll erupts in a tower of flame!"); + 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) diff --git a/src/restore.c b/src/restore.c index 509ff6ed9..7d83575dc 100644 --- a/src/restore.c +++ b/src/restore.c @@ -744,7 +744,7 @@ xchar ltmp; } #endif /* ?AMIGA */ pline("Be seeing you..."); - terminate(EXIT_SUCCESS); + nh_terminate(EXIT_SUCCESS); } #endif /* MFLOPPY */ bufon(nfd); diff --git a/src/save.c b/src/save.c index 71b611e1f..cdd5f02d7 100644 --- a/src/save.c +++ b/src/save.c @@ -64,8 +64,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 @@ -94,7 +92,7 @@ dosave() /* make sure they see the Saving message */ display_nhwindow(WIN_MESSAGE, TRUE); exit_nhwindows("Be seeing you..."); - terminate(EXIT_SUCCESS); + nh_terminate(EXIT_SUCCESS); } else (void) doredraw(); } @@ -728,7 +726,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); @@ -834,7 +832,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) */ @@ -860,7 +858,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); @@ -1175,23 +1173,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 @@ -1201,21 +1202,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; } @@ -1225,6 +1227,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)); diff --git a/src/spell.c b/src/spell.c index dba05de6c..955620f57 100644 --- a/src/spell.c +++ b/src/spell.c @@ -883,7 +883,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; @@ -933,13 +933,29 @@ 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) { You_feel("the amulet draining your energy away."); - 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) { You("don't have enough energy to cast that spell."); - return 0; + return res; } else { if (spellid(spell) != SPE_DETECT_FOOD) { int hungr = energy * 2; diff --git a/src/sys.c b/src/sys.c index c0803d480..6adc8f71f 100644 --- a/src/sys.c +++ b/src/sys.c @@ -40,6 +40,7 @@ sys_early_init() 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; diff --git a/src/timeout.c b/src/timeout.c index 81285fc37..7e391cb13 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 timeout.c $NHDT-Date: 1496619133 2017/06/04 23:32:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.71 $ */ +/* 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. */ /* NetHack may be freely redistributed. See license for details. */ @@ -145,13 +145,13 @@ stoned_dialogue() 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[] = { "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 */ }; STATIC_OVL void @@ -188,12 +188,25 @@ vomiting_dialogue() case 2: txt = vomiting_texts[4]; if (cantvomit(youmonst.data)) - txt = "gag uncontrolably."; + txt = "gag uncontrollably."; + 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 a more specific at which hero became unable to move + [vomit() issues its own message for the cantvomit() case] */ + You("%s!", !Hallucination ? "vomit" : "hurl chunks"); + } vomit(); break; default: @@ -363,6 +376,8 @@ nh_timeout() 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(); } diff --git a/src/trap.c b/src/trap.c index ddf065a0c..d6b3f8de9 100644 --- a/src/trap.c +++ b/src/trap.c @@ -409,7 +409,7 @@ int x, y, 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) */ @@ -3287,6 +3287,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)) @@ -3298,6 +3299,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; diff --git a/src/u_init.c b/src/u_init.c index 3dadf09d0..447d16d16 100644 --- a/src/u_init.c +++ b/src/u_init.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 u_init.c $NHDT-Date: 1454660565 2016/02/05 08:22:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.37 $ */ +/* 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. */ /* NetHack may be freely redistributed. See license for details. */ @@ -124,7 +124,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 } }; diff --git a/src/uhitm.c b/src/uhitm.c index b11cb0fd8..81a71a406 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 uhitm.c $NHDT-Date: 1496860757 2017/06/07 18:39:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.166 $ */ +/* NetHack 3.6 uhitm.c $NHDT-Date: 1504999056 2017/09/09 23:17:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.167 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1609,8 +1609,9 @@ register struct attack *mattk; pline("%s suddenly seems weaker!", Monnam(mdef)); mdef->mhpmax -= xtmp; mdef->mhp -= xtmp; - /* !m_lev: level 0 monster is killed rather than drop to -1 */ - if (mdef->mhp <= 0 && !mdef->m_lev) { + /* !m_lev: level 0 monster is killed regardless of hit points + rather than drop to level -1 */ + if (mdef->mhp <= 0 || !mdef->m_lev) { pline("%s dies!", Monnam(mdef)); xkilled(mdef, XKILL_NOMSG); } else diff --git a/src/were.c b/src/were.c index c8ee49650..b61d16402 100644 --- a/src/were.c +++ b/src/were.c @@ -1,4 +1,4 @@ -/* 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. */ /* NetHack may be freely redistributed. See license for details. */ @@ -183,7 +183,7 @@ you_were() /* `+4' => skip "were" prefix to get name of beast */ Sprintf(qbuf, "Do you want to change into %s?", an(mons[u.ulycn].mname + 4)); - if (yn(qbuf) == 'n') + if (!paranoid_query(ParanoidWerechange, qbuf)) return; } (void) polymon(u.ulycn); @@ -200,8 +200,11 @@ boolean purify; set_ulycn(NON_PM); /* cure lycanthropy */ } if (!Unchanging && is_were(youmonst.data) - && (!controllable_poly || yn("Remain in beast form?") == 'n')) + && (!controllable_poly + || !paranoid_query(ParanoidWerechange, "Remain in beast form?"))) 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 */ diff --git a/src/windows.c b/src/windows.c index 55678a0b4..a23ec95c7 100644 --- a/src/windows.c +++ b/src/windows.c @@ -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 @@ -1157,15 +1172,6 @@ dump_close_log() } } -void -dump_putc(ch) -int ch; -{ - /* Not very efficient, but we mostly don't care. */ - if (dumplog_file) - putc(ch, dumplog_file); -} - void dump_forward_putstr(win, attr, str, no_forward) winid win; diff --git a/src/zap.c b/src/zap.c index 9cf38e030..add78a0de 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 zap.c $NHDT-Date: 1470819844 2016/08/10 09:04:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.263 $ */ +/* NetHack 3.6 zap.c $NHDT-Date: 1505475171 2017/09/15 11:32:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.267 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2127,6 +2127,7 @@ backfire(otmp) struct obj *otmp; { int dmg; + otmp->in_use = TRUE; /* in case losehp() is fatal */ pline("%s suddenly explodes!", The(xname(otmp))); dmg = d(otmp->spe + 2, 6); @@ -3070,6 +3071,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) @@ -3300,7 +3302,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; @@ -3880,10 +3882,10 @@ const char *fltxt; } void -buzz(type,nd,sx,sy,dx,dy) +buzz(type, nd, sx, sy, dx, dy) int type, nd; -xchar sx,sy; -int dx,dy; +xchar sx, sy; +int dx, dy; { dobuzz(type, nd, sx, sy, dx, dy, TRUE); } @@ -3898,7 +3900,7 @@ int dx,dy; * called with dx = dy = 0 with vertical bolts */ void -dobuzz(type, nd, sx, sy, dx, dy,say) +dobuzz(type, nd, sx, sy, dx, dy, say) register int type, nd; register xchar sx, sy; register int dx, dy; @@ -4145,7 +4147,7 @@ boolean say; /* Announce out of sight hit/miss events if true */ ? "shatter" /* "damage" indicates wall rather than door */ : abstype == ZT_ACID - ? "damage" + ? "damage" : abstype == ZT_DEATH ? "disintegrate" : "destroy", @@ -4410,7 +4412,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 { @@ -4508,7 +4510,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); diff --git a/sys/amiga/winami.c b/sys/amiga/winami.c index daabd859d..58d4165da 100644 --- a/sys/amiga/winami.c +++ b/sys/amiga/winami.c @@ -436,7 +436,7 @@ amii_askname() if (*plname == '\33') { clearlocks(); exit_nhwindows(NULL); - terminate(0); + nh_terminate(0); } } @@ -543,7 +543,7 @@ amii_player_selection() CloseShWindow( cwin ); clearlocks(); exit_nhwindows(NULL); - terminate(0); + nh_terminate(0); } else DisplayBeep( NULL ); @@ -573,7 +573,7 @@ amii_player_selection() CloseShWindow( cwin ); clearlocks(); exit_nhwindows(NULL); - terminate(0); + nh_terminate(0); break; } } @@ -1368,7 +1368,7 @@ amii_player_selection() free((genericptr_t) selected); clearlocks(); exit_nhwindows(NULL); - terminate(0); + nh_terminate(0); /*NOTREACHED*/ return; } diff --git a/sys/share/pcmain.c b/sys/share/pcmain.c index df756234a..d62d234cc 100644 --- a/sys/share/pcmain.c +++ b/sys/share/pcmain.c @@ -776,7 +776,9 @@ char *argv[]; NHWinMainInit(); } */ + config_error_init(FALSE, "command line", FALSE); choose_windows(&argv[0][2]); + config_error_done(); break; #endif case '@': diff --git a/sys/unix/hints/linux b/sys/unix/hints/linux index 4310e6afe..8edd35afc 100644 --- a/sys/unix/hints/linux +++ b/sys/unix/hints/linux @@ -26,6 +26,7 @@ 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: diff --git a/sys/unix/sysconf b/sys/unix/sysconf index d83aeff7d..eacca35ed 100644 --- a/sys/unix/sysconf +++ b/sys/unix/sysconf @@ -98,6 +98,14 @@ MAXPLAYERS=10 # %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. diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index 1c0d55f90..2270ab262 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -97,19 +97,18 @@ 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 (!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 @@ -127,30 +126,33 @@ 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 - prscore(argc, argv); - exit(EXIT_SUCCESS); - } - } + prscore(argc, argv); + /* 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 @@ -168,7 +170,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 @@ -217,7 +219,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, @@ -252,17 +254,17 @@ char *argv[]; 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. + * 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. - */ + /* + * 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) { const char *fq_save = fqname(SAVEF, SAVEPREFIX, 1); @@ -283,9 +285,10 @@ attempt_restore: resuming = TRUE; /* not starting new game */ wd_message(); if (discover || wizard) { - if (yn("Do you want to keep the save file?") == 'n') + /* this seems like a candidate for paranoid_confirmation... */ + if (yn("Do you want to keep the save file?") == 'n') { (void) delete_savefile(); - else { + } else { (void) chmod(fq_save, FCMASK); /* back to readable */ nh_compress(fq_save); } @@ -316,10 +319,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 @@ -363,14 +368,15 @@ char *argv[]; break; #endif case 'u': - if (argv[0][2]) - (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1); - else if (argc > 1) { + if (argv[0][2]) { + (void) strncpy(plname, argv[0] + 2, sizeof plname - 1); + } else if (argc > 1) { argc--; argv++; - (void) strncpy(plname, argv[0], sizeof(plname) - 1); - } else + (void) strncpy(plname, argv[0], sizeof plname - 1); + } else { raw_print("Player name expected after -u"); + } break; case 'I': case 'i': @@ -405,7 +411,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; @@ -455,10 +463,10 @@ boolean wr; (void) setuid(getuid()); /* Ron Wessels */ #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); @@ -481,9 +489,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]; @@ -574,6 +583,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; @@ -626,6 +636,7 @@ char *optstr; int pwlen; char *eop, *w; char *pwname; + if (optstr[0] == '*') return TRUE; /* allow any user */ if (!pw) diff --git a/sys/unix/unixres.c b/sys/unix/unixres.c index c60df7669..cd0954a1f 100644 --- a/sys/unix/unixres.c +++ b/sys/unix/unixres.c @@ -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; diff --git a/sys/unix/unixunix.c b/sys/unix/unixunix.c index d02d70c63..9c4f312b3 100644 --- a/sys/unix/unixunix.c +++ b/sys/unix/unixunix.c @@ -28,7 +28,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 +37,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 +50,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 */ /* This will work on 4.1cbsd, 4.2bsd and system 3? & 5. */ @@ -62,10 +63,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 +86,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 +140,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,17 +158,20 @@ 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[] = + "There is already a game in progress under your name. Destroy old game?"; + if (iflags.window_inited) { - c = yn("There is already a game in progress under your name. " - "Destroy old game?"); + /* this is a candidate for paranoid_confirmation */ + c = yn(destroy_old_game_prompt); } else { - (void) printf( - "\nThere is already a game in progress under your name."); - (void) printf(" Destroy old game? [yn] "); + (void) printf("\n%s [yn] ", destroy_old_game_prompt); (void) fflush(stdout); if ((c = getchar()) != EOF) { int tmp; @@ -178,10 +182,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."); } @@ -197,8 +202,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) { @@ -207,13 +212,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__) @@ -258,10 +265,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; } @@ -284,6 +294,7 @@ child(wt) int wt; { register int f; + suspend_nhwindows((char *) 0); /* also calls end_screen() */ #ifdef _M_UNIX sco_mapon(); @@ -297,13 +308,13 @@ int wt; #ifdef CHDIR (void) chdir(getenv("HOME")); #endif - 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); @@ -325,9 +336,9 @@ int wt; wait_synch(); } resume_nhwindows(); - return (0); + return 0; } -#endif +#endif /* SHELL || DEF_PAGER || DEF_MAILREADER */ #ifdef GETRES_SUPPORT @@ -338,34 +349,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(); } @@ -375,12 +389,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; } diff --git a/sys/vms/sysconf b/sys/vms/sysconf index 8b52270da..0d46cd4f6 100644 --- a/sys/vms/sysconf +++ b/sys/vms/sysconf @@ -53,6 +53,14 @@ # 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 diff --git a/sys/wince/mhmain.c b/sys/wince/mhmain.c index 58af9f7dd..98abd0177 100644 --- a/sys/wince/mhmain.c +++ b/sys/wince/mhmain.c @@ -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; /*-----------------------------------------------------------------------*/ diff --git a/sys/wince/mswproc.c b/sys/wince/mswproc.c index 5a0ff989d..500306875 100644 --- a/sys/wince/mswproc.c +++ b/sys/wince/mswproc.c @@ -680,7 +680,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 +1726,7 @@ bail(const char *mesg) { clearlocks(); mswin_exit_nhwindows(mesg); - terminate(EXIT_SUCCESS); + nh_terminate(EXIT_SUCCESS); /*NOTREACHED*/ } diff --git a/sys/winnt/Install.nt b/sys/winnt/Install.nt index a9b2201b0..477213b72 100644 --- a/sys/winnt/Install.nt +++ b/sys/winnt/Install.nt @@ -21,10 +21,18 @@ tty and graphical win32 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 2017 Express + + OR + + o A copy of Microsoft Visual Studio 2015 Express + + OR + o A copy of Microsoft Visual Studio 2013 Express The current NetHack code has not been tested with earlier versions of the compiler. - + OR o A copy of MinGW. MinGW is a collection of header @@ -34,12 +42,44 @@ version. You can use one of the following build environments: 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, proceed +to "FIRST STEP - MOVING THINGS AROUND". + +When using either Visual Studio 2015 or Visual Studio 2017, you do not +need to move things around. 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. + 4. From 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. + +Change to the appropriate directory (i.e. win\win32\vs2015 for VS2015 builds) +and run "build.bat". /-----------------------------------\ | FIRST STEP - MOVING THINGS AROUND | @@ -49,11 +89,11 @@ The first step in building either version of NetHack 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 + double-click on nhsetup.bat A "binary" directory will be created off the top of the NetHack source tree to house the completed build. diff --git a/sys/winnt/defaults.nh b/sys/winnt/defaults.nh index 50e801f03..7dfef2713 100644 --- a/sys/winnt/defaults.nh +++ b/sys/winnt/defaults.nh @@ -44,6 +44,28 @@ OPTIONS=symset:IBMGraphics_2,roguesymset:RogueEpyx #OPTIONS=hilite_status:hitpoints/30%/bright-magenta/normal #OPTIONS=perm_invent + +# 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 + + + # Turn off all status hilites. #OPTIONS=!statushilites # @@ -54,6 +76,9 @@ OPTIONS=symset:IBMGraphics_2,roguesymset:RogueEpyx # 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 diff --git a/sys/winnt/nhsetup.bat b/sys/winnt/nhsetup.bat index d477b301c..4a7dfb6b2 100755 --- a/sys/winnt/nhsetup.bat +++ b/sys/winnt/nhsetup.bat @@ -10,7 +10,38 @@ set BUILDPATH=..\..\build set BINPATH=..\..\binary set VCDir= -:studiocheck +goto :main + +: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 + +:main + +:vscheck2015 +rem cannot use the registry trick as in vc2010 +rem 14 = 2015 +SET VCVERS=14 +rem Finally, let's determine the root folder for this VC installation. +call 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 + +if not defined VCDir goto :studiocheck2010 +if not exist "%VCDir%" goto :studiocheck2010 + +goto :fallback + +:studiocheck2010 @REM Set fallbacks here for 32-bit VS2010 SET REGTREE=HKLM\Software\Microsoft\VCExpress\12.0\Setup\VC SET MSVCVERSION=2010 diff --git a/sys/winnt/sysconf b/sys/winnt/sysconf index 2ce1da300..7e4d9da0a 100644 --- a/sys/winnt/sysconf +++ b/sys/winnt/sysconf @@ -32,6 +32,14 @@ WIZARDS=* # %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 diff --git a/sys/winnt/win32api.h b/sys/winnt/win32api.h index 2b63c8005..b4dc7e4c8 100644 --- a/sys/winnt/win32api.h +++ b/sys/winnt/win32api.h @@ -17,6 +17,13 @@ #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 #include diff --git a/util/dlb_main.c b/util/dlb_main.c index 0a4b938dd..6cda2b3ab 100644 --- a/util/dlb_main.c +++ b/util/dlb_main.c @@ -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)); diff --git a/win/Qt/qt_win.cpp b/win/Qt/qt_win.cpp index db995f7ea..52c925ae6 100644 --- a/win/Qt/qt_win.cpp +++ b/win/Qt/qt_win.cpp @@ -4039,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: @@ -4639,7 +4639,7 @@ void NetHackQtBind::qt_askname() // Quit clearlocks(); qt_exit_nhwindows(0); - terminate(0); + nh_terminate(0); } void NetHackQtBind::qt_get_nh_event() diff --git a/win/X11/winmisc.c b/win/X11/winmisc.c index b96902588..7f71b0ca3 100644 --- a/win/X11/winmisc.c +++ b/win/X11/winmisc.c @@ -370,7 +370,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) { @@ -439,7 +439,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) { @@ -507,7 +507,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) { @@ -573,7 +573,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) { diff --git a/win/gem/wingem.c b/win/gem/wingem.c index 1d059eed0..72daffd14 100644 --- a/win/gem/wingem.c +++ b/win/gem/wingem.c @@ -129,7 +129,7 @@ const char *mesg; { clearlocks(); Gem_exit_nhwindows(mesg); - terminate(EXIT_SUCCESS); + nh_terminate(EXIT_SUCCESS); /*NOTREACHED*/ } diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 3ac407a56..7e504d669 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -221,7 +221,7 @@ const char *mesg; { clearlocks(); tty_exit_nhwindows(mesg); - terminate(EXIT_SUCCESS); + nh_terminate(EXIT_SUCCESS); /*NOTREACHED*/ } @@ -2663,7 +2663,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 diff --git a/win/win32/.gitignore b/win/win32/.gitignore index c40993f47..3f210da5d 100644 --- a/win/win32/.gitignore +++ b/win/win32/.gitignore @@ -1,4 +1,9 @@ # Build-generated stuff that we don't want *.bmp *.ico - +*.db +record +*.user +*.opendb +*.log +*.aps diff --git a/win/win32/mhfont.c b/win/win32/mhfont.c index c04419982..1b802f2d0 100644 --- a/win/win32/mhfont.c +++ b/win/win32/mhfont.c @@ -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; diff --git a/win/win32/mhmain.c b/win/win32/mhmain.c index 2b52f71cf..48c2ea3a6 100644 --- a/win/win32/mhmain.c +++ b/win/win32/mhmain.c @@ -370,7 +370,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 { diff --git a/win/win32/mhmenu.c b/win/win32/mhmenu.c index 6c07b5081..bbf364cd4 100644 --- a/win/win32/mhmenu.c +++ b/win/win32/mhmenu.c @@ -586,8 +586,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; @@ -605,6 +603,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 */ @@ -884,6 +884,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 { diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index fe3ce07b5..7b80cfbc6 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -84,7 +84,7 @@ 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, 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, @@ -212,6 +212,7 @@ 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("mouse_support", SET_IN_GAME); /* initialize map tiles bitmap */ initMapTiles(); @@ -1382,9 +1383,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; @@ -2067,7 +2070,7 @@ bail(const char *mesg) { clearlocks(); mswin_exit_nhwindows(mesg); - terminate(EXIT_SUCCESS); + nh_terminate(EXIT_SUCCESS); /*NOTREACHED*/ } diff --git a/win/win32/nethack.rc b/win/win32/nethack.rc new file mode 100644 index 000000000..72ce4e0df --- /dev/null +++ b/win/win32/nethack.rc @@ -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 - 2017. 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 index 000000000..119608c0d --- /dev/null +++ b/win/win32/nhresource.h @@ -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/vs2015/NetHack.sln b/win/win32/vs2015/NetHack.sln new file mode 100755 index 000000000..2c2e78230 --- /dev/null +++ b/win/win32/vs2015/NetHack.sln @@ -0,0 +1,197 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetHackW", "NetHackW.vcxproj", "{CEC5D360-8804-454F-8591-002184C23499}" + ProjectSection(ProjectDependencies) = postProject + {93F10526-209E-41D7-BBEA-775787876895} = {93F10526-209E-41D7-BBEA-775787876895} + {63F9B82B-F589-4082-ABE5-D4F0682050AB} = {63F9B82B-F589-4082-ABE5-D4F0682050AB} + {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + {642BC75D-ABAF-403E-8224-7C725FD4CB42} = {642BC75D-ABAF-403E-8224-7C725FD4CB42} + {6813477F-64B6-4B97-B230-438D0D233385} = {6813477F-64B6-4B97-B230-438D0D233385} + {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} = {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} + {8A3F81C7-2968-49A8-86BF-2669412AD7DE} = {8A3F81C7-2968-49A8-86BF-2669412AD7DE} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dgncomp", "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}") = "dlb", "dlb.vcxproj", "{0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}" + ProjectSection(ProjectDependencies) = postProject + {63F9B82B-F589-4082-ABE5-D4F0682050AB} = {63F9B82B-F589-4082-ABE5-D4F0682050AB} + {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + {8A3F81C7-2968-49A8-86BF-2669412AD7DE} = {8A3F81C7-2968-49A8-86BF-2669412AD7DE} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "levcomp", "levcomp.vcxproj", "{9DD9C52E-E8C9-4533-BD22-83C055C0AABA}" + ProjectSection(ProjectDependencies) = postProject + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makedefs", "makedefs.vcxproj", "{BA3DD34C-04B7-40D0-B373-9329AA9E8945}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "recover", "recover.vcxproj", "{2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tile2bmp", "tile2bmp.vcxproj", "{642BC75D-ABAF-403E-8224-7C725FD4CB42}" + ProjectSection(ProjectDependencies) = postProject + {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tilemap", "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}") = "uudecode", "uudecode.vcxproj", "{63F9B82B-F589-4082-ABE5-D4F0682050AB}" + ProjectSection(ProjectDependencies) = postProject + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetHack", "NetHack.vcxproj", "{609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}" + ProjectSection(ProjectDependencies) = postProject + {63F9B82B-F589-4082-ABE5-D4F0682050AB} = {63F9B82B-F589-4082-ABE5-D4F0682050AB} + {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + {6813477F-64B6-4B97-B230-438D0D233385} = {6813477F-64B6-4B97-B230-438D0D233385} + {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} = {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} + {8A3F81C7-2968-49A8-86BF-2669412AD7DE} = {8A3F81C7-2968-49A8-86BF-2669412AD7DE} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nhdefkey", "nhdefkey.vcxproj", "{6813477F-64B6-4B97-B230-438D0D233385}" + ProjectSection(ProjectDependencies) = postProject + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nh340key", "nh340key.vcxproj", "{BE04E242-A1E9-4593-B95B-057F37330B76}" + ProjectSection(ProjectDependencies) = postProject + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nhraykey", "nhraykey.vcxproj", "{2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}" + ProjectSection(ProjectDependencies) = postProject + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +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 + {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 + {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 + {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 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|Win32.ActiveCfg = Debug|Win32 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|Win32.Build.0 = Debug|Win32 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|x64.ActiveCfg = Debug|x64 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|x64.Build.0 = Debug|x64 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|Win32.ActiveCfg = Release|Win32 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|Win32.Build.0 = Release|Win32 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|x64.ActiveCfg = Release|x64 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|x64.Build.0 = Release|x64 + {6813477F-64B6-4B97-B230-438D0D233385}.Debug|Win32.ActiveCfg = Debug|Win32 + {6813477F-64B6-4B97-B230-438D0D233385}.Debug|Win32.Build.0 = Debug|Win32 + {6813477F-64B6-4B97-B230-438D0D233385}.Debug|x64.ActiveCfg = Debug|x64 + {6813477F-64B6-4B97-B230-438D0D233385}.Debug|x64.Build.0 = Debug|x64 + {6813477F-64B6-4B97-B230-438D0D233385}.Release|Win32.ActiveCfg = Release|Win32 + {6813477F-64B6-4B97-B230-438D0D233385}.Release|Win32.Build.0 = Release|Win32 + {6813477F-64B6-4B97-B230-438D0D233385}.Release|x64.ActiveCfg = Release|x64 + {6813477F-64B6-4B97-B230-438D0D233385}.Release|x64.Build.0 = Release|x64 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|Win32.ActiveCfg = Debug|Win32 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|Win32.Build.0 = Debug|Win32 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|x64.ActiveCfg = Debug|x64 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|x64.Build.0 = Debug|x64 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|Win32.ActiveCfg = Release|Win32 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|Win32.Build.0 = Release|Win32 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|x64.ActiveCfg = Release|x64 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|x64.Build.0 = Release|x64 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|Win32.ActiveCfg = Debug|Win32 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|Win32.Build.0 = Debug|Win32 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|x64.ActiveCfg = Debug|x64 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|x64.Build.0 = Debug|x64 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|Win32.ActiveCfg = Release|Win32 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|Win32.Build.0 = Release|Win32 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|x64.ActiveCfg = Release|x64 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win/win32/vs2015/NetHack.vcxproj b/win/win32/vs2015/NetHack.vcxproj new file mode 100755 index 000000000..3c0ce9911 --- /dev/null +++ b/win/win32/vs2015/NetHack.vcxproj @@ -0,0 +1,233 @@ + + + + + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751} + Win32Proj + NetHack + + + + + + + + + + $(BinDir) + + + + /Gs /Oi- %(AdditionalOptions) + Disabled + Default + Speed + true + $(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories) + TILES;WIN32CON;DLB;MSWIN_GRAPHICS;_LIB;%(PreprocessorDefinitions) + + + 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) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GUISTUB;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/NetHackW.vcxproj b/win/win32/vs2015/NetHackW.vcxproj new file mode 100755 index 000000000..52403bbf6 --- /dev/null +++ b/win/win32/vs2015/NetHackW.vcxproj @@ -0,0 +1,192 @@ + + + + + + {CEC5D360-8804-454F-8591-002184C23499} + NetHackW + + + + + + + + + + + $(BinDir) + + + + + /Gs /Oi- %(AdditionalOptions) + Disabled + true + $(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories) + TILES;_WINDOWS;DLB;MSWIN_GRAPHICS;WIN32CONNDEBUG;%(PreprocessorDefinitions) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + Windows + comctl32.lib;winmm.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TTYSTUB; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/afterdgncomp.proj b/win/win32/vs2015/afterdgncomp.proj new file mode 100644 index 000000000..7aebee743 --- /dev/null +++ b/win/win32/vs2015/afterdgncomp.proj @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/afterdlb.proj b/win/win32/vs2015/afterdlb.proj new file mode 100644 index 000000000..ed68ba33e --- /dev/null +++ b/win/win32/vs2015/afterdlb.proj @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/win/win32/vs2015/afterlevcomp.proj b/win/win32/vs2015/afterlevcomp.proj new file mode 100644 index 000000000..924f66cd5 --- /dev/null +++ b/win/win32/vs2015/afterlevcomp.proj @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/win/win32/vs2015/aftermakedefs.proj b/win/win32/vs2015/aftermakedefs.proj new file mode 100644 index 000000000..20adf1b15 --- /dev/null +++ b/win/win32/vs2015/aftermakedefs.proj @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/win/win32/vs2015/afternethack.proj b/win/win32/vs2015/afternethack.proj new file mode 100644 index 000000000..3b769323e --- /dev/null +++ b/win/win32/vs2015/afternethack.proj @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/win/win32/vs2015/afterrecover.proj b/win/win32/vs2015/afterrecover.proj new file mode 100644 index 000000000..0652e7828 --- /dev/null +++ b/win/win32/vs2015/afterrecover.proj @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/win/win32/vs2015/aftertile2bmp.proj b/win/win32/vs2015/aftertile2bmp.proj new file mode 100644 index 000000000..28d2b2e39 --- /dev/null +++ b/win/win32/vs2015/aftertile2bmp.proj @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/win/win32/vs2015/aftertilemap.proj b/win/win32/vs2015/aftertilemap.proj new file mode 100644 index 000000000..bfdb48fe9 --- /dev/null +++ b/win/win32/vs2015/aftertilemap.proj @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/win/win32/vs2015/afteruudecode.proj b/win/win32/vs2015/afteruudecode.proj new file mode 100644 index 000000000..b33e3c4f4 --- /dev/null +++ b/win/win32/vs2015/afteruudecode.proj @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/win/win32/vs2015/build.bat b/win/win32/vs2015/build.bat new file mode 100644 index 000000000..78b7356ad --- /dev/null +++ b/win/win32/vs2015/build.bat @@ -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 index 000000000..5889dbb7d --- /dev/null +++ b/win/win32/vs2015/common.props @@ -0,0 +1,41 @@ + + + + true + + + false + + + + Level3 + WIN32;CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + Console + $(SymbolsDir)$(TargetName).pdb + + + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + true + + + + + MaxSpeed + OnlyExplicitInline + NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + + + UseLinkTimeCodeGeneration + + + \ No newline at end of file diff --git a/win/win32/vs2015/config.props b/win/win32/vs2015/config.props new file mode 100644 index 000000000..84ef04da2 --- /dev/null +++ b/win/win32/vs2015/config.props @@ -0,0 +1,21 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + \ No newline at end of file diff --git a/win/win32/vs2015/console.props b/win/win32/vs2015/console.props new file mode 100644 index 000000000..8fdca9d9e --- /dev/null +++ b/win/win32/vs2015/console.props @@ -0,0 +1,11 @@ + + + + + _CONSOLE;%(PreprocessorDefinitions) + + + Console + + + \ No newline at end of file diff --git a/win/win32/vs2015/default.props b/win/win32/vs2015/default.props new file mode 100644 index 000000000..688b5d311 --- /dev/null +++ b/win/win32/vs2015/default.props @@ -0,0 +1,17 @@ + + + + Application + false + MultiByte + v140 + + + true + + + false + true + + + \ 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 index 000000000..94a07f465 --- /dev/null +++ b/win/win32/vs2015/default_dll.props @@ -0,0 +1,17 @@ + + + + DynamicLibrary + false + MultiByte + v140 + + + true + + + false + true + + + \ No newline at end of file diff --git a/win/win32/vs2015/dgncomp.vcxproj b/win/win32/vs2015/dgncomp.vcxproj new file mode 100755 index 000000000..a44735de3 --- /dev/null +++ b/win/win32/vs2015/dgncomp.vcxproj @@ -0,0 +1,125 @@ + + + + + + {8A3F81C7-2968-49A8-86BF-2669412AD7DE} + + + + + + + + + + + + + $(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Lex; + Yacc; + $(BuildDependsOn); + + + + + + + NoLex; + NoYacc; + $(BuildDependsOn); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/dirs.props b/win/win32/vs2015/dirs.props new file mode 100644 index 000000000..8cdcf60c2 --- /dev/null +++ b/win/win32/vs2015/dirs.props @@ -0,0 +1,24 @@ + + + + $(MSBuildProjectDirectory)\..\..\..\ + $(RootDir)bin\$(Configuration)\$(Platform)\ + $(ProjectDir)obj\$(Configuration)\$(Platform)\$(TargetName)\ + $(ProjectDir)symbols\$(Configuration)\$(Platform)\$(TargetName)\ + $(RootDir)tools\$(Configuration)\$(Platform)\ + $(RootDir)util\ + $(RootDir)dat\ + $(RootDir)doc\ + $(RootDir)include\ + $(RootDir)src\ + $(RootDir)sys\ + $(RootDir)util\ + $(RootDir)sys\share\ + $(RootDir)sys\winnt\ + $(RootDir)win\share\ + $(RootDir)win\tty\ + $(RootDir)win\win32\ + $(ToolsDir) + $(ObjDir) + + \ No newline at end of file diff --git a/win/win32/vs2015/dlb.vcxproj b/win/win32/vs2015/dlb.vcxproj new file mode 100644 index 000000000..06424d447 --- /dev/null +++ b/win/win32/vs2015/dlb.vcxproj @@ -0,0 +1,43 @@ + + + + + + {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} + + + + + + + + + + + + + $(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/dll.props b/win/win32/vs2015/dll.props new file mode 100644 index 000000000..3b37e2ede --- /dev/null +++ b/win/win32/vs2015/dll.props @@ -0,0 +1,11 @@ + + + + + WIN32CON;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + Windows + + + \ No newline at end of file diff --git a/win/win32/vs2015/files.props b/win/win32/vs2015/files.props new file mode 100644 index 000000000..d905edbdd --- /dev/null +++ b/win/win32/vs2015/files.props @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/levcomp.vcxproj b/win/win32/vs2015/levcomp.vcxproj new file mode 100755 index 000000000..1d01ffa87 --- /dev/null +++ b/win/win32/vs2015/levcomp.vcxproj @@ -0,0 +1,88 @@ + + + + + + {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} + + + + + + + + + + + + + $(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;YY_NO_UNISTD_H;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + Lex; + Yacc; + $(BuildDependsOn); + + + + + + + NoLex; + NoYacc; + $(BuildDependsOn); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/makedefs.vcxproj b/win/win32/vs2015/makedefs.vcxproj new file mode 100755 index 000000000..cedd41204 --- /dev/null +++ b/win/win32/vs2015/makedefs.vcxproj @@ -0,0 +1,55 @@ + + + + + + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + + + + + + + + + + + + + $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/nh340key.def b/win/win32/vs2015/nh340key.def new file mode 100644 index 000000000..f484a536f --- /dev/null +++ b/win/win32/vs2015/nh340key.def @@ -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 index 000000000..8b2068662 --- /dev/null +++ b/win/win32/vs2015/nh340key.vcxproj @@ -0,0 +1,42 @@ + + + + + {be04e242-a1e9-4593-b95b-057f37330b76} + Win32Proj + nh340key + + + + + + + + + + $(BinDir) + + + + $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) + + + $(ToolsDir)$(TargetName).lib + + + + + nh340key.def + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/nhdefkey.def b/win/win32/vs2015/nhdefkey.def new file mode 100644 index 000000000..2950904e4 --- /dev/null +++ b/win/win32/vs2015/nhdefkey.def @@ -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 100755 index 000000000..84fdf2fd3 --- /dev/null +++ b/win/win32/vs2015/nhdefkey.vcxproj @@ -0,0 +1,42 @@ + + + + + {6813477F-64B6-4B97-B230-438D0D233385} + Win32Proj + nhdefkey + + + + + + + + + + $(BinDir) + + + + $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) + + + $(ToolsDir)$(TargetName).lib + + + + + nhdefkey.def + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/nhraykey.def b/win/win32/vs2015/nhraykey.def new file mode 100644 index 000000000..5432a1af3 --- /dev/null +++ b/win/win32/vs2015/nhraykey.def @@ -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 index 000000000..0017f4a49 --- /dev/null +++ b/win/win32/vs2015/nhraykey.vcxproj @@ -0,0 +1,42 @@ + + + + + {2e1f4bb3-3bd7-43ad-8e64-d3b8a2f5d7b2} + Win32Proj + nhraykey + + + + + + + + + + $(BinDir) + + + + $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) + + + $(ToolsDir)$(TargetName).lib + + + + + nhraykey.def + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/notes.txt b/win/win32/vs2015/notes.txt new file mode 100644 index 000000000..5a7d93371 --- /dev/null +++ b/win/win32/vs2015/notes.txt @@ -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 100755 index 000000000..7abba076f --- /dev/null +++ b/win/win32/vs2015/recover.vcxproj @@ -0,0 +1,45 @@ + + + + + {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E} + + + + + + + + + + $(BinDir) + + + + $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/tile2bmp.vcxproj b/win/win32/vs2015/tile2bmp.vcxproj new file mode 100755 index 000000000..9b72b98f1 --- /dev/null +++ b/win/win32/vs2015/tile2bmp.vcxproj @@ -0,0 +1,47 @@ + + + + + + {642BC75D-ABAF-403E-8224-7C725FD4CB42} + + + + + + + + + + + + + $(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + TILETEXT;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/tilemap.vcxproj b/win/win32/vs2015/tilemap.vcxproj new file mode 100755 index 000000000..a970b2aa6 --- /dev/null +++ b/win/win32/vs2015/tilemap.vcxproj @@ -0,0 +1,81 @@ + + + + + + {93F10526-209E-41D7-BBEA-775787876895} + + + + + + + + + + + + + $(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2015/tiles.vcxproj b/win/win32/vs2015/tiles.vcxproj new file mode 100755 index 000000000..f617646f0 --- /dev/null +++ b/win/win32/vs2015/tiles.vcxproj @@ -0,0 +1,124 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {55946465-FC65-47B3-BB48-742C7694C0D6} + MakeFileProj + + + + Makefile + false + v120 + + + Makefile + false + v120 + + + Makefile + false + v120 + + + Makefile + false + v120 + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\..\util\ + .\..\util\ + .\Debug\ + .\Debug\ + nmake /f "tiles.mak" + nmake /f "tiles.mak" + nmake /f "tiles.mak" /a + nmake /f "tiles.mak" /a + + + ..\win\win32\tiles.bmp + ..\win\win32\tiles.bmp + $(NMakePreprocessorDefinitions) + $(NMakePreprocessorDefinitions) + $(NMakeIncludeSearchPath) + $(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) + $(NMakeForcedUsingAssemblies) + .\..\util\ + .\..\util\ + .\Release\ + .\Release\ + nmake /f "tiles.mak" + nmake /f "tiles.mak" + nmake /f "tiles.mak" /a + nmake /f "tiles.mak" /a + + + ..\win\win32\tiles.bmp + ..\win\win32\tiles.bmp + $(NMakePreprocessorDefinitions) + $(NMakePreprocessorDefinitions) + $(NMakeIncludeSearchPath) + $(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) + $(NMakeForcedUsingAssemblies) + + + + + + {642bc75d-abaf-403e-8224-7c725fd4cb42} + false + + + + + + diff --git a/win/win32/vs2015/uudecode.vcxproj b/win/win32/vs2015/uudecode.vcxproj new file mode 100755 index 000000000..d37115eed --- /dev/null +++ b/win/win32/vs2015/uudecode.vcxproj @@ -0,0 +1,29 @@ + + + + + + {63F9B82B-F589-4082-ABE5-D4F0682050AB} + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/.gitignore b/win/win32/vs2017/.gitignore new file mode 100644 index 000000000..6d1d5c867 --- /dev/null +++ b/win/win32/vs2017/.gitignore @@ -0,0 +1,4 @@ +!NetHack.sln +*.db-shm +*.db-wal + diff --git a/win/win32/vs2017/NetHack.sln b/win/win32/vs2017/NetHack.sln new file mode 100644 index 000000000..a64b1cba1 --- /dev/null +++ b/win/win32/vs2017/NetHack.sln @@ -0,0 +1,197 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetHackW", "NetHackW.vcxproj", "{CEC5D360-8804-454F-8591-002184C23499}" + ProjectSection(ProjectDependencies) = postProject + {93F10526-209E-41D7-BBEA-775787876895} = {93F10526-209E-41D7-BBEA-775787876895} + {63F9B82B-F589-4082-ABE5-D4F0682050AB} = {63F9B82B-F589-4082-ABE5-D4F0682050AB} + {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + {642BC75D-ABAF-403E-8224-7C725FD4CB42} = {642BC75D-ABAF-403E-8224-7C725FD4CB42} + {6813477F-64B6-4B97-B230-438D0D233385} = {6813477F-64B6-4B97-B230-438D0D233385} + {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} = {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} + {8A3F81C7-2968-49A8-86BF-2669412AD7DE} = {8A3F81C7-2968-49A8-86BF-2669412AD7DE} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dgncomp", "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}") = "dlb", "dlb.vcxproj", "{0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}" + ProjectSection(ProjectDependencies) = postProject + {63F9B82B-F589-4082-ABE5-D4F0682050AB} = {63F9B82B-F589-4082-ABE5-D4F0682050AB} + {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + {8A3F81C7-2968-49A8-86BF-2669412AD7DE} = {8A3F81C7-2968-49A8-86BF-2669412AD7DE} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "levcomp", "levcomp.vcxproj", "{9DD9C52E-E8C9-4533-BD22-83C055C0AABA}" + ProjectSection(ProjectDependencies) = postProject + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makedefs", "makedefs.vcxproj", "{BA3DD34C-04B7-40D0-B373-9329AA9E8945}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "recover", "recover.vcxproj", "{2F35F228-6733-4FE5-9B46-B3AA10D4BC2E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tile2bmp", "tile2bmp.vcxproj", "{642BC75D-ABAF-403E-8224-7C725FD4CB42}" + ProjectSection(ProjectDependencies) = postProject + {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tilemap", "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}") = "uudecode", "uudecode.vcxproj", "{63F9B82B-F589-4082-ABE5-D4F0682050AB}" + ProjectSection(ProjectDependencies) = postProject + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetHack", "NetHack.vcxproj", "{609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}" + ProjectSection(ProjectDependencies) = postProject + {63F9B82B-F589-4082-ABE5-D4F0682050AB} = {63F9B82B-F589-4082-ABE5-D4F0682050AB} + {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + {6813477F-64B6-4B97-B230-438D0D233385} = {6813477F-64B6-4B97-B230-438D0D233385} + {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} = {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} + {8A3F81C7-2968-49A8-86BF-2669412AD7DE} = {8A3F81C7-2968-49A8-86BF-2669412AD7DE} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nhdefkey", "nhdefkey.vcxproj", "{6813477F-64B6-4B97-B230-438D0D233385}" + ProjectSection(ProjectDependencies) = postProject + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nh340key", "nh340key.vcxproj", "{BE04E242-A1E9-4593-B95B-057F37330B76}" + ProjectSection(ProjectDependencies) = postProject + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nhraykey", "nhraykey.vcxproj", "{2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}" + ProjectSection(ProjectDependencies) = postProject + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + EndProjectSection +EndProject +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 + {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 + {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 + {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 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|Win32.ActiveCfg = Debug|Win32 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|Win32.Build.0 = Debug|Win32 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|x64.ActiveCfg = Debug|x64 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Debug|x64.Build.0 = Debug|x64 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|Win32.ActiveCfg = Release|Win32 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|Win32.Build.0 = Release|Win32 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|x64.ActiveCfg = Release|x64 + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|x64.Build.0 = Release|x64 + {6813477F-64B6-4B97-B230-438D0D233385}.Debug|Win32.ActiveCfg = Debug|Win32 + {6813477F-64B6-4B97-B230-438D0D233385}.Debug|Win32.Build.0 = Debug|Win32 + {6813477F-64B6-4B97-B230-438D0D233385}.Debug|x64.ActiveCfg = Debug|x64 + {6813477F-64B6-4B97-B230-438D0D233385}.Debug|x64.Build.0 = Debug|x64 + {6813477F-64B6-4B97-B230-438D0D233385}.Release|Win32.ActiveCfg = Release|Win32 + {6813477F-64B6-4B97-B230-438D0D233385}.Release|Win32.Build.0 = Release|Win32 + {6813477F-64B6-4B97-B230-438D0D233385}.Release|x64.ActiveCfg = Release|x64 + {6813477F-64B6-4B97-B230-438D0D233385}.Release|x64.Build.0 = Release|x64 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|Win32.ActiveCfg = Debug|Win32 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|Win32.Build.0 = Debug|Win32 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|x64.ActiveCfg = Debug|x64 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|x64.Build.0 = Debug|x64 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|Win32.ActiveCfg = Release|Win32 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|Win32.Build.0 = Release|Win32 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|x64.ActiveCfg = Release|x64 + {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|x64.Build.0 = Release|x64 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|Win32.ActiveCfg = Debug|Win32 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|Win32.Build.0 = Debug|Win32 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|x64.ActiveCfg = Debug|x64 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|x64.Build.0 = Debug|x64 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|Win32.ActiveCfg = Release|Win32 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|Win32.Build.0 = Release|Win32 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|x64.ActiveCfg = Release|x64 + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win/win32/vs2017/NetHack.vcxproj b/win/win32/vs2017/NetHack.vcxproj new file mode 100644 index 000000000..dfa15c391 --- /dev/null +++ b/win/win32/vs2017/NetHack.vcxproj @@ -0,0 +1,233 @@ + + + + + {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751} + Win32Proj + NetHack + + + + + + + + + + $(BinDir) + + + + /Gs /Oi- %(AdditionalOptions) + Disabled + Default + Speed + true + $(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories) + TILES;WIN32CON;DLB;MSWIN_GRAPHICS;_LIB;%(PreprocessorDefinitions) + + + 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) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GUISTUB;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/NetHackW.vcxproj b/win/win32/vs2017/NetHackW.vcxproj new file mode 100644 index 000000000..d1cd0bb91 --- /dev/null +++ b/win/win32/vs2017/NetHackW.vcxproj @@ -0,0 +1,184 @@ + + + + + {CEC5D360-8804-454F-8591-002184C23499} + NetHackW + + + + + + + + + $(BinDir) + + + + /Gs /Oi- %(AdditionalOptions) + Disabled + true + $(WinWin32Dir);$(IncDir);$(SysWinntDir);$(SysShareDir);$(WinShareDir);%(AdditionalIncludeDirectories) + TILES;_WINDOWS;DLB;MSWIN_GRAPHICS;WIN32CONNDEBUG;%(PreprocessorDefinitions) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Windows + comctl32.lib;winmm.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TTYSTUB; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/afterdgncomp.proj b/win/win32/vs2017/afterdgncomp.proj new file mode 100644 index 000000000..38aee3247 --- /dev/null +++ b/win/win32/vs2017/afterdgncomp.proj @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/win/win32/vs2017/afterdlb.proj b/win/win32/vs2017/afterdlb.proj new file mode 100644 index 000000000..eff63117b --- /dev/null +++ b/win/win32/vs2017/afterdlb.proj @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/win/win32/vs2017/afterlevcomp.proj b/win/win32/vs2017/afterlevcomp.proj new file mode 100644 index 000000000..c0d8dd464 --- /dev/null +++ b/win/win32/vs2017/afterlevcomp.proj @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/win/win32/vs2017/aftermakedefs.proj b/win/win32/vs2017/aftermakedefs.proj new file mode 100644 index 000000000..744806639 --- /dev/null +++ b/win/win32/vs2017/aftermakedefs.proj @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/win/win32/vs2017/afternethack.proj b/win/win32/vs2017/afternethack.proj new file mode 100644 index 000000000..912d75e89 --- /dev/null +++ b/win/win32/vs2017/afternethack.proj @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/win/win32/vs2017/afterrecover.proj b/win/win32/vs2017/afterrecover.proj new file mode 100644 index 000000000..46ab13a55 --- /dev/null +++ b/win/win32/vs2017/afterrecover.proj @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/win/win32/vs2017/aftertile2bmp.proj b/win/win32/vs2017/aftertile2bmp.proj new file mode 100644 index 000000000..44e031223 --- /dev/null +++ b/win/win32/vs2017/aftertile2bmp.proj @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/win/win32/vs2017/aftertilemap.proj b/win/win32/vs2017/aftertilemap.proj new file mode 100644 index 000000000..d68eabab9 --- /dev/null +++ b/win/win32/vs2017/aftertilemap.proj @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/win/win32/vs2017/afteruudecode.proj b/win/win32/vs2017/afteruudecode.proj new file mode 100644 index 000000000..fd0370be4 --- /dev/null +++ b/win/win32/vs2017/afteruudecode.proj @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/win/win32/vs2017/build.bat b/win/win32/vs2017/build.bat new file mode 100644 index 000000000..2a10d6239 --- /dev/null +++ b/win/win32/vs2017/build.bat @@ -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 index 000000000..8f5d2a450 --- /dev/null +++ b/win/win32/vs2017/common.props @@ -0,0 +1,41 @@ + + + + true + + + false + + + + Level3 + WIN32;CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + Console + $(SymbolsDir)$(TargetName).pdb + + + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + true + + + + + MaxSpeed + OnlyExplicitInline + NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + + + UseLinkTimeCodeGeneration + + + diff --git a/win/win32/vs2017/config.props b/win/win32/vs2017/config.props new file mode 100644 index 000000000..2533b76c9 --- /dev/null +++ b/win/win32/vs2017/config.props @@ -0,0 +1,25 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + 10.0.15063.0 + + diff --git a/win/win32/vs2017/console.props b/win/win32/vs2017/console.props new file mode 100644 index 000000000..f91d9dad4 --- /dev/null +++ b/win/win32/vs2017/console.props @@ -0,0 +1,11 @@ + + + + + _CONSOLE;%(PreprocessorDefinitions) + + + Console + + + diff --git a/win/win32/vs2017/default.props b/win/win32/vs2017/default.props new file mode 100644 index 000000000..3ad8bdd10 --- /dev/null +++ b/win/win32/vs2017/default.props @@ -0,0 +1,17 @@ + + + + Application + false + MultiByte + v141 + + + true + + + false + true + + + diff --git a/win/win32/vs2017/default_dll.props b/win/win32/vs2017/default_dll.props new file mode 100644 index 000000000..51d90a3ee --- /dev/null +++ b/win/win32/vs2017/default_dll.props @@ -0,0 +1,17 @@ + + + + DynamicLibrary + false + MultiByte + v141 + + + true + + + false + true + + + diff --git a/win/win32/vs2017/dgncomp.vcxproj b/win/win32/vs2017/dgncomp.vcxproj new file mode 100644 index 000000000..5ef5aec3e --- /dev/null +++ b/win/win32/vs2017/dgncomp.vcxproj @@ -0,0 +1,120 @@ + + + + + {8A3F81C7-2968-49A8-86BF-2669412AD7DE} + + + + + + + + + + + $(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Lex; + Yacc; + $(BuildDependsOn); + + + + + + + NoLex; + NoYacc; + $(BuildDependsOn); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/dirs.props b/win/win32/vs2017/dirs.props new file mode 100644 index 000000000..9d4ed49e4 --- /dev/null +++ b/win/win32/vs2017/dirs.props @@ -0,0 +1,24 @@ + + + + $(MSBuildProjectDirectory)\..\..\..\ + $(RootDir)bin\$(Configuration)\$(Platform)\ + $(ProjectDir)obj\$(Configuration)\$(Platform)\$(TargetName)\ + $(ProjectDir)symbols\$(Configuration)\$(Platform)\$(TargetName)\ + $(RootDir)tools\$(Configuration)\$(Platform)\ + $(RootDir)util\ + $(RootDir)dat\ + $(RootDir)doc\ + $(RootDir)include\ + $(RootDir)src\ + $(RootDir)sys\ + $(RootDir)util\ + $(RootDir)sys\share\ + $(RootDir)sys\winnt\ + $(RootDir)win\share\ + $(RootDir)win\tty\ + $(RootDir)win\win32\ + $(ToolsDir) + $(ObjDir) + + diff --git a/win/win32/vs2017/dlb.vcxproj b/win/win32/vs2017/dlb.vcxproj new file mode 100644 index 000000000..03b56b881 --- /dev/null +++ b/win/win32/vs2017/dlb.vcxproj @@ -0,0 +1,39 @@ + + + + + {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} + + + + + + + + + + + $(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/dll.props b/win/win32/vs2017/dll.props new file mode 100644 index 000000000..bd90844f1 --- /dev/null +++ b/win/win32/vs2017/dll.props @@ -0,0 +1,11 @@ + + + + + WIN32CON;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + Windows + + + diff --git a/win/win32/vs2017/files.props b/win/win32/vs2017/files.props new file mode 100644 index 000000000..7a93b0d68 --- /dev/null +++ b/win/win32/vs2017/files.props @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win/win32/vs2017/levcomp.vcxproj b/win/win32/vs2017/levcomp.vcxproj new file mode 100644 index 000000000..3fbcffe5c --- /dev/null +++ b/win/win32/vs2017/levcomp.vcxproj @@ -0,0 +1,83 @@ + + + + + {9DD9C52E-E8C9-4533-BD22-83C055C0AABA} + + + + + + + + + + + $(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;YY_NO_UNISTD_H;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + Lex; + Yacc; + $(BuildDependsOn); + + + + + + + NoLex; + NoYacc; + $(BuildDependsOn); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/makedefs.vcxproj b/win/win32/vs2017/makedefs.vcxproj new file mode 100644 index 000000000..46cc21bd7 --- /dev/null +++ b/win/win32/vs2017/makedefs.vcxproj @@ -0,0 +1,50 @@ + + + + + {BA3DD34C-04B7-40D0-B373-9329AA9E8945} + + + + + + + + + + + $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/nh340key.def b/win/win32/vs2017/nh340key.def new file mode 100644 index 000000000..f484a536f --- /dev/null +++ b/win/win32/vs2017/nh340key.def @@ -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 index 000000000..4c01d59b2 --- /dev/null +++ b/win/win32/vs2017/nh340key.vcxproj @@ -0,0 +1,42 @@ + + + + + {BE04E242-A1E9-4593-B95B-057F37330B76} + Win32Proj + nh340key + + + + + + + + + + $(BinDir) + + + + $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) + + + $(ToolsDir)$(TargetName).lib + + + + + nh340key.def + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/nhdefkey.def b/win/win32/vs2017/nhdefkey.def new file mode 100644 index 000000000..2950904e4 --- /dev/null +++ b/win/win32/vs2017/nhdefkey.def @@ -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 index 000000000..37a36e01d --- /dev/null +++ b/win/win32/vs2017/nhdefkey.vcxproj @@ -0,0 +1,42 @@ + + + + + {6813477F-64B6-4B97-B230-438D0D233385} + Win32Proj + nhdefkey + + + + + + + + + + $(BinDir) + + + + $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) + + + $(ToolsDir)$(TargetName).lib + + + + + nhdefkey.def + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/nhraykey.def b/win/win32/vs2017/nhraykey.def new file mode 100644 index 000000000..5432a1af3 --- /dev/null +++ b/win/win32/vs2017/nhraykey.def @@ -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 index 000000000..fd6c415dd --- /dev/null +++ b/win/win32/vs2017/nhraykey.vcxproj @@ -0,0 +1,42 @@ + + + + + {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2} + Win32Proj + nhraykey + + + + + + + + + + $(BinDir) + + + + $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) + + + $(ToolsDir)$(TargetName).lib + + + + + nhraykey.def + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/recover.vcxproj b/win/win32/vs2017/recover.vcxproj new file mode 100644 index 000000000..75fe4db9a --- /dev/null +++ b/win/win32/vs2017/recover.vcxproj @@ -0,0 +1,45 @@ + + + + + {2F35F228-6733-4FE5-9B46-B3AA10D4BC2E} + + + + + + + + + + $(BinDir) + + + + $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/tile2bmp.vcxproj b/win/win32/vs2017/tile2bmp.vcxproj new file mode 100644 index 000000000..0c2db97c7 --- /dev/null +++ b/win/win32/vs2017/tile2bmp.vcxproj @@ -0,0 +1,41 @@ + + + + + {642BC75D-ABAF-403E-8224-7C725FD4CB42} + + + + + + + + + + + $(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + TILETEXT;%(PreprocessorDefinitions) + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/tilemap.vcxproj b/win/win32/vs2017/tilemap.vcxproj new file mode 100644 index 000000000..d9edb8fa4 --- /dev/null +++ b/win/win32/vs2017/tilemap.vcxproj @@ -0,0 +1,77 @@ + + + + + {93F10526-209E-41D7-BBEA-775787876895} + + + + + + + + + + + $(IncDir);$(SysWinntDir);$(SysShareDir);%(AdditionalIncludeDirectories) + WIN32CON;DLB;MSWIN_GRAPHICS;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/vs2017/tiles.vcxproj b/win/win32/vs2017/tiles.vcxproj new file mode 100644 index 000000000..f17bd023f --- /dev/null +++ b/win/win32/vs2017/tiles.vcxproj @@ -0,0 +1,124 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {55946465-FC65-47B3-BB48-742C7694C0D6} + MakeFileProj + + + + Makefile + false + v120 + + + Makefile + false + v120 + + + Makefile + false + v120 + + + Makefile + false + v120 + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\..\util\ + .\..\util\ + .\Debug\ + .\Debug\ + nmake /f "tiles.mak" + nmake /f "tiles.mak" + nmake /f "tiles.mak" /a + nmake /f "tiles.mak" /a + + + ..\win\win32\tiles.bmp + ..\win\win32\tiles.bmp + $(NMakePreprocessorDefinitions) + $(NMakePreprocessorDefinitions) + $(NMakeIncludeSearchPath) + $(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) + $(NMakeForcedUsingAssemblies) + .\..\util\ + .\..\util\ + .\Release\ + .\Release\ + nmake /f "tiles.mak" + nmake /f "tiles.mak" + nmake /f "tiles.mak" /a + nmake /f "tiles.mak" /a + + + ..\win\win32\tiles.bmp + ..\win\win32\tiles.bmp + $(NMakePreprocessorDefinitions) + $(NMakePreprocessorDefinitions) + $(NMakeIncludeSearchPath) + $(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) + $(NMakeForcedUsingAssemblies) + + + + + + {642bc75d-abaf-403e-8224-7c725fd4cb42} + false + + + + + + diff --git a/win/win32/vs2017/uudecode.vcxproj b/win/win32/vs2017/uudecode.vcxproj new file mode 100644 index 000000000..bb03d7f7c --- /dev/null +++ b/win/win32/vs2017/uudecode.vcxproj @@ -0,0 +1,27 @@ + + + + + {63F9B82B-F589-4082-ABE5-D4F0682050AB} + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/win/win32/winMS.h b/win/win32/winMS.h index f35e601c9..e34cb006f 100644 --- a/win/win32/winMS.h +++ b/win/win32/winMS.h @@ -20,6 +20,13 @@ #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 #include @@ -226,7 +233,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()) diff --git a/win/win32/winhack.rc b/win/win32/winhack.rc index fbe856b42..4c69358c9 100644 --- a/win/win32/winhack.rc +++ b/win/win32/winhack.rc @@ -326,8 +326,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 @@ -343,13 +343,13 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "NetHack for Windows - Graphical Interface\0" - VALUE "FileVersion", "3.5.0\0" + VALUE "FileVersion", "3.6.1\0" VALUE "InternalName", "NetHackW\0" - VALUE "LegalCopyright", "Copyright (C) 1985 - 2006. By Stichting Mathematisch Centrum and M. Stephenson. See license for details.\0" + VALUE "LegalCopyright", "Copyright (C) 1985 - 2017. 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 "ProductVersion", "3.6.1\0" END END BLOCK "VarFileInfo"