From 6c84ccc2410921cf07c53867b5c787804e51a561 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 19 Apr 2019 12:28:14 -0700 Subject: [PATCH 1/4] status 'fieldorder' DEC C in one of its non-ANSI modes didn't like fieldorder = test ? &array1 : &array2; It first complained that '&' applied to an array has no effect (which was typically true in pre-ANSI environments) and once those '&'s are ignored, the attempted assignment didn't match the variable's type. That code was actually more complicated that it needed to be; slightly simpler code works as intended. --- win/curses/cursstat.c | 10 +++++----- win/tty/wintty.c | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/win/curses/cursstat.c b/win/curses/cursstat.c index 8b81839fe..68962bf7a 100644 --- a/win/curses/cursstat.c +++ b/win/curses/cursstat.c @@ -287,7 +287,7 @@ boolean border; BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD } }; - const enum statusfields (*fieldorder)[3][15]; + const enum statusfields (*fieldorder)[15]; xchar spacing[MAXBLSTATS], valline[MAXBLSTATS]; enum statusfields fld, prev_fld; char *text, *p, cbuf[BUFSZ], ebuf[STATVAL_WIDTH]; @@ -327,7 +327,7 @@ boolean border; */ number_of_lines = (iflags.wc2_statuslines < 3) ? 2 : 3; - fieldorder = (number_of_lines != 3) ? &twolineorder : &threelineorder; + fieldorder = (number_of_lines != 3) ? twolineorder : threelineorder; cbuf[0] = '\0'; x = y = border ? 1 : 0; /* origin; ignored by curs_stat_conds(0) */ @@ -349,7 +349,7 @@ boolean border; /* simplify testing which fields reside on which lines; assume line #0 */ (void) memset((genericptr_t) valline, 0, sizeof valline); for (j = 1; j < number_of_lines; ++j) - for (i = 0; (fld = (*fieldorder)[j][i]) != BL_FLUSH; ++i) + for (i = 0; (fld = fieldorder[j][i]) != BL_FLUSH; ++i) valline[fld] = j; /* iterate 0 and 1 and maybe 2 for status lines 1 and 2 and maybe 3 */ @@ -360,7 +360,7 @@ boolean border; (void) memset((genericptr_t) spacing, 0, sizeof spacing); w = xtra = 0; /* w: width so far; xtra: number of extra spaces */ prev_fld = BL_FLUSH; - for (i = 0; (fld = (*fieldorder)[j][i]) != BL_FLUSH; ++i) { + for (i = 0; (fld = fieldorder[j][i]) != BL_FLUSH; ++i) { /* when the core marks a field as disabled, it doesn't call status_update() to tell us to throw away the old value, so polymorph leaves stale XP and rehumanize leaves stale HD */ @@ -484,7 +484,7 @@ boolean border; /* second pass for line #j -- render it */ x = y = border ? 1 : 0; wmove(win, y + j, x); - for (i = 0; (fld = (*fieldorder)[j][i]) != BL_FLUSH; ++i) { + for (i = 0; (fld = fieldorder[j][i]) != BL_FLUSH; ++i) { if (!status_activefields[fld]) continue; diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 0e39b90d6..6d03a0ce1 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 wintty.c $NHDT-Date: 1554554181 2019/04/06 12:36:21 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.201 $ */ +/* NetHack 3.6 wintty.c $NHDT-Date: 1555702074 2019/04/19 19:27:54 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.202 $ */ /* Copyright (c) David Cohrs, 1991 */ /* NetHack may be freely redistributed. See license for details. */ @@ -3698,7 +3698,7 @@ static const enum statusfields { BL_LEVELDESC, BL_TIME, BL_CONDITION, BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD } }; -static const enum statusfields (*fieldorder)[3][MAX_PER_ROW]; +static const enum statusfields (*fieldorder)[MAX_PER_ROW]; static int finalx[3][2]; /* [rows][NOW or BEFORE] */ static boolean windowdata_init = FALSE; @@ -3738,7 +3738,7 @@ tty_status_init() int i, num_rows; num_rows = (iflags.wc2_statuslines < 3) ? 2 : 3; - fieldorder = (num_rows != 3) ? &twolineorder : &threelineorder; + fieldorder = (num_rows != 3) ? twolineorder : threelineorder; for (i = 0; i < MAXBLSTATS; ++i) { tty_status[NOW][i].idx = BL_FLUSH; @@ -3876,9 +3876,9 @@ unsigned long *colormasks; /* should be checking for first enabled field here rather than just first field, but 'fieldorder' doesn't start any rows with fields which can be disabled so [any_row][0] suffices */ - if (*fmt == ' ' && (fldidx == (*fieldorder)[0][0] - || fldidx == (*fieldorder)[1][0] - || fldidx == (*fieldorder)[2][0])) + if (*fmt == ' ' && (fldidx == fieldorder[0][0] + || fldidx == fieldorder[1][0] + || fldidx == fieldorder[2][0])) ++fmt; /* skip leading space for first field on line */ Sprintf(status_vals[fldidx], fmt, text); tty_status[NOW][fldidx].idx = fldidx; @@ -4025,7 +4025,7 @@ int sz[3]; sz[row] = 0; col = 1; update_right = FALSE; - for (i = 0; (idx = (*fieldorder)[row][i]) != BL_FLUSH; ++i) { + for (i = 0; (idx = fieldorder[row][i]) != BL_FLUSH; ++i) { if (!status_activefields[idx]) continue; if (!tty_status[NOW][idx].valid) @@ -4328,7 +4328,7 @@ render_status(VOID_ARGS) HUPSKIP(); y = row; tty_curs(WIN_STATUS, 1, y); - for (i = 0; (idx = (*fieldorder)[row][i]) != BL_FLUSH; ++i) { + for (i = 0; (idx = fieldorder[row][i]) != BL_FLUSH; ++i) { if (!status_activefields[idx]) continue; x = tty_status[NOW][idx].x; From edd412e56cc520524d5c6707b0f219a029af909e Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 19 Apr 2019 12:42:35 -0700 Subject: [PATCH 2/4] VMS config1.h Some port of yacc was generating '#include ' before our '#include "config.h" and needed a specific define from config1.h to be supplied on the command line to avoid conflicting contents within that header file, but then config1.h drew complaints about redefining the macro. Guard against that. --- include/config1.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/config1.h b/include/config1.h index ee9e5c921..411cf583b 100644 --- a/include/config1.h +++ b/include/config1.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 config1.h $NHDT-Date: 1552007489 2019/03/08 01:11:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.20 $ */ +/* NetHack 3.6 config1.h $NHDT-Date: 1555702947 2019/04/19 19:42:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.21 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -154,13 +154,15 @@ #define NHSTDC #define USE_STDARG #define POSIX_TYPES -#define _DECC_V4_SOURCE /* avoid some incompatible V5.x changes */ +#ifndef _DECC_V4_SOURCE /* only def here if not already def'd on comd line */ +#define _DECC_V4_SOURCE /* avoid some incompatible V5.x (and later) changes */ #endif +#endif /*__DECC_VER*/ #undef __HIDE_FORBIDDEN_NAMES /* need non-ANSI library support functions */ #ifdef VAXC /* DEC C in VAX C compatibility mode; 'signed' works */ #define signed /* but causes diagnostic about VAX C not supporting it */ #endif -#else +#else /*!__DECC*/ #ifdef VAXC /* must use CC/DEFINE=ANCIENT_VAXC for vaxc v2.2 or older */ #define signed #ifdef ANCIENT_VAXC /* vaxc v2.2 and earlier [lots of warnings to come] */ From ab4625a6bf4d4d5a10968d67396184749b9ba6f2 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 19 Apr 2019 17:32:36 -0700 Subject: [PATCH 3/4] quantum mechanic hits Noticed while trying to find the reason for the wildmiss impossible(), you could be teleported and then drop dead at the destination. A QM's AD_TLPT hit also does 1d4 physical damage which gets applied after the teleport. Getting "You die." seemed pretty strange, particularly after picking the destination with telport control. This makes sure that the damage will never be fatal when teleport is attempted. --- doc/fixes36.2 | 5 ++++- src/mhitm.c | 11 +++++++++-- src/mhitu.c | 37 ++++++++++++++++++++++++++++++++++--- src/uhitm.c | 9 +++++++-- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 67d11f665..09a4b8a71 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.305 $ $NHDT-Date: 1555627306 2019/04/18 22:41:46 $ +$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.306 $ $NHDT-Date: 1555720351 2019/04/20 00:32:31 $ This fixes36.2 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.1 in April 2018. Please note, however, @@ -411,6 +411,9 @@ if a migrating long worm couldn't be placed, or some other monster was given a "trying to place monster at <0,0>" warning would occur if hero throws a pick-axe into a shop and shopkeeper catches it, shk will say "get out of my way, scum" even if there's no monster at pick-axe spot +a quantum mechanic hit that teleported the target could also kill it at the + destination; make sure that the small amount of physical damage isn't + fatal unless the teleport is negated by cancellation (magic or armor) Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/mhitm.c b/src/mhitm.c index 30a569283..3a95815f7 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mhitm.c $NHDT-Date: 1547118629 2019/01/10 11:10:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.112 $ */ +/* NetHack 3.6 mhitm.c $NHDT-Date: 1555720096 2019/04/20 00:28:16 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.113 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1101,6 +1101,7 @@ register struct attack *mattk; if (!cancelled && tmp < mdef->mhp && !tele_restrict(mdef)) { char mdef_Monnam[BUFSZ]; boolean wasseen = canspotmon(mdef); + /* save the name before monster teleports, otherwise we'll get "it" in the suddenly disappears message */ if (vis && wasseen) @@ -1109,6 +1110,11 @@ register struct attack *mattk; (void) rloc(mdef, TRUE); if (vis && wasseen && !canspotmon(mdef) && mdef != u.usteed) pline("%s suddenly disappears!", mdef_Monnam); + if (tmp >= mdef->mhp) { /* see hitmu(mhitu.c) */ + if (mdef->mhp == 1) + ++mdef->mhp; + tmp = mdef->mhp - 1; + } } break; case AD_SLEE: @@ -1356,7 +1362,8 @@ register struct attack *mattk; break; /* physical damage only */ if (!rn2(4) && !slimeproof(pd)) { if (!munslime(mdef, FALSE) && !DEADMONSTER(mdef)) { - if (newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, vis && canseemon(mdef))) + if (newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, + (boolean) (vis && canseemon(mdef)))) pd = mdef->data; mdef->mstrategy &= ~STRAT_WAITFORU; res = MM_HIT; diff --git a/src/mhitu.c b/src/mhitu.c index a981aba5f..25f10b660 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mhitu.c $NHDT-Date: 1547118629 2019/01/10 11:10:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.161 $ */ +/* NetHack 3.6 mhitu.c $NHDT-Date: 1555720104 2019/04/20 00:28:24 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.162 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -925,7 +925,7 @@ register struct attack *mattk; { struct permonst *mdat = mtmp->data; int uncancelled, ptmp; - int dmg, armpro, permdmg; + int dmg, armpro, permdmg, tmphp; char buf[BUFSZ]; struct permonst *olduasmon = youmonst.data; int res; @@ -1400,8 +1400,39 @@ register struct attack *mattk; hitmsg(mtmp, mattk); if (uncancelled) { if (flags.verbose) - Your("position suddenly seems very uncertain!"); + Your("position suddenly seems %suncertain!", + (Teleport_control && !Stunned && !unconscious()) ? "" + : "very "); tele(); + /* 3.6.2: make sure damage isn't fatal; previously, it + was possible to be teleported and then drop dead at + the destination when QM's 1d4 damage gets applied below; + even though that wasn't "wrong", it seemed strange, + particularly if the teleportation had been controlled + [applying the damage first and not teleporting if fatal + is another alternative but it has its own complications] */ + if ((Half_physical_damage ? (dmg - 1) / 2 : dmg) + >= (tmphp = (Upolyd ? u.mh : u.uhp))) { + dmg = tmphp - 1; + if (Half_physical_damage) + dmg *= 2; /* doesn't actually increase damage; we only + * get here if half the original damage would + * would have been fatal, so double reduced + * damage will be less than original damage */ + if (dmg < 1) { /* implies (tmphp <= 1) */ + dmg = 1; + /* this might increase current HP beyond maximum HP but + it will be immediately reduced below, so that should + be indistinguishable from zero damage; we don't drop + damage all the way to zero because that inhibits any + passive counterattack if poly'd hero has one */ + if (Upolyd && u.mh == 1) + ++u.mh; + else if (!Upolyd && u.uhp == 1) + ++u.uhp; + /* [don't set context.botl here] */ + } + } } break; case AD_RUST: diff --git a/src/uhitm.c b/src/uhitm.c index 8ed66e919..a02bc80f4 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 uhitm.c $NHDT-Date: 1553644725 2019/03/26 23:58:45 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.206 $ */ +/* NetHack 3.6 uhitm.c $NHDT-Date: 1555720104 2019/04/20 00:28:24 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.207 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1742,7 +1742,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */ case AD_TLPT: if (tmp <= 0) tmp = 1; - if (!negated && tmp < mdef->mhp) { + if (!negated) { char nambuf[BUFSZ]; boolean u_saw_mon = (canseemon(mdef) || (u.uswallow && u.ustuck == mdef)); @@ -1752,6 +1752,11 @@ int specialdmg; /* blessed and/or silver bonus against various things */ if (u_teleport_mon(mdef, FALSE) && u_saw_mon && !(canseemon(mdef) || (u.uswallow && u.ustuck == mdef))) pline("%s suddenly disappears!", nambuf); + if (tmp >= mdef->mhp) { /* see hitmu(mhitu.c) */ + if (mdef->mhp == 1) + ++mdef->mhp; + tmp = mdef->mhp - 1; + } } break; case AD_BLND: From cd6b5ef93342826cdaf9771ee021c78304ac25b3 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 20 Apr 2019 16:00:29 -0700 Subject: [PATCH 4/4] mimicking a corpse Noticed while looking over mimic hiding. When on an object, a mimic will hide as that type of object. But for a corpse, it picked a random monster type and could choose one that doesn't leave a corpse. Also as a tin it would always be an empty one, but there doesn't seem to be any way for a player to learn that. --- doc/fixes36.2 | 4 +++- src/makemon.c | 25 +++++++++++++++++-------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 09a4b8a71..88a9c2a68 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.306 $ $NHDT-Date: 1555720351 2019/04/20 00:32:31 $ +$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.307 $ $NHDT-Date: 1555801218 2019/04/20 23:00:18 $ This fixes36.2 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.1 in April 2018. Please note, however, @@ -414,6 +414,8 @@ if hero throws a pick-axe into a shop and shopkeeper catches it, shk will say a quantum mechanic hit that teleported the target could also kill it at the destination; make sure that the small amount of physical damage isn't fatal unless the teleport is negated by cancellation (magic or armor) +if a mimic concealed itself as a corpse, it could pick a monster type which + never leaves a corpse Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/makemon.c b/src/makemon.c index 9ec531866..d93b98354 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 makemon.c $NHDT-Date: 1550524560 2019/02/18 21:16:00 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.132 $ */ +/* NetHack 3.6 makemon.c $NHDT-Date: 1555801218 2019/04/20 23:00:18 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.133 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1083,7 +1083,7 @@ coord *cc; } } } else { - gotgood: + gotgood: cc->x = nx; cc->y = ny; return TRUE; @@ -2208,7 +2208,7 @@ register struct monst *mtmp; } } else { s_sym = syms[rn2((int) sizeof(syms))]; - assign_sym: + assign_sym: if (s_sym == MAXOCLASSES || s_sym == MAXOCLASSES + 1) { ap_type = M_AP_FURNITURE; appear = (s_sym == MAXOCLASSES) ? S_upstair : S_dnstair; @@ -2228,12 +2228,21 @@ register struct monst *mtmp; } mtmp->m_ap_type = ap_type; mtmp->mappearance = appear; - if (ap_type == M_AP_OBJECT && (appear == STATUE || appear == CORPSE - || appear == FIGURINE || appear == EGG)) { + /* when appearing as an object based on a monster type, pick a shape */ + if (ap_type == M_AP_OBJECT + && (appear == STATUE || appear == FIGURINE + || appear == CORPSE || appear == EGG || appear == TIN)) { + int mndx = rndmonnum(), + nocorpse_ndx = (mvitals[mndx].mvflags & G_NOCORPSE) != 0; + + if (appear == CORPSE && nocorpse_ndx) + mndx = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1, PM_ARCHEOLOGIST); + else if ((appear == EGG && !can_be_hatched(mndx)) + || (appear == TIN && nocorpse_ndx)) + mndx = NON_PM; /* revert to generic egg or empty tin */ + newmcorpsenm(mtmp); - MCORPSENM(mtmp) = rndmonnum(); - if (appear == EGG && !can_be_hatched(MCORPSENM(mtmp))) - MCORPSENM(mtmp) = NON_PM; /* revert to generic egg */ + MCORPSENM(mtmp) = mndx; } if (does_block(mx, my, &levl[mx][my]))