From: nethack.rankin Date: Sun, 6 Aug 2006 05:13:22 +0000 (+0000) Subject: fix #H166 - trapdoors on quest levels X-Git-Tag: MOVE2GIT~937 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47327a3b991faab4fcbb8d055766efb2c408d674;p=nethack fix #H166 - trapdoors on quest levels 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.) --- diff --git a/doc/fixes34.4 b/doc/fixes34.4 index bfa5d36c2..ccb91eec7 100644 --- a/doc/fixes34.4 +++ b/doc/fixes34.4 @@ -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 diff --git a/src/dungeon.c b/src/dungeon.c index 53c52dc86..fca349c94 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -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); } diff --git a/src/teleport.c b/src/teleport.c index 85a1f7825..aa6b7edd8 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -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 */ diff --git a/src/trap.c b/src/trap.c index bb05aa4e1..2b4dea113 100644 --- a/src/trap.c +++ b/src/trap.c @@ -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) {