static boolean can_reach_location(struct monst *, coordxy, coordxy, coordxy,
coordxy);
static boolean could_reach_item(struct monst *, coordxy, coordxy);
-static void quickmimic(struct monst *);
/* pick a carried item for pet to drop */
struct obj *
boolean devour)
{
register struct edog *edog = EDOG(mtmp);
- boolean poly, grow, heal, eyes, slimer, deadmimic;
- int nutrit, res, corpsenm;
+ int nutrit, res;
long oprice;
char objnambuf[BUFSZ], *obj_name;
edog->hungrytime = gm.moves;
nutrit = dog_nutrition(mtmp, obj);
- deadmimic = (obj->otyp == CORPSE && (obj->corpsenm == PM_SMALL_MIMIC
- || obj->corpsenm == PM_LARGE_MIMIC
- || obj->corpsenm == PM_GIANT_MIMIC));
- slimer = (obj->otyp == GLOB_OF_GREEN_SLIME);
- poly = polyfodder(obj);
- grow = mlevelgain(obj);
- heal = mhealup(obj);
- eyes = (obj->otyp == CARROT);
- corpsenm = (obj->otyp == CORPSE ? obj->corpsenm : NON_PM);
-
if (devour) {
if (mtmp->meating > 1)
mtmp->meating /= 2;
Strcpy(objnambuf, xname(obj));
iflags.suppress_price--;
}
- /* some monsters that eat items could eat a container with contents */
- if (Has_contents(obj))
- meatbox(mtmp, obj);
- /* It's a reward if it's DOGFOOD and the player dropped/threw it.
- We know the player had it if invlet is set. -dlc */
- if (dogfood(mtmp, obj) == DOGFOOD && obj->invlet)
- edog->apport += (int) (200L / ((long) edog->dropdist + gm.moves
- - edog->droptime));
if (mtmp->data == &mons[PM_RUST_MONSTER] && obj->oerodeproof) {
/* The object's rustproofing is gone now */
if (obj->unpaid)
pline("%s spits %s out in disgust!",
Monnam(mtmp), obj_name);
}
- } else if (obj == uball) {
- unpunish();
- delobj(obj); /* we assume this can't be unpaid */
- } else if (obj == uchain) {
- unpunish();
} else {
+ /* It's a reward if it's DOGFOOD and the player dropped/threw it.
+ We know the player had it if invlet is set. -dlc */
+ if (dogfood(mtmp, obj) == DOGFOOD && obj->invlet)
+ edog->apport += (int) (200L / ((long) edog->dropdist + gm.moves
+ - edog->droptime));
+ m_consume_obj(mtmp, obj);
if (obj->unpaid) {
/* edible item owned by shop has been thrown or kicked
by hero and caught by tame or food-tameable monst */
oprice = unpaid_cost(obj, TRUE);
pline("That %s will cost you %ld %s.", objnambuf, oprice,
currency(oprice));
- /* delobj->obfree will handle actual shop billing update */
+ /* m_consume_obj->delobj->obfree will handle actual shop billing update */
}
- delobj(obj);
- }
-
-#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 (DEADMONSTER(mtmp))
- 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,
- cansee(mtmp->mx, mtmp->my) ? NC_SHOW_MSG : 0);
}
- /* limit "instant" growth to prevent potential abuse */
- if (grow && (int) mtmp->m_lev < (int) mtmp->data->mlevel + 15) {
- if (!grow_up(mtmp, (struct monst *) 0))
- return 2;
- }
- if (heal)
- mtmp->mhp = mtmp->mhpmax;
- if ((eyes || heal) && !mtmp->mcansee)
- mcureblindness(mtmp, canseemon(mtmp));
- if (deadmimic)
- quickmimic(mtmp);
- if (corpsenm != NON_PM)
- mon_givit(mtmp, &mons[corpsenm]);
- return 1;
+ return (DEADMONSTER(mtmp)) ? 2 : 1;
}
static void
}
}
-static void
+void
quickmimic(struct monst *mtmp)
{
int idx = 0, trycnt = 5, spotted, seeloc;
(ofood(obj) && (touch_petrifies(&mons[(obj)->corpsenm]) \
|| (obj)->corpsenm == PM_MEDUSA))
+/* monster consumes an object.
+
+ monster may die, polymorph, grow up, heal, etc; meating is not changed.
+ object is extracted from any linked list and freed. */
+void
+m_consume_obj(struct monst *mtmp, struct obj *otmp)
+{
+ boolean ispet = mtmp->mtame;
+
+ /* non-pet: Heal up to the object's weight in hp */
+ if (!ispet && mtmp->mhp < mtmp->mhpmax) {
+ mtmp->mhp += objects[otmp->otyp].oc_weight;
+ if (mtmp->mhp > mtmp->mhpmax)
+ mtmp->mhp = mtmp->mhpmax;
+ }
+ if (Has_contents(otmp))
+ meatbox(mtmp, otmp);
+ if (otmp == uball) {
+ unpunish();
+ delobj(otmp);
+ } else if (otmp == uchain) {
+ unpunish(); /* frees uchain */
+ } else {
+ boolean deadmimic, slimer;
+ int poly, grow, heal, eyes, mstone, vis = canseemon(mtmp);
+ int corpsenm = (otmp->otyp == CORPSE ? otmp->corpsenm : NON_PM);
+
+ deadmimic = (otmp->otyp == CORPSE && (otmp->corpsenm == PM_SMALL_MIMIC
+ || otmp->corpsenm == PM_LARGE_MIMIC
+ || otmp->corpsenm == PM_GIANT_MIMIC));
+ slimer = (otmp->otyp == GLOB_OF_GREEN_SLIME);
+ poly = polyfodder(otmp);
+ grow = mlevelgain(otmp);
+ heal = mhealup(otmp);
+ eyes = (otmp->otyp == CARROT);
+ mstone = mstoning(otmp);
+ delobj(otmp); /* munch */
+ if (poly || slimer) {
+ struct permonst *ptr = slimer ? &mons[PM_GREEN_SLIME] : 0;
+
+ (void) newcham(mtmp, ptr, vis ? NC_SHOW_MSG : NO_NC_FLAGS);
+ }
+ if (grow) {
+ if ((ispet && (int) mtmp->m_lev < (int) mtmp->data->mlevel + 15)
+ || !ispet)
+ (void) grow_up(mtmp, (struct monst *) 0);
+ }
+ if (mstone) {
+ if (poly_when_stoned(mtmp->data)) {
+ mon_to_stone(mtmp);
+ } else if (!resists_ston(mtmp)) {
+ if (vis)
+ pline("%s turns to stone!", Monnam(mtmp));
+ monstone(mtmp);
+ }
+ }
+ if (heal)
+ mtmp->mhp = mtmp->mhpmax;
+ if ((eyes || heal) && !mtmp->mcansee)
+ mcureblindness(mtmp, canseemon(mtmp));
+ if (ispet && deadmimic)
+ quickmimic(mtmp);
+ if (corpsenm != NON_PM)
+ mon_givit(mtmp, &mons[corpsenm]);
+ }
+}
+
/*
* Maybe eat a metallic object (not just gold).
* Return value: 0 => nothing happened, 1 => monster ate something,
meatmetal(struct monst *mtmp)
{
struct obj *otmp;
- struct permonst *ptr;
char *otmpname;
- int poly, grow, heal, mstone, vis = canseemon(mtmp);
+ int vis = canseemon(mtmp);
/* If a pet, eating is handled separately, in dog.c */
if (mtmp->mtame)
}
}
mtmp->meating = otmp->owt / 2 + 1;
- /* Heal up to the object's weight in hp */
- if (mtmp->mhp < mtmp->mhpmax) {
- mtmp->mhp += objects[otmp->otyp].oc_weight;
- if (mtmp->mhp > mtmp->mhpmax)
- mtmp->mhp = mtmp->mhpmax;
- }
- /* Currently there shouldn't be any metal object with
- contents, but just in case... */
- if (Has_contents(otmp))
- meatbox(mtmp, otmp);
- if (otmp == uball) {
- unpunish();
- delobj(otmp);
- } else if (otmp == uchain) {
- unpunish(); /* frees uchain */
- } else {
- /* these can occur via eating metal if it's a tin
- [can't be slimed; that could only happen via glob] */
- poly = polyfodder(otmp);
- grow = mlevelgain(otmp);
- heal = mhealup(otmp);
- mstone = mstoning(otmp);
- delobj(otmp);
- ptr = mtmp->data;
- if (poly) {
- if (newcham(mtmp, (struct permonst *) 0,
- vis ? NC_SHOW_MSG : NO_NC_FLAGS))
- ptr = mtmp->data;
- } else if (grow) {
- ptr = grow_up(mtmp, (struct monst *) 0);
- } else if (mstone) {
- if (poly_when_stoned(ptr)) {
- mon_to_stone(mtmp);
- ptr = mtmp->data;
- } else if (!resists_ston(mtmp)) {
- if (vis)
- pline("%s turns to stone!", Monnam(mtmp));
- monstone(mtmp);
- /* might be life-saved if had a previous shape
- which was capable to putting on an amulet */
- if (DEADMONSTER(mtmp))
- ptr = (struct permonst *) 0;
- }
- } else if (heal) {
- mtmp->mhp = mtmp->mhpmax;
- mcureblindness(mtmp, canseemon(mtmp));
- }
- if (!ptr)
- return 2; /* it died */
- }
+ m_consume_obj(mtmp, otmp);
+ if (DEADMONSTER(mtmp))
+ return 2;
/* Left behind a pile? */
if (rnd(25) < 3)
(void) mksobj_at(ROCK, mtmp->mx, mtmp->my, TRUE, FALSE);
{
struct obj *otmp, *otmp2;
struct permonst *ptr, *original_ptr = mtmp->data;
- int poly, grow, heal, eyes, count = 0, ecount = 0, vis = canseemon(mtmp);
+ int count = 0, ecount = 0;
char buf[BUFSZ], *otmpname;
buf[0] = '\0';
if (otmp->oclass == SCROLL_CLASS
&& objdescr_is(otmp, "YUM YUM"))
pline("Yum%c", otmp->blessed ? '!' : '.');
- if (otmp->otyp == CORPSE)
- mon_givit(mtmp, &mons[otmp->corpsenm]);
} else {
Soundeffect(se_slurping_sound, 30);
if (Verbose(2, meatobj2))
You_hear("a slurping sound.");
}
- /* Heal up to the object's weight in hp */
- if (mtmp->mhp < mtmp->mhpmax) {
- mtmp->mhp += objects[otmp->otyp].oc_weight;
- if (mtmp->mhp > mtmp->mhpmax)
- mtmp->mhp = mtmp->mhpmax;
- }
- if (Has_contents(otmp))
- meatbox(mtmp, otmp);
- /* possibility of being turned to stone or into slime can't
- reach here (don't touch for cockatrice corpse, engulf rather
- than eat for tin, cockatrice egg, or glob of green slime) */
- poly = polyfodder(otmp);
- grow = mlevelgain(otmp);
- heal = mhealup(otmp);
- eyes = (otmp->otyp == CARROT);
- delobj(otmp); /* munch */
- ptr = mtmp->data;
- if (poly) {
- if (newcham(mtmp, (struct permonst *) 0,
- vis ? NC_SHOW_MSG : NO_NC_FLAGS))
- ptr = mtmp->data;
- } else if (grow) {
- ptr = grow_up(mtmp, (struct monst *) 0);
- } else if (heal) {
- mtmp->mhp = mtmp->mhpmax;
- }
- if ((eyes || heal) && !mtmp->mcansee)
- mcureblindness(mtmp, canseemon(mtmp));
+ m_consume_obj(mtmp, otmp);
/* in case it polymorphed or died */
+ ptr = mtmp->data;
if (ptr != original_ptr)
return !ptr ? 2 : 1;
}
{
struct obj *otmp;
struct permonst *ptr, *original_ptr = mtmp->data, *corpsepm;
- boolean poly, grow, heal, eyes = FALSE, vis = canseemon(mtmp);
coordxy x = mtmp->mx, y = mtmp->my;
/* if a pet, eating is handled separately, in dog.c */
You_hear("a masticating sound.");
}
- mon_givit(mtmp, &mons[otmp->corpsenm]);
-
- /* [should include quickmimic but can't handle that unless this
- gets changed to set mtmp->meating] */
- poly = polyfodder(otmp);
- grow = mlevelgain(otmp);
- heal = mhealup(otmp);
- eyes = (otmp->otyp == CARROT); /*[always false since not a corpse]*/
- ptr = original_ptr;
- delobj(otmp);
- if (poly) {
- if (newcham(mtmp, (struct permonst *) 0,
- vis ? NC_SHOW_MSG : NO_NC_FLAGS))
- ptr = mtmp->data;
- } else if (grow) {
- ptr = grow_up(mtmp, (struct monst *) 0);
- } else if (heal) {
- mtmp->mhp = mtmp->mhpmax;
- }
- if ((eyes || heal) && !mtmp->mcansee)
- mcureblindness(mtmp, canseemon(mtmp));
+ m_consume_obj(mtmp, otmp);
/* in case it polymorphed or died */
+ ptr = mtmp->data;
if (ptr != original_ptr)
return !ptr ? 2 : 1;