diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 67d11f665..88a9c2a68 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.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, @@ -411,6 +411,11 @@ 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) +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/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] */ 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])) 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: 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;