]> granicus.if.org Git - nethack/commitdiff
fix #H166 - trapdoors on quest levels
authornethack.rankin <nethack.rankin>
Sun, 6 Aug 2006 05:13:22 +0000 (05:13 +0000)
committernethack.rankin <nethack.rankin>
Sun, 6 Aug 2006 05:13:22 +0000 (05:13 +0000)
     From a bug report, it was possible
to fall from above the quest locate level to below it even though it has
nondiggable floors (hence no trapdoors or holes to pass through).  Since
the game can't verify that it is nondiggable (which could vary on a role
by role basis depending upon their quest descriptions) when it is not the
current level, restrict falling past it only when it hasn't been visited
yet.  Impose the same restriction for random level teleport.  This enforces
proper sequencing of the quest feedback, which was the more significant
thing that went wrong in the reported case (player finally got the full
locate level message on a return visit, when descending from above, after
having already cleared out that level on his way back up from falling).

     Once the locate level has been reached or passed, it is no longer a
barrier to falling or random teleport.  (When it is eventually visited,
there's no attempt to remember whether it allows holes, since that
information and the corresponding fall check would need to be extended to
every level in the dungeon.  Also, controlled teleport is still allowed to
bypass it even when it hasn't yet been visited, so the "enforces proper
sequencing" claim above is an exaggeration.)

doc/fixes34.4
src/dungeon.c
src/teleport.c
src/trap.c

index bfa5d36c203123499dd6fbd5ce624c0429edb61c..ccb91eec711f4b4051c0917d15f02f9e2b937bf3 100644 (file)
@@ -242,6 +242,8 @@ terminal window set to 21 lines can cause a crash during player selection
        menus; have bot() check for valid youmonst.data
 free storage used to hold region messages in free_region()
 honor pushweapon when applying a tool or weapon causes it to become wielded
+in the quest, if the locate level hasn't been reached yet, don't fall or
+       randomly teleport past it
 
 
 Platform- and/or Interface-Specific Fixes
index 53c52dc8642b53fabcda5704c623e85c30b8c34f..fca349c94bd413106d7622c287e51d53052fa1c2 100644 (file)
@@ -991,9 +991,9 @@ boolean noquest;
        register schar ret = 0;
 
        for(i = 0; i < n_dgns; i++) {
-           if((tmp.dlevel = dungeons[i].dunlev_ureached) == 0) continue;
-           if(!strcmp(dungeons[i].dname, "The Quest") && noquest) continue;
-
+           if (noquest && i == quest_dnum) continue;
+           tmp.dlevel = dungeons[i].dunlev_ureached;
+           if (tmp.dlevel == 0) continue;
            tmp.dnum = i;
            if(depth(&tmp) > ret) ret = depth(&tmp);
        }
index 85a1f782594c455cab9132fc2cf0151e49ecf954..aa6b7edd8bbf95dabb13d46669eed9284739f181 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)teleport.c 3.5     2006/03/18      */
+/*     SCCS Id: @(#)teleport.c 3.5     2006/08/05      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1244,11 +1244,23 @@ random_teleport_level()
         * monsters sometimes level teleporting out of it into main dungeon.
         * Also prevent monsters reaching the Sanctum prior to invocation.
         */
-       min_depth = In_quest(&u.uz) ? dungeons[u.uz.dnum].depth_start : 1;
-       max_depth = dunlevs_in_dungeon(&u.uz) +
+       if (In_quest(&u.uz)) {
+           int bottom = dunlevs_in_dungeon(&u.uz),
+               qlocate_depth = qlocate_level.dlevel;
+
+           /* if hero hasn't reached the middle locate level yet,
+              no one can randomly teleport past it */
+           if (dunlev_reached(&u.uz) < qlocate_depth)
+               bottom = qlocate_depth;
+           min_depth = dungeons[u.uz.dnum].depth_start;
+           max_depth = bottom + (dungeons[u.uz.dnum].depth_start - 1);
+       } else {
+           min_depth = 1;
+           max_depth = dunlevs_in_dungeon(&u.uz) +
                        (dungeons[u.uz.dnum].depth_start - 1);
-       /* can't reach the Sanctum if the invocation hasn't been performed */
-       if (Inhell && !u.uevent.invoked) max_depth -= 1;
+           /* can't reach Sanctum if the invocation hasn't been performed */
+           if (Inhell && !u.uevent.invoked) max_depth -= 1;
+       }
 
        /* Get a random value relative to the current dungeon */
        /* Range is 1 to current+3, current not counting */
index bb05aa4e131a5ffde245e28b3259f146413e83dd..2b4dea11387210f643f535615051381d45b9482e 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)trap.c     3.5     2006/06/16      */
+/*     SCCS Id: @(#)trap.c     3.5     2006/08/05      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -316,14 +316,25 @@ boolean td;       /* td == TRUE : trap door or hole */
        d_level dtmp;
        char msgbuf[BUFSZ];
        const char *dont_fall = 0;
-       register int newlevel = dunlev(&u.uz);
+       int newlevel, bottom;
 
        /* KMH -- You can't escape the Sokoban level traps */
        if(Blind && Levitation && !In_sokoban(&u.uz)) return;
 
+       bottom = dunlevs_in_dungeon(&u.uz);
+       /* when in the upper half of the quest, don't fall past the
+          middle "quest locate" level if hero hasn't been there yet */
+       if (In_quest(&u.uz)) {
+           int qlocate_depth = qlocate_level.dlevel;
+
+           /* deepest reached < qlocate implies current < qlocate */
+           if (dunlev_reached(&u.uz) < qlocate_depth)
+               bottom = qlocate_depth; /* early cut-off */
+       }
+       newlevel = dunlev(&u.uz);       /* current level */
        do {
            newlevel++;
-       } while(!rn2(4) && newlevel < dunlevs_in_dungeon(&u.uz));
+       } while (!rn2(4) && newlevel < bottom);
 
        if(td) {
            struct trap *t = t_at(u.ux,u.uy);
@@ -341,8 +352,7 @@ boolean td; /* td == TRUE : trap door or hole */
        else if(Levitation || u.ustuck
           || (!Can_fall_thru(&u.uz) && !levl[u.ux][u.uy].candig)
           || Flying || is_clinger(youmonst.data)
-          || (Inhell && !u.uevent.invoked &&
-                                       newlevel == dunlevs_in_dungeon(&u.uz))
+          || (Inhell && !u.uevent.invoked && newlevel == bottom)
                ) {
            dont_fall = "don't fall in.";
        } else if (youmonst.data->msize >= MZ_HUGE) {