diff --git a/include/extern.h b/include/extern.h index 43488aa24..7fac7b2ba 100644 --- a/include/extern.h +++ b/include/extern.h @@ -600,7 +600,7 @@ extern void mon_arrive(struct monst *, int); extern void mon_catchup_elapsed_time(struct monst *, long); extern void keepdogs(boolean); extern void migrate_to_level(struct monst *, coordxy, coordxy, coord *); -extern void discard_migrating_mons(void); +extern void discard_migrations(void); extern int dogfood(struct monst *, struct obj *); extern boolean tamedog(struct monst *, struct obj *); extern void abuse_dog(struct monst *); diff --git a/src/do.c b/src/do.c index 5daeecbd5..fe2717023 100644 --- a/src/do.c +++ b/src/do.c @@ -1463,8 +1463,8 @@ goto_level( /* mark #overview data for all dungeon branches as uninteresting */ for (l_idx = 0; l_idx < g.n_dgns; ++l_idx) remdun_mapseen(l_idx); - /* get rid of monsters scheduled to migrate to discarded levels */ - discard_migrating_mons(); + /* get rid of mons & objs scheduled to migrate to discarded levels */ + discard_migrations(); } if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz)) diff --git a/src/dog.c b/src/dog.c index a984f03db..3260ef15c 100644 --- a/src/dog.c +++ b/src/dog.c @@ -845,23 +845,49 @@ migrate_to_level( /* when entering the endgame, levels from the dungeon and its branches are discarded because they can't be reached again; do the same for monsters - scheduled to migrate to those levels */ + and objects scheduled to migrate to those levels */ void -discard_migrating_mons(void) +discard_migrations(void) { struct monst *mtmp, **mprev; - d_level mdest; + struct obj *otmp, **oprev; + d_level dest; for (mprev = &g.migrating_mons; (mtmp = *mprev) != 0; ) { - mdest.dnum = mtmp->mux; - mdest.dlevel = mtmp->muy; + dest.dnum = mtmp->mux; + dest.dlevel = mtmp->muy; /* the Wizard is kept regardless of location so that he is ready to be brought back; nothing should be scheduled to migrate to the endgame but if we find such, we'll keep it */ - if (!mtmp->iswiz && !In_endgame(&mdest)) - *mprev = mtmp->nmon; /* remove mtmp from migrating_mons */ - else + if (mtmp->iswiz || In_endgame(&dest)) { mprev = &mtmp->nmon; /* keep mtmp on migrating_mons */ + } else { + *mprev = mtmp->nmon; /* remove mtmp from migrating_mons */ + mtmp->nmon = 0; + discard_minvent(mtmp, FALSE); + /* bypass mongone() and its call to m_detach() plus dmonsfree() */ + dealloc_monst(mtmp); + } + } + + /* objects get similar treatment */ + for (oprev = &g.migrating_objs; (otmp = *oprev) != 0; ) { + dest.dnum = otmp->ox; + dest.dlevel = otmp->oy; + /* there is no special case like the Wizard (certainly not the + Amulet; the hero has to be carrying it to enter the endgame + which triggers the call to this routine); again we don't + expect any objects to be migrating to the endgame but will + keep any we find so that they could be delivered */ + if (In_endgame(&dest)) { + oprev = &otmp->nobj; /* keep otmp on migrating_objs */ + } else { + /* bypass obj_extract_self() */ + *oprev = otmp->nobj; /* remove otmp from migrating_objs */ + otmp->nobj = 0; + otmp->where = OBJ_FREE; + obfree(otmp, (struct obj *) 0); /* releases any contents too */ + } } }