]> granicus.if.org Git - nethack/commitdiff
fix #H285 - hiders not hiding while hero is on another level (trunk only)
authornethack.rankin <nethack.rankin>
Sun, 22 Apr 2007 01:01:22 +0000 (01:01 +0000)
committernethack.rankin <nethack.rankin>
Sun, 22 Apr 2007 01:01:22 +0000 (01:01 +0000)
     From a bug report, mimics
which were exposed at the time the hero leaves a level remain unhidden
upon return no matter how long the hero is away.  It was actually expected
behavior since the old level is stuck in stasis and hiders only hide when
it's their turn to move, but it was noticeably odd.  This makes unhidden
hiders attempt to hide when hero returns to a previous level or enters a
bones level.  I reorganized the monster handling in getlev() because the
relevant part was taking place before floor objects got restored, so
hidesunder() monsters had nothing to hide under at the time.

doc/fixes35.0
include/extern.h
src/mon.c
src/restore.c

index d1096d98fa15861e3339f45ecb073339c63c8935..fc9fe04fd005e45678fcbcb318a68d73c2c5ae98 100644 (file)
@@ -220,6 +220,7 @@ when doppelgangers taking on new shape don't specifically pick nasty monster
 salamanders can use green slime corpses to cure themselves of petrification
 feedback about summoned monsters may use singular when it should use plural
 rogue's backstab bonus doesn't apply for throwing attacks
+hiding monsters who are unhidden when hero leaves a level can hide upon return
 
 
 Platform- and/or Interface-Specific Fixes
index af63b95039caa5caaa51c494a617ff2243a39ea4..73ff153a8bf88fffb52e56b042aebd37b75bba29 100644 (file)
@@ -1296,6 +1296,7 @@ E void NDECL(rescham);
 E void NDECL(restartcham);
 E void FDECL(restore_cham, (struct monst *));
 E boolean FDECL(hideunder, (struct monst*));
+E void FDECL(hide_monst, (struct monst *));
 E void FDECL(mon_animal_list, (BOOLEAN_P));
 E int FDECL(select_newcham_form, (struct monst *));
 E int FDECL(newcham, (struct monst *,struct permonst *,BOOLEAN_P,BOOLEAN_P));
index f2e163bb1615ee4794a4e3241405987a28f05b32..027ccb51fd7a46b911fcaeca2312cb04b08ff2d9 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -2467,6 +2467,26 @@ struct monst *mtmp;
        return undetected;
 }
 
+/* called when returning to a previously visited level */
+void
+hide_monst(mon)
+struct monst *mon;
+{
+    if ((is_hider(mon->data) || hides_under(mon->data)) &&
+           !(mon->mundetected || mon->m_ap_type)) {
+       xchar x = mon->mx, y = mon->my;
+       char save_viz = viz_array[y][x];
+
+       /* override vision, forcing hero to be unable to see monster's spot */
+       viz_array[y][x] &= ~(IN_SIGHT | COULD_SEE);
+       if (is_hider(mon->data)) (void)restrap(mon);
+       /* try again if mimic missed its 1/3 chance to hide */
+       if (mon->data->mlet == S_MIMIC && !mon->m_ap_type) (void)restrap(mon);
+       if (hides_under(mon->data)) (void)hideunder(mon);
+       viz_array[y][x] = save_viz;
+    }
+}
+
 short *animal_list = 0;                /* list of PM values for animal monsters */
 int animal_list_count;
 
index bc946a4be1bcb46c3c0b78a6d58b4bfb577a5883..f0470be5788d497c0a53e468e58ed03b0db55292 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)restore.c  3.5     2007/02/03      */
+/*     SCCS Id: @(#)restore.c  3.5     2007/04/21      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -951,6 +951,7 @@ boolean ghostly;
 {
        register struct trap *trap;
        register struct monst *mtmp;
+       long elapsed;
        branch *br;
        int hpid;
        xchar dlvl;
@@ -994,6 +995,7 @@ boolean ghostly;
        }
        rest_levl(fd, (boolean)((sfrestinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP));
        mread(fd, (genericptr_t)&omoves, sizeof(omoves));
+       elapsed = monstermoves - omoves;
        mread(fd, (genericptr_t)&upstair, sizeof(stairway));
        mread(fd, (genericptr_t)&dnstair, sizeof(stairway));
        mread(fd, (genericptr_t)&upladder, sizeof(stairway));
@@ -1009,36 +1011,10 @@ boolean ghostly;
        else
            doorindex = 0;
 
-       restore_timers(fd, RANGE_LEVEL, ghostly, monstermoves - omoves);
+       restore_timers(fd, RANGE_LEVEL, ghostly, elapsed);
        restore_light_sources(fd);
        fmon = restmonchn(fd, ghostly);
 
-       /* regenerate animals while on another level */
-       if (u.uz.dlevel) {
-           register struct monst *mtmp2;
-
-           for (mtmp = fmon; mtmp; mtmp = mtmp2) {
-               mtmp2 = mtmp->nmon;
-               if (ghostly) {
-                       /* reset peaceful/malign relative to new character */
-                       /* shopkeepers will reset based on name */
-                       if(!mtmp->isshk) {
-                           if (is_unicorn(mtmp->data) &&
-                              sgn(u.ualign.type) == sgn(mtmp->data->maligntyp))
-                               mtmp->mpeaceful = TRUE;
-                           else
-                               mtmp->mpeaceful = peace_minded(mtmp->data);
-                       }
-                       set_malign(mtmp);
-               } else if (monstermoves > omoves)
-                       mon_catchup_elapsed_time(mtmp, monstermoves - omoves);
-
-               /* update shape-changers in case protection against
-                  them is different now than when the level was saved */
-               restore_cham(mtmp);
-           }
-       }
-
        rest_worm(fd);  /* restore worm information */
        ftrap = 0;
        while (trap = newtrap(),
@@ -1060,14 +1036,32 @@ boolean ghostly;
        for (x = 0; x < COLNO; x++)
            for (y = 0; y < ROWNO; y++)
                level.monsters[x][y] = (struct monst *) 0;
-       for (mtmp = level.monlist; mtmp; mtmp = mtmp->nmon) {
-           if (mtmp->isshk)
-               set_residency(mtmp, FALSE);
+       for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+           if (mtmp->isshk) set_residency(mtmp, FALSE);
            place_monster(mtmp, mtmp->mx, mtmp->my);
            if (mtmp->wormno) place_wsegs(mtmp);
+
+           /* regenerate monsters while on another level */
+           if (!u.uz.dlevel) continue;
+           if (ghostly) {
+               /* reset peaceful/malign relative to new character;
+                  shopkeepers will reset based on name */
+               if (!mtmp->isshk)
+                   mtmp->mpeaceful = (is_unicorn(mtmp->data) &&
+                           sgn(u.ualign.type) == sgn(mtmp->data->maligntyp)) ?
+                                     TRUE : peace_minded(mtmp->data);
+               set_malign(mtmp);
+           } else if (elapsed > 0L) {
+               mon_catchup_elapsed_time(mtmp, elapsed);
+           }
+           /* update shape-changers in case protection against
+              them is different now than when the level was saved */
+           restore_cham(mtmp);
+           /* give hiders a chance to hide before their next move */
+           if (ghostly || elapsed > (long)rnd(10)) hide_monst(mtmp);
        }
-       restdamage(fd, ghostly);
 
+       restdamage(fd, ghostly);
        rest_regions(fd, ghostly);
        if (ghostly) {
            /* Now get rid of all the temp fruits... */