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
+3
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 to a new symset, as observed and reported for Windows RogueEpyx symset
successfully paying for shop damage with shop credit would be followed by successfully paying for shop damage with shop credit would be followed by
impossible "zero payment in money2mon" 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 Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
+23 -3
View File
@@ -7,6 +7,11 @@
STATIC_DCL int NDECL(pet_type); 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 void
newedog(mtmp) newedog(mtmp)
struct monst *mtmp; struct monst *mtmp;
@@ -79,6 +84,7 @@ boolean quietly;
do { do {
if (otmp) { /* figurine; otherwise spell */ if (otmp) { /* figurine; otherwise spell */
int mndx = otmp->corpsenm; int mndx = otmp->corpsenm;
pm = &mons[mndx]; pm = &mons[mndx];
/* activating a figurine provides one way to exceed the /* activating a figurine provides one way to exceed the
maximum number of the target critter created--unless maximum number of the target critter created--unless
@@ -294,6 +300,7 @@ struct monst *mtmp;
boolean with_you; boolean with_you;
{ {
struct trap *t; struct trap *t;
struct obj *obj;
xchar xlocale, ylocale, xyloc, xyflags, wander; xchar xlocale, ylocale, xyloc, xyflags, wander;
int num_segs; int num_segs;
@@ -417,8 +424,10 @@ boolean with_you;
/* monster moved a bit; pick a nearby location */ /* monster moved a bit; pick a nearby location */
/* mnearto() deals w/stone, et al */ /* mnearto() deals w/stone, et al */
char *r = in_rooms(xlocale, ylocale, 0); char *r = in_rooms(xlocale, ylocale, 0);
if (r && *r) { if (r && *r) {
coord c; coord c;
/* somexy() handles irregular rooms */ /* somexy() handles irregular rooms */
if (somexy(&rooms[*r - ROOMOFFSET], &c)) if (somexy(&rooms[*r - ROOMOFFSET], &c))
xlocale = c.x, ylocale = c.y; xlocale = c.x, ylocale = c.y;
@@ -426,6 +435,7 @@ boolean with_you;
xlocale = ylocale = 0; xlocale = ylocale = 0;
} else { /* not in a room */ } else { /* not in a room */
int i, j; int i, j;
i = max(1, xlocale - wander); i = max(1, xlocale - wander);
j = min(COLNO - 1, xlocale + wander); j = min(COLNO - 1, xlocale + wander);
xlocale = rn1(j - i, i); xlocale = rn1(j - i, i);
@@ -446,8 +456,11 @@ boolean with_you;
* Failed to place migrating monster, * Failed to place migrating monster,
* probably because the level is full. * probably because the level is full.
* Dump the monster's cargo and leave the monster dead. * 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: fail_mon_placement:
while ((obj = mtmp->minvent) != 0) { while ((obj = mtmp->minvent) != 0) {
obj_extract_self(obj); obj_extract_self(obj);
@@ -462,8 +475,15 @@ fail_mon_placement:
impossible("Can't find relocated object."); 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 */ mtmp->mx = mtmp->my = -1; /* for mongone, mon is not anywhere */
mongone(mtmp); mongone(mtmp);
} }
+3 -1
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(m_detach, (struct monst *, struct permonst *));
STATIC_DCL void FDECL(lifesaved_monster, (struct monst *)); STATIC_DCL void FDECL(lifesaved_monster, (struct monst *));
/* note: duplicated in dog.c */
#define LEVEL_SPECIFIC_NOCORPSE(mdat) \ #define LEVEL_SPECIFIC_NOCORPSE(mdat) \
(Is_rogue_level(&u.uz) \ (Is_rogue_level(&u.uz) \
|| (level.flags.graveyard && is_undead(mdat) && rn2(3))) || (level.flags.graveyard && is_undead(mdat) && rn2(3)))
@@ -446,7 +447,8 @@ unsigned corpseflags;
} }
/* All special cases should precede the G_NOCORPSE check */ /* 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, /* if polymorph or undead turning has killed this monster,
prevent the same attack beam from hitting its corpse */ prevent the same attack beam from hitting its corpse */