static int wiz_migrate_mons(void);
#endif
-static void makemap_unmakemon(struct monst *);
+static void makemap_unmakemon(struct monst *, boolean);
static void makemap_remove_mons(void);
static void wiz_map_levltyp(void);
static void wiz_levltyp_legend(void);
/* used when wiz_makemap() gets rid of monsters for the old incarnation of
a level before creating a new incarnation of it */
static void
-makemap_unmakemon(struct monst *mtmp)
+makemap_unmakemon(struct monst *mtmp, boolean migratory)
{
int ndx = monsndx(mtmp->data);
} else if (mtmp->isshk && on_level(&u.uz, &ESHK(mtmp)->shoplevel)) {
setpaid(mtmp);
}
+ if (migratory) {
+ /* caller has removed 'mtmp' from migrating_mons; put it onto fmon
+ so that dmonsfree() bookkeeping for number of dead or removed
+ monsters won't get out of sync; it is not on the map but
+ mongone() -> m_detach() -> mon_leaving_level() copes with that */
+ mtmp->nmon = fmon;
+ fmon = mtmp;
+ }
mongone(mtmp);
}
keepdogs(TRUE); /* (pets-only; normally we'd be using 'FALSE') */
/* get rid of all the monsters that didn't make it to 'mydogs' */
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
- makemap_unmakemon(mtmp);
+ makemap_unmakemon(mtmp, FALSE);
/* some monsters retain details of this level in mon->mextra; that
data becomes invalid when the level is replaced by a new one;
get rid of them now if migrating or already arrived elsewhere;
|| (mtmp->ispriest && on_level(&u.uz, &EPRI(mtmp)->shrlevel))
|| (mtmp->isgd && on_level(&u.uz, &EGD(mtmp)->gdlevel)))) {
*mprev = mtmp->nmon;
- makemap_unmakemon(mtmp);
+ makemap_unmakemon(mtmp, TRUE);
} else {
mprev = &mtmp->nmon;
}
}
/* release dead and 'unmade' monsters */
dmonsfree();
+ if (fmon) {
+ impossible("makemap_remove_mons: 'fmon' did not get emptied?");
+ }
return;
}
#endif
if (DEADMONSTER(mtmp)) {
#if 0
- /* bad if not fmons list or if not vault guard */
+ /* bad if not fmon list or if not vault guard */
if (strcmp(msg, "fmon") || !mtmp->isgd)
impossible("dead monster on %s; %s at <%d,%d>",
msg, mons[mndx].pmnames[NEUTRAL],
char buf[QBUFSZ];
buf[0] = '\0';
- for (mtmp = &fmon; *mtmp;) {
+ for (mtmp = &fmon; *mtmp; ) {
freetmp = *mtmp;
if (DEADMONSTER(freetmp) && !freetmp->isgd) {
*mtmp = freetmp->nmon;
if (In_endgame(&u.uz))
mtmp->mstate |= MON_ENDGAME_FREE;
- mtmp->mstate |= MON_DETACH;
- iflags.purge_monsters++;
+ if ((mtmp->mstate & MON_DETACH) != 0) {
+ impossible("m_detach: %s is already detached?",
+ minimal_monnam(mtmp, FALSE));
+ } else {
+ mtmp->mstate |= MON_DETACH;
+ iflags.purge_monsters++;
+ }
}
/* give a life-saved monster a reasonable mhpmax value in case it has
if (!on_level(&egrd->gdlevel, &u.uz))
return TRUE;
- /* note: guard remains on 'fmons' list (alive or dead, at off-map
+ /* note: guard remains on 'fmon' list (alive or dead, at off-map
coordinate <0,0>), until temporary corridor from vault back to
civilization has been removed */
while ((fcbeg = egrd->fcbeg) < egrd->fcend) {