]> granicus.if.org Git - nethack/commitdiff
Holes and trapdoors have predetermined exit level
authorPasi Kallinen <paxed@alt.org>
Wed, 27 Jul 2022 19:51:13 +0000 (22:51 +0300)
committerPasi Kallinen <paxed@alt.org>
Wed, 27 Jul 2022 19:51:17 +0000 (22:51 +0300)
Same hole/trapdoor will always take you to the same level.

doc/fixes3-7-0.txt
include/trap.h
src/do.c
src/trap.c

index 12d9f538a88e8f74e1b442ca73cecf0a9a6d2274..a19f030a2741ae31780b1013a89daad6148db05c 100644 (file)
@@ -978,6 +978,7 @@ wielding Giantslayer prevents knockback from larger monsters
 scared hostile monster which cannot move away will attack
 prevent a fog cloud that has engulfed the hero from moving under closed doors
 allow cutting a known spider web with wielded weapon by force-fighting the web
+holes and trapdoors have a fixed exit level
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 18adfb2a2e4a8de6939c1b665d19e36cb02cda79..e54aa9052b404c6f429d7c33e296aaff865b6765 100644 (file)
@@ -18,7 +18,7 @@ union vlaunchinfo {
 struct trap {
     struct trap *ntrap;
     coordxy tx, ty;
-    d_level dst; /* destination for portals */
+    d_level dst; /* destination for portals/holes/trapdoors */
     coord launch;
     Bitfield(ttyp, 5);
     Bitfield(tseen, 1);
index 4d3547d2ebcb692522c6a5759f2c42d2c6df5a4a..8bb2aab5bb0b8f89bf8f1c2676b3bc10185e159c 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1133,6 +1133,8 @@ dodown(void)
     }
     if (trap && Is_stronghold(&u.uz)) {
         goto_hell(FALSE, TRUE);
+    } else if (trap) {
+        goto_level(&(trap->dst), FALSE, FALSE, FALSE);
     } else {
         g.at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
         next_level(!trap);
index 524d9d4714ebcaaafda74bc53f779c4237de949f..5901eeb7a80074bcada0fd56cc4868bf21f37c93 100644 (file)
@@ -8,6 +8,8 @@
 extern const char *const destroy_strings[][3]; /* from zap.c */
 
 static void mk_trap_statue(coordxy, coordxy);
+static int dng_bottom(void);
+static void hole_destination(d_level *);
 static boolean keep_saddle_with_steedcorpse(unsigned, struct obj *,
                                             struct obj *);
 static boolean mu_maybe_destroy_web(struct monst *, boolean, struct trap *);
@@ -373,6 +375,37 @@ mk_trap_statue(coordxy x, coordxy y)
     mongone(mtmp);
 }
 
+/* find "bottom" level of current dungeon, stopping at quest locate */
+static int
+dng_bottom(void)
+{
+    int 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 */
+    }
+    return bottom;
+}
+
+/* destination dlevel for holes or trapdoors */
+static void
+hole_destination(d_level *dst)
+{
+    int bottom = dng_bottom();
+
+    dst->dnum = u.uz.dnum;
+    dst->dlevel = dunlev(&u.uz);
+    do {
+        dst->dlevel++;
+    } while (!rn2(4) && dst->dlevel < bottom);
+}
+
 struct trap *
 maketrap(coordxy x, coordxy y, int typ)
 {
@@ -435,6 +468,8 @@ maketrap(coordxy x, coordxy y, int typ)
         /*FALLTHRU*/
     case HOLE:
     case TRAPDOOR:
+        if (is_hole(typ))
+            hole_destination(&(ttmp->dst));
         if (*in_rooms(x, y, SHOPBASE)
             && (is_hole(typ) || IS_DOOR(lev->typ) || IS_WALL(lev->typ)))
             add_damage(x, y, /* schedule repair */
@@ -481,7 +516,7 @@ fall_through(
     d_level dtmp;
     char msgbuf[BUFSZ];
     const char *dont_fall = 0;
-    int newlevel, bottom;
+    int newlevel, bottom = dng_bottom();
     struct trap *t = (struct trap *) 0;
 
     /* we'll fall even while levitating in Sokoban; otherwise, if we
@@ -489,20 +524,8 @@ fall_through(
     if (Blind && Levitation && !Sokoban)
         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 < bottom);
+    newlevel++;
 
     if (td) {
         t = t_at(u.ux, u.uy);
@@ -555,8 +578,14 @@ fall_through(
     } else {
         int dist = newlevel - dunlev(&u.uz);
 
-        dtmp.dnum = u.uz.dnum;
-        dtmp.dlevel = newlevel;
+        if (t) {
+            dtmp.dnum = t->dst.dnum;
+            dtmp.dlevel = t->dst.dlevel;
+            dist = dtmp.dlevel - dunlev(&u.uz);
+        } else {
+            dtmp.dnum = u.uz.dnum;
+            dtmp.dlevel = newlevel;
+        }
         if (dist > 1)
             You("fall down a %s%sshaft!", dist > 3 ? "very " : "",
                 dist > 2 ? "deep " : "");