monster eating (1 of 2)
Move the recently adopted swallower-eats-dropped-corpse code into a separate routine to unclutter dropz(). Eat all corpses (also globs and meatball/meat ring/meat stick/huge chunk of meat) rather than just the few types which trigger special effects (polymorph, turn to stone, etc). Also guard against using a freed pointer if somehow a dropped edible item merges with an existing inventory item (something carried prior to shape change perhaps?) before having the worm eat it.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
/* NetHack 3.6 do.c $NHDT-Date: 1586815086 2020/04/13 21:58:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.237 $ */
|
/* NetHack 3.6 do.c $NHDT-Date: 1588191740 2020/04/29 20:22:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.243 $ */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/*-Copyright (c) Derek S. Ray, 2015. */
|
/*-Copyright (c) Derek S. Ray, 2015. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
@@ -12,6 +12,7 @@ static void NDECL(polymorph_sink);
|
|||||||
static boolean NDECL(teleport_sink);
|
static boolean NDECL(teleport_sink);
|
||||||
static void FDECL(dosinkring, (struct obj *));
|
static void FDECL(dosinkring, (struct obj *));
|
||||||
static int FDECL(drop, (struct obj *));
|
static int FDECL(drop, (struct obj *));
|
||||||
|
static boolean FDECL(engulfer_digests_food, (struct obj *));
|
||||||
static int NDECL(wipeoff);
|
static int NDECL(wipeoff);
|
||||||
static int FDECL(menu_drop, (int));
|
static int FDECL(menu_drop, (int));
|
||||||
static NHFILE *NDECL(currentlevel_rewrite);
|
static NHFILE *NDECL(currentlevel_rewrite);
|
||||||
@@ -705,46 +706,15 @@ boolean with_impact;
|
|||||||
|
|
||||||
if (!u.uswallow && flooreffects(obj, u.ux, u.uy, "drop"))
|
if (!u.uswallow && flooreffects(obj, u.ux, u.uy, "drop"))
|
||||||
return;
|
return;
|
||||||
/* uswallow check done by GAN 01/29/87 */
|
|
||||||
if (u.uswallow) {
|
if (u.uswallow) {
|
||||||
boolean could_petrify = FALSE;
|
/* hero has dropped an item while inside an engulfer */
|
||||||
boolean could_poly = FALSE;
|
|
||||||
boolean could_slime = FALSE;
|
|
||||||
boolean could_grow = FALSE;
|
|
||||||
boolean could_heal = FALSE;
|
|
||||||
|
|
||||||
if (obj != uball) { /* mon doesn't pick up ball */
|
if (obj != uball) { /* mon doesn't pick up ball */
|
||||||
if (obj->otyp == CORPSE) {
|
/* moving shop item into engulfer's inventory treated as theft */
|
||||||
could_petrify = touch_petrifies(&mons[obj->corpsenm]);
|
|
||||||
could_poly = polyfodder(obj);
|
|
||||||
could_grow = (obj->corpsenm == PM_WRAITH);
|
|
||||||
could_heal = (obj->corpsenm == PM_NURSE);
|
|
||||||
} else if (obj->otyp == GLOB_OF_GREEN_SLIME) {
|
|
||||||
could_slime = TRUE;
|
|
||||||
}
|
|
||||||
if (is_unpaid(obj))
|
if (is_unpaid(obj))
|
||||||
(void) stolen_value(obj, u.ux, u.uy, TRUE, FALSE);
|
(void) stolen_value(obj, u.ux, u.uy, TRUE, FALSE);
|
||||||
(void) mpickobj(u.ustuck, obj);
|
/* add to engulfer's inventory if not immediately eaten */
|
||||||
if (is_animal(u.ustuck->data)) {
|
if (!engulfer_digests_food(obj))
|
||||||
if (could_poly || could_slime) {
|
(void) mpickobj(u.ustuck, obj);
|
||||||
(void) newcham(u.ustuck,
|
|
||||||
could_poly ? (struct permonst *) 0
|
|
||||||
: &mons[PM_GREEN_SLIME],
|
|
||||||
FALSE, could_slime);
|
|
||||||
delobj(obj); /* corpse or glob is digested */
|
|
||||||
} else if (could_petrify) {
|
|
||||||
minstapetrify(u.ustuck, TRUE);
|
|
||||||
/* Don't leave a cockatrice corpse in a statue */
|
|
||||||
if (!u.uswallow)
|
|
||||||
delobj(obj);
|
|
||||||
} else if (could_grow) {
|
|
||||||
(void) grow_up(u.ustuck, (struct monst *) 0);
|
|
||||||
delobj(obj); /* corpse is digested */
|
|
||||||
} else if (could_heal) {
|
|
||||||
u.ustuck->mhp = u.ustuck->mhpmax;
|
|
||||||
delobj(obj); /* corpse is digested */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
place_object(obj, u.ux, u.uy);
|
place_object(obj, u.ux, u.uy);
|
||||||
@@ -761,6 +731,52 @@ boolean with_impact;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* when swallowed, move dropped object from OBJ_FREE to u.ustuck's inventory;
|
||||||
|
for purple worm, immediately eat any corpse, glob, or special meat item
|
||||||
|
from object polymorph; return True if object is used up, False otherwise */
|
||||||
|
static boolean
|
||||||
|
engulfer_digests_food(obj)
|
||||||
|
struct obj *obj;
|
||||||
|
{
|
||||||
|
/* animal swallower (purple worn, trapper, lurker above) eats any
|
||||||
|
corpse, glob, or meat <item> but not other types of food */
|
||||||
|
if (is_animal(u.ustuck->data)
|
||||||
|
&& (obj->otyp == CORPSE || obj->globby
|
||||||
|
|| obj->otyp == MEATBALL || obj->otyp == HUGE_CHUNK_OF_MEAT
|
||||||
|
|| obj->otyp == MEAT_RING || obj->otyp == MEAT_STICK)) {
|
||||||
|
boolean could_petrify = FALSE,
|
||||||
|
could_poly = FALSE, could_slime = FALSE,
|
||||||
|
could_grow = FALSE, could_heal = FALSE;
|
||||||
|
|
||||||
|
if (obj->otyp == CORPSE) {
|
||||||
|
could_petrify = touch_petrifies(&mons[obj->corpsenm]);
|
||||||
|
could_poly = polyfodder(obj);
|
||||||
|
could_grow = (obj->corpsenm == PM_WRAITH);
|
||||||
|
could_heal = (obj->corpsenm == PM_NURSE);
|
||||||
|
} else if (obj->otyp == GLOB_OF_GREEN_SLIME) {
|
||||||
|
could_slime = TRUE;
|
||||||
|
}
|
||||||
|
/* see or feel the effect */
|
||||||
|
pline("%s instantly digested!", Tobjnam(obj, "are"));
|
||||||
|
|
||||||
|
if (could_poly || could_slime) {
|
||||||
|
(void) newcham(u.ustuck, could_slime ? &mons[PM_GREEN_SLIME] : 0,
|
||||||
|
FALSE, could_slime);
|
||||||
|
} else if (could_petrify) {
|
||||||
|
minstapetrify(u.ustuck, TRUE);
|
||||||
|
} else if (could_grow) {
|
||||||
|
(void) grow_up(u.ustuck, (struct monst *) 0);
|
||||||
|
} else if (could_heal) {
|
||||||
|
u.ustuck->mhp = u.ustuck->mhpmax;
|
||||||
|
/* False: don't realize that sight is cured from inside */
|
||||||
|
mcureblindness(u.ustuck, FALSE);
|
||||||
|
}
|
||||||
|
delobj(obj); /* always used up */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* things that must change when not held; recurse into containers.
|
/* things that must change when not held; recurse into containers.
|
||||||
Called for both player and monsters */
|
Called for both player and monsters */
|
||||||
void
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user