From e639c09f58c2f9152428cd3835b25824f131877a Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Fri, 8 Nov 2002 12:45:58 +0000 Subject: [PATCH] fix B14012 - polymorph of monster possessions Forwarded from the newsgroup: when a monster gets hit by wand or spell of polymorph, any armor that fell off was protected from being hit by that same zap, but a dropped weapon wasn't. Nor was the whole dropped inventory in the case where the monster is killed by system shock rather than transformed. Protect its entire inventory. --- doc/fixes34.1 | 2 ++ include/extern.h | 2 +- src/apply.c | 4 ++-- src/bones.c | 1 + src/mhitm.c | 6 +++--- src/mon.c | 4 ++-- src/mthrowu.c | 4 ++-- src/uhitm.c | 4 ++-- src/weapon.c | 30 +++++++++++++++++------------- src/were.c | 4 ++-- src/worn.c | 38 ++++++++++++++++++++++++++------------ src/zap.c | 7 ++++--- 12 files changed, 64 insertions(+), 42 deletions(-) diff --git a/doc/fixes34.1 b/doc/fixes34.1 index 2120876e3..5ed827fed 100644 --- a/doc/fixes34.1 +++ b/doc/fixes34.1 @@ -301,6 +301,8 @@ don't reveal deity name when a high priest(ess) gives temple entry greeting for ordinary remove curse, don't uncurse quivered object unless it is suitable to be used as a quivered weapon (ammo or missile) salamanders have no legs and cannot ride +all objects carried by a monster who's hit by a polymorph zap are protected + from that zap, not just worn armor which falls off due to shape change Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index f97d06de1..0bf4a7a6b 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2187,7 +2187,7 @@ E int FDECL(hitval, (struct obj *,struct monst *)); E int FDECL(dmgval, (struct obj *,struct monst *)); E struct obj *FDECL(select_rwep, (struct monst *)); E struct obj *FDECL(select_hwep, (struct monst *)); -E void FDECL(possibly_unwield, (struct monst *)); +E void FDECL(possibly_unwield, (struct monst *,BOOLEAN_P)); E int FDECL(mon_wield_item, (struct monst *)); E int NDECL(abon); E int NDECL(dbon); diff --git a/src/apply.c b/src/apply.c index 2b6ec335f..82b7a7003 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)apply.c 3.4 2002/09/25 */ +/* SCCS Id: @(#)apply.c 3.4 2002/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2248,7 +2248,7 @@ struct obj *obj; } if (gotit) { obj_extract_self(otmp); - possibly_unwield(mtmp); + possibly_unwield(mtmp, FALSE); setmnotwielded(mtmp,otmp); switch (rn2(proficient + 1)) { diff --git a/src/bones.c b/src/bones.c index b01eb643d..e4bd22837 100644 --- a/src/bones.c +++ b/src/bones.c @@ -201,6 +201,7 @@ struct obj *corpse; /* caller has already checked `can_make_bones()' */ + clear_bypasses(); fd = open_bonesfile(&u.uz, &bonesid); if (fd >= 0) { (void) close(fd); diff --git a/src/mhitm.c b/src/mhitm.c index 593ad5606..5bf713dc5 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mhitm.c 3.4 2002/10/17 */ +/* SCCS Id: @(#)mhitm.c 3.4 2002/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -242,7 +242,7 @@ mattackm(magr, mdef) magr->weapon_check = NEED_HTH_WEAPON; if (mon_wield_item(magr) != 0) return 0; } - possibly_unwield(magr); + possibly_unwield(magr, FALSE); otmp = MON_WEP(magr); if (otmp) { @@ -1011,7 +1011,7 @@ label2: if (mdef->mhp > 0) return 0; pline("%s steals %s from %s!", buf, onambuf, mdefnambuf); } - possibly_unwield(mdef); + possibly_unwield(mdef, FALSE); mdef->mstrategy &= ~STRAT_WAITFORU; mselftouch(mdef, (const char *)0, FALSE); if (mdef->mhp <= 0) diff --git a/src/mon.c b/src/mon.c index c2a51f53e..b2b858be8 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mon.c 3.4 2002/04/06 */ +/* SCCS Id: @(#)mon.c 3.4 2002/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2459,11 +2459,11 @@ boolean msg; /* "The oldmon turns into a newmon!" */ mtmp->mnamelth = save_mnamelth; } + possibly_unwield(mtmp, polyspot); /* might lose use of weapon */ mon_break_armor(mtmp, polyspot); if (!(mtmp->misc_worn_check & W_ARMG)) mselftouch(mtmp, "No longer petrify-resistant, ", !flags.mon_moving); - possibly_unwield(mtmp); m_dowear(mtmp, FALSE); /* This ought to re-test can_carry() on each item in the inventory diff --git a/src/mthrowu.c b/src/mthrowu.c index b2a979aac..e368b0994 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mthrowu.c 3.4 2002/09/08 */ +/* SCCS Id: @(#)mthrowu.c 3.4 2002/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -489,7 +489,7 @@ struct obj *obj; obj->owt = weight(obj); } else { obj_extract_self(obj); - possibly_unwield(mon); + possibly_unwield(mon, FALSE); if (obj->owornmask) { mon->misc_worn_check &= ~obj->owornmask; update_mon_intrinsics(mon, obj, FALSE, FALSE); diff --git a/src/uhitm.c b/src/uhitm.c index 017e11ebd..49880d9aa 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)uhitm.c 3.4 2002/10/17 */ +/* SCCS Id: @(#)uhitm.c 3.4 2002/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1154,7 +1154,7 @@ struct attack *mattk; } /* more take-away handling, after theft message */ if (unwornmask & W_WEP) { /* stole wielded weapon */ - possibly_unwield(mdef); + possibly_unwield(mdef, FALSE); } else if (unwornmask & W_ARMG) { /* stole worn gloves */ mselftouch(mdef, (const char *)0, TRUE); if (mdef->mhp <= 0) /* it's now a statue */ diff --git a/src/weapon.c b/src/weapon.c index 9089f7983..b3ff14ee5 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)weapon.c 3.4 2002/03/22 */ +/* SCCS Id: @(#)weapon.c 3.4 2002/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -527,18 +527,18 @@ register struct monst *mtmp; } /* Called after polymorphing a monster, robbing it, etc.... Monsters - * otherwise never unwield stuff on their own. Shouldn't print messages. + * otherwise never unwield stuff on their own. Might print message. */ void -possibly_unwield(mon) -register struct monst *mon; +possibly_unwield(mon, polyspot) +struct monst *mon; +boolean polyspot; { - register struct obj *obj; - struct obj *mw_tmp; + struct obj *obj, *mw_tmp; if (!(mw_tmp = MON_WEP(mon))) return; - for(obj=mon->minvent; obj; obj=obj->nobj) + for (obj = mon->minvent; obj; obj = obj->nobj) if (obj == mw_tmp) break; if (!obj) { /* The weapon was stolen or destroyed */ MON_NOWEP(mon); @@ -550,13 +550,16 @@ register struct monst *mon; MON_NOWEP(mon); mon->weapon_check = NO_WEAPON_WANTED; obj_extract_self(obj); - /* flooreffects unnecessary, can't wield boulders */ - place_object(obj, mon->mx, mon->my); - stackobj(obj); if (cansee(mon->mx, mon->my)) { - pline("%s drops %s.", Monnam(mon), - distant_name(obj, doname)); - newsym(mon->mx, mon->my); + pline("%s drops %s.", Monnam(mon), + distant_name(obj, doname)); + newsym(mon->mx, mon->my); + } + /* might be dropping object into water or lava */ + if (!flooreffects(obj, mon->mx, mon->my, "drop")) { + if (polyspot) bypass_obj(obj); + place_object(obj, mon->mx, mon->my); + stackobj(obj); } return; } @@ -575,6 +578,7 @@ register struct monst *mon; */ if (!(mw_tmp->cursed && mon->weapon_check == NO_WEAPON_WANTED)) mon->weapon_check = NEED_WEAPON; + return; } /* Let a monster try to wield a weapon, based on mon->weapon_check. diff --git a/src/were.c b/src/were.c index 97c91112b..933fdde32 100644 --- a/src/were.c +++ b/src/were.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)were.c 3.4 1997/05/25 */ +/* SCCS Id: @(#)were.c 3.4 2002/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -83,7 +83,7 @@ register struct monst *mon; mon->mhp += (mon->mhpmax - mon->mhp) / 4; newsym(mon->mx,mon->my); mon_break_armor(mon, FALSE); - possibly_unwield(mon); + possibly_unwield(mon, FALSE); } boolean diff --git a/src/worn.c b/src/worn.c index 1e646aa88..1078d9a9e 100644 --- a/src/worn.c +++ b/src/worn.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)worn.c 3.4 2002/09/08 */ +/* SCCS Id: @(#)worn.c 3.4 2002/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -519,35 +519,49 @@ struct obj *obj; newsym(mon->mx, mon->my); } +/* all objects with their bypass bit set should now be reset to normal */ void clear_bypasses() { struct obj *otmp, *nobj; + struct monst *mtmp; for (otmp = fobj; otmp; otmp = nobj) { nobj = otmp->nobj; if (otmp->bypass) { otmp->bypass = 0; + /* bypass will have inhibited any stacking, but since it's + used for polymorph handling, the objects here probably + have been transformed and won't be stacked in the usual + manner afterwards; so don't bother with this */ #if 0 - /* setting otmp->bypass changes mergability. - * If monster can ever drop anything that - * can and should merge, this code block - * should be enabled. - */ - { + if (otmp->where == OBJ_FLOOR) { struct obj *obj; xchar ox, oy; + (void) get_obj_location(otmp, &ox, &oy, 0); obj_extract_self(otmp); - obj = merge_choice(fobj, otmp); - /* If it can't merge, then place it */ - if (!obj || (obj && !merged(&obj, &otmp))) + obj = merge_choice(level.objects[ox][oy], otmp); + /* if it doesn't merge then place it back */ + if (!obj || !merged(&obj, &otmp)) place_object(otmp, ox, oy); newsym(ox, oy); } -#endif +#endif /*0*/ } } + /* invent and mydogs chains shouldn't matter here */ + for (otmp = migrating_objs; otmp; otmp = otmp->nobj) + otmp->bypass = 0; + for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { + if (DEADMONSTER(mtmp)) continue; + for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) + otmp->bypass = 0; + } + for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) { + for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) + otmp->bypass = 0; + } flags.bypasses = FALSE; } @@ -647,11 +661,11 @@ boolean polyspot; #endif } if (nohands(mdat) || verysmall(mdat)) { + /* [caller needs to handle weapon checks] */ if ((otmp = which_armor(mon, W_ARMG)) != 0) { if (vis) pline("%s drops %s gloves%s!", Monnam(mon), ppronoun, MON_WEP(mon) ? " and weapon" : ""); - possibly_unwield(mon); if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } diff --git a/src/zap.c b/src/zap.c index 00f87fd3e..465834cdf 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)zap.c 3.4 2002/09/08 */ +/* SCCS Id: @(#)zap.c 3.4 2002/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -109,9 +109,7 @@ struct obj *otmp; boolean dbldam = Role_if(PM_KNIGHT) && u.uhave.questart; int dmg, otyp = otmp->otyp; const char *zap_type_text = "spell"; -#ifdef STEED struct obj *obj; -#endif boolean disguised_mimic = (mtmp->data->mlet == S_MIMIC && mtmp->m_ap_type != M_AP_NOTHING); @@ -189,6 +187,9 @@ struct obj *otmp; pline("%s shudders!", Monnam(mtmp)); makeknown(otyp); } + /* dropped inventory shouldn't be hit by this zap */ + for (obj = mtmp->minvent; obj; obj = obj->nobj) + bypass_obj(obj); /* flags.bypasses = TRUE; ## for make_corpse() */ /* no corpse after system shock */ xkilled(mtmp, 3);