From 6dc1bbd544f9e3b18bdb96b23110eb1295c34510 Mon Sep 17 00:00:00 2001 From: "nethack.allison" Date: Sun, 11 Apr 2004 18:39:14 +0000 Subject: [PATCH] giant carrying boulder dies while trapped in a pit (trunk only) wrote: > "You kill the invisible storm giant. The boulder fills a pit." > [...] why did I find the corpse *lying on* and not *buried in* the > former pit? Ensure that the corpse ends up buried in that case. --- doc/fixes35.0 | 2 ++ include/extern.h | 2 +- include/hack.h | 5 +++++ src/dog.c | 2 +- src/mklev.c | 2 +- src/mkmaze.c | 2 +- src/mkobj.c | 9 +++++--- src/mon.c | 57 ++++++++++++++++++++++++++++++++++-------------- src/trap.c | 2 +- 9 files changed, 59 insertions(+), 24 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index dd8235f78..4e5255888 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -62,6 +62,8 @@ tripping over a cockatrice corpse didn't petrify, even when not wearing boots do not call swamps on the Juiblex level "moat" when freezing keep score from wrapping around and becoming negative by capping it kicked objects do not slide when on the air or water levels +when a giant carrying a boulder dies in a pit, ensure that the corpse is + buried under the filled pit Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index ff09d477b..8b77c0bec 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1088,7 +1088,7 @@ E int FDECL(bcsign, (struct obj *)); E int FDECL(weight, (struct obj *)); E struct obj *FDECL(mkgold, (long,int,int)); E struct obj *FDECL(mkcorpstat, - (int,struct monst *,struct permonst *,int,int,BOOLEAN_P)); + (int,struct monst *,struct permonst *,int,int,unsigned)); E int FDECL(corpse_revive_type, (struct obj *)); E struct obj *FDECL(obj_attach_mid, (struct obj *, unsigned)); E struct monst *FDECL(get_mtraits, (struct obj *, BOOLEAN_P)); diff --git a/include/hack.h b/include/hack.h index b1677b1f5..26cde3aae 100644 --- a/include/hack.h +++ b/include/hack.h @@ -143,6 +143,11 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */ #define MM_IGNOREWATER 0x80 /* ignore water when positioning */ #define MM_ADJACENTOK 0x100 /* it is acceptable to use adjacent coordinates */ +/* flags for make_corpse() and mkcorpstat() */ +#define CORPSTAT_NONE 0x00 +#define CORPSTAT_INIT 0x01 /* pass init flag to mkcorpstat */ +#define CORPSTAT_BURIED 0x02 /* bury the corpse or statue */ + /* special mhpmax value when loading bones monster to flag as extinct or genocided */ #define DEFUNCT_MONSTER (-100) diff --git a/src/dog.c b/src/dog.c index 0c99ff768..98301e8f7 100644 --- a/src/dog.c +++ b/src/dog.c @@ -379,7 +379,7 @@ boolean with_you; } } corpse = mkcorpstat(CORPSE, (struct monst *)0, mtmp->data, - xlocale, ylocale, FALSE); + xlocale, ylocale, CORPSTAT_NONE); #ifndef GOLDOBJ if (mtmp->mgold) { if (xlocale == 0 && ylocale == 0 && corpse) { diff --git a/src/mklev.c b/src/mklev.c index c1fb7cc2c..60d954924 100644 --- a/src/mklev.c +++ b/src/mklev.c @@ -791,7 +791,7 @@ skip0: if(!rn2(20)) (void) mkcorpstat(STATUE, (struct monst *)0, (struct permonst *)0, - somex(croom), somey(croom), TRUE); + somex(croom), somey(croom), CORPSTAT_INIT); /* put box/chest inside; * 40% chance for at least 1 box, regardless of number * of rooms; about 5 - 7.5% for 2 boxes, least likely diff --git a/src/mkmaze.c b/src/mkmaze.c index 12aaee699..0a810067c 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -431,7 +431,7 @@ fixup_special() otmp = mk_tt_object(STATUE, somex(croom), somey(croom)); else /* Medusa statues don't contain books */ otmp = mkcorpstat(STATUE, (struct monst *)0, (struct permonst *)0, - somex(croom), somey(croom), FALSE); + somex(croom), somey(croom), CORPSTAT_NONE); if (otmp) { while (pm_resistance(&mons[otmp->corpsenm],MR_STONE) || poly_when_stoned(&mons[otmp->corpsenm])) { diff --git a/src/mkobj.c b/src/mkobj.c index f34c8e3da..d067deb0a 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -884,14 +884,15 @@ int x, y; * resurrection. */ struct obj * -mkcorpstat(objtype, mtmp, ptr, x, y, init) +mkcorpstat(objtype, mtmp, ptr, x, y, corpstatflags) int objtype; /* CORPSE or STATUE */ struct monst *mtmp; struct permonst *ptr; int x, y; -boolean init; +unsigned corpstatflags; { register struct obj *otmp; + boolean init = ((corpstatflags & CORPSTAT_INIT) != 0); if (objtype != CORPSE && objtype != STATUE) impossible("making corpstat type %d", objtype); @@ -1058,9 +1059,11 @@ int x, y; const char *nm; { struct obj *otmp; + unsigned corpstatflags = (objtype != STATUE) ? + CORPSTAT_INIT : CORPSTAT_NONE; otmp = mkcorpstat(objtype, (struct monst *)0, ptr, - x, y, (boolean)(objtype != STATUE)); + x, y, corpstatflags); if (nm) otmp = oname(otmp, nm); return(otmp); diff --git a/src/mon.c b/src/mon.c index 2eea44bab..6312e6122 100644 --- a/src/mon.c +++ b/src/mon.c @@ -30,7 +30,6 @@ STATIC_DCL void FDECL(kill_eggs, (struct obj *)); (level.flags.graveyard && is_undead(mdat) && rn2(3)) #endif - #if 0 /* part of the original warning code which was replaced in 3.3.1 */ #define warnDelay 10 @@ -44,7 +43,7 @@ const char *warnings[] = { STATIC_DCL void NDECL(warn_effects); #endif /* 0 */ -STATIC_DCL struct obj *FDECL(make_corpse,(struct monst *)); +STATIC_DCL struct obj *FDECL(make_corpse,(struct monst *, unsigned)); STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *)); STATIC_DCL void FDECL(lifesaved_monster, (struct monst *)); @@ -162,14 +161,17 @@ STATIC_VAR short cham_to_pm[] = { * etc.... */ STATIC_OVL struct obj * -make_corpse(mtmp) +make_corpse(mtmp,corpseflags) register struct monst *mtmp; +unsigned corpseflags; { register struct permonst *mdat = mtmp->data; int num; struct obj *obj = (struct obj *)0; int x = mtmp->mx, y = mtmp->my; int mndx = monsndx(mdat); + unsigned corpstatflags = corpseflags; + boolean burythem = ((corpstatflags & CORPSTAT_BURIED) != 0); switch(mndx) { case PM_GRAY_DRAGON: @@ -211,7 +213,8 @@ register struct monst *mtmp; case PM_VAMPIRE_LORD: /* include mtmp in the mkcorpstat() call */ num = undead_to_corpse(mndx); - obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, TRUE); + corpstatflags |= CORPSTAT_INIT; + obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, corpstatflags); obj->age -= 100; /* this is an *OLD* corpse */ break; case PM_KOBOLD_MUMMY: @@ -231,7 +234,8 @@ register struct monst *mtmp; case PM_GIANT_ZOMBIE: case PM_ETTIN_ZOMBIE: num = undead_to_corpse(mndx); - obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, TRUE); + corpstatflags |= CORPSTAT_INIT; + obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, corpstatflags); obj->age -= 100; /* this is an *OLD* corpse */ break; case PM_IRON_GOLEM: @@ -253,8 +257,9 @@ register struct monst *mtmp; mtmp->mnamelth = 0; break; case PM_STONE_GOLEM: + corpstatflags &= ~CORPSTAT_INIT; obj = mkcorpstat(STATUE, (struct monst *)0, - mdat, x, y, FALSE); + mdat, x, y, corpstatflags); break; case PM_WOOD_GOLEM: num = d(2,4); @@ -284,9 +289,17 @@ register struct monst *mtmp; default: if (mvitals[mndx].mvflags & G_NOCORPSE) return (struct obj *)0; - else /* preserve the unique traits of some creatures */ + else { + corpstatflags |= CORPSTAT_INIT; + /* preserve the unique traits of some creatures */ obj = mkcorpstat(CORPSE, KEEPTRAITS(mtmp) ? mtmp : 0, - mdat, x, y, TRUE); + mdat, x, y, corpstatflags); + if (burythem) { + (void) bury_an_obj(obj); + newsym(x, y); + return obj; + } + } break; } /* All special cases should precede the G_NOCORPSE check */ @@ -1578,7 +1591,7 @@ register struct monst *mdef; if (corpse_chance(mdef, (struct monst *)0, FALSE) && (accessible(mdef->mx, mdef->my) || is_pool(mdef->mx, mdef->my))) - (void) make_corpse(mdef); + (void) make_corpse(mdef,CORPSTAT_NONE); } /* monster disappears, not dies */ @@ -1650,7 +1663,7 @@ register struct monst *mdef; /* defer statue creation until after inventory removal so that saved monster traits won't retain any stale item-conferred attributes */ - otmp = mkcorpstat(STATUE, mdef, mdef->data, x, y, FALSE); + otmp = mkcorpstat(STATUE, mdef, mdef->data, x, y, CORPSTAT_NONE); if (mdef->mnamelth) otmp = oname(otmp, NAME(mdef)); while ((obj = oldminvent) != 0) { oldminvent = obj->nobj; @@ -1760,7 +1773,7 @@ xkilled(mtmp, dest) register struct trap *t; boolean redisp = FALSE; boolean wasinside = u.uswallow && (u.ustuck == mtmp); - + boolean burycorpse = FALSE; /* KMH, conduct */ u.uconduct.killer++; @@ -1782,14 +1795,18 @@ xkilled(mtmp, dest) } if (mtmp->mtrapped && (t = t_at(x, y)) != 0 && - (t->ttyp == PIT || t->ttyp == SPIKED_PIT) && - sobj_at(BOULDER, x, y)) - dest |= 2; /* + (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) { + + if (sobj_at(BOULDER, x, y)) + dest |= 2; /* * Prevent corpses/treasure being created "on top" * of the boulder that is about to fall in. This is * out of order, but cannot be helped unless this * whole routine is rearranged. */ + if (m_carrying(mtmp, BOULDER)) + burycorpse = TRUE; + } /* your pet knows who just killed it...watch out */ if (mtmp->mtame && !mtmp->isminion) EDOG(mtmp)->killed_by_u = 1; @@ -1857,8 +1874,16 @@ xkilled(mtmp, dest) * different from whether or not the corpse is "special"; * if we want both, we have to specify it explicitly. */ - if (corpse_chance(mtmp, (struct monst *)0, FALSE)) - (void) make_corpse(mtmp); + if (corpse_chance(mtmp, (struct monst *)0, FALSE)) { + struct obj *cadaver = make_corpse(mtmp, burycorpse ? + CORPSTAT_BURIED : CORPSTAT_NONE); + if (burycorpse && cadaver && cansee(x,y) && + !mtmp->minvis && + cadaver->where == OBJ_BURIED && (dest & 1)) { + pline("%s corpse ends up buried.", + s_suffix(Monnam(mtmp))); + } + } } if(redisp) newsym(x,y); cleanup: diff --git a/src/trap.c b/src/trap.c index 8d0c0b4ac..abe053714 100644 --- a/src/trap.c +++ b/src/trap.c @@ -245,7 +245,7 @@ register int x, y, typ; struct obj *otmp, *statue; statue = mkcorpstat(STATUE, (struct monst *)0, - &mons[rndmonnum()], x, y, FALSE); + &mons[rndmonnum()], x, y, CORPSTAT_NONE); mtmp = makemon(&mons[statue->corpsenm], 0, 0, NO_MM_FLAGS); if (!mtmp) break; /* should never happen */ while(mtmp->minvent) {