]> granicus.if.org Git - nethack/commitdiff
more abandoned migrations when entering endgame
authorPatR <rankin@nethack.org>
Fri, 5 Aug 2022 23:55:05 +0000 (16:55 -0700)
committerPatR <rankin@nethack.org>
Fri, 5 Aug 2022 23:55:05 +0000 (16:55 -0700)
The earlier commit just removed monsters from migrating_mons and left
them orphaned.  Also it ignored migrating objects.

Actually release the monsters that can no longer arrive at their
migration destinations.  Release their inventories too.

Release objects that can no longer arrive at migration destinations.

include/extern.h
src/do.c
src/dog.c

index 43488aa24fc98fcb04eaf5c52688b0e66d733f2d..7fac7b2ba5da3e698fc68b133c1fadabb2d1d523 100644 (file)
@@ -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 *);
index 5daeecbd576fcfa6e048e5bc2a2273a8c15a7e12..fe27170234799ce19822bd34672c3735988f6c74 100644 (file)
--- 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))
index a984f03dbc92335c2da56f88d0f3e632d1ea4e02..3260ef15ceafda2981d3550eb258e2908c3208c9 100644 (file)
--- 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 */
+        }
     }
 }