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 (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 (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*/