]> granicus.if.org Git - nethack/commitdiff
unhiding during level change
authornethack.rankin <nethack.rankin>
Sun, 22 Oct 2006 02:53:31 +0000 (02:53 +0000)
committernethack.rankin <nethack.rankin>
Sun, 22 Oct 2006 02:53:31 +0000 (02:53 +0000)
     From the newsgroup:  if a pet was hiding under an object next to you
when you changed levels, it could arrive hidden at the destination if there
was something available to hide under there too, and sometimes you'd start
the new level with a hidden monster glyph at its location.  I was able to
reproduce that once with current trunk code, but while trying to figure
out what is actually happening I've been unable to make it happen again.
However, it doesn't make sense for a monster to be able to remain in hiding
during the level change in the first place, so this patch prevents that.
(I'd still like to know how/why map_invisible() is sometimes getting called.
[The test character was a level 1 tourist without auto-search capability.]
I'm reasonably sure that it won't happen any more once this fix in place.)

     This also brings adjacent pets out of hiding when they accompany you
during ascension or dungeon escape, but it seems that that wasn't actually
necessary.  The end of game disclosure already lists such by name rather
than as "it", contrary to my expectations.  (I had forgotten that end-of-
game forces true names so that blindness and hallucination don't interfere
with disclosure; obviously that ends up handling hidden monsters too.)

doc/fixes34.4
include/extern.h
src/dog.c
src/mon.c

index e2cda30c06d393b10257884d1eca5fba2c92c9b4..2e0c416fc810a010caa6b4a5ac2e47ef5e42fb25 100644 (file)
@@ -263,6 +263,7 @@ try harder to keep dragged chain between ball and hero
 fireproof containers should not burn in lava
 fix invalid pointer dereference after applying a wielded cream pie
 avoid drowned in a drowning and burned by burning if life-saving is inadequate
+hidden monsters who change levels come out of hiding in the process
 
 
 Platform- and/or Interface-Specific Fixes
index 585159854c3bca23ed2d50cc94720c950649617f..ea4cd319322655a6bfa7241f4b339022b217bd31 100644 (file)
@@ -1247,7 +1247,7 @@ E void NDECL(dmonsfree);
 E int FDECL(mcalcmove, (struct monst*));
 E void NDECL(mcalcdistress);
 E void FDECL(replmon, (struct monst *,struct monst *));
-E void FDECL(relmon, (struct monst *));
+E void FDECL(relmon, (struct monst *,struct monst **));
 E struct obj *FDECL(mlifesaver, (struct monst *));
 E boolean FDECL(corpse_chance,(struct monst *,struct monst *,BOOLEAN_P));
 E void FDECL(mondead, (struct monst *));
index 037c12659410f360ec05ad30aaaf74c0dfef9fc1..cc7e81ead4c43adf5a3481c5f95015a75f191c61 100644 (file)
--- a/src/dog.c
+++ b/src/dog.c
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)dog.c      3.5     2006/06/11      */
+/*     SCCS Id: @(#)dog.c      3.5     2006/10/20      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -604,13 +604,10 @@ boolean pets_only;        /* true for ascension or final escape */
                    obj->no_charge = 0;
                }
 
-               relmon(mtmp);
-               newsym(mtmp->mx,mtmp->my);
+               relmon(mtmp, &mydogs);  /* move it from map to mydogs */
                mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
                mtmp->wormno = num_segs;
                mtmp->mlstmv = monstermoves;
-               mtmp->nmon = mydogs;
-               mydogs = mtmp;
            } else if (mtmp->iswiz) {
                /* we want to be able to find him when his next resurrection
                   chance comes up, but have him resume his present location
@@ -660,10 +657,7 @@ migrate_to_level(mtmp, tolev, xyloc, cc)
                mtmp->mtame--;
                m_unleash(mtmp, TRUE);
        }
-       relmon(mtmp);
-       mtmp->nmon = migrating_mons;
-       migrating_mons = mtmp;
-       newsym(mtmp->mx,mtmp->my);
+       relmon(mtmp, &migrating_mons); /* move it from map to migrating_mons */
 
        new_lev.dnum = ledger_to_dnum((xchar)tolev);
        new_lev.dlevel = ledger_to_dlev((xchar)tolev);
index 0642fcc6714b0e2e7b972276a9f78082d6f17700..b205d1f26cdacf64b10afa964edbff3ba858f72e 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)mon.c      3.5     2006/09/06      */
+/*     SCCS Id: @(#)mon.c      3.5     2006/10/20      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1297,7 +1297,7 @@ register struct monst *mtmp, *mtmp2;
     mtmp->minvent = 0;
 
     /* remove the old monster from the map and from `fmon' list */
-    relmon(mtmp);
+    relmon(mtmp, (struct monst **)0);
 
     /* finish adding its replacement */
 #ifdef STEED
@@ -1326,22 +1326,48 @@ register struct monst *mtmp, *mtmp2;
     dealloc_monst(mtmp);
 }
 
-/* release mon from display and monster list */
+/* release mon from the display and the map's monster list,
+   maybe transfer it to one of the other monster lists */
 void
-relmon(mon)
+relmon(mon, monst_list)
 register struct monst *mon;
+struct monst **monst_list;     /* &migrating_mons or &mydogs or null */
 {
        register struct monst *mtmp;
+       boolean unhide = (monst_list != 0);
+       int mx = mon->mx, my = mon->my;
 
-       if (fmon == (struct monst *)0)  panic ("relmon: no fmon available.");
+       if (!fmon) panic("relmon: no fmon available.");
 
-       remove_monster(mon->mx, mon->my);
+       if (unhide) {
+           /* can't remain hidden across level changes (exception: wizard
+              clone can continue imitating some other monster form); also,
+              might be imitating a boulder so need line-of-sight unblocking */
+           mon->mundetected = 0;
+           if (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER)
+               seemimic(mon);
+       }
+
+       remove_monster(mx, my);
+
+       if (mon == fmon) {
+           fmon = fmon->nmon;
+       } else {
+           for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
+               if (mtmp->nmon == mon) break;
 
-       if(mon == fmon) fmon = fmon->nmon;
-       else {
-               for(mtmp = fmon; mtmp && mtmp->nmon != mon; mtmp = mtmp->nmon) ;
-               if(mtmp)    mtmp->nmon = mon->nmon;
-               else        panic("relmon: mon not in list.");
+           if (mtmp) mtmp->nmon = mon->nmon;
+           else panic("relmon: mon not in list.");
+       }
+
+       if (unhide) {
+           newsym(mx, my);
+           /* insert into mydogs or migrating_mons */
+           mon->nmon = *monst_list;
+           *monst_list = mon;
+       } else {
+           /* orphan has no next monster */
+           mon->nmon = 0;
        }
 }