fix github issue #401 - roast/rust/rot in peace

This tries to fix the problem of the extra message when a tame
golem is completely destroyed (paper or straw golem burned, iron
golem rusted, wood or leather golem rotted) being issued at odd
times.  I basically punted on the visibility aspect since the
original logic was strange:  you had to be able to see both the
attacker's and defender's spots and at least one of those two
monsters.  Now mon-attacks-mon visibility requires that you be
able to see one of the two and if you don't see both, the unseen
one will be referred to as "it".  The "may the iron golem rust
in peace" message is independent of that and may be displayed
after "you have a sad feeling", but now that's intentional and
will refer to an unseen pet by name or monster type, not "it".

This needs a lot of testing and hasn't attempted to address
issue #402:  only some attacks that should compeletely destroy
a golem actually do so.  (So a hit by fire elemental against a
paper golem does, but passive fire counterattack when a paper
golem hits a fire elemental doesn't, nor does a wand of fire
or being hit by Firebrand.)

Fixes #401
This commit is contained in:
PatR
2020-11-27 02:38:17 -08:00
parent 8d91a9f764
commit bb9df368af
7 changed files with 65 additions and 44 deletions

View File

@@ -1,4 +1,4 @@
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.364 $ $NHDT-Date: 1606385979 2020/11/26 10:19:39 $
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.365 $ $NHDT-Date: 1606473484 2020/11/27 10:38:04 $
General Fixes and Modified Features
-----------------------------------
@@ -311,6 +311,7 @@ wizard mode (only way to get timed flying): if levitation and flying time out
throwing or kicking a shop container (that's light enough to move) made the
hero pay for any gold inside, then didn't refund that amount if the
container landed inside the shop
try to fix message sequencing for tame golems that "roast/rot/rust in peace"
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 mondata.h $NHDT-Date: 1596498548 2020/08/03 23:49:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.44 $ */
/* NetHack 3.7 mondata.h $NHDT-Date: 1606473485 2020/11/27 10:38:05 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.45 $ */
/* Copyright (c) 1989 Mike Threepoint */
/* NetHack may be freely redistributed. See license for details. */
@@ -224,9 +224,12 @@
#define nonliving(ptr) \
(is_undead(ptr) || (ptr) == &mons[PM_MANES] || weirdnonliving(ptr))
/* no corpse (ie, blank scrolls) if killed by fire */
/* no corpse (ie, blank scrolls) if killed by fire; special case instakill */
#define completelyburns(ptr) \
((ptr) == &mons[PM_PAPER_GOLEM] || (ptr) == &mons[PM_STRAW_GOLEM])
#define completelyrots(ptr) \
((ptr) == &mons[PM_WOOD_GOLEM] || (ptr) == &mons[PM_LEATHER_GOLEM])
#define completelyrusts(ptr) ((ptr) == &mons[PM_IRON_GOLEM])
/* Used for conduct with corpses, tins, and digestion attacks */
/* G_NOCORPSE monsters might still be swallowed as a purple worm */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 mhitm.c $NHDT-Date: 1596498178 2020/08/03 23:42:58 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.140 $ */
/* NetHack 3.7 mhitm.c $NHDT-Date: 1606473486 2020/11/27 10:38:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.144 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -335,8 +335,8 @@ register struct monst *magr, *mdef;
tmp++;
/* Set up the visibility of action */
g.vis = (cansee(magr->mx, magr->my) && cansee(mdef->mx, mdef->my)
&& (canspotmon(magr) || canspotmon(mdef)));
g.vis = ((cansee(magr->mx, magr->my) && canspotmon(magr))
|| (cansee(mdef->mx, mdef->my) && canspotmon(mdef)));
/* Set flag indicating monster has moved this turn. Necessary since a
* monster might get an attack out of sequence (i.e. before its move) in
@@ -369,7 +369,7 @@ register struct monst *magr, *mdef;
/* D: Do a ranged attack here! */
strike = thrwmm(magr, mdef);
if (strike)
/* We don't really know if we hit or not; pretend we did. */
/* don't really know if we hit or not; pretend we did */
res[i] |= MM_HIT;
if (DEADMONSTER(mdef))
res[i] = MM_DEF_DIED;
@@ -1024,11 +1024,9 @@ int dieroll;
if (completelyburns(pd)) { /* paper golem or straw golem */
if (g.vis && canseemon(mdef))
pline("%s burns completely!", Monnam(mdef));
mondead(mdef); /* was mondied() but that dropped paper scrolls */
monkilled(mdef, (char *) 0, AD_FIRE);
if (!DEADMONSTER(mdef))
return 0;
else if (mdef->mtame && !g.vis)
pline("May %s roast in peace.", mon_nam(mdef));
return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
}
tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
@@ -1100,14 +1098,12 @@ int dieroll;
case AD_RUST:
if (magr->mcan)
break;
if (pd == &mons[PM_IRON_GOLEM]) {
if (completelyrusts(pd)) { /* PM_IRON_GOLEM */
if (g.vis && canseemon(mdef))
pline("%s falls to pieces!", Monnam(mdef));
mondied(mdef);
monkilled(mdef, (char *) 0, AD_RUST);
if (!DEADMONSTER(mdef))
return 0;
else if (mdef->mtame && !g.vis)
pline("May %s rust in peace.", mon_nam(mdef));
return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
}
erode_armor(mdef, ERODE_RUST);
@@ -1124,14 +1120,12 @@ int dieroll;
case AD_DCAY:
if (magr->mcan)
break;
if (pd == &mons[PM_WOOD_GOLEM] || pd == &mons[PM_LEATHER_GOLEM]) {
if (completelyrots(pd)) { /* PM_WOOD_GOLEM || PM_LEATHER_GOLEM */
if (g.vis && canseemon(mdef))
pline("%s falls to pieces!", Monnam(mdef));
mondied(mdef);
monkilled(mdef, (char *) 0, AD_DCAY);
if (!DEADMONSTER(mdef))
return 0;
else if (mdef->mtame && !g.vis)
pline("May %s rot in peace.", mon_nam(mdef));
return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
}
erode_armor(mdef, ERODE_CORRODE);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 mhitu.c $NHDT-Date: 1596498179 2020/08/03 23:42:59 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.194 $ */
/* NetHack 3.7 mhitu.c $NHDT-Date: 1606473488 2020/11/27 10:38:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.196 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1490,7 +1490,7 @@ register struct attack *mattk;
hitmsg(mtmp, mattk);
if (mtmp->mcan)
break;
if (u.umonnum == PM_IRON_GOLEM) {
if (completelyrusts(g.youmonst.data)) {
You("rust!");
/* KMH -- this is okay with unchanging */
rehumanize();
@@ -1508,7 +1508,7 @@ register struct attack *mattk;
hitmsg(mtmp, mattk);
if (mtmp->mcan)
break;
if (u.umonnum == PM_WOOD_GOLEM || u.umonnum == PM_LEATHER_GOLEM) {
if (completelyrots(g.youmonst.data)) {
You("rot!");
/* KMH -- this is okay with unchanging */
rehumanize();

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 mon.c $NHDT-Date: 1604880454 2020/11/09 00:07:34 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.351 $ */
/* NetHack 3.7 mon.c $NHDT-Date: 1606473489 2020/11/27 10:38:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.354 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2582,20 +2582,39 @@ struct monst *mdef;
const char *fltxt;
int how;
{
if ((mdef->wormno ? worm_known(mdef) : cansee(mdef->mx, mdef->my))
&& fltxt)
struct permonst *mptr = mdef->data;
if (fltxt && (mdef->wormno ? worm_known(mdef)
: cansee(mdef->mx, mdef->my)))
pline("%s is %s%s%s!", Monnam(mdef),
nonliving(mdef->data) ? "destroyed" : "killed",
nonliving(mptr) ? "destroyed" : "killed",
*fltxt ? " by the " : "", fltxt);
else
/* sad feeling is deferred until after potential life-saving */
iflags.sad_feeling = (mdef->mtame != 0);
/* no corpses if digested or disintegrated */
g.disintegested = (how == AD_DGST || how == -AD_RBRE);
/* no corpse if digested or disintegrated or flammable golem burnt up;
no corpse for a paper golem means no scrolls; golems that rust or
rot completely are described as "falling to pieces" so they do
leave a corpse (which means staves for wood golem, leather armor for
leather golem, iron chains for iron golem, not a regular corpse) */
g.disintegested = (how == AD_DGST || how == -AD_RBRE
|| (how == AD_FIRE && completelyburns(mptr)));
if (g.disintegested)
mondead(mdef);
mondead(mdef); /* never leaves a corpse */
else
mondied(mdef);
mondied(mdef); /* calls mondead() and maybe leaves a corpse */
/* extra message if pet golem is completely destroyed;
if not visible, this will follow "you have a sad feeling" */
if (mdef->mtame) {
const char *rxt = (how == AD_FIRE && completelyburns(mptr)) ? "roast"
: (how == AD_RUST && completelyrusts(mptr)) ? "rust"
: (how == AD_DCAY && completelyrots(mptr)) ? "rot"
: 0;
if (rxt)
pline("May %s %s in peace.", noit_mon_nam(mdef), rxt);
}
}
void

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 mondata.c $NHDT-Date: 1603507386 2020/10/24 02:43:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.86 $ */
/* NetHack 3.7 mondata.c $NHDT-Date: 1606473489 2020/11/27 10:38:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.87 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -509,7 +509,7 @@ int
max_passive_dmg(mdef, magr)
register struct monst *mdef, *magr;
{
int i, dmg = 0, multi2 = 0;
int i, dmg, multi2 = 0;
uchar adtyp;
/* each attack by magr can result in passive damage */
@@ -531,25 +531,29 @@ register struct monst *mdef, *magr;
break;
}
dmg = 0;
for (i = 0; i < NATTK; i++)
if (mdef->data->mattk[i].aatyp == AT_NONE
|| mdef->data->mattk[i].aatyp == AT_BOOM) {
adtyp = mdef->data->mattk[i].adtyp;
if ((adtyp == AD_ACID && !resists_acid(magr))
|| (adtyp == AD_COLD && !resists_cold(magr))
|| (adtyp == AD_FIRE && !resists_fire(magr))
|| (adtyp == AD_ELEC && !resists_elec(magr))
|| adtyp == AD_PHYS) {
if ((adtyp == AD_FIRE && completelyburns(magr->data))
|| (adtyp == AD_DCAY && completelyrots(magr->data))
|| (adtyp == AD_RUST && completelyrusts(magr->data))) {
dmg = magr->mhp;
} else if ((adtyp == AD_ACID && !resists_acid(magr))
|| (adtyp == AD_COLD && !resists_cold(magr))
|| (adtyp == AD_FIRE && !resists_fire(magr))
|| (adtyp == AD_ELEC && !resists_elec(magr))
|| adtyp == AD_PHYS) {
dmg = mdef->data->mattk[i].damn;
if (!dmg)
dmg = mdef->data->mlevel + 1;
dmg *= mdef->data->mattk[i].damd;
} else
dmg = 0;
return dmg * multi2;
}
dmg *= multi2;
break;
}
return 0;
return dmg;
}
/* determine whether two monster types are from the same species */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 uhitm.c $NHDT-Date: 1604880456 2020/11/09 00:07:36 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.242 $ */
/* NetHack 3.7 uhitm.c $NHDT-Date: 1606473490 2020/11/27 10:38:10 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.243 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1935,7 +1935,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */
}
break;
case AD_RUST:
if (pd == &mons[PM_IRON_GOLEM]) {
if (completelyrusts(pd)) { /* iron golem */
pline("%s falls to pieces!", Monnam(mdef));
xkilled(mdef, XKILL_NOMSG);
}
@@ -1947,7 +1947,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */
tmp = 0;
break;
case AD_DCAY:
if (pd == &mons[PM_WOOD_GOLEM] || pd == &mons[PM_LEATHER_GOLEM]) {
if (completelyrots(pd)) { /* wood golem or leather golem */
pline("%s falls to pieces!", Monnam(mdef));
xkilled(mdef, XKILL_NOMSG);
}