From: nethack.rankin Date: Thu, 13 Apr 2006 07:10:48 +0000 (+0000) Subject: munstone fixes (trunk only) X-Git-Tag: MOVE2GIT~1069 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a157ceae1b74eefd986635ea3c4051182d7f1d18;p=nethack munstone fixes (trunk only) From a bug report, a monster who eats a lizard corpse in order to cure confusion was treated the same as one who did so to cure petrification, losing intrinsic speed in the process. In the same report by , monsters wouldn't eat lizard corpses to cure being stunned, and those who ate them for another reason weren't cured of stunning, even though the hero gets that benefit. While fixing those, I added some code to let monsters who are carrying tins of lizard or acidic monster use them if they're also carrying a tin opener, dagger, or knife. I don't think any monsters except for nymphs are willing to pick up tins, so it won't have much effect. It now works for nymphs though. Examining the code while testing showed that mon_consume_unstone() has been accessing the potion (acid) or corpse (lizard or acidic monster) after the item had been used up, so that has been fixed too. I never saw any detectable problems due to this, but folks using a debugging malloc implementation which overwrites freed memory may have not been suffering collateral acid damage or receiving intended confusion cure, or perhaps did get either or both of those effects when they shouldn't have. Since it only applied to monsters it wouldn't have been easy to observe. --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 6262b4e2c..1c694c3e0 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -136,6 +136,10 @@ preform autopickup and/or report on objects at the spot when a failed #untrap attempt causes the hero to move onto a trap's location thrown silver weapon hitting silver-hating poly'd hero got double silver damage wielded silver weapon hitting silver-hating poly'd hero lacked silver message +monsters who ate lizard corpses to cure confusion would lose intrinsic speed +monsters couldn't eat lizard corpses to cure being stunned +code handling a monster's use of potion or food to cure stoning or confusion + was accessing freed memory after the object had been used up Platform- and/or Interface-Specific Fixes @@ -198,6 +202,7 @@ new effect for reading a scroll of light while confused allow digging an adjacent pit with wand of digging while trapped in a pit #terrain command for debug mode digging can activate or disarm some types of traps +some monsters can eat tins in addition to corpses to cure some ailments Platform- and/or Interface-Specific New Features diff --git a/src/muse.c b/src/muse.c index 9eff95241..157341465 100644 --- a/src/muse.c +++ b/src/muse.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)muse.c 3.5 2006/01/04 */ +/* SCCS Id: @(#)muse.c 3.5 2006/04/11 */ /* Copyright (C) 1990 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -28,6 +28,7 @@ STATIC_DCL void FDECL(mbhit, (struct monst *,int,int FDECL((*),(MONST_P,OBJ_P)), int FDECL((*),(OBJ_P,OBJ_P)),struct obj *)); STATIC_DCL void FDECL(you_aggravate, (struct monst *)); +STATIC_DCL boolean FDECL(mcould_eat_tin, (struct monst *)); STATIC_DCL void FDECL(mon_consume_unstone, (struct monst *,struct obj *, BOOLEAN_P,BOOLEAN_P)); @@ -282,14 +283,25 @@ struct monst *mtmp; } } - if (mtmp->mconf) { - for(obj = mtmp->minvent; obj; obj = obj->nobj) { + if (mtmp->mconf || mtmp->mstun) { + struct obj *liztin = 0; + + for (obj = mtmp->minvent; obj; obj = obj->nobj) { if (obj->otyp == CORPSE && obj->corpsenm == PM_LIZARD) { m.defensive = obj; m.has_defense = MUSE_LIZARD_CORPSE; return TRUE; + } else if (obj->otyp == TIN && obj->corpsenm == PM_LIZARD) { + liztin = obj; } } + /* confused or stunned monster might not be able to open tin */ + if (liztin && mcould_eat_tin(mtmp) && rn2(3)) { + m.defensive = liztin; + /* tin and corpse ultimately end up being handled the same */ + m.has_defense = MUSE_LIZARD_CORPSE; + return TRUE; + } } /* It so happens there are two unrelated cases when we might want to @@ -2107,14 +2119,19 @@ struct monst *mon; boolean by_you; { struct obj *obj; + boolean tinok; if (resists_ston(mon)) return FALSE; if (mon->meating || !mon->mcanmove || mon->msleeping) return FALSE; - for(obj = mon->minvent; obj; obj = obj->nobj) { - /* Monsters can also use potions of acid */ - if ((obj->otyp == POT_ACID) || (obj->otyp == CORPSE && - (obj->corpsenm == PM_LIZARD || (acidic(&mons[obj->corpsenm]) && obj->corpsenm != PM_GREEN_SLIME)))) { + tinok = mcould_eat_tin(mon); + for (obj = mon->minvent; obj; obj = obj->nobj) { + /* monsters can also use potions of acid */ + if (obj->otyp == POT_ACID || + ((obj->otyp == CORPSE || (obj->otyp == TIN && tinok)) && + obj->corpsenm == PM_LIZARD || + (acidic(&mons[obj->corpsenm]) && + obj->corpsenm != PM_GREEN_SLIME))) { mon_consume_unstone(mon, obj, by_you, TRUE); return TRUE; } @@ -2129,46 +2146,54 @@ struct obj *obj; boolean by_you; boolean stoning; { - int nutrit = (obj->otyp == CORPSE) ? dog_nutrition(mon, obj) : 0; - /* also sets meating */ + boolean vis = canseemon(mon), + tinned = obj->otyp == TIN, + food = obj->otyp == CORPSE || tinned, + acid = obj->otyp == POT_ACID || (food && acidic(&mons[obj->corpsenm])), + lizard = food && obj->corpsenm == PM_LIZARD; + int nutrit = food ? dog_nutrition(mon, obj) : 0; /* also sets meating */ /* give a " is slowing down" message and also remove intrinsic speed (comparable to similar effect on the hero) */ - mon_adjust_speed(mon, -3, (struct obj *)0); + if (stoning) mon_adjust_speed(mon, -3, (struct obj *)0); - if (canseemon(mon)) { + if (vis) { long save_quan = obj->quan; obj->quan = 1L; - pline("%s %ss %s.", Monnam(mon), - (obj->otyp == POT_ACID) ? "quaff" : "eat", - distant_name(obj,doname)); + pline("%s %s %s.", Monnam(mon), + (obj->oclass == POTION_CLASS) ? "quaffs" : + (obj->otyp == TIN) ? "opens and eats the contents of" : + "eats", + distant_name(obj, doname)); obj->quan = save_quan; } else if (!Deaf) You_hear("%s.", (obj->otyp == POT_ACID) ? "drinking" : "chewing"); + m_useup(mon, obj); - if (((obj->otyp == POT_ACID) || acidic(&mons[obj->corpsenm])) && - !resists_acid(mon)) { + + if (acid && !tinned && !resists_acid(mon)) { mon->mhp -= rnd(15); - pline("%s has a very bad case of stomach acid.", - Monnam(mon)); - } - if (mon->mhp <= 0) { - pline("%s dies!", Monnam(mon)); - if (by_you) xkilled(mon, 0); - else mondead(mon); - return; + if (vis) + pline("%s has a very bad case of stomach acid.", Monnam(mon)); + if (mon->mhp <= 0) { + pline("%s dies!", Monnam(mon)); + if (by_you) xkilled(mon, 0); + else mondead(mon); + return; + } } - if (stoning && canseemon(mon)) { + if (stoning && vis) { if (Hallucination) - pline("What a pity - %s just ruined a future piece of art!", - mon_nam(mon)); + pline("What a pity - %s just ruined a future piece of art!", + mon_nam(mon)); else pline("%s seems limber!", Monnam(mon)); } - if (obj->otyp == CORPSE && obj->corpsenm == PM_LIZARD && mon->mconf) { + if (lizard && (mon->mconf || mon->mstun)) { mon->mconf = 0; - if (canseemon(mon)) + mon->mstun = 0; + if (vis && !is_bat(mon->data) && mon->data != &mons[PM_STALKER]) pline("%s seems steadier now.", Monnam(mon)); } if (mon->mtame && !mon->isminion && nutrit > 0) { @@ -2181,4 +2206,31 @@ boolean stoning; mon->mlstmv = monstermoves; /* it takes a turn */ } +STATIC_OVL boolean +mcould_eat_tin(mon) +struct monst *mon; +{ + struct obj *obj, *mwep; + + /* 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); + /* 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 (obj->otyp == TIN_OPENER || + (obj->oclass == WEAPON_CLASS && + (objects[obj->otyp].oc_skill == P_DAGGER || + objects[obj->otyp].oc_skill == P_KNIFE))) return TRUE; + } + return FALSE; +} + /*muse.c*/