From 7c64dbaf83a6d05165e725d4a969e9f091a23e2b Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Sat, 10 Feb 2007 05:14:22 +0000 Subject: [PATCH] fix #Q404 - monster wielding cursed corpse From a bug report, applying a bullwhip towards a monster to try to steal its weapon would report that a cursed cockatrice corpse was welded to the monster's hands even though corpses wielded by the player never become welded. Code for monsters deciding what to wield knew that corpses don't weld; everywhere else seems to assume that they only wield weldable weapons. Add a routine to check whether a wielded item is welded, similar to what's done for the hero. I fixed a couple of other spots besides use_whip() but didn't hunt all over. --- doc/fixes34.4 | 1 + include/extern.h | 1 + src/apply.c | 2 +- src/muse.c | 4 +++- src/weapon.c | 12 ++++++------ src/wield.c | 10 ++++++++++ 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/doc/fixes34.4 b/doc/fixes34.4 index 02316e495..6faeacc73 100644 --- a/doc/fixes34.4 +++ b/doc/fixes34.4 @@ -315,6 +315,7 @@ shapechangers who take on mimic or hider form will mimic or hide when feasible avoid War message if tinning a Rider corpse fails prevent long messages from triggering access violation or segmentation fault due to buffer overflow in pline() +cursed corpse wielded by a monster isn't welded to its hand or paw Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index b4cd47610..4a3320078 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2510,6 +2510,7 @@ E int FDECL(chwepon, (struct obj *,int)); E int FDECL(welded, (struct obj *)); E void FDECL(weldmsg, (struct obj *)); E void FDECL(setmnotwielded, (struct monst *,struct obj *)); +E boolean FDECL(mwelded, (struct obj *)); /* ### windows.c ### */ diff --git a/src/apply.c b/src/apply.c index e114a914a..ef080c525 100644 --- a/src/apply.c +++ b/src/apply.c @@ -2397,7 +2397,7 @@ struct obj *obj; mon_hand = 0; /* lint suppression */ You("wrap your bullwhip around %s.", yname(otmp)); - if (gotit && otmp->cursed) { + if (gotit && mwelded(otmp)) { pline("%s welded to %s %s%c", (otmp->quan == 1L) ? "It is" : "They are", mhis(mtmp), mon_hand, diff --git a/src/muse.c b/src/muse.c index f9e96b4a0..a8466ad42 100644 --- a/src/muse.c +++ b/src/muse.c @@ -2210,19 +2210,21 @@ mcould_eat_tin(mon) struct monst *mon; { struct obj *obj, *mwep; + boolean welded_wep; /* monkeys who manage to steal tins can't open and eat them even if they happen to also have the appropriate tool */ if (is_animal(mon->data)) return FALSE; mwep = MON_WEP(mon); + welded_wep = mwep && mwelded(mwep); /* this is different from the player; tin opener or dagger doesn't have to be wielded, and knife can be used instead of dagger (even so, non-nymphs don't pick up tins, so only nymphs might end up being able to benefit from them) */ for (obj = mon->minvent; obj; obj = obj->nobj) { /* if stuck with a cursed weapon, don't check rest of inventory */ - if (mwep && mwep->cursed && obj != mwep) continue; + if (welded_wep && obj != mwep) continue; if (obj->otyp == TIN_OPENER || (obj->oclass == WEAPON_CLASS && diff --git a/src/weapon.c b/src/weapon.c index cc148852f..1127d0ddd 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)weapon.c 3.5 2006/12/14 */ +/* SCCS Id: @(#)weapon.c 3.5 2007/02/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -458,7 +458,7 @@ register struct monst *mtmp; case P_CROSSBOW: propellor = (oselect(mtmp, CROSSBOW)); } - if ((otmp = MON_WEP(mtmp)) && otmp->cursed && otmp != propellor + if ((otmp = MON_WEP(mtmp)) && mwelded(otmp) && otmp != propellor && mtmp->weapon_check == NO_WEAPON_WANTED) propellor = 0; } @@ -474,7 +474,7 @@ register struct monst *mtmp; if (rwep[i] != LOADSTONE) { /* Don't throw a cursed weapon-in-hand or an artifact */ if ((otmp = oselect(mtmp, rwep[i])) && !otmp->oartifact - && (!otmp->cursed || otmp != MON_WEP(mtmp))) + && !(otmp == MON_WEP(mtmp) && mwelded(otmp))) return(otmp); } else for(otmp=mtmp->minvent; otmp; otmp=otmp->nobj) { if (otmp->otyp == LOADSTONE && !otmp->cursed) @@ -592,7 +592,7 @@ boolean polyspot; * polymorphed into little monster. But it's not quite clear how to * handle this anyway.... */ - if (!(mw_tmp->cursed && mon->weapon_check == NO_WEAPON_WANTED)) + if (!(mwelded(mw_tmp) && mon->weapon_check == NO_WEAPON_WANTED)) mon->weapon_check = NEED_WEAPON; return; } @@ -653,7 +653,7 @@ register struct monst *mon; * can know it's cursed and needn't even bother trying. * Still.... */ - if (mw_tmp && mw_tmp->cursed && mw_tmp->otyp != CORPSE) { + if (mw_tmp && mwelded(mw_tmp)) { if (canseemon(mon)) { char welded_buf[BUFSZ]; const char *mon_hand = mbodypart(mon, HAND); @@ -684,7 +684,7 @@ register struct monst *mon; mon->weapon_check = NEED_WEAPON; if (canseemon(mon)) { pline("%s wields %s!", Monnam(mon), doname(obj)); - if (obj->cursed && obj->otyp != CORPSE) { + if (mwelded(mw_tmp)) { pline("%s %s to %s %s!", Tobjnam(obj, "weld"), is_plural(obj) ? "themselves" : "itself", diff --git a/src/wield.c b/src/wield.c index 3a4883e0a..c0ac03192 100644 --- a/src/wield.c +++ b/src/wield.c @@ -855,4 +855,14 @@ register struct obj *obj; obj->owornmask = savewornmask; } +/* test whether monster's wielded weapon is stuck to hand/paw/whatever */ +boolean +mwelded(obj) +struct obj *obj; +{ + /* caller is responsible for making sure this is a monster's item */ + if (obj && (obj->owornmask & W_WEP) && will_weld(obj)) return TRUE; + return FALSE; +} + /*wield.c*/