diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 0ede291cc..60815050a 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -291,6 +291,7 @@ if breaking a wand of polymorph causes hero to drop items, don't transform them give "shuddering vibrations" feedback if breaking a poly wand uses up items if polymorph causes a monster to drop items, they won't be used up via shuddering vibrations or as golem creation fodder +monsters who ate green slime corpses weren't turned into green slime Platform- and/or Interface-Specific Fixes diff --git a/src/dog.c b/src/dog.c index 5fd97fb93..9c8099fd4 100644 --- a/src/dog.c +++ b/src/dog.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dog.c 3.5 2007/03/02 */ +/* SCCS Id: @(#)dog.c 3.5 2008/10/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -727,6 +727,10 @@ register struct obj *obj; (acidic(fptr) && !resists_acid(mon)) || (poisonous(fptr) && !resists_poison(mon))) return POISON; + /* turning into slime is preferrable to starvation */ + else if (fptr == &mons[PM_GREEN_SLIME] && + !slimeproof(mon->data)) + return (starving ? ACCFOOD : POISON); else if (vegan(fptr)) return (herbi ? CADAVER : MANFOOD); /* most humanoids will avoid cannibalism unless starving; diff --git a/src/dogmove.c b/src/dogmove.c index 5d1149033..300023cb0 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dogmove.c 3.5 2007/08/20 */ +/* SCCS Id: @(#)dogmove.c 3.5 2008/10/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -200,7 +200,7 @@ int x, y; /* dog's starting location, might be different from current */ boolean devour; { register struct edog *edog = EDOG(mtmp); - boolean poly = FALSE, grow = FALSE, heal = FALSE, deadmimic; + boolean poly, grow, heal, slimer, deadmimic; int nutrit; long oprice; char objnambuf[BUFSZ]; @@ -214,10 +214,11 @@ boolean devour; (obj->corpsenm == PM_SMALL_MIMIC || obj->corpsenm == PM_LARGE_MIMIC || obj->corpsenm == PM_GIANT_MIMIC)); - + slimer = (obj->otyp == CORPSE && obj->corpsenm == PM_GREEN_SLIME); poly = polyfodder(obj); grow = mlevelgain(obj); heal = mhealup(obj); + if (devour) { if (mtmp->meating > 1) mtmp->meating /= 2; if (nutrit > 1) nutrit = (nutrit * 3) / 4; @@ -300,9 +301,19 @@ boolean devour; delobj(obj); } - if (poly) { - (void) newcham(mtmp, (struct permonst *)0, FALSE, - cansee(mtmp->mx, mtmp->my)); +#if 0 /* pet is eating, so slime recovery is not feasible... */ + /* turning into slime might be cureable */ + if (slimer && munslime(mtmp, FALSE)) { + /* but the cure (fire directed at self) might be fatal */ + if (mtmp->mhp < 1) return 2; + slimer = FALSE; /* sliming is avoided, skip polymorph */ + } +#endif + + if (poly || slimer) { + struct permonst *ptr = slimer ? &mons[PM_GREEN_SLIME] : 0; + + (void) newcham(mtmp, ptr, FALSE, cansee(mtmp->mx, mtmp->my)); } /* limit "instant" growth to prevent potential abuse */ diff --git a/src/mon.c b/src/mon.c index e89447d0a..96a8fc135 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mon.c 3.5 2008/02/07 */ +/* SCCS Id: @(#)mon.c 3.5 2008/10/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -697,12 +697,13 @@ meatmetal(mtmp) return 0; } +/* monster eats a pile of objects */ int meatobj(mtmp) /* for gelatinous cubes */ register struct monst *mtmp; { register struct obj *otmp, *otmp2; - struct permonst *ptr; + struct permonst *ptr, *original_ptr = mtmp->data; int poly, grow, heal, count = 0, ecount = 0; char buf[BUFSZ]; @@ -710,18 +711,56 @@ meatobj(mtmp) /* for gelatinous cubes */ /* If a pet, eating is handled separately, in dog.c */ if (mtmp->mtame) return 0; - /* Eats organic objects, including cloth and wood, if there */ - /* Engulfs others, except huge rocks and metal attached to player */ + /* eat organic objects, including cloth and wood, if present; + engulf others, except huge rocks and metal attached to player + [despite comment at top, doesn't assume that eater is a g.cube] */ for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) { otmp2 = otmp->nexthere; - if (is_organic(otmp) && !obj_resists(otmp, 5, 95) && - touch_artifact(otmp,mtmp)) { - if (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]) && - !resists_ston(mtmp)) - continue; - if (otmp->otyp == AMULET_OF_STRANGULATION || - otmp->otyp == RIN_SLOW_DIGESTION) - continue; + + /* touch senstive items */ + if (otmp->otyp == CORPSE && + is_rider(&mons[otmp->corpsenm])) { + /* Rider corpse isn't just inedible; can't engulf it either */ + (void)revive_corpse(otmp); + + /* untouchable (or inaccessible) items */ + } else if ((otmp->otyp == CORPSE && + touch_petrifies(&mons[otmp->corpsenm]) && + !resists_ston(mtmp)) || + /* don't engulf boulders and statues or ball&chain */ + otmp->oclass == ROCK_CLASS || + otmp == uball || otmp == uchain) { + /* do nothing--neither eaten nor engulfed */ + continue; + + /* inedible items -- engulf these */ + } else if (!is_organic(otmp) || + obj_resists(otmp, 5, 95) || + !touch_artifact(otmp, mtmp) || + /* redundant due to non-organic composition but + included for emphasis */ + (otmp->otyp == AMULET_OF_STRANGULATION || + otmp->otyp == RIN_SLOW_DIGESTION) || + /* cockatrice corpses handled above; this + touch_petrifies() check catches eggs */ + ((otmp->otyp == CORPSE || otmp->otyp == EGG) && + ((touch_petrifies(&mons[otmp->corpsenm]) && + !resists_ston(mtmp)) || + (otmp->corpsenm == PM_GREEN_SLIME && + !slimeproof(mtmp->data))))) { + /* engulf */ + ++ecount; + if (ecount == 1) + Sprintf(buf, "%s engulfs %s.", Monnam(mtmp), + distant_name(otmp,doname)); + else if (ecount == 2) + Sprintf(buf, "%s engulfs several objects.", Monnam(mtmp)); + obj_extract_self(otmp); + (void) mpickobj(mtmp, otmp); /* slurp */ + + /* lastly, edible items; yum! */ + } else { + /* devour */ ++count; if (cansee(mtmp->mx,mtmp->my) && flags.verbose) pline("%s eats %s!", Monnam(mtmp), @@ -760,33 +799,19 @@ meatobj(mtmp) /* for gelatinous cubes */ mtmp->mhp = mtmp->mhpmax; } /* in case it polymorphed or died */ - if (ptr != &mons[PM_GELATINOUS_CUBE]) + if (ptr != original_ptr) return !ptr ? 2 : 1; - } else if (otmp->otyp == CORPSE && - is_rider(&mons[otmp->corpsenm])) { - /* Rider corpse will always pass the obj_resists() test above - and not be eaten; we don't want it to be engulfed either */ - (void)revive_corpse(otmp); - /* continue; -- regardless of whether it revived */ - } else if (otmp->oclass != ROCK_CLASS && - otmp != uball && otmp != uchain) { - ++ecount; - if (ecount == 1) { - Sprintf(buf, "%s engulfs %s.", Monnam(mtmp), - distant_name(otmp,doname)); - } else if (ecount == 2) - Sprintf(buf, "%s engulfs several objects.", Monnam(mtmp)); - obj_extract_self(otmp); - (void) mpickobj(mtmp, otmp); /* slurp */ } + /* Engulf & devour is instant, so don't set meating */ if (mtmp->minvis) newsym(mtmp->mx, mtmp->my); } + if (ecount > 0) { if (cansee(mtmp->mx, mtmp->my) && flags.verbose && buf[0]) pline("%s", buf); else if (!Deaf && flags.verbose) - You_hear("%s slurping sound%s.", + You_hear("%s slurping sound%s.", ecount == 1 ? "a" : "several", ecount == 1 ? "" : "s"); }