From 69e1113aa9886fbc312ac46fb849adedc83d2fad Mon Sep 17 00:00:00 2001 From: Haoyang Wang Date: Wed, 23 Dec 2015 04:53:28 -0800 Subject: [PATCH 01/31] fix #H4082: create games group from package postinstall script --- sys/unix/hints/macosx10.10 | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/unix/hints/macosx10.10 b/sys/unix/hints/macosx10.10 index 3f0387c17..222690349 100644 --- a/sys/unix/hints/macosx10.10 +++ b/sys/unix/hints/macosx10.10 @@ -274,6 +274,7 @@ build_package_root: mkdir -p PKGSCRIPTS echo '#!/bin/sh' > PKGSCRIPTS/postinstall + echo dseditgroup -o create -r '"Games Group"' -s 3600 $(GAMEGRP) >> PKGSCRIPTS/postinstall echo $(CHOWN) -R $(GAMEUID) $(HACKDIR) >> PKGSCRIPTS/postinstall echo $(CHGRP) -R $(GAMEGRP) $(HACKDIR) >> PKGSCRIPTS/postinstall echo $(CHOWN) $(GAMEUID) $(SHELLDIR)/nethack >> PKGSCRIPTS/postinstall From 9df552543bc2491e235047d1c86ccab2566e34ff Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 24 Dec 2015 16:00:50 -0800 Subject: [PATCH 02/31] fix "Patch for dos mode nethackrc file on linux" Reported directly to devteam (12 Dec), user had a config file originally from MSDOS or Windows and used it on a linux system. That works as-is except when it contained an invalid option line. Feedback was "ad option line: "whatever-the-line-was because of the carriage return character staying in the option buffer after linefeed was stripped off from CR+LF line end. He included a patch which replaced this existing fixup after fgets() if ((p = index(buf, '\n')) != 0) *p = '\0'; with a loop over the whole string changing either '\n' or '\r' to '\0'. This uses if ((p = index(buf, '\n')) != 0) { if (p > buf && *(p - 1) == '\r') --p; *p = '\0'; } instead. Ordinarily I would have just cloned the original line and then substituted \r for \n in the copy, but the report mentioned "I couldn't get index to work with carriage return". I don't know what he tried to do or why simple index(buf,'\r') might not work as intended on his platform, so I went with something that will work even if index() behaves as strangely as the report suggested. (We already have a couple of index(string,'\r') calls in use, but I'm not going to change those unless someone complains about a problem.) --- doc/fixes36.1 | 3 +++ src/files.c | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index a2e3933f8..84c2a161f 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -68,6 +68,9 @@ tty: specifying all four of role, race, gender, and alignment still prompted unix/X11: in top level Makefile, some commented out definitions of VARDATND misspelled pilemark.xbm (as pilemark.xpm) unix/tty: fix compile warning about 'has_colors' for some configurations +unix: options file with CR+LF line ends and an invalid option line resulted in + "ad option line: "whatever-the-line-was + because embedded carriage return character changed cursor's position win32gui: getversionstring() was overflowing the provided Help About buffer win32gui: guard against buffer overflow in in mswin_getlin() MacOSX: initial binary release was built from out of date source code that diff --git a/src/files.c b/src/files.c index 9e4f1d21e..18481a5f4 100644 --- a/src/files.c +++ b/src/files.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 files.c $NHDT-Date: 1449830204 2015/12/11 10:36:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.194 $ */ +/* NetHack 3.6 files.c $NHDT-Date: 1451001643 2015/12/25 00:00:43 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.197 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2581,8 +2581,12 @@ line at this level. OR: Forbid multiline stuff for alternate config sources. */ #endif - if ((p = index(buf, '\n')) != 0) - *p = '\0'; + if ((p = index(buf, '\n')) != 0) { + /* in case file has CR+LF format on non-CR+LF platform */ + if (p > buf && *(p - 1) == '\r') + --p; + *p = '\0'; /* strip newline */ + } if (!parse_config_line(fp, buf, src)) { static const char badoptionline[] = "Bad option line: \"%s\""; From 6f595dabcc50d57b11a6d140c67d5100cc5fd13b Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 25 Dec 2015 14:13:05 -0800 Subject: [PATCH 03/31] fix #H4142 - resistance from Excalibur Enlightenment and end of game disclosure didn't report level-drain resistance if that was obtained via wielding Excalibur (or Stormbringer or Staff of Aesculapius). Drain_resistance wasn't one of the attributes set for intrinsics/extrinsics when wielding or unwielding weapon or wearing/unwearing other equipment. loseexp() checks resists_drli() which does check for items in use, so level drain would be aborted, possibly after messages claimed that it was taming place. I didn't try to untangle any of that, just changed set_artifact_intrinsic to include a test for DRAIN_RES. --- doc/fixes36.1 | 2 ++ src/artifact.c | 37 ++++++++++++++++++++----------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 84c2a161f..054b53ffa 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -57,6 +57,8 @@ do not autopickup unpaid items in shops death due an unseen gas spore's explosion resulted in "killed by a died" allow optional parameter "true", "yes", "false", or "no" for boolean options actually make the castle chest not trapped +level-drain resistance wasn't shown during enlightenment if it was conferred + by worn/wielded equipment Platform- and/or Interface-Specific Fixes diff --git a/src/artifact.c b/src/artifact.c index 23c7c49c2..39525b8d0 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 artifact.c $NHDT-Date: 1446369462 2015/11/01 09:17:42 $ $NHDT-Branch: master $:$NHDT-Revision: 1.96 $ */ +/* NetHack 3.6 artifact.c $NHDT-Date: 1451081581 2015/12/25 22:13:01 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.99 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -18,13 +18,12 @@ extern boolean notonhead; /* for long worms */ #define get_artifact(o) \ (((o) && (o)->oartifact) ? &artilist[(int) (o)->oartifact] : 0) -STATIC_DCL boolean -FDECL(bane_applies, (const struct artifact *, struct monst *)); +STATIC_DCL boolean FDECL(bane_applies, (const struct artifact *, + struct monst *)); STATIC_DCL int FDECL(spec_applies, (const struct artifact *, struct monst *)); STATIC_DCL int FDECL(arti_invoke, (struct obj *)); -STATIC_DCL boolean -FDECL(Mb_hit, (struct monst * magr, struct monst *mdef, struct obj *, int *, - int, BOOLEAN_P, char *)); +STATIC_DCL boolean FDECL(Mb_hit, (struct monst * magr, struct monst *mdef, + struct obj *, int *, int, BOOLEAN_P, char *)); STATIC_DCL unsigned long FDECL(abil_to_spfx, (long *)); STATIC_DCL uchar FDECL(abil_to_adtyp, (long *)); STATIC_DCL boolean FDECL(untouchable, (struct obj *, BOOLEAN_P)); @@ -462,12 +461,13 @@ boolean being_worn; */ void set_artifact_intrinsic(otmp, on, wp_mask) -register struct obj *otmp; +struct obj *otmp; boolean on; long wp_mask; { long *mask = 0; - register const struct artifact *oart = get_artifact(otmp); + register const struct artifact *art, *oart = get_artifact(otmp); + register struct obj *obj; register uchar dtyp; register long spfx; @@ -489,19 +489,21 @@ long wp_mask; mask = &EDisint_resistance; else if (dtyp == AD_DRST) mask = &EPoison_resistance; + else if (dtyp == AD_DRLI) + mask = &EDrain_resistance; if (mask && wp_mask == W_ART && !on) { - /* find out if some other artifact also confers this intrinsic */ - /* if so, leave the mask alone */ - register struct obj *obj; - for (obj = invent; obj; obj = obj->nobj) + /* find out if some other artifact also confers this intrinsic; + if so, leave the mask alone */ + for (obj = invent; obj; obj = obj->nobj) { if (obj != otmp && obj->oartifact) { - register const struct artifact *art = get_artifact(obj); + art = get_artifact(obj); if (art->cary.adtyp == dtyp) { mask = (long *) 0; break; } } + } } if (mask) { if (on) @@ -514,10 +516,9 @@ long wp_mask; spfx = (wp_mask != W_ART) ? oart->spfx : oart->cspfx; if (spfx && wp_mask == W_ART && !on) { /* don't change any spfx also conferred by other artifacts */ - register struct obj *obj; for (obj = invent; obj; obj = obj->nobj) if (obj != otmp && obj->oartifact) { - register const struct artifact *art = get_artifact(obj); + art = get_artifact(obj); spfx &= ~art->cspfx; } } @@ -1738,6 +1739,7 @@ long *abil; { &EAntimagic, AD_MAGM }, { &EDisint_resistance, AD_DISN }, { &EPoison_resistance, AD_DRST }, + { &EDrain_resistance, AD_DRLI }, }; int k; @@ -1792,7 +1794,6 @@ long *abil; long wornmask = (W_ARM | W_ARMC | W_ARMH | W_ARMS | W_ARMG | W_ARMF | W_ARMU | W_AMUL | W_RINGL | W_RINGR | W_TOOL - /* [do W_ART and W_ARTI actually belong here?] */ | W_ART | W_ARTI); if (u.twoweap) @@ -1808,7 +1809,9 @@ long *abil; if (art) { if (dtyp) { - if (art->cary.adtyp == dtyp || art->defn.adtyp == dtyp) + if (art->cary.adtyp == dtyp /* carried */ + || (art->defn.adtyp == dtyp /* defends while worn */ + && (obj->owornmask & ~(W_ART | W_ARTI)))) return obj; } if (spfx) { From 0ed3d8be4cf8e58088611c64ba0beff752f51854 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 25 Dec 2015 14:15:00 -0800 Subject: [PATCH 04/31] from_what() Enlightenment/attribute disclosure while in wizard mode shows reasons for some of the intrinsics. This adds some more of those: innately due to polymorph for lots of things, and innately due to role for knight's jumping. (Drain_resistance from equipped item came with the 'resistance from Excalibur' patch.) --- doc/fixes36.1 | 1 + src/attrib.c | 49 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 054b53ffa..852ab6ce8 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -59,6 +59,7 @@ allow optional parameter "true", "yes", "false", or "no" for boolean options actually make the castle chest not trapped level-drain resistance wasn't shown during enlightenment if it was conferred by worn/wielded equipment +wizard mode enlightenment now shows more reasons for various intrinsics Platform- and/or Interface-Specific Fixes diff --git a/src/attrib.c b/src/attrib.c index 3866dbf26..76a9fc0e7 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 attrib.c $NHDT-Date: 1449269911 2015/12/04 22:58:31 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */ +/* NetHack 3.6 attrib.c $NHDT-Date: 1451081651 2015/12/25 22:14:11 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.52 $ */ /* Copyright 1988, 1989, 1990, 1992, M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -707,31 +707,46 @@ long frommask; return (struct innate *) 0; } -/* - * returns 1 if FROMRACE or FROMEXPER and exper level == 1 - * returns 2 if FROMEXPER and exper level > 1 - * otherwise returns 0 - */ +/* reasons for innate ability */ +#define FROM_NONE 0 +#define FROM_ROLE 1 /* from experience at level 1 */ +#define FROM_RACE 2 +#define FROM_EXP 3 /* from experience for some level > 1 */ +#define FROM_FORM 4 + + +/* check whether particular ability has been obtained via innate attribute */ STATIC_OVL int innately(ability) long *ability; { const struct innate *iptr; + if ((iptr = check_innate_abil(ability, FROMEXPER)) != 0) + return (iptr->ulevel == 1) ? FROM_ROLE : FROM_EXP; if ((iptr = check_innate_abil(ability, FROMRACE)) != 0) - return 1; - else if ((iptr = check_innate_abil(ability, FROMEXPER)) != 0) - return (iptr->ulevel == 1) ? 1 : 2; - return 0; + return FROM_RACE; + if ((*ability & FROMFORM) != 0L) + return FROM_FORM; + return FROM_NONE; } int is_innate(propidx) int propidx; { + int innateness = innately(&u.uprops[propidx].intrinsic); + + if (innateness != FROM_NONE) + return innateness; + if (propidx == JUMPING && Role_if(PM_KNIGHT) + /* knight has intrinsic jumping, but extrinsic is more versatile so + ignore innateness if equipment is going to claim responsibility */ + && !u.uprops[propidx].extrinsic) + return FROM_ROLE; if (propidx == BLINDED && !haseyes(youmonst.data)) - return 1; - return innately(&u.uprops[propidx].intrinsic); + return FROM_FORM; + return FROM_NONE; } char * @@ -750,14 +765,16 @@ int propidx; /* special cases can have negative values */ if (propidx >= 0) { char *p; struct obj *obj = (struct obj *) 0; - int innate = is_innate(propidx); + int innateness = is_innate(propidx); - if (innate == 2) + if (innateness == FROM_EXP) Strcpy(buf, " because of your experience"); - else if (innate == 1) + else if (innateness == FROM_FORM) + Strcpy(buf, " from current creature form"); + else if (innateness == FROM_ROLE || innateness == FROM_RACE) Strcpy(buf, " innately"); else if (wizard - && (obj = what_gives(&u.uprops[propidx].extrinsic))) + && (obj = what_gives(&u.uprops[propidx].extrinsic)) != 0) Sprintf(buf, because_of, obj->oartifact ? bare_artifactname(obj) : ysimple_name(obj)); From 67826ff67b3eb13d26db70300e1af5a5229d9482 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 25 Dec 2015 14:24:18 -0800 Subject: [PATCH 05/31] inappropriately sensing humans and elves Discovered while testing the from-what enhancements to enlightenment. Polymorphing into a vampire confers the ability to sense humans and elves without having telepathy or being triggered by blindness. That would be taken away if you polymorphed into something else, but was being left in effect if polymorph just timed out and hero returned to normal form. Same thing occurred for sensing shriekers if you poly'd into a purple worm and then reverted to normal (something much less likely to get noticed and not really subject to abuse if it ever did). Bonus fix: the code involved was using 0 to mean that Warn_of_mon from polymorph wasn't in effect, but 0 is also giant ant. This makes it use NON_PM for that instead. --- doc/fixes36.1 | 4 ++++ src/cmd.c | 4 ++-- src/polyself.c | 34 +++++++++++++--------------------- src/restore.c | 4 ++-- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 852ab6ce8..f690b1ec3 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -60,6 +60,10 @@ actually make the castle chest not trapped level-drain resistance wasn't shown during enlightenment if it was conferred by worn/wielded equipment wizard mode enlightenment now shows more reasons for various intrinsics +rehumanizing after being poly'd into vampire left hero with ability to sense + humans and elves +Warn_of_mon wouldn't have been able to sense giant ants if any creature were + to have that ability, caused by using 0 instead of NON_PM for 'none' Platform- and/or Interface-Specific Fixes diff --git a/src/cmd.c b/src/cmd.c index 9ed18debd..51fd17f70 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1450473780 2015/12/18 21:23:00 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.211 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1451082253 2015/12/25 22:24:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.212 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2040,7 +2040,7 @@ int final; : "certain monsters"); you_are(buf, ""); } - if (Warn_of_mon && context.warntype.speciesidx) { + if (Warn_of_mon && context.warntype.speciesidx >= LOW_PM) { Sprintf(buf, "aware of the presence of %s", makeplural(mons[context.warntype.speciesidx].mname)); you_are(buf, from_what(WARN_OF_MON)); diff --git a/src/polyself.c b/src/polyself.c index 4cd01d0d6..9cdc83be8 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 polyself.c $NHDT-Date: 1448496566 2015/11/26 00:09:26 $ $NHDT-Branch: master $:$NHDT-Revision: 1.104 $ */ +/* NetHack 3.6 polyself.c $NHDT-Date: 1451082254 2015/12/25 22:24:14 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.105 $ */ /* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -28,7 +28,7 @@ STATIC_DCL void FDECL(drop_weapon, (int)); STATIC_DCL void NDECL(uunstick); STATIC_DCL int FDECL(armor_to_dragon, (int)); STATIC_DCL void NDECL(newman); -STATIC_DCL boolean FDECL(polysense, (struct permonst *)); +STATIC_DCL void NDECL(polysense); STATIC_VAR const char no_longer_petrify_resistant[] = "No longer petrify-resistant, you"; @@ -100,6 +100,8 @@ set_uasmon() #ifdef STATUS_VIA_WINDOWPORT status_initialize(REASSESS_ONLY); #endif + + polysense(); } /* Levitation overrides Flying; set or clear BFlying|I_SPECIAL */ @@ -347,7 +349,6 @@ newman() Strcpy(killer.name, "unsuccessful polymorph"); done(DIED); newuhs(FALSE); - (void) polysense(youmonst.data); return; /* lifesaved */ } } @@ -362,7 +363,6 @@ newman() make_slimed(10L, (const char *) 0); } - (void) polysense(youmonst.data); context.botl = 1; see_monsters(); (void) encumber_msg(); @@ -827,7 +827,6 @@ int mntmp; u.utrap = 0; } check_strangling(TRUE); /* maybe start strangling */ - (void) polysense(youmonst.data); context.botl = 1; vision_full_recalc = 1; @@ -1777,20 +1776,18 @@ int atyp; } } -/* - * Some species have awareness of other species - */ -static boolean -polysense(mptr) -struct permonst *mptr; +/* some species have awareness of other species */ +static void +polysense() { - short warnidx = 0; + short warnidx = NON_PM; - context.warntype.speciesidx = 0; + context.warntype.speciesidx = NON_PM; context.warntype.species = 0; context.warntype.polyd = 0; + HWarn_of_mon &= ~FROMRACE; - switch (monsndx(mptr)) { + switch (u.umonnum) { case PM_PURPLE_WORM: warnidx = PM_SHRIEKER; break; @@ -1798,18 +1795,13 @@ struct permonst *mptr; case PM_VAMPIRE_LORD: context.warntype.polyd = M2_HUMAN | M2_ELF; HWarn_of_mon |= FROMRACE; - return TRUE; + return; } - if (warnidx) { + if (warnidx >= LOW_PM) { context.warntype.speciesidx = warnidx; context.warntype.species = &mons[warnidx]; HWarn_of_mon |= FROMRACE; - return TRUE; } - context.warntype.speciesidx = 0; - context.warntype.species = 0; - HWarn_of_mon &= ~FROMRACE; - return FALSE; } /*polyself.c*/ diff --git a/src/restore.c b/src/restore.c index d56af4ea6..509ff6ed9 100644 --- a/src/restore.c +++ b/src/restore.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 restore.c $NHDT-Date: 1450231174 2015/12/16 01:59:34 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.102 $ */ +/* NetHack 3.6 restore.c $NHDT-Date: 1451082255 2015/12/25 22:24:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.103 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -531,7 +531,7 @@ unsigned int *stuckid, *steedid; return FALSE; } mread(fd, (genericptr_t) &context, sizeof(struct context_info)); - if (context.warntype.speciesidx) + if (context.warntype.speciesidx >= LOW_PM) context.warntype.species = &mons[context.warntype.speciesidx]; /* we want to be able to revert to command line/environment/config From 192372a9aca2f062fae2b78178cac469dd7ed63e Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 25 Dec 2015 15:00:28 -0800 Subject: [PATCH 06/31] "fix" #H4040 - energy vortex power drain Reporter thought the fact that two different DREN cases had different chances to inflict energy drain was an inconsistency, but it was intentional. Attack for DREN damage has 25% chance to drain energy, and is never used since no monster has such an attack. Engulf for DREN damage has 75% chance to drain energy; energy vortices have this, and the higher chance to be drained while engulfed was intentional. So add comments explicitly spelling out the 25% and 75% chances. During beta testing there was a complaint that the energy drain was much too severe: once hero's current energy drops to 0, excess drain for current attack and future drains come out of max-energy instead. That's survivable for caster-type characters with really high energy, but drained low energy characters to 0 max energy very quickly. I agreed with the complaint but didn't implement a fix until too late for 3.6.0. I've since thrown that one out and done this one instead. Change base drain amount from 4d6 to 2d6, and weaken it more to 1d6 when energy is low or strengthen it to 3d6 when energy is high. It almost certainly will need further tuning. --- doc/fixes36.1 | 1 + src/mhitu.c | 26 ++++++- src/monst.c | 197 +++++++++++++++++++++++++------------------------- 3 files changed, 122 insertions(+), 102 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index f690b1ec3..dec33ac71 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -64,6 +64,7 @@ rehumanizing after being poly'd into vampire left hero with ability to sense humans and elves Warn_of_mon wouldn't have been able to sense giant ants if any creature were to have that ability, caused by using 0 instead of NON_PM for 'none' +tone down energy vortex's drain energy attack Platform- and/or Interface-Specific Fixes diff --git a/src/mhitu.c b/src/mhitu.c index 998c86be1..1e620dc7d 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mhitu.c $NHDT-Date: 1450016149 2015/12/13 14:15:49 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.131 $ */ +/* NetHack 3.6 mhitu.c $NHDT-Date: 1451084422 2015/12/25 23:00:22 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.132 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -273,6 +273,26 @@ struct attack *alt_attk_buf; *alt_attk_buf = *attk; attk = alt_attk_buf; attk->adtyp = AD_STUN; + + /* make drain-energy damage be somewhat in proportion to energy */ + } else if (attk->adtyp == AD_DREN) { + int ulev = max(u.ulevel, 6); + + *alt_attk_buf = *attk; + attk = alt_attk_buf; + /* 3.6.0 used 4d6 but since energy drain came out of max energy + once current energy was gone, that tended to have a severe + effect on low energy characters; it's now 2d6 with ajustments */ + if (u.uen <= 5 * ulev && attk->damn > 1) { + attk->damn -= 1; /* low energy: 2d6 -> 1d6 */ + if (u.uenmax <= 2 * ulev && attk->damd > 3) + attk->damd -= 3; /* very low energy: 1d6 -> 1d3 */ + } else if (u.uen > 12 * ulev) { + attk->damn += 1; /* high energy: 2d6 -> 3d6 */ + if (u.uenmax > 20 * ulev) + attk->damd += 3; /* very high energy: 3d6 -> 3d9 */ + /* note: 3d9 is slightly higher than previous 4d6 */ + } } return attk; } @@ -1450,7 +1470,7 @@ register struct attack *mattk; break; case AD_DREN: hitmsg(mtmp, mattk); - if (uncancelled && !rn2(4)) + if (uncancelled && !rn2(4)) /* 25% chance */ drain_en(dmg); dmg = 0; break; @@ -1840,7 +1860,7 @@ register struct attack *mattk; break; case AD_DREN: /* AC magic cancellation doesn't help when engulfed */ - if (!mtmp->mcan && rn2(4)) + if (!mtmp->mcan && rn2(4)) /* 75% chance */ drain_en(tmp); tmp = 0; break; diff --git a/src/monst.c b/src/monst.c index cf14f9e29..7839b06cc 100644 --- a/src/monst.c +++ b/src/monst.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 monst.c $NHDT-Date: 1445556875 2015/10/22 23:34:35 $ $NHDT-Branch: master $:$NHDT-Revision: 1.53 $ */ +/* NetHack 3.6 monst.c $NHDT-Date: 1451084423 2015/12/25 23:00:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.55 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -28,17 +28,17 @@ void NDECL(monst_init); /* - * Entry Format: (from permonst.h) + * Entry Format: (from permonst.h) * - * name, symbol (S_* defines), - * difficulty level, move rate, armor class, magic resistance, - * alignment, creation/geno flags (G_* defines), - * 6 * attack structs ( type , damage-type, # dice, # sides ), - * weight (WT_* defines), nutritional value, extension length, - * sounds made (MS_* defines), physical size (MZ_* defines), - * resistances, resistances conferred (both MR_* defines), - * 3 * flag bitmaps (M1_*, M2_*, and M3_* defines respectively) - * symbol color (C(x) macro) + * name, symbol (S_* defines), + * difficulty level, move rate, armor class, magic resistance, + * alignment, creation/geno flags (G_* defines), + * 6 * attack structs ( type , damage-type, # dice, # sides ), + * weight (WT_* defines), nutritional value, extension length, + * sounds made (MS_* defines), physical size (MZ_* defines), + * resistances, resistances conferred (both MR_* defines), + * 3 * flag bitmaps (M1_*, M2_*, and M3_* defines respectively) + * symbol color (C(x) macro) */ #define MON(nam, sym, lvl, gen, atk, siz, mr1, mr2, flg1, flg2, flg3, col) \ { \ @@ -59,37 +59,37 @@ void NDECL(monst_init); } /* - * Rule #1: monsters of a given class are contiguous in the - * mons[] array. + * Rule #1: monsters of a given class are contiguous in the + * mons[] array. * - * Rule #2: monsters of a given class are presented in ascending - * order of strength. + * Rule #2: monsters of a given class are presented in ascending + * order of strength. * - * Rule #3: monster frequency is included in the geno mask; - * the frequency can be from 0 to 7. 0's will also - * be skipped during generation. + * Rule #3: monster frequency is included in the geno mask; + * the frequency can be from 0 to 7. 0's will also + * be skipped during generation. * - * Rule #4: monster subclasses (e.g. giants) should be kept - * together, unless it violates Rule 2. NOGEN monsters - * won't violate Rule 2. + * Rule #4: monster subclasses (e.g. giants) should be kept + * together, unless it violates Rule 2. NOGEN monsters + * won't violate Rule 2. * * Guidelines for color assignment: * - * * Use the same color for all `growth stages' of a monster (ex. - * little dog/big dog, baby naga/full-grown naga. + * * Use the same color for all `growth stages' of a monster (ex. + * little dog/big dog, baby naga/full-grown naga. * - * * Use colors given in names wherever possible. If the class has `real' - * members with strong color associations, use those. + * * Use colors given in names wherever possible. If the class has `real' + * members with strong color associations, use those. * - * * Favor `cool' colors for cold-resistant monsters, `warm' ones for - * fire-resistant ones. + * * Favor `cool' colors for cold-resistant monsters, `warm' ones for + * fire-resistant ones. * - * * Try to reserve purple (magenta) for powerful `ruler' monsters (queen - * bee, kobold lord, &c.). + * * Try to reserve purple (magenta) for powerful `ruler' monsters (queen + * bee, kobold lord, &c.). * - * * Subject to all these constraints, try to use color to make as many - * distinctions as the / command (that is, within a monster letter - * distinct names should map to distinct colors). + * * Subject to all these constraints, try to use color to make as many + * distinctions as the / command (that is, within a monster letter + * distinct names should map to distinct colors). * * The aim in assigning colors is to be consistent enough so a player can * become `intuitive' about them, deducing some or all of these rules @@ -331,13 +331,13 @@ NEARDATA struct permonst mons[] = { M2_HOSTILE | M2_NEUTER, M3_INFRAVISIBLE, HI_ZAP), #if 0 /* not yet implemented */ MON("beholder", S_EYE, - LVL(6, 3, 4, 0, -10), (G_GENO | 2), - A(ATTK(AT_GAZE, AD_SLOW, 0, 0), ATTK(AT_GAZE, AD_SLEE, 2,25), - ATTK(AT_GAZE, AD_DISN, 0, 0), ATTK(AT_GAZE, AD_STON, 0, 0), - ATTK(AT_GAZE, AD_CNCL, 2, 4), ATTK(AT_BITE, AD_PHYS, 2, 4)), - SIZ(10, 10, MS_SILENT, MZ_SMALL), MR_COLD, 0, - M1_FLY | M1_BREATHLESS | M1_NOLIMBS | M1_NOHEAD | M1_MINDLESS, - M2_NOPOLY | M2_HOSTILE | M2_NEUTER, M3_INFRAVISIBLE, CLR_BROWN), + LVL(6, 3, 4, 0, -10), (G_GENO | 2), + A(ATTK(AT_GAZE, AD_SLOW, 0, 0), ATTK(AT_GAZE, AD_SLEE, 2,25), + ATTK(AT_GAZE, AD_DISN, 0, 0), ATTK(AT_GAZE, AD_STON, 0, 0), + ATTK(AT_GAZE, AD_CNCL, 2, 4), ATTK(AT_BITE, AD_PHYS, 2, 4)), + SIZ(10, 10, MS_SILENT, MZ_SMALL), MR_COLD, 0, + M1_FLY | M1_BREATHLESS | M1_NOLIMBS | M1_NOHEAD | M1_MINDLESS, + M2_NOPOLY | M2_HOSTILE | M2_NEUTER, M3_INFRAVISIBLE, CLR_BROWN), #endif /* * felines @@ -878,7 +878,7 @@ NEARDATA struct permonst mons[] = { M2_HOSTILE | M2_NEUTER, M3_INFRAVISIBLE, CLR_CYAN), MON("energy vortex", S_VORTEX, LVL(6, 20, 2, 30, 0), (G_GENO | G_NOCORPSE | 1), - A(ATTK(AT_ENGL, AD_ELEC, 1, 6), ATTK(AT_ENGL, AD_DREN, 4, 6), + A(ATTK(AT_ENGL, AD_ELEC, 1, 6), ATTK(AT_ENGL, AD_DREN, 2, 6), ATTK(AT_NONE, AD_ELEC, 0, 4), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(0, 0, MS_SILENT, MZ_HUGE), MR_ELEC | MR_SLEEP | MR_DISINT | MR_POISON | MR_STONE, 0, @@ -1104,12 +1104,12 @@ NEARDATA struct permonst mons[] = { M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0, DRAGON_SILVER), #if 0 /* DEFERRED */ MON("baby shimmering dragon", S_DRAGON, - LVL(12, 9, 2, 10, 0), G_GENO, - A(ATTK(AT_BITE, AD_PHYS, 2, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), - SIZ(1500, 500, MS_ROAR, MZ_HUGE), 0, 0, - M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE, - M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0, CLR_CYAN), + LVL(12, 9, 2, 10, 0), G_GENO, + A(ATTK(AT_BITE, AD_PHYS, 2, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + SIZ(1500, 500, MS_ROAR, MZ_HUGE), 0, 0, + M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_CARNIVORE, + M2_HOSTILE | M2_STRONG | M2_GREEDY | M2_JEWELS, 0, CLR_CYAN), #endif MON("baby red dragon", S_DRAGON, LVL(12, 9, 2, 10, 0), G_GENO, A(ATTK(AT_BITE, AD_PHYS, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, @@ -1174,15 +1174,15 @@ NEARDATA struct permonst mons[] = { 0, DRAGON_SILVER), #if 0 /* DEFERRED */ MON("shimmering dragon", S_DRAGON, - LVL(15, 9, -1, 20, 4), (G_GENO | 1), - A(ATTK(AT_BREA, AD_MAGM, 4, 6), ATTK(AT_BITE, AD_PHYS, 3, 8), - ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_CLAW, AD_PHYS, 1, 4), - NO_ATTK, NO_ATTK), - SIZ(WT_DRAGON, 1500, MS_ROAR, MZ_GIGANTIC), 0, 0, - M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_SEE_INVIS | M1_OVIPAROUS - | M1_CARNIVORE, - M2_HOSTILE | M2_STRONG | M2_NASTY | M2_GREEDY | M2_JEWELS | M2_MAGIC, - 0, CLR_CYAN), + LVL(15, 9, -1, 20, 4), (G_GENO | 1), + A(ATTK(AT_BREA, AD_MAGM, 4, 6), ATTK(AT_BITE, AD_PHYS, 3, 8), + ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_CLAW, AD_PHYS, 1, 4), + NO_ATTK, NO_ATTK), + SIZ(WT_DRAGON, 1500, MS_ROAR, MZ_GIGANTIC), 0, 0, + M1_FLY | M1_THICK_HIDE | M1_NOHANDS | M1_SEE_INVIS | M1_OVIPAROUS + | M1_CARNIVORE, + M2_HOSTILE | M2_STRONG | M2_NASTY | M2_GREEDY | M2_JEWELS | M2_MAGIC, + 0, CLR_CYAN), #endif MON("red dragon", S_DRAGON, LVL(15, 9, -1, 20, -4), (G_GENO | 1), A(ATTK(AT_BREA, AD_FIRE, 6, 6), ATTK(AT_BITE, AD_PHYS, 3, 8), @@ -1465,13 +1465,13 @@ struct permonst _mons2[] = { CLR_ORANGE), #if 0 /* DEFERRED */ MON("vorpal jabberwock", S_JABBERWOCK, - LVL(20, 12, -2, 50, 0), (G_GENO | 1), - A(ATTK(AT_BITE, AD_PHYS, 3, 10), ATTK(AT_BITE, AD_PHYS, 3, 10), - ATTK(AT_CLAW, AD_PHYS, 3, 10), ATTK(AT_CLAW, AD_PHYS, 3, 10), - NO_ATTK, NO_ATTK), - SIZ(1300, 600, MS_BURBLE, MZ_LARGE), 0, 0, - M1_ANIMAL | M1_FLY | M1_CARNIVORE, - M2_HOSTILE | M2_STRONG | M2_NASTY | M2_COLLECT, M3_INFRAVISIBLE, + LVL(20, 12, -2, 50, 0), (G_GENO | 1), + A(ATTK(AT_BITE, AD_PHYS, 3, 10), ATTK(AT_BITE, AD_PHYS, 3, 10), + ATTK(AT_CLAW, AD_PHYS, 3, 10), ATTK(AT_CLAW, AD_PHYS, 3, 10), + NO_ATTK, NO_ATTK), + SIZ(1300, 600, MS_BURBLE, MZ_LARGE), 0, 0, + M1_ANIMAL | M1_FLY | M1_CARNIVORE, + M2_HOSTILE | M2_STRONG | M2_NASTY | M2_COLLECT, M3_INFRAVISIBLE, HI_LORD), #endif /* @@ -1857,12 +1857,12 @@ struct permonst _mons2[] = { M3_INFRAVISIBLE, CLR_BLUE), #if 0 /* DEFERRED */ MON("vampire mage", S_VAMPIRE, - LVL(20, 14, -4, 50, -9), (G_GENO | G_NOCORPSE | 1), - A(ATTK(AT_CLAW, AD_DRLI, 2, 8), ATTK(AT_BITE, AD_DRLI, 1, 8), - ATTK(AT_MAGC, AD_SPEL, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK), - SIZ(WT_HUMAN, 400, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP | MR_POISON, 0, - M1_FLY | M1_BREATHLESS | M1_HUMANOID | M1_POIS | M1_REGEN, - M2_UNDEAD | M2_STALK | M2_HOSTILE | M2_STRONG | M2_NASTY | M2_LORD + LVL(20, 14, -4, 50, -9), (G_GENO | G_NOCORPSE | 1), + A(ATTK(AT_CLAW, AD_DRLI, 2, 8), ATTK(AT_BITE, AD_DRLI, 1, 8), + ATTK(AT_MAGC, AD_SPEL, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK), + SIZ(WT_HUMAN, 400, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP | MR_POISON, 0, + M1_FLY | M1_BREATHLESS | M1_HUMANOID | M1_POIS | M1_REGEN, + M2_UNDEAD | M2_STALK | M2_HOSTILE | M2_STRONG | M2_NASTY | M2_LORD | M2_MALE | M2_MAGIC | M2_SHAPESHIFTER, M3_INFRAVISIBLE, HI_ZAP), #endif @@ -2848,26 +2848,26 @@ struct permonst _mons2[] = { | M2_COLLECT | M2_MAGIC, M3_CLOSE | M3_INFRAVISIBLE, HI_LORD), #if 0 /* OBSOLETE */ - /* Two for elves - one of each sex. - */ + /* Two for elves - one of each sex. + */ MON("Earendil", S_HUMAN, - LVL(20, 12, 0, 50, -20), (G_NOGEN | G_UNIQ), - A(ATTK(AT_WEAP, AD_PHYS, 1, 8), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), - SIZ(WT_ELF, 350, MS_LEADER, MZ_HUMAN), MR_SLEEP, MR_SLEEP, - M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE, - M2_NOPOLY | M2_ELF | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG + LVL(20, 12, 0, 50, -20), (G_NOGEN | G_UNIQ), + A(ATTK(AT_WEAP, AD_PHYS, 1, 8), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + SIZ(WT_ELF, 350, MS_LEADER, MZ_HUMAN), MR_SLEEP, MR_SLEEP, + M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE, + M2_NOPOLY | M2_ELF | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE | M2_COLLECT | M2_MAGIC, - M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, HI_LORD), + M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, HI_LORD), MON("Elwing", S_HUMAN, - LVL(20, 12, 0, 50, -20), (G_NOGEN | G_UNIQ), - A(ATTK(AT_WEAP, AD_PHYS, 1, 8), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), - SIZ(WT_ELF, 350, MS_LEADER, MZ_HUMAN), MR_SLEEP, MR_SLEEP, - M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE, - M2_NOPOLY | M2_ELF | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG + LVL(20, 12, 0, 50, -20), (G_NOGEN | G_UNIQ), + A(ATTK(AT_WEAP, AD_PHYS, 1, 8), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + SIZ(WT_ELF, 350, MS_LEADER, MZ_HUMAN), MR_SLEEP, MR_SLEEP, + M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE, + M2_NOPOLY | M2_ELF | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_FEMALE | M2_COLLECT | M2_MAGIC, - M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, HI_LORD), + M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, HI_LORD), #endif MON("Hippocrates", S_HUMAN, LVL(20, 12, 0, 40, 0), (G_NOGEN | G_UNIQ), A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, @@ -3000,14 +3000,14 @@ struct permonst _mons2[] = { M3_WANTSARTI | M3_WAITFORU | M3_INFRAVISIBLE, HI_LORD), #if 0 /* OBSOLETE */ MON("Goblin King", S_ORC, - LVL(15, 12, 10, 0, -15), (G_NOGEN | G_UNIQ), - A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6), - ATTK(AT_CLAW, AD_SAMU, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK), - SIZ(750, 350, MS_NEMESIS, MZ_HUMAN), 0, 0, - M1_HUMANOID | M1_OMNIVORE, - M2_NOPOLY | M2_ORC | M2_HOSTILE | M2_STRONG | M2_STALK | M2_NASTY + LVL(15, 12, 10, 0, -15), (G_NOGEN | G_UNIQ), + A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6), + ATTK(AT_CLAW, AD_SAMU, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK), + SIZ(750, 350, MS_NEMESIS, MZ_HUMAN), 0, 0, + M1_HUMANOID | M1_OMNIVORE, + M2_NOPOLY | M2_ORC | M2_HOSTILE | M2_STRONG | M2_STALK | M2_NASTY | M2_MALE | M2_GREEDY | M2_JEWELS | M2_COLLECT | M2_MAGIC, - M3_WANTSARTI | M3_WAITFORU | M3_INFRAVISION | M3_INFRAVISIBLE, + M3_WANTSARTI | M3_WAITFORU | M3_INFRAVISION | M3_INFRAVISIBLE, HI_LORD), #endif MON("Cyclops", S_GIANT, LVL(18, 12, 0, 0, -15), (G_NOGEN | G_UNIQ), @@ -3126,13 +3126,13 @@ struct permonst _mons2[] = { M3_INFRAVISIBLE, HI_DOMESTIC), #if 0 /* OBSOLETE */ MON("High-elf", S_HUMAN, - LVL(5, 12, 10, 10, -7), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_MAGC, AD_CLRC, 0, 0), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), - SIZ(WT_ELF, 350, MS_GUARDIAN, MZ_HUMAN), MR_SLEEP, MR_SLEEP, - M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE, - M2_NOPOLY | M2_ELF | M2_PEACEFUL | M2_COLLECT, - M3_INFRAVISION | M3_INFRAVISIBLE, HI_DOMESTIC), + LVL(5, 12, 10, 10, -7), G_NOGEN, + A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_MAGC, AD_CLRC, 0, 0), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + SIZ(WT_ELF, 350, MS_GUARDIAN, MZ_HUMAN), MR_SLEEP, MR_SLEEP, + M1_HUMANOID | M1_SEE_INVIS | M1_OMNIVORE, + M2_NOPOLY | M2_ELF | M2_PEACEFUL | M2_COLLECT, + M3_INFRAVISION | M3_INFRAVISIBLE, HI_DOMESTIC), #endif MON("attendant", S_HUMAN, LVL(5, 12, 10, 10, 3), G_NOGEN, A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, @@ -3230,7 +3230,6 @@ monst_init() struct attack sa_yes[NATTK] = SEDUCTION_ATTACKS_YES; struct attack sa_no[NATTK] = SEDUCTION_ATTACKS_NO; - #endif /*monst.c*/ From 0d36c443a3f15e1e5059807b22086c27afd9988d Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 25 Dec 2015 15:33:56 -0800 Subject: [PATCH 07/31] fix #4040:2 - message typo for pet mind flayer Mentioned in a completely unrelated report (about energy drain for vortex attack): the message given if a tame mind flayer is killed by attempting to eat Medusa's brains had "then is passes" where "then it passes" was intended. --- doc/fixes36.1 | 4 ++-- src/eat.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index dec33ac71..c308855e5 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -5,7 +5,7 @@ General Fixes and Modified Features doc/*.6 man pages and corresponding doc/*.txt text copies were out of date data.base entry for "lava" had wrong first name for Don Woods' attribution cursed genocide of "none" sent in monsters, but "that's enough tries" didn't -update MAXPLAYERS documentation in sysconf file and allow 0 for it +update MAXPLAYERS documentation in sysconf file and accept 0 for 'no limit' wizard mode: don't include feedback about named fruit for ^X and enlightenment looking at distant objects while wearing the Eyes of the Overworld made their up-close descriptions known when not intended @@ -41,7 +41,6 @@ don't show the old level when you die going down the stairs because of an new high score with ", while helpless" attribute appended would erroneously result in ", while helpless" being appended to all scores allow bright aliases for colors in menucolors -make MAXPLAYERS option in sysconf accept 0 value avoid hearing yelps when you are deaf make corpse visible if stethoscope told you about it being there sceptre of might database entry word change @@ -65,6 +64,7 @@ rehumanizing after being poly'd into vampire left hero with ability to sense Warn_of_mon wouldn't have been able to sense giant ants if any creature were to have that ability, caused by using 0 instead of NON_PM for 'none' tone down energy vortex's drain energy attack +fix message typo if tame mind flayer dies trying to eat Medusa's brains Platform- and/or Interface-Specific Fixes diff --git a/src/eat.c b/src/eat.c index 4e97a5818..bea0ccc4c 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 eat.c $NHDT-Date: 1450573885 2015/12/20 01:11:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.156 $ */ +/* NetHack 3.6 eat.c $NHDT-Date: 1451086430 2015/12/25 23:33:50 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.157 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -494,7 +494,7 @@ int *dmg_p; /* for dishing out extra damage in lieu of Int loss */ } else { if (magr->mtame && !visflag) /* parallels mhitm.c's brief_feeling */ - You("have a sad thought for a moment, then is passes."); + You("have a sad thought for a moment, then it passes."); return MM_AGR_DIED; } } From 1c80503938330c414907c5ee4356dfa13320ca5e Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 25 Dec 2015 16:46:02 -0800 Subject: [PATCH 08/31] fix #H4146 - more enlightenment vs drain resistance Duplicate of another recent report as far as drain resistance from Excalibur/Stormbringer/Staff of Aesculapius not being shown by enlightenment goes, but this one mentioned that it also wasn't being shown for lycanthropy. Being inflicted by that does confers level- drain resistance. were_change() wasn't calling set_uasmon() since it isn't changing youmonst.data, but set_uasmon() is were intrinsics conferred by creature form are set up. So call it when changing were-form. Direct access to u.ulycn wasn't calling it either, so add a new routine to assign the value to that instead doing so directly. --- doc/fixes36.1 | 2 +- include/extern.h | 1 + src/attrib.c | 4 +++- src/eat.c | 21 ++++++++++----------- src/mhitu.c | 2 +- src/potion.c | 2 +- src/were.c | 26 +++++++++++++++++++------- 7 files changed, 36 insertions(+), 22 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index c308855e5..0c9ff48a9 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -57,7 +57,7 @@ death due an unseen gas spore's explosion resulted in "killed by a died" allow optional parameter "true", "yes", "false", or "no" for boolean options actually make the castle chest not trapped level-drain resistance wasn't shown during enlightenment if it was conferred - by worn/wielded equipment + by worn/wielded equipment or by lycanthropy wizard mode enlightenment now shows more reasons for various intrinsics rehumanizing after being poly'd into vampire left hero with ability to sense humans and elves diff --git a/include/extern.h b/include/extern.h index 4839a9c20..5bfae6080 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2609,6 +2609,7 @@ E void FDECL(new_were, (struct monst *)); E int FDECL(were_summon, (struct permonst *, BOOLEAN_P, int *, char *)); E void NDECL(you_were); E void FDECL(you_unwere, (BOOLEAN_P)); +E void FDECL(set_ulycn, (int)); /* ### wield.c ### */ diff --git a/src/attrib.c b/src/attrib.c index 76a9fc0e7..611456f90 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -770,7 +770,9 @@ int propidx; /* special cases can have negative values */ if (innateness == FROM_EXP) Strcpy(buf, " because of your experience"); else if (innateness == FROM_FORM) - Strcpy(buf, " from current creature form"); + Strcpy(buf, (u.ulycn >= LOW_PM) + ? " due to your lycanthropy" + : " from current creature form"); else if (innateness == FROM_ROLE || innateness == FROM_RACE) Strcpy(buf, " innately"); else if (wizard diff --git a/src/eat.c b/src/eat.c index bea0ccc4c..d041976dd 100644 --- a/src/eat.c +++ b/src/eat.c @@ -903,7 +903,7 @@ cpostfx(pm) register int pm; { register int tmp = 0; - boolean catch_lycanthropy = FALSE; + int catch_lycanthropy = NON_PM; /* in case `afternmv' didn't get called for previously mimicking gold, clean up now to avoid `eatmbuf' memory leak */ @@ -931,16 +931,13 @@ register int pm; pluslvl(FALSE); break; case PM_HUMAN_WERERAT: - catch_lycanthropy = TRUE; - u.ulycn = PM_WERERAT; + catch_lycanthropy = PM_WERERAT; break; case PM_HUMAN_WEREJACKAL: - catch_lycanthropy = TRUE; - u.ulycn = PM_WEREJACKAL; + catch_lycanthropy = PM_WEREJACKAL; break; case PM_HUMAN_WEREWOLF: - catch_lycanthropy = TRUE; - u.ulycn = PM_WEREWOLF; + catch_lycanthropy = PM_WEREWOLF; break; case PM_NURSE: if (Upolyd) @@ -1096,12 +1093,14 @@ register int pm; gainstr((struct obj *) 0, 0, TRUE); else if (tmp > 0) givit(tmp, ptr); - } break; - } + break; + } /* default case */ + } /* switch */ - if (catch_lycanthropy) + if (catch_lycanthropy >= LOW_PM) { + set_ulycn(catch_lycanthropy); retouch_equipment(2); - + } return; } diff --git a/src/mhitu.c b/src/mhitu.c index 1e620dc7d..814061ccd 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1248,7 +1248,7 @@ register struct attack *mattk; && !Protection_from_shape_changers && !defends(AD_WERE, uwep)) { You_feel("feverish."); exercise(A_CON, FALSE); - u.ulycn = monsndx(mdat); + set_ulycn(monsndx(mdat)); retouch_equipment(2); } break; diff --git a/src/potion.c b/src/potion.c index 2631955b5..c18c560b9 100644 --- a/src/potion.c +++ b/src/potion.c @@ -604,7 +604,7 @@ register struct obj *otmp; makeplural(mons[u.ulycn].mname)); if (youmonst.data == &mons[u.ulycn]) you_unwere(FALSE); - u.ulycn = NON_PM; /* cure lycanthropy */ + set_ulycn(NON_PM); /* cure lycanthropy */ } losehp(Maybe_Half_Phys(d(2, 6)), "potion of holy water", KILLED_BY_AN); diff --git a/src/were.c b/src/were.c index 7ab1051ba..b9e58dd2b 100644 --- a/src/were.c +++ b/src/were.c @@ -37,6 +37,8 @@ register struct monst *mon; } else if (!rn2(30) || Protection_from_shape_changers) { new_were(mon); /* change back into human form */ } + /* update innate intrinsics (mainly Drain_resistance) */ + set_uasmon(); /* new_were() doesn't do this */ } int @@ -118,15 +120,15 @@ register struct monst *mon; possibly_unwield(mon, FALSE); } -int were_summon(ptr, yours, visible, - genbuf) /* were-creature (even you) summons a horde */ -register struct permonst *ptr; -register boolean yours; +/* were-creature (even you) summons a horde */ +int were_summon(ptr, yours, visible, genbuf) +struct permonst *ptr; +boolean yours; int *visible; /* number of visible helpers created */ char *genbuf; { - register int i, typ, pm = monsndx(ptr); - register struct monst *mtmp; + int i, typ, pm = monsndx(ptr); + struct monst *mtmp; int total = 0; *visible = 0; @@ -194,11 +196,21 @@ boolean purify; if (purify) { You_feel("purified."); - u.ulycn = NON_PM; /* cure lycanthropy */ + set_ulycn(NON_PM); /* cure lycanthropy */ } if (!Unchanging && is_were(youmonst.data) && (!controllable_poly || yn("Remain in beast form?") == 'n')) rehumanize(); } +/* lycanthropy is being caught or cured, but no shape change is involved */ +void +set_ulycn(which) +int which; +{ + u.ulycn = which; + /* add or remove lycanthrope's innate intrinsics (Drain_resistance) */ + set_uasmon(); +} + /*were.c*/ From c4a9d6a45c90b4d4f9514e10c63a883f676fa821 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 25 Dec 2015 21:54:01 -0800 Subject: [PATCH 09/31] newline handling In light of the recent 'bad options' feedback issue where \r messed up message display, try to to make newline handling be more consistent. I'm sure there are lots of places that still handle \n manually, but it's a start. --- include/extern.h | 1 + src/files.c | 19 ++++--------------- src/hacklib.c | 16 ++++++++++++++++ src/pager.c | 11 ++++------- src/version.c | 7 ++----- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/include/extern.h b/include/extern.h index 5bfae6080..ad7748bb5 100644 --- a/include/extern.h +++ b/include/extern.h @@ -835,6 +835,7 @@ E char *FDECL(lcase, (char *)); E char *FDECL(ucase, (char *)); E char *FDECL(upstart, (char *)); E char *FDECL(mungspaces, (char *)); +E char *FDECL(strip_newline, (char *)); E char *FDECL(eos, (char *)); E boolean FDECL(str_end_is, (const char *, const char *)); E char *FDECL(strkitten, (char *, CHAR_P)); diff --git a/src/files.c b/src/files.c index 18481a5f4..a524af027 100644 --- a/src/files.c +++ b/src/files.c @@ -2563,7 +2563,7 @@ read_config_file(filename, src) const char *filename; int src; { - char buf[4 * BUFSZ], *p; + char buf[4 * BUFSZ]; FILE *fp; boolean rv = TRUE; /* assume successful parse */ @@ -2581,13 +2581,7 @@ line at this level. OR: Forbid multiline stuff for alternate config sources. */ #endif - if ((p = index(buf, '\n')) != 0) { - /* in case file has CR+LF format on non-CR+LF platform */ - if (p > buf && *(p - 1) == '\r') - --p; - *p = '\0'; /* strip newline */ - } - if (!parse_config_line(fp, buf, src)) { + 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 */ @@ -3505,7 +3499,6 @@ char *nowin_buf; unsigned oid; /* book identifier */ { dlb *fp; - char *endp; char line[BUFSZ], lastline[BUFSZ]; int scope = 0; @@ -3556,18 +3549,14 @@ unsigned oid; /* book identifier */ *line = *lastline = '\0'; while (dlb_fgets(line, sizeof line, fp) != 0) { linect++; - if ((endp = index(line, '\n')) != 0) - *endp = 0; + (void) strip_newline(line); switch (line[0]) { case '%': if (!strncmpi(&line[1], "section ", sizeof("section ") - 1)) { char *st = &line[9]; /* 9 from "%section " */ scope = SECTIONSCOPE; - if (!strcmpi(st, tribsection)) - matchedsection = TRUE; - else - matchedsection = FALSE; + matchedsection = !strcmpi(st, tribsection) ? TRUE : FALSE; } else if (!strncmpi(&line[1], "title ", sizeof("title ") - 1)) { char *st = &line[7]; /* 7 from "%title " */ char *p1, *p2; diff --git a/src/hacklib.c b/src/hacklib.c index a8ecfaea1..256ac5743 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -18,6 +18,7 @@ char * ucase (char *) char * upstart (char *) char * mungspaces (char *) + char * strip_newline (char *) char * eos (char *) boolean str_end_is (const char *, const char *) char * strkitten (char *,char) @@ -158,6 +159,21 @@ char *bp; return bp; } +/* remove \n from end of line; remove \r too if one is there */ +char * +strip_newline(str) +char *str; +{ + char *p = index(str, '\n'); + + if (p) { + if (p > str && *(p - 1) == '\r') + --p; + *p = '\0'; + } + return str; +} + /* return the end of a string (pointing at '\0') */ char * eos(s) diff --git a/src/pager.c b/src/pager.c index 0a4fc87a7..0664bef5e 100644 --- a/src/pager.c +++ b/src/pager.c @@ -476,7 +476,7 @@ boolean user_typed_name, without_asking; } else if (!skipping_entry) { if (!(ep = index(buf, '\n'))) goto bad_data_file; - *ep = 0; + (void) strip_newline((ep > buf) ? ep - 1 : ep); /* if we match a key that begins with "~", skip this entry */ chk_skip = (*buf == '~') ? 1 : 0; if (pmatch(&buf[chk_skip], dbase_str) @@ -524,8 +524,7 @@ boolean user_typed_name, without_asking; for (i = 0; i < entry_count; i++) { if (!dlb_fgets(buf, BUFSZ, fp)) goto bad_data_file; - if ((ep = index(buf, '\n')) != 0) - *ep = 0; + (void) strip_newline(buf); if (index(buf + 1, '\t') != 0) (void) tabexpand(buf + 1); putstr(datawin, 0, buf + 1); @@ -1126,7 +1125,7 @@ char *cbuf; { dlb *fp; char bufr[BUFSZ]; - register char *buf = &bufr[6], *ep, ctrl, meta; + register char *buf = &bufr[6], ctrl, meta; fp = dlb_fopen(CMDHELPFILE, "r"); if (!fp) { @@ -1140,9 +1139,7 @@ char *cbuf; if ((ctrl && *buf == '^' && *(buf + 1) == ctrl) || (meta && *buf == 'M' && *(buf + 1) == '-' && *(buf + 2) == meta) || *buf == q) { - ep = index(buf, '\n'); - if (ep) - *ep = 0; + (void) strip_newline(buf); if (ctrl && buf[2] == '\t') { buf = bufr + 1; (void) strncpy(buf, "^? ", 8); diff --git a/src/version.c b/src/version.c index 97c8d0321..becefd8f7 100644 --- a/src/version.c +++ b/src/version.c @@ -57,7 +57,7 @@ int doextversion() { dlb *f; - char *cr, *pd, buf[BUFSZ]; + char *pd, buf[BUFSZ]; winid win = create_nhwindow(NHW_TEXT); boolean rtadded = FALSE; @@ -94,10 +94,7 @@ doextversion() boolean prolog = TRUE; /* to skip indented program name */ while (dlb_fgets(buf, BUFSZ, f)) { - if ((cr = index(buf, '\n')) != 0) - *cr = 0; - if ((cr = index(buf, '\r')) != 0) - *cr = 0; + (void) strip_newline(buf); if (index(buf, '\t') != 0) (void) tabexpand(buf); From eea54fb77327bf497ae127d20e13415d8fcd4e85 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 25 Dec 2015 22:25:56 -0800 Subject: [PATCH 10/31] more attribute from-what A change earlier today resulted in infravision being described by enlightenment (wizard mode only) as "from current creature form" when it was actually due to hero's non-human race. Now it'll be "innately". --- src/attrib.c | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/attrib.c b/src/attrib.c index 611456f90..4d4df2dff 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 attrib.c $NHDT-Date: 1451081651 2015/12/25 22:14:11 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.52 $ */ +/* NetHack 3.6 attrib.c $NHDT-Date: 1451111134 2015/12/26 06:25:34 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.54 $ */ /* Copyright 1988, 1989, 1990, 1992, M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -83,10 +83,21 @@ static const struct innate { { 0, 0, 0, 0 } }, /* Intrinsics conferred by race */ - elf_abil[] = { { 4, &(HSleep_resistance), "awake", "tired" }, - { 0, 0, 0, 0 } }, + dwa_abil[] = { { 1, &HInfravision, "", "" }, + { 0, 0, 0, 0 } }, - orc_abil[] = { { 1, &(HPoison_resistance), "", "" }, { 0, 0, 0, 0 } }; + elf_abil[] = { { 1, &HInfravision, "", "" }, + { 4, &HSleep_resistance, "awake", "tired" }, + { 0, 0, 0, 0 } }, + + gno_abil[] = { { 1, &HInfravision, "", "" }, + { 0, 0, 0, 0 } }, + + orc_abil[] = { { 1, &HInfravision, "", "" }, + { 1, &HPoison_resistance, "", "" }, + { 0, 0, 0, 0 } }, + + hum_abil[] = { { 0, 0, 0, 0 } }; STATIC_DCL void NDECL(exerper); STATIC_DCL void FDECL(postadjabil, (long *)); @@ -686,15 +697,19 @@ long frommask; } else if (frommask == FROMRACE) switch (Race_switch) { + case PM_DWARF: + abil = dwa_abil; + break; case PM_ELF: abil = elf_abil; break; + case PM_GNOME: + abil = gno_abil; + break; case PM_ORC: abil = orc_abil; break; case PM_HUMAN: - case PM_DWARF: - case PM_GNOME: default: break; } @@ -713,6 +728,7 @@ long frommask; #define FROM_RACE 2 #define FROM_EXP 3 /* from experience for some level > 1 */ #define FROM_FORM 4 +#define FROM_LYCN 5 /* check whether particular ability has been obtained via innate attribute */ @@ -728,16 +744,19 @@ long *ability; return FROM_RACE; if ((*ability & FROMFORM) != 0L) return FROM_FORM; - return FROM_NONE; + return FROM_NONE; } int is_innate(propidx) int propidx; { - int innateness = innately(&u.uprops[propidx].intrinsic); + int innateness; - if (innateness != FROM_NONE) + /* innately() would report FROM_FORM for this; caller wants specificity */ + if (propidx == DRAIN_RES && u.ulycn >= LOW_PM) + return FROM_LYCN; + if ((innateness = innately(&u.uprops[propidx].intrinsic)) != FROM_NONE) return innateness; if (propidx == JUMPING && Role_if(PM_KNIGHT) /* knight has intrinsic jumping, but extrinsic is more versatile so @@ -769,10 +788,10 @@ int propidx; /* special cases can have negative values */ if (innateness == FROM_EXP) Strcpy(buf, " because of your experience"); + else if (innateness == FROM_LYCN) + Strcpy(buf, " due to your lycanthropy"); else if (innateness == FROM_FORM) - Strcpy(buf, (u.ulycn >= LOW_PM) - ? " due to your lycanthropy" - : " from current creature form"); + Strcpy(buf, " from current creature form"); else if (innateness == FROM_ROLE || innateness == FROM_RACE) Strcpy(buf, " innately"); else if (wizard From e4294158325e4a6b76557137921c19d856fcba75 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 25 Dec 2015 23:36:44 -0800 Subject: [PATCH 11/31] fix #H4144 - rejecting named monster's own name Some monsters can't be named, but if the user tried to assign them a name that matched what they were already called, the rejection message could be silly. Reported case was "I'm Izchak, not Izchak!". The fix is more general than just for shopkeepers, although their reject message was silliest when complaining about the name already in use. For the cited case, feedback will now be 'He is already called Izchak.' --- doc/fixes36.1 | 2 ++ src/do_name.c | 74 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 0c9ff48a9..ded18dec8 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -65,6 +65,8 @@ Warn_of_mon wouldn't have been able to sense giant ants if any creature were to have that ability, caused by using 0 instead of NON_PM for 'none' tone down energy vortex's drain energy attack fix message typo if tame mind flayer dies trying to eat Medusa's brains +use alternate rejection message if attempting to name an unnameable monster + with the name it already has Platform- and/or Interface-Specific Fixes diff --git a/src/do_name.c b/src/do_name.c index 3d8669be0..889609034 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -7,6 +7,7 @@ STATIC_DCL char *NDECL(nextmbuf); STATIC_DCL void FDECL(getpos_help, (BOOLEAN_P, const char *)); STATIC_DCL void NDECL(do_mname); +STATIC_DCL boolean FDECL(alreadynamed, (struct monst *, char *, char *)); STATIC_DCL void FDECL(do_oname, (struct obj *)); STATIC_DCL void NDECL(namefloorobj); STATIC_DCL char *FDECL(bogusmon, (char *,char *)); @@ -409,15 +410,45 @@ const char *name; return mtmp; } +/* check whether user-supplied name matches or nearly matches an unnameable + monster's name; if so, give an alternate reject message for do_mname() */ +STATIC_OVL boolean +alreadynamed(mtmp, monnambuf, usrbuf) +struct monst *mtmp; +char *monnambuf, *usrbuf; +{ + char pronounbuf[10], *p; + + if (fuzzymatch(usrbuf, monnambuf, " -_", TRUE) + /* catch trying to name "the Oracle" as "Oracle" */ + || (!strncmpi(monnambuf, "the ", 4) + && fuzzymatch(usrbuf, monnambuf + 4, " -_", TRUE)) + /* catch trying to name "invisible Orcus" as "Orcus" */ + || ((p = strstri(monnambuf, "invisible ")) != 0 + && fuzzymatch(usrbuf, p + 10, " -_", TRUE)) + /* catch trying to name "the {priest,Angel} of Crom" as "Crom" */ + || ((p = strstri(monnambuf, " of ")) != 0 + && fuzzymatch(usrbuf, p + 4, " -_", TRUE))) { + pline("%s is already called %s.", + upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf); + return TRUE; + } else if (mtmp->data == &mons[PM_JUIBLEX] + && strstri(monnambuf, "Juiblex") + && !strcmpi(usrbuf, "Jubilex")) { + pline("%s doesn't like being called %s.", upstart(monnambuf), usrbuf); + return TRUE; + } + return FALSE; +} + /* allow player to assign a name to some chosen monster */ STATIC_OVL void do_mname() { - char buf[BUFSZ], monnambuf[BUFSZ]; + char buf[BUFSZ], monnambuf[BUFSZ], qbuf[QBUFSZ]; coord cc; - register int cx, cy; - register struct monst *mtmp; - char qbuf[QBUFSZ]; + int cx, cy; + struct monst *mtmp = 0; if (Hallucination) { You("would never recognize it anyway."); @@ -431,9 +462,9 @@ do_mname() cy = cc.y; if (cx == u.ux && cy == u.uy) { - if (u.usteed && canspotmon(u.usteed)) + if (u.usteed && canspotmon(u.usteed)) { mtmp = u.usteed; - else { + } else { pline("This %s creature is called %s and cannot be renamed.", beautiful(), plname); return; @@ -459,18 +490,25 @@ do_mname() /* strip leading and trailing spaces; unnames monster if all spaces */ (void) mungspaces(buf); - /* unique monsters have their own specific names or titles; - shopkeepers, temple priests and other minions use alternate - name formatting routines which ignore any user-supplied name */ - if ((mtmp->data->geno & G_UNIQ) && !mtmp->ispriest) - pline("%s doesn't like being called names!", upstart(monnambuf)); - else if (mtmp->isshk - && !(Deaf || mtmp->msleeping || !mtmp->mcanmove - || mtmp->data->msound <= MS_ANIMAL)) - verbalize("I'm %s, not %s.", shkname(mtmp), buf); - else if (mtmp->ispriest || mtmp->isminion || mtmp->isshk) - pline("%s will not accept the name %s.", upstart(monnambuf), buf); - else + /* Unique monsters have their own specific names or titles. + * Shopkeepers, temple priests and other minions use alternate + * name formatting routines which ignore any user-supplied name. + * + * Don't say the name is being rejected if it happens to match + * the existing name. + */ + if ((mtmp->data->geno & G_UNIQ) && !mtmp->ispriest) { + if (!alreadynamed(mtmp, monnambuf, buf)) + pline("%s doesn't like being called names!", upstart(monnambuf)); + } else if (mtmp->isshk + && !(Deaf || mtmp->msleeping || !mtmp->mcanmove + || mtmp->data->msound <= MS_ANIMAL)) { + if (!alreadynamed(mtmp, monnambuf, buf)) + verbalize("I'm %s, not %s.", shkname(mtmp), buf); + } else if (mtmp->ispriest || mtmp->isminion || mtmp->isshk) { + if (!alreadynamed(mtmp, monnambuf, buf)) + pline("%s will not accept the name %s.", upstart(monnambuf), buf); + } else (void) christen_monst(mtmp, buf); } From 3c9b0f25b6d209b0be2d6cfaf62a0d29551d2343 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Sat, 26 Dec 2015 13:12:59 +0200 Subject: [PATCH 12/31] Add alternate spelling of prot from shape changers --- src/objnam.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/objnam.c b/src/objnam.c index 449be7057..e6ca04521 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -2386,6 +2386,7 @@ struct alt_spellings { { "grappling iron", GRAPPLING_HOOK }, { "grapnel", GRAPPLING_HOOK }, { "grapple", GRAPPLING_HOOK }, + { "protection from shape shifters", RIN_PROTECTION_FROM_SHAPE_CHAN }, /* normally we wouldn't have to worry about unnecessary , but " stone" will get stripped off, preventing a wishymatch; that actually lets "flint stone" be a match, so we also accept bogus "flintstone" */ From e55dd6919acd12dbc85b44c9f55cf376f8e8c2bd Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Sat, 26 Dec 2015 21:40:17 +0200 Subject: [PATCH 13/31] Fix prot from shape changers at level generation Mimics and other shape changers created at level generation did not obey protection from shape changers. --- src/makemon.c | 2 +- src/sp_lev.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/makemon.c b/src/makemon.c index 55cf66fab..422a446c2 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1988,7 +1988,7 @@ register struct monst *mtmp; struct obj *otmp; int mx, my; - if (!mtmp) + if (!mtmp || Protection_from_shape_changers) return; mx = mtmp->mx; my = mtmp->my; diff --git a/src/sp_lev.c b/src/sp_lev.c index f65e3c270..61740b436 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -1585,7 +1585,8 @@ struct mkroom *croom; * eventually be expanded. */ if (m->appear_as.str - && ((mtmp->data->mlet == S_MIMIC) || mtmp->cham)) { + && ((mtmp->data->mlet == S_MIMIC) || mtmp->cham) + && !Protection_from_shape_changers) { int i; switch (m->appear) { From 6117eddc62e21a189d20e6be0ad2b8bf471d6293 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 26 Dec 2015 19:08:08 -0500 Subject: [PATCH 14/31] one statue from single vampire via cockatrice corpse Changes to be committed: modified: doc/fixes36.1 modified: include/extern.h modified: src/mon.c Fixes H4148 (bz246) and H4150 (bz248) comments: I wielded a c-corpse against a shapeshifting vampire bat (checked with a stethoscope, it said "shapeshifter".) The bat turned to stone and spawned a vampire. I hit the vampire and it also turned to stone, so I had two statues from one monster (vampire bat and vampire.) Not sure if this is a bug or a feature... comments: Engulfed by a fog cloud that was actually a Vampire, and got the message: "You break out of the vampire!" --- doc/fixes36.1 | 1 + include/extern.h | 3 +- src/mon.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index ded18dec8..f74d853b8 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -67,6 +67,7 @@ tone down energy vortex's drain energy attack fix message typo if tame mind flayer dies trying to eat Medusa's brains use alternate rejection message if attempting to name an unnameable monster with the name it already has +cockatrice corpse no longer leaves multiple statues for shape-shifted vampire Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index ad7748bb5..a74ea10a4 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1450432755 2015/12/18 09:59:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.521 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1451174855 2015/12/27 00:07:35 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.526 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1351,6 +1351,7 @@ E void FDECL(golemeffects, (struct monst *, int, int)); E boolean FDECL(angry_guards, (BOOLEAN_P)); E void NDECL(pacify_guards); E void FDECL(decide_to_shapeshift, (struct monst *, int)); +E boolean FDECL(vamp_stone, (struct monst *)); /* ### mondata.c ### */ diff --git a/src/mon.c b/src/mon.c index 467ec58b5..7ce460b1d 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1449908726 2015/12/12 08:25:26 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.200 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1451174868 2015/12/27 00:07:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.201 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2311,6 +2311,69 @@ struct monst *mtmp; impossible("Can't polystone %s!", a_monnam(mtmp)); } +boolean +vamp_stone(mtmp) +struct monst *mtmp; +{ + if (is_vampshifter(mtmp)) { + int mndx = mtmp->cham; + int x = mtmp->mx, y = mtmp->my; + + /* this only happens if shapeshifted */ + if (mndx >= LOW_PM && mndx != monsndx(mtmp->data) + && !(mvitals[mndx].mvflags & G_GENOD)) { + char buf[BUFSZ]; + boolean in_door = (amorphous(mtmp->data) + && closed_door(mtmp->mx, mtmp->my)), + /* alternate message phrasing for some monster types */ + spec_mon = (nonliving(mtmp->data) + || noncorporeal(mtmp->data) + || amorphous(mtmp->data)); + + /* construct a format string before transformation */ + Sprintf(buf, "The lapidifying %s %s %s", + x_monnam(mtmp, ARTICLE_NONE, (char *) 0, + SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION + | SUPPRESS_INVISIBLE | SUPPRESS_IT, + FALSE), + amorphous(mtmp->data) ? "coalesces on the" : + is_flyer(mtmp->data) ? "drops to the" : "writhes on the", + surface(x,y)); + mtmp->mcanmove = 1; + mtmp->mfrozen = 0; + if (mtmp->mhpmax <= 0) + mtmp->mhpmax = 10; + mtmp->mhp = mtmp->mhpmax; + /* this can happen if previously a fog cloud */ + if (u.uswallow && (mtmp == u.ustuck)) + expels(mtmp, mtmp->data, FALSE); + if (in_door) { + coord new_xy; + + if (enexto(&new_xy, mtmp->mx, mtmp->my, &mons[mndx])) { + rloc_to(mtmp, new_xy.x, new_xy.y); + } + } + if (canspotmon(mtmp)) { + pline("%s!", buf); + display_nhwindow(WIN_MESSAGE, FALSE); + } + newcham(mtmp, &mons[mndx], FALSE, FALSE); + if (mtmp->data == &mons[mndx]) + mtmp->cham = NON_PM; + else + mtmp->cham = mndx; + if (canspotmon(mtmp)) { + pline("%s rises from the %s with renewed agility!", + Amonnam(mtmp), surface(mtmp->mx, mtmp->my)); + } + newsym(mtmp->mx, mtmp->my); + return FALSE; /* didn't petrify */ + } + } + return TRUE; +} + /* make monster mtmp next to you (if possible); might place monst on far side of a wall or boulder */ void @@ -3184,8 +3247,17 @@ boolean msg; /* "The oldmon turns into a newmon!" */ /* Does mdat care? */ if (!noncorporeal(mdat) && !amorphous(mdat) && !is_whirly(mdat) && (mdat != &mons[PM_YELLOW_LIGHT])) { - You("break out of %s%s!", mon_nam(mtmp), - (is_animal(mdat) ? "'s stomach" : "")); + char msgtrail[BUFSZ]; + + if (is_vampshifter(mtmp)) { + Strcpy(msgtrail, " that had been shapeshifted"); + } else if (is_animal(mdat)) { + Strcpy(msgtrail, "'s stomach"); + } else { + msgtrail[0] = '\0'; + } + + You("break out of %s%s!", mon_nam(mtmp), msgtrail); mtmp->mhp = 1; /* almost dead */ } expels(mtmp, olddata, FALSE); From a156a4a3a5400b49291dfb18bc726b6d695e269d Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 26 Dec 2015 19:27:15 -0500 Subject: [PATCH 15/31] meant to be part of previous commit Changes to be committed: modified: src/trap.c --- src/trap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/trap.c b/src/trap.c index 7770d4188..b5cda7a5b 100644 --- a/src/trap.c +++ b/src/trap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 trap.c $NHDT-Date: 1450461008 2015/12/18 17:50:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.251 $ */ +/* NetHack 3.6 trap.c $NHDT-Date: 1451176031 2015/12/27 00:27:11 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.252 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2661,6 +2661,8 @@ boolean byplayer; mon_to_stone(mon); return; } + if (!vamp_stone(mon)) + return; /* give a " is slowing down" message and also remove intrinsic speed (comparable to similar effect on the hero) */ From 5226484bab0b27f164b0101d8932d49a1fbbbb38 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 26 Dec 2015 19:35:58 -0500 Subject: [PATCH 16/31] remove extraneous bit from cut and paste --- src/mon.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/mon.c b/src/mon.c index 7ce460b1d..2e38e9298 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1451174868 2015/12/27 00:07:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.201 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1451176552 2015/12/27 00:35:52 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.202 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2324,11 +2324,7 @@ struct monst *mtmp; && !(mvitals[mndx].mvflags & G_GENOD)) { char buf[BUFSZ]; boolean in_door = (amorphous(mtmp->data) - && closed_door(mtmp->mx, mtmp->my)), - /* alternate message phrasing for some monster types */ - spec_mon = (nonliving(mtmp->data) - || noncorporeal(mtmp->data) - || amorphous(mtmp->data)); + && closed_door(mtmp->mx, mtmp->my)); /* construct a format string before transformation */ Sprintf(buf, "The lapidifying %s %s %s", From 67e602972371ff5fd2feb54339291422d6955fe8 Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 27 Dec 2015 01:46:12 -0800 Subject: [PATCH 17/31] tribute: Snuff --- dat/tribute | 252 +++++++++++++++++++++++++++++++++++++++++++++++++- doc/fixes36.1 | 2 +- 2 files changed, 248 insertions(+), 6 deletions(-) diff --git a/dat/tribute b/dat/tribute index f73ff0787..6f19a1d03 100644 --- a/dat/tribute +++ b/dat/tribute @@ -5265,17 +5265,259 @@ ag-rreeeed arr-angement, ye ken!" # # # -%title Snuff (2) +%title Snuff (16) +# p. 168 (Harper edition; 'ax' is spelled without the 'e' there...) %passage 1 They were crude weapons, to be sure, but a flint axe hitting your head does -not need a degree in physics. +not need a degree in physics. [Snuff, by Terry Pratchett] %e passage %passage 2 -It is a strange thing to find yourself doing something you -have apparently always wanted to do, when in fact up until -that moment you had never known that you always wanted to do it... +It is a strange thing to find yourself doing something you have apparently +always wanted to do, when in fact up until that moment you had never known +that you always wanted to do it... + + [Snuff, by Terry Pratchett] +%e passage +# p. 2 (the subject is goblins) +%passage 3 +At this point, Lord Vetinari, Patrician of Ankh-Morpork, stopped reading +and stared at nothing. After a few seconds, nothing was eclipsed by the +form of Drumknott, his secretary (who, it must be said, had spent a career +turning himself as much like nothing as anything). + +Drumknott said, "You look pensive, my lord," to which observation he +appended a most delicate question mark, which gradually evaporated. + +"Awash with tears, Drumknott, awash with tears." + +Drumknott stopped dusting the impeccably shiny black lacquered desk. +"Pastor Oats is a very persuasive writer, isn't he, sir...?" + +"Indeed he is, Drumknott, but the basic problem remains and it is this: +humanity may come to terms with the dwarf, the troll and even the orc, +terrifying though all these have proved to be at times, and you know why +this is, Drumknott?" + +The secretary carefully folded the duster he had been using and looked at +the ceiling. "I would venture to suggest, my lord, that in their violence +we recognize ourselves?" + +"Oh, well done, Drumknott, I shall make a cynic of you yet! Predators +respect other predators, do they not? They may perhaps even respect the +prey: the lion may lie down with the lamb, even if only the lion is +likely to get up again, but the lion will not lie down with the rat. +Vermin, Drumknott, an entire race reduced to vermin!" + + [Snuff, by Terry Pratchett] +%e passage +# p. 6 +%passage 4 +Vimes grunted. "Where there are policemen there's crime, sergeant, +remember that." + +"Yes, I do, sir, although I think it sounds better with a little reordering +of the words." + + [Snuff, by Terry Pratchett] +%e passage +# pp. 46-47 (passage starts mid-paragraph and ends mid-paragraph; it's a +# long slog for a weak punchline...) +%passage 5 +"[...] The third earl, 'Mad' Jack Ramkin, had a brother called +Woolsthorpe, probably for his sins. He was something of a scholar and +would have been sent to the university to become a wizard were it not for +the fact that his brother let it be known that any male sibling of his who +took up a profession that involved wearing a dress would be disinherited +with a cleaver. + +"Nevertheless, young Woolsthorpe persevered in his studies in natural +philosophy in the way a gentleman should, by digging into any suspicious- +looking burial mounds he could find in the neighborhood, filling up his +lizard press with as many rare species as he could collect, and drying +samples of any flowers he could find before they became extinct. The +story runs that, on one warm summer day, he dozed off under an apple tree +and was awakened when an apple fell on his head. A lesser man, as his +biographer put it, would have seen nothing untoward about this, but +Woolsthorpe surmised that, since apples and practically everything else +always fell down, then the world would eventually become dangerously +unbalanced... unless there was another agency involved that natural +philosophy had yet to discover. He lost no time in dragging one of the +footmen to the orchard and ordering him, on the pain of dismissal, to lie +under the tree until an apple hit him on the head! The possibility of +this happening was increased by another footman who had been told by +Woolsthorpe to shake the tree vigorously until the required apple fell. +Woolsthorpe was ready to observe this from a distance. + +"Who can imagine his joy when the inevitable apple fell and a second apple +was seen rising from the tree and disappearing at speed into the vaults of +heaven, proving the hypothesis that what goes up must come down, provided +that what goes down must come up, thus safeguarding the equilibrium of the +Universe. Regrettably, this only works with apples and, amazingly, only +the apples on this one tree, /Malus equilibria/! I hear that someone has +worked out that the apples at the top of the tree fill with gas and fly up +when the tree is disturbed so that it can set its seeds some way off. +Wonderful thing, nature, shame the fruit tastes like dog's business," +Willikins added as Young Sam spat some out. [...] + + [Snuff, by Terry Pratchett] +%e passage +# p. 100 +%passage 6 +"Look, Willikins, I don't like to involve you in all this. It's only a +hunch, after all." + +Willikins waved this away. "You wouldn't keep me out of it for a big +clock, sir, because all this is tickling my fancy as well. I shall lay +out a selection of cutting edges for you in your dressing room, sir, and I +myself will go up to the copse half an hour before you're due to be there, +with my trusty bow and an assortment of favorite playthings. It's nearly +full moon, clear skies, there'll be shadows everywhere, and I'll be +standing in the darkest one of them." + +Vimes looked at him for a moment and said, "Could I please amend that +suggestion? Could you not be there in the second darkest shadow one hour +before midnight, to see who steps into the darkest shadow?" + +"Ah yes, that's why you command the watch, sir," said Willikins, and to +Vimes's shock there was a hint of a tear in the man's voice. "You're +listening to the street, aren't you, sir, yes?" + +Vimes shrugged. "No streets here, Willikins." + +Willikins shook his head. "Once a street boy, always a street boy, sir. +It comes with us, in the pinch. Mothers go, fathers go--if we ever knew +who they were--but the Street, well, the Street looks after us. In the +pinch it keeps us alive." + + [Snuff, by Terry Pratchett] +%e passage +# p. 116 (passage ends mid-paragraph) +%passage 7 +Well, we live and learn, Vimes thought, or perhaps more importantly, we +learn and live. [...] + + [Snuff, by Terry Pratchett] +%e passage +# p. 153 +%passage 8 +In the country, there is always somebody watching you, he thought as they +sped along. Well, there was always somebody watching you in the city, too, +but that was generally in the hope that you might drop dead and they could +run off with your wallet. They were never /interested/. But here he +thought he could feel many eyes on him. Maybe they belonged to squirrels +or badgers, or whatever the damn things were that Vimes heard at night; +gorillas, possibly. + + [Snuff, by Terry Pratchett] +%e passage +# pp. 169-170 +%passage 9 +"Well, sir, it looks as though they're pleased to see us, yes?" + +Feeney's relief and hope should have been bottled and sold to despairing +people everywhere. Vimes just nodded, because the ranks were pulling +apart, leaving a pathway of sorts, at the end of which there was, +inarguably, a corpse. It was a mild relief to see that it was a goblin +corpse, but no corpse is good news, particularly when seen in a grimy low +light and especially for the corpse. And yet something inside him exulted +and cried /Hallelujah!/, because here was a corpse and he was a copper +and this was a crime and this place was smoky and dirty and full of +suspicious-looking goblins and here was a /crime/. His world. Yes, here +was /his/ world. + + [Snuff, by Terry Pratchett] +%e passage +# p. 211 +%passage 10 +Vimes lay back in the bed, enjoying the wonderful sensation of gradually +being eaten by the pillows, and said to Sybil, "Do the Rust family have a +place down here?" + +Too late he reflected that this might be a bad move because she might well +have told him all about it on one of those occasions when, so unusally for +a married man, he was not paying much attention to what his wife was +saying, and therefore he might be the cause of grumpiness in those +precious, warm minutes before sleep. All he could see of her right now +was the very tip of her nose, as the pillows claimed her, but she mumbled, +drowsily, "Oh, they bought Hangnail Manor ten years or so ago, after the +Marquis of Fantailer murdered his wife with a pruning knife in the +pineapple house. Don't you remember? You spent weeks searching the city +for him. In the end everybody seemed to think he'd gone off to Fourecks +and disguised himself by not calling himself the Marquis of Fantailer." + +"Oh yes," said Vimes, "and I remember that a lot of his chums were quite +indignant about the investigation! They said he'd only done one murder, +and it was his wife's fault for having the bad taste to die after just one +little stab!" + + [Snuff, by Terry Pratchett] +%e passage +# p. 212 (passage starts mid-paragraph and ends mid-paragraph) +%passage 11 +[...] he had heard that writers spent all day in their dressing gowns +drinking champagne.(1) [...] + +(1) This is, of course, absolutely true. + + [Snuff, by Terry Pratchett] +%e passage +# p. 217 (passage starts mid-paragraph and ends mid-paragraph) +%passage 12 +"[...] and the Summoning Dark is /real/. It's not all in your head, +commander: no matter what you hear, I sometimes hear it too. Oh dear, +you of all people must recognize a substition when you're possessed by it? +It's the opposite of superstition: it's real even if you don't believe +in it. [...]" + + [Snuff, by Terry Pratchett] +%e passage +# p. 233 +%passage 13 +Vimes frowned. He couldn't remember ever going into a church or a temple +or one of the numerous other places of more or less spirituality for any +other reason than the occasional requirements of the job. These days he +tended to go in for reasons of Sybil, i.e., his wife dragging him along +so that he could be seen, and, if possible, seen remaining awake. + +No, the world of next worlds, afterlives, and purgatorial destinations +simply did not fit into his head. Whether you wanted it or not, you were +born, you did the best you could, and then, whether you really wanted to +or not, you died. They were the only certainties, and so the best thing +for a copper to do was to get on with the job. And it was about time +that Sam Vimes got back to doing his. + + [Snuff, by Terry Pratchett] +%e passage +# p. 254 (passage starts mid-paragraph) +%passage 14 +[...] And maybe if I distinguish myself I can get a job in the city, so +that my mum can live in a place where you don't lie awake at night +listening to the mice fighting the cockroaches--hooray!(1) + +(1) Regrettably, Constable Upshot was overly hopeful: in Ankh-Morpork the +mice and cockroaches had decided to forget their differences and gang up +on the humans. + + [Snuff, by Terry Pratchett] +%e passage +# p. 403 (passage starts mid-paragraph) +%passage 15 +"[...] And I remember reading somewhere that you would arrest the gods +for doing it wrong." + +Vimes shook his head. "I'm sure I never said anything of the sort! But +law is order and order is law and it must be the highest thing. The world +runs on it, the heavens run on it and without order, lad, one second +cannot follow another." + + [Snuff, by Terry Pratchett] +%e passage +# p. 404 (footnote) +%passage 16 +The sound of the gentle rattle of china cup on china saucer drives away +all demons, a little-known fact. [Snuff, by Terry Pratchett] %e passage diff --git a/doc/fixes36.1 b/doc/fixes36.1 index f74d853b8..f8c07baaa 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -98,7 +98,7 @@ wizard mode #wizintrinsic reading non-cursed scroll of enchant weapon uncurses welded tin opener if hero has no jumping ability but knows the jumping spell, the #jump command will attempt to cast the spell -additional passages for Raising Steam +additional tribute passages for Snuff and for Raising Steam Platform- and/or Interface-Specific New Features From e43e97b021365cc126f4315ede66c62a74eb573c Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 27 Dec 2015 17:43:58 -0800 Subject: [PATCH 18/31] death-reason sanitizing Prevent commas, equal signs, and tabs in reason for death. Comma can make while-helpless reason ambiguous in record and basic logfile. Equal sign can do the same for fixrecord.awk, the awk program that can be used to fix up corrupted 3.6.0 record files, if it resorts to constructing logfile records out of xlogfile records. And tab could break parsing of xlogfile (it should already be excluded though; the code that lets players assign names to monsters uses mungspaces(), and one of the things that does is to convert any tab into a space before squeezing consecutive spaces down to one). The name alteration shows up for tombstone as well as for file entries. That could be changed but hardly seems worth the effort. Perhaps the name sanitizing ought to be moved to the initial naming? At least then it would be pretty obvious that it was intentional rather by mistake. --- doc/fixes36.1 | 2 ++ src/topten.c | 31 ++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index f8c07baaa..f3881c599 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -68,6 +68,8 @@ fix message typo if tame mind flayer dies trying to eat Medusa's brains use alternate rejection message if attempting to name an unnameable monster with the name it already has cockatrice corpse no longer leaves multiple statues for shape-shifted vampire +alter name of monster causing hero's death if name contains characters that + could cause confusion when using record, logfile, or xlogfile later Platform- and/or Interface-Specific Fixes diff --git a/src/topten.c b/src/topten.c index 9af1d54df..4056d2ac6 100644 --- a/src/topten.c +++ b/src/topten.c @@ -100,9 +100,9 @@ boolean incl_helpless; "", "", "", "", "" }; unsigned l; - char *kname = killer.name; + char c, *kname = killer.name; - buf[0] = '\0'; /* so strncat() can find the end */ + buf[0] = '\0'; /* lint suppression */ switch (killer.format) { default: impossible("bad killer format? (%d)", killer.format); @@ -118,13 +118,30 @@ boolean incl_helpless; buf += l, siz -= l; break; } - /* we're writing into buf[0] (after possibly advancing buf) rather than - appending, but strncat() appends a terminator and strncpy() doesn't */ - (void) strncat(buf, kname, siz - 1); + /* Copy kname into buf[]. + * Object names and named fruit have already been sanitized, but + * monsters can have "called 'arbitrary text'" attached to them, + * so make sure that that text can't confuse field splitting when + * record, logfile, or xlogfile is re-read at some later point. + */ + while (--siz > 0) { + c = *kname++; + if (c == ',') + c = ';'; + /* 'xlogfile' doesn't really need protection for '=', but + fixrecord.awk for corrupted 3.6.0 'record' does (only + if using xlogfile rather than logfile to repair record) */ + else if (c == '=') + c = '_'; + /* tab is not possible due to use of mungspaces() when naming; + it would disrupt xlogfile parsing if it were present */ + else if (c == '\t') + c = ' '; + *buf++ = c; + } + *buf = '\0'; if (incl_helpless && multi) { - siz -= strlen(buf); - buf = eos(buf); /* X <= siz: 'sizeof "string"' includes 1 for '\0' terminator */ if (multi_reason && strlen(multi_reason) + sizeof ", while " <= siz) Sprintf(buf, ", while %s", multi_reason); From 32305ace5cfec0df0b88853c00d8b93fda787893 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Mon, 28 Dec 2015 17:42:55 +0200 Subject: [PATCH 19/31] Prevent minotaur in mines end and bigroom mazes --- dat/bigroom.des | 2 +- dat/mines.des | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dat/bigroom.des b/dat/bigroom.des index f6d1657b1..3726d74c0 100644 --- a/dat/bigroom.des +++ b/dat/bigroom.des @@ -708,7 +708,7 @@ LOOP [28] { MONSTER:random,random } -MAZEWALK:(4, 2), south +MAZEWALK:(4, 2), south, false # Stairs up, not in the fog maze STAIR:(00,00,70,18),(02,03,68,15),up diff --git a/dat/mines.des b/dat/mines.des index 7f76d7b3e..ec1a0964c 100644 --- a/dat/mines.des +++ b/dat/mines.des @@ -1140,7 +1140,7 @@ DOOR:closed,(37,8) DOOR:closed,(47,8) DOOR:closed,(73,5) DOOR:closed,(2,15) -MAZEWALK:(36,8),west +MAZEWALK:(36,8),west,false STAIR:(42,8),up WALLIFY From a5ed69288fd0daf56a66ffd2e306c1681b685abc Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Mon, 28 Dec 2015 18:06:48 +0200 Subject: [PATCH 20/31] Split get_rnd_toptenentry from tt_oname --- include/extern.h | 1 + src/topten.c | 47 +++++++++++++++++++++++++++++++---------------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/include/extern.h b/include/extern.h index a74ea10a4..c25c634b6 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2299,6 +2299,7 @@ E void NDECL(timer_sanity_check); E void FDECL(formatkiller, (char *, unsigned, int, BOOLEAN_P)); E void FDECL(topten, (int, time_t)); E void FDECL(prscore, (int, char **)); +E struct toptenentry *NDECL(get_rnd_toptenentry); E struct obj *FDECL(tt_oname, (struct obj *)); /* ### track.c ### */ diff --git a/src/topten.c b/src/topten.c index 4056d2ac6..84146e9ad 100644 --- a/src/topten.c +++ b/src/topten.c @@ -1171,25 +1171,19 @@ boolean fem; /* * Get a random player name and class from the high score list, - * and attach them to an object (for statues or morgue corpses). */ -struct obj * -tt_oname(otmp) -struct obj *otmp; +struct toptenentry * +get_rnd_toptenentry() { - int rank; - register int i; - register struct toptenentry *tt; + int rank, i; FILE *rfile; - struct toptenentry tt_buf; - - if (!otmp) - return (struct obj *) 0; + register struct toptenentry *tt; + static struct toptenentry tt_buf; rfile = fopen_datafile(RECORD, "r", SCOREPREFIX); if (!rfile) { impossible("Cannot open record file!"); - return (struct obj *) 0; + return NULL; } tt = &tt_buf; @@ -1207,13 +1201,34 @@ pickentry: rewind(rfile); goto pickentry; } - otmp = (struct obj *) 0; - } else { - set_corpsenm(otmp, classmon(tt->plrole, (tt->plgend[0] == 'F'))); - otmp = oname(otmp, tt->name); + tt = NULL; } (void) fclose(rfile); + return tt; +} + + +/* + * Attach random player name and class from high score list + * to an object (for statues or morgue corpses). + */ +struct obj * +tt_oname(otmp) +struct obj *otmp; +{ + struct toptenentry *tt; + if (!otmp) + return (struct obj *) 0; + + tt = get_rnd_toptenentry(); + + if (!tt) + return (struct obj *) 0; + + set_corpsenm(otmp, classmon(tt->plrole, (tt->plgend[0] == 'F'))); + otmp = oname(otmp, tt->name); + return otmp; } From ff30a56e3eb96089dd2d56e1cc4dc7264c1add84 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Mon, 28 Dec 2015 19:56:20 +0200 Subject: [PATCH 21/31] Add config file examples to Guidebook --- doc/Guidebook.mn | 23 +++++++++++++++++++++-- doc/Guidebook.tex | 26 ++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index e20efeb9c..0656e2f63 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -1947,8 +1947,27 @@ option. There is a section of this Guidebook that discusses that. .pg The default name of the configuration file varies on different -operating systems, but NETHACKOPTIONS can also be set to -the full name of a file you want to use (possibly preceded by an `@'). +operating systems. On DOS and Windows, it is ``defaults.nh'' +in the same folder as nethack.exe or nethackW.exe. On Unix, linux +and Mac OS X it is ``.nethackrc'' in the user's home directory. +NETHACKOPTIONS can also be set to the full name of a file you +want to use (possibly preceded by an `@'). +.pg +Here is a short example of config file contents: +.sd +\fB# Set your character's role, race, gender, and alignment.\fP +\fBOPTIONS=role:Valkyrie, race:Human, gender:female, align:lawful\fP + +\fB# Turn on autopickup, and set automatically picked up object types\fP +\fBOPTIONS=autopickup,pickup_types:$"=/!?+\fP +\fB# Show colored text if possible\fP +\fBOPTIONS=color\fP +\fB# Show lit corridors differently\fP +\fBOPTIONS=lit_corridor\fP + +\fB# No startup splash screen. Windows GUI only.\fP +\fBOPTIONS=!splash_screen\fP +.ed .hn 2 Customization options .pg diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index a2e3e0a55..5ccc9bdef 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -2346,8 +2346,30 @@ There is a section of this Guidebook that discusses that. %.pg The default name of the configuration file varies on different -operating systems, but NETHACKOPTIONS can also be set to -the full name of a file you want to use (possibly preceded by an `{\tt @}'). +operating systems. On DOS and Windows, it is ``{\tt defaults.nh}'' +in the same folder as nethack.exe or nethackW.exe. On Unix, linux +and Mac OS X it is ``{\tt.nethackrc}'' in the user's home directory. +NETHACKOPTIONS can also be set to the full name of a file you +want to use (possibly preceded by an `{\tt @}'). + +%.pg +Here is a short example of config file contents: +%.sd +\begin{verbatim} + # Set your character's role, race, gender, and alignment. + OPTIONS=role:Valkyrie, race:Human, gender:female, align:lawful + + # Turn on autopickup, and set automatically picked up object types + OPTIONS=autopickup,pickup_types:$"=/!?+ + # Show colored text if possible + OPTIONS=color + # Show lit corridors differently + OPTIONS=lit_corridor + + # No startup splash screen. Windows GUI only. + OPTIONS=!splash_screen +\end{verbatim} +%.ed %.hn 2 \subsection*{Customization options} From 901317f57c5b2b65a99c0d23d3e1183c7213c7ea Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 28 Dec 2015 14:35:23 -0800 Subject: [PATCH 22/31] force TIMED_DELAY for OSX Outputing extra characters to induce a delay is useless on OSX, so set TIMED_DELAY by default instead of relying on user to do it. --- doc/fixes36.1 | 2 ++ include/unixconf.h | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index f3881c599..5f2f61fcd 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -88,6 +88,8 @@ win32gui: getversionstring() was overflowing the provided Help About buffer win32gui: guard against buffer overflow in in mswin_getlin() MacOSX: initial binary release was built from out of date source code that had 'BETA' and 'DEBUG' inappropriately enabled +MacOSX: force TIMED_DELAY build option on so that 'runmode' run-time option + is functional X11: core bug for '`' (backtick) command was only noticed by X11 interface, which issued impossible message "add_menu: called before start_menu" diff --git a/include/unixconf.h b/include/unixconf.h index 0447b8295..bc6984eec 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 unixconf.h $NHDT-Date: 1447755973 2015/11/17 10:26:13 $ $NHDT-Branch: master $:$NHDT-Revision: 1.24 $ */ +/* NetHack 3.6 unixconf.h $NHDT-Date: 1451342112 2015/12/28 22:35:12 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.25 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -130,6 +130,9 @@ */ /* #define TIMED_DELAY */ /* usleep() */ #endif +#if defined(MACOSX) && !defined(TIMED_DELAY) +#define TIMED_DELAY +#endif /* * If you define MAIL, then the player will be notified of new mail From a05826d06d810dc56afa45c534626f4fba281f87 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 28 Dec 2015 15:10:22 -0800 Subject: [PATCH 23/31] occupation vs running Noticed while testing a potential change to running while confused: when confusion timed out, I kept running even though I was headed in the wrong direction. Timeout calls stop_occupation() but running is not an occupation. Make stop_occupation() also stop counted activity under control of the player (ie, multi > 0). Some places in the code use both stop_occuation() and nomul(0), some just use one or the other. But most of those probably intend for both. --- src/allmain.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/allmain.c b/src/allmain.c index 02fa6480f..9f4329143 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 allmain.c $NHDT-Date: 1450231173 2015/12/16 01:59:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.67 $ */ +/* NetHack 3.6 allmain.c $NHDT-Date: 1451344214 2015/12/28 23:10:14 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.68 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -296,10 +296,7 @@ boolean resuming; change = 2; if (change && !Unchanging) { if (multi >= 0) { - if (occupation) - stop_occupation(); - else - nomul(0); + stop_occupation(); if (change == 1) polyself(0); else @@ -491,6 +488,8 @@ stop_occupation() context.botl = 1; /* in case u.uhs changed */ nomul(0); pushch(0); + } else if (multi >= 0) { + nomul(0); } } From 0c2443ebd07b6f3d27c8566628c173eaed937e23 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 28 Dec 2015 17:32:31 -0800 Subject: [PATCH 24/31] fix 'blind sink behavior' Reported directly to devteam: teleporting or polymorphing a sink when dropping the relevant ring into it was suppressed if the hero couldn't see it happen. Being unable to see the sink transform or vanish shouldn't stop that from happening. Since the hero is known to not be levitating (because of the sink), it can be assumed that he can feel the transformation or vanishment (is that a real word?), so use the same messages regardless of blindness. --- doc/fixes36.1 | 2 ++ src/do.c | 44 +++++++++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 5f2f61fcd..9b33f06c8 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -70,6 +70,8 @@ use alternate rejection message if attempting to name an unnameable monster cockatrice corpse no longer leaves multiple statues for shape-shifted vampire alter name of monster causing hero's death if name contains characters that could cause confusion when using record, logfile, or xlogfile later +teleporting or polymorphing a sink via ring drop shouldn't depend upon being + able to see it happen Platform- and/or Interface-Specific Fixes diff --git a/src/do.c b/src/do.c index 2081016a4..c5030f73a 100644 --- a/src/do.c +++ b/src/do.c @@ -270,6 +270,8 @@ register struct obj *obj; STATIC_DCL void polymorph_sink() { + uchar sym = S_sink; + if (levl[u.ux][u.uy].typ != SINK) return; @@ -278,24 +280,33 @@ polymorph_sink() switch (rn2(4)) { default: case 0: + sym = S_fountain; levl[u.ux][u.uy].typ = FOUNTAIN; level.flags.nfountains++; break; case 1: + sym = S_throne; levl[u.ux][u.uy].typ = THRONE; break; case 2: + sym = S_altar; levl[u.ux][u.uy].typ = ALTAR; levl[u.ux][u.uy].altarmask = Align2amask(rn2((int) A_LAWFUL + 2) - 1); break; case 3: + sym = S_room; levl[u.ux][u.uy].typ = ROOM; make_grave(u.ux, u.uy, (char *) 0); + if (levl[u.ux][u.uy].typ == GRAVE) + sym = S_grave; break; } - pline_The("sink transforms into %s!", (levl[u.ux][u.uy].typ == THRONE) - ? "a throne" - : an(surface(u.ux, u.uy))); + /* give message even if blind; we know we're not levitating, + so can feel the outcome even if we can't directly see it */ + if (levl[u.ux][u.uy].typ != ROOM) + pline_The("sink transforms into %s!", an(defsyms[sym].explanation)); + else + pline_The("sink vanishes."); newsym(u.ux, u.uy); } @@ -407,11 +418,24 @@ register struct obj *obj; /* Not the same as aggravate monster; besides, it's obvious. */ pline("Several flies buzz around the sink."); break; + case RIN_TELEPORTATION: + nosink = teleport_sink(); + /* give message even if blind; we know we're not levitating, + so can feel the outcome even if we can't directly see it */ + pline_The("sink %svanishes.", nosink ? "" : "momentarily "); + ideed = FALSE; + break; + case RIN_POLYMORPH: + polymorph_sink(); + nosink = TRUE; + /* for S_room case, same message as for teleportation is given */ + ideed = (levl[u.ux][u.uy].typ != ROOM); + break; default: ideed = FALSE; break; } - if (!Blind && !ideed && obj->otyp != RIN_HUNGER) { + if (!Blind && !ideed) { ideed = TRUE; switch (obj->otyp) { /* effects that need eyes */ case RIN_ADORNMENT: @@ -449,20 +473,14 @@ register struct obj *obj; case RIN_WARNING: pline_The("sink glows %s for a moment.", hcolor(NH_WHITE)); break; - case RIN_TELEPORTATION: - nosink = teleport_sink(); - pline_The("sink %svanishes.", nosink ? "" : "momentarily "); - break; case RIN_TELEPORT_CONTROL: pline_The("sink looks like it is being beamed aboard somewhere."); break; - case RIN_POLYMORPH: - polymorph_sink(); - nosink = TRUE; - break; case RIN_POLYMORPH_CONTROL: pline_The( - "sink momentarily looks like a regularly erupting geyser."); + "sink momentarily looks like a regularly erupting geyser."); + break; + default: break; } } From 5834ace82358d0f9e957394d8399ce57a7662821 Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 29 Dec 2015 15:09:50 -0800 Subject: [PATCH 25/31] fix 'doterrain menu bug' From a report sent directly to devteam: the #terrain command had the same bug as the '`' command (which was one of the very first ones reported): impossible("add_menu called before start_menu"). Only X11 notices. --- doc/fixes36.1 | 4 ++-- src/cmd.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 9b33f06c8..5465960ad 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -92,8 +92,8 @@ MacOSX: initial binary release was built from out of date source code that had 'BETA' and 'DEBUG' inappropriately enabled MacOSX: force TIMED_DELAY build option on so that 'runmode' run-time option is functional -X11: core bug for '`' (backtick) command was only noticed by X11 interface, - which issued impossible message "add_menu: called before start_menu" +X11: core bug for '`' (backtick) and #terrain commands was only noticed by + X11 interface: impossible "add_menu: called before start_menu" General New Features diff --git a/src/cmd.c b/src/cmd.c index 51fd17f70..191ab71f3 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1176,6 +1176,7 @@ doterrain(VOID_ARGS) * a legend for the levl[][].typ codes dump */ men = create_nhwindow(NHW_MENU); + start_menu(men); any = zeroany; any.a_int = 1; add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE, From 5964438e8fd1467d36ceb8b0008f4b55d8799a50 Mon Sep 17 00:00:00 2001 From: nhmall Date: Tue, 29 Dec 2015 21:21:05 -0500 Subject: [PATCH 26/31] use explicit int sizes in win/share/tile2bin.c 64-bit longs caused tile2bin to write an invalid bmp file. --- win/share/tile2bmp.c | 71 ++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/win/share/tile2bmp.c b/win/share/tile2bmp.c index 00bc76ab9..7a6c736a4 100644 --- a/win/share/tile2bmp.c +++ b/win/share/tile2bmp.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 tile2bmp.c $NHDT-Date: 1431192770 2015/05/09 17:32:50 $ $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */ +/* NetHack 3.6 tile2bmp.c $NHDT-Date: 1451442061 2015/12/30 02:21:01 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $ */ /* Copyright (c) NetHack PC Development Team 1995 */ /* NetHack may be freely redistributed. See license for details. */ @@ -18,6 +18,21 @@ #include "win32api.h" #endif +#include +#if defined(UINT32_MAX) && defined(INT32_MAX) && defined(UINT16_MAX) +#define UINT8 uint8_t +#define UINT16 uint16_t +#define UINT32 uint32_t +#define INT32 int32_t +#else +# ifdef _MSC_VER +#define UINT8 unsigned char +#define UINT16 unsigned short +#define UINT32 unsigned long +#define INT32 long +# endif +#endif + #if (TILE_X == 32) #define COLORS_IN_USE 256 #else @@ -61,8 +76,8 @@ leshort(short x) #endif } -static long -lelong(long x) +static INT32 +lelong(INT32 x) { #ifdef __BIG_ENDIAN__ return ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) @@ -74,37 +89,35 @@ lelong(long x) #ifdef __GNUC__ typedef struct tagBMIH { - unsigned long biSize; - long biWidth; - long biHeight; - unsigned short biPlanes; - unsigned short biBitCount; - unsigned long biCompression; - unsigned long biSizeImage; - long biXPelsPerMeter; - long biYPelsPerMeter; - unsigned long biClrUsed; - unsigned long biClrImportant; + UINT32 biSize; + INT32 biWidth; + INT32 biHeight; + UINT16 biPlanes; + UINT16 biBitCount; + UINT32 biCompression; + UINT32 biSizeImage; + INT32 biXPelsPerMeter; + INT32 biYPelsPerMeter; + UINT32 biClrUsed; + UINT32 biClrImportant; } PACK BITMAPINFOHEADER; typedef struct tagBMFH { - unsigned short bfType; - unsigned long bfSize; - unsigned short bfReserved1; - unsigned short bfReserved2; - unsigned long bfOffBits; + UINT16 bfType; + UINT32 bfSize; + UINT16 bfReserved1; + UINT16 bfReserved2; + UINT32 bfOffBits; } PACK BITMAPFILEHEADER; typedef struct tagRGBQ { - unsigned char rgbBlue; - unsigned char rgbGreen; - unsigned char rgbRed; - unsigned char rgbReserved; + UINT8 rgbBlue; + UINT8 rgbGreen; + UINT8 rgbRed; + UINT8 rgbReserved; } PACK RGBQUAD; -#define UINT unsigned int -#define DWORD unsigned long -#define LONG long -#define WORD unsigned short +#define DWORD UINT32 +#define WORD UINT16 #define BI_RGB 0L #define BI_RLE8 1L #define BI_RLE4 2L @@ -256,8 +269,8 @@ BITMAPFILEHEADER *pbmfh; { pbmfh->bfType = leshort(0x4D42); pbmfh->bfSize = lelong(BMPFILESIZE); - pbmfh->bfReserved1 = (UINT) 0; - pbmfh->bfReserved2 = (UINT) 0; + pbmfh->bfReserved1 = (UINT32) 0; + pbmfh->bfReserved2 = (UINT32) 0; pbmfh->bfOffBits = lelong(sizeof(bmp.bmfh) + sizeof(bmp.bmih) + (RGBQUAD_COUNT * sizeof(RGBQUAD))); } From da0876482e7778d63c4ed359aca14d1c1ed61556 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 30 Dec 2015 02:33:42 -0800 Subject: [PATCH 27/31] fix #H4147 - "unlockable chest" desc is misleading Change "unlockable" to "broken" so that it won't be misunderstood to mean "capable of being unlocked". The accompanying suggestion to omit "broken" unless/until a lock or unlock attempt is made is no good since the main reason for describing the broken lock is to avoid unnecessary attempts to lock or unlock a container that the hero knows to be broken but the player may have forgotten. I also changed remote look-at for objects to use distant_name(doname) instead of distant_name(xname) so that qualifiers like "empty" and "broken" will show up on chests you've investigated before but aren't standing on now. Monster type for corpse also gets shown, instead of just 'food (corpse)'. Other remote items will become more verbose, but only those that the hero has already seen up close. --- doc/fixes36.1 | 3 +++ src/objnam.c | 5 ++++- src/pager.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 5465960ad..0ae0d278d 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -72,6 +72,9 @@ alter name of monster causing hero's death if name contains characters that could cause confusion when using record, logfile, or xlogfile later teleporting or polymorphing a sink via ring drop shouldn't depend upon being able to see it happen +change "unlockable chest" to "broken chest" so that it won't be misunderstood + ("capable of being unlocked" vs intended "not capable of being locked") +use doname instead of xname when using '/' or ';' to look at objects on map Platform- and/or Interface-Specific Fixes diff --git a/src/objnam.c b/src/objnam.c index e6ca04521..8c94eed15 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -828,7 +828,10 @@ boolean with_price; if (lknown && Is_box(obj)) { if (obj->obroken) - Strcat(prefix, "unlockable "); + /* 3.6.0 used "unlockable" here but that could be misunderstood + to mean "capable of being unlocked" rather than the intended + "not capable of being locked" */ + Strcat(prefix, "broken "); else if (obj->olocked) Strcat(prefix, "locked "); else diff --git a/src/pager.c b/src/pager.c index 0664bef5e..8157bce8e 100644 --- a/src/pager.c +++ b/src/pager.c @@ -127,7 +127,7 @@ int x, y, glyph; if (otmp) { Strcpy(buf, (otmp->otyp != STRANGE_OBJECT) - ? distant_name(otmp, xname) + ? distant_name(otmp, doname) : obj_descr[STRANGE_OBJECT].oc_name); if (fakeobj) dealloc_obj(otmp), otmp = 0; From e29c21f367a60048fc7592c5f2d8eb877e998501 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Wed, 30 Dec 2015 17:29:44 +0200 Subject: [PATCH 28/31] Tiny formatting fix --- include/obj.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/obj.h b/include/obj.h index eacbd42d3..f2acaf80e 100644 --- a/include/obj.h +++ b/include/obj.h @@ -95,9 +95,7 @@ struct obj { Bitfield(recharged, 3); /* number of times it's been recharged */ #define on_ice recharged /* corpse on ice */ Bitfield(lamplit, 1); /* a light-source -- can be lit */ - Bitfield( - globby, - 1); /* globby; will combine with like types on adjacent squares */ + Bitfield(globby, 1); /* combines with like types on adjacent squares */ Bitfield(greased, 1); /* covered with grease */ Bitfield(nomerge, 1); /* set temporarily to prevent merging */ Bitfield(was_thrown, 1); /* thrown by hero since last picked up */ From 7be8e1f8bb0fe47df3e62788f02583d3f4874fcb Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Wed, 30 Dec 2015 17:41:48 +0200 Subject: [PATCH 29/31] Another tiny formatting fix --- include/global.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/global.h b/include/global.h index 2674c92b7..0a4c76ac5 100644 --- a/include/global.h +++ b/include/global.h @@ -318,9 +318,7 @@ struct savefile_info { #define PL_NSIZ 32 /* name of player, ghost, shopkeeper */ #define PL_CSIZ 32 /* sizeof pl_character */ #define PL_FSIZ 32 /* fruit name */ -#define PL_PSIZ \ - 63 /* player-given names for pets, other \ - * monsters, objects */ +#define PL_PSIZ 63 /* player-given names for pets, other monsters, objects */ #define MAXDUNGEON 16 /* current maximum number of dungeons */ #define MAXLEVEL 32 /* max number of levels in one dungeon */ From a236f9d5f664e9043c2d964c750e57c5a6cc9980 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 30 Dec 2015 23:38:11 -0800 Subject: [PATCH 30/31] fix bz265 - accessibility fix for reluctant pet Requested by a blind player. The message "Fido moves only reluctantly" didn't convey enough information to be useful. Describe the reason why the move is reluctant: "Fido steps reluctantly over ." If there is a pile, it will describe the top item rather than whichever cursed item the pet doesn't want to step on. --- doc/fixes36.1 | 2 ++ src/dogmove.c | 39 ++++++++++++++++++++++++++------------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 0ae0d278d..35bbf53c2 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -75,6 +75,8 @@ teleporting or polymorphing a sink via ring drop shouldn't depend upon being change "unlockable chest" to "broken chest" so that it won't be misunderstood ("capable of being unlocked" vs intended "not capable of being locked") use doname instead of xname when using '/' or ';' to look at objects on map +when a pet moves reluctantly, name the top item of the pile it is reluctant + to step on if the hero sees or remembers any object(s) at that spot Platform- and/or Interface-Specific Fixes diff --git a/src/dogmove.c b/src/dogmove.c index 472e3e416..34fa4a2cd 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -405,9 +405,10 @@ int udist; omx = mtmp->mx; omy = mtmp->my; - /* if we are carrying something then we drop it (perhaps near @) */ - /* Note: if apport == 1 then our behaviour is independent of udist */ - /* Use udist+1 so steed won't cause divide by zero */ + /* If we are carrying something then we drop it (perhaps near @). + * Note: if apport == 1 then our behaviour is independent of udist. + * Use udist+1 so steed won't cause divide by zero. + */ if (droppables(mtmp)) { if (!rn2(udist + 1) || !rn2(edog->apport)) if (rn2(10) < edog->apport) { @@ -459,7 +460,7 @@ int udist; return 0; } -/* set dog's goal -- gtyp, gx, gy +/* set dog's goal -- gtyp, gx, gy; returns -1/0/1 (dog's desire to approach player) or -2 (abort move) */ STATIC_OVL int dog_goal(mtmp, edog, after, udist, whappr) @@ -613,7 +614,7 @@ int after, udist, whappr; int dog_move(mtmp, after) register struct monst *mtmp; -register int after; /* this is extra fast monster movement */ +int after; /* this is extra fast monster movement */ { int omx, omy; /* original mtmp position */ int appr, whappr, udist; @@ -794,6 +795,7 @@ register int after; /* this is extra fast monster movement */ && better_with_displacing && !undesirable_disp(mtmp, nx, ny)) { int mstatus; register struct monst *mtmp2 = m_at(nx, ny); + mstatus = mdisplacem(mtmp, mtmp2, FALSE); /* displace monster */ if (mstatus & MM_DEF_DIED) return 2; @@ -814,12 +816,13 @@ register int after; /* this is extra fast monster movement */ if (mtmp->mleashed) { if (!Deaf) whimper(mtmp); - } else + } else { /* 1/40 chance of stepping on it anyway, in case * it has to pass one to follow the player... */ if (trap->tseen && rn2(40)) - continue; + continue; + } } } @@ -827,9 +830,9 @@ register int after; /* this is extra fast monster movement */ /* (minion isn't interested; `cursemsg' stays FALSE) */ if (has_edog) for (obj = level.objects[nx][ny]; obj; obj = obj->nexthere) { - if (obj->cursed) + if (obj->cursed) { cursemsg[i] = TRUE; - else if ((otyp = dogfood(mtmp, obj)) < MANFOOD + } else if ((otyp = dogfood(mtmp, obj)) < MANFOOD && (otyp < ACCFOOD || edog->hungrytime <= monstermoves)) { /* Note: our dog likes the food so much that he @@ -906,13 +909,23 @@ newdogpos: wasseen = canseemon(mtmp); remove_monster(omx, omy); place_monster(mtmp, nix, niy); - if (cursemsg[chi] && (wasseen || canseemon(mtmp))) - pline("%s moves only reluctantly.", noit_Monnam(mtmp)); + if (cursemsg[chi] && (wasseen || canseemon(mtmp))) { + /* describe top item of pile, not necessarily cursed item itself; + don't use glyph_at() here--it would return the pet but we want + to know whether an object is remembered at this map location */ + struct obj *o = (!Hallucination + && glyph_is_object(levl[nix][niy].glyph)) + ? vobj_at(nix, niy) : 0; + const char *what = o ? distant_name(o, doname) : something; + + pline("%s %s reluctantly over %s.", noit_Monnam(mtmp), + vtense((char *) 0, locomotion(mtmp->data, "step")), what); + } for (j = MTSZ - 1; j > 0; j--) mtmp->mtrack[j] = mtmp->mtrack[j - 1]; mtmp->mtrack[0].x = omx; mtmp->mtrack[0].y = omy; - /* We have to know if the pet's gonna do a combined eat and + /* We have to know if the pet's going to do a combined eat and * move before moving it, but it can't eat until after being * moved. Thus the do_eat flag. */ @@ -1012,7 +1025,7 @@ xchar mx, my, fx, fy; return FALSE; } -/*ARGSUSED*/ /* do_clear_area client */ +/* do_clear_area client */ STATIC_PTR void wantdoor(x, y, distance) int x, y; From fff3425de42d27c766b2a4cdfb8e3583537f30d4 Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 31 Dec 2015 17:26:25 -0500 Subject: [PATCH 31/31] Happy New Year 2016 Changes to be committed: modified: include/patchlevel.h --- include/patchlevel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/patchlevel.h b/include/patchlevel.h index c0aa090a5..0d2828ffc 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 patchlevel.h $NHDT-Date: 1450306740 2015/12/16 22:59:00 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.115 $ */ +/* NetHack 3.6 patchlevel.h $NHDT-Date: 1451600769 2015/12/31 22:26:09 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.116 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -15,7 +15,7 @@ */ #define EDITLEVEL 0 -#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2015" +#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2016" #define COPYRIGHT_BANNER_B \ " By Stichting Mathematisch Centrum and M. Stephenson." /* COPYRIGHT_BANNER_C is generated by makedefs into date.h */