fix #H7530 - corpse from corpseless monster

Migrating monster attempting to arrive on a level which is already
full of monsters gets killed off.  It was leaving a corpse without
regard for whether it was a type of of monster which should never
leave corpses.

I'd prefer that it be put back on the migrating_mons list rather
than be killed off, but this just suppresses impossible corpses.
This commit is contained in:
PatR
2018-11-20 13:13:23 -08:00
parent ffac5f1a65
commit d15dacc44c
3 changed files with 29 additions and 4 deletions

View File

@@ -202,6 +202,9 @@ a stale gold symbol could be displayed on the status line following a switch
to a new symset, as observed and reported for Windows RogueEpyx symset
successfully paying for shop damage with shop credit would be followed by
impossible "zero payment in money2mon"
if a migrating monster was killed off because there was no room on the
destination level, it would leave a corpse even if it was a type
which should never leave one (demon, golem, blob, &c)
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository

View File

@@ -7,6 +7,11 @@
STATIC_DCL int NDECL(pet_type);
/* cloned from mon.c; used here if mon_arrive() can't place mon */
#define LEVEL_SPECIFIC_NOCORPSE(mdat) \
(Is_rogue_level(&u.uz) \
|| (level.flags.graveyard && is_undead(mdat) && rn2(3)))
void
newedog(mtmp)
struct monst *mtmp;
@@ -79,6 +84,7 @@ boolean quietly;
do {
if (otmp) { /* figurine; otherwise spell */
int mndx = otmp->corpsenm;
pm = &mons[mndx];
/* activating a figurine provides one way to exceed the
maximum number of the target critter created--unless
@@ -294,6 +300,7 @@ struct monst *mtmp;
boolean with_you;
{
struct trap *t;
struct obj *obj;
xchar xlocale, ylocale, xyloc, xyflags, wander;
int num_segs;
@@ -417,8 +424,10 @@ boolean with_you;
/* monster moved a bit; pick a nearby location */
/* mnearto() deals w/stone, et al */
char *r = in_rooms(xlocale, ylocale, 0);
if (r && *r) {
coord c;
/* somexy() handles irregular rooms */
if (somexy(&rooms[*r - ROOMOFFSET], &c))
xlocale = c.x, ylocale = c.y;
@@ -426,6 +435,7 @@ boolean with_you;
xlocale = ylocale = 0;
} else { /* not in a room */
int i, j;
i = max(1, xlocale - wander);
j = min(COLNO - 1, xlocale + wander);
xlocale = rn1(j - i, i);
@@ -446,8 +456,11 @@ boolean with_you;
* Failed to place migrating monster,
* probably because the level is full.
* Dump the monster's cargo and leave the monster dead.
*
* TODO? Put back on migrating_mons list instead so
* that if hero leaves this level and then returns,
* monster will have another chance to arrive.
*/
struct obj *obj;
fail_mon_placement:
while ((obj = mtmp->minvent) != 0) {
obj_extract_self(obj);
@@ -462,8 +475,15 @@ fail_mon_placement:
impossible("Can't find relocated object.");
}
}
(void) mkcorpstat(CORPSE, (struct monst *) 0, mtmp->data, xlocale,
ylocale, CORPSTAT_NONE);
/*
* TODO? Maybe switch to make_corpse() [won't be needed if
* we re-migrate as suggested above], probably with new
* CORPSTAT_NOOBJS flag to suppress dragon scales and such.
*/
if (!(mvitals[monsndx(mtmp->data)].mvflags & G_NOCORPSE)
&& !LEVEL_SPECIFIC_NOCORPSE(mtmp->data))
(void) mkcorpstat(CORPSE, mtmp, mtmp->data,
xlocale, ylocale, CORPSTAT_NONE);
mtmp->mx = mtmp->my = -1; /* for mongone, mon is not anywhere */
mongone(mtmp);
}

View File

@@ -29,6 +29,7 @@ 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 *));
/* note: duplicated in dog.c */
#define LEVEL_SPECIFIC_NOCORPSE(mdat) \
(Is_rogue_level(&u.uz) \
|| (level.flags.graveyard && is_undead(mdat) && rn2(3)))
@@ -446,7 +447,8 @@ unsigned corpseflags;
}
/* All special cases should precede the G_NOCORPSE check */
if (!obj) return NULL;
if (!obj)
return (struct obj *) 0;
/* if polymorph or undead turning has killed this monster,
prevent the same attack beam from hitting its corpse */