]> granicus.if.org Git - nethack/commitdiff
show trapped doors,chests as themselves \
authorPatR <rankin@nethack.org>
Thu, 28 Apr 2022 00:16:23 +0000 (17:16 -0700)
committerPatR <rankin@nethack.org>
Thu, 28 Apr 2022 00:16:23 +0000 (17:16 -0700)
instead of as fake bear traps

Use the new traps and their tiles when confused gold detection finds
trapped doors and trapped chests.  (Large boxes can be trapped too;
they use the trapped chest trap and corresponding tile rather than
have their own.)

Usually these pseudo-traps go away when as soon as they are within
line of sight.  (While testing, I noticed that seeing a trapped door
from outside its room rather than inside didn't behave that way.
The door was created by wizard mode wishing; I don't know whether
that was a factor.)

I also discovered that secret doors weren't being handled correctly.
They can't be trapped because of their use of both the doormask and
wall_info overlays of levl[][].flags, but I had a secret door be
falsely displayed as a trap.  This fixes that.

We should have obj->tknown and rm->D_TRAPKNOWN so that the hero won't
forget about these traps after declining to attempt to untrap them.
But that's more work than I care to tackle.

doc/fixes3-7-0.txt
src/detect.c
src/pager.c

index b708a4fb569ffe372bf4dd4a349df085e739a261..7bcbe1cac2cf4007c54c0560e489c0adb03a9bda 100644 (file)
@@ -894,6 +894,8 @@ inventory #adjust for !fixinv, after picking 'from' slot the prompt for 'to'
        where x is last letter used (despite that, y could still be picked)
 with two-weapon combat or Cleaver attacking multiple targets, hero kept going
        with next attack after being paralyzed by passive counter-attack
+trap detection could falsely find trapped secret doors; those can't be trapped
+       due to details of how they use overlaid fields in the rm structure
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
@@ -1595,6 +1597,8 @@ pets are more likely to follow you closely if you are carrying something they
        really like to eat; behave as if you are carrying such whenever you
        are standing on stairs so that pets will try harder to come to you
 allow setting msgtype in SOUND line
+display detected door traps and chest traps as trapped doors and trapped
+       chests rather than as fake bear traps
 
 
 Platform- and/or Interface-Specific New Features
index 387729bca232784d8271641888885a1871913994..e388930a2997ae81118ee978b17088567539607a 100644 (file)
@@ -28,6 +28,12 @@ static void openone(int, int, genericptr_t);
 static int mfind0(struct monst *, boolean);
 static int reveal_terrain_getglyph(int, int, int, unsigned, int, int);
 
+/* dummytrap: used when detecting traps finds a door or chest trap; the
+   couple of fields that matter are always re-initialized during use so
+   this does not need to be part of 'struct instance_globals g'; fields
+   that aren't used are compile-/link-/load-time initialized to 0 */
+static struct trap dummytrap;
+
 /* wildcard class for clear_stale_map - this used to be used as a getobj()
    input but it's no longer used for that function */
 #define ALL_CLASSES (MAXOCLASSES + 1)
@@ -111,7 +117,7 @@ trapped_chest_at(int ttyp, int x, int y)
 
     if (!glyph_is_trap(glyph_at(x, y)))
         return FALSE;
-    if (ttyp != BEAR_TRAP || (Hallucination && rn2(20)))
+    if (ttyp != TRAPPED_CHEST || (Hallucination && rn2(20)))
         return FALSE;
 
     /*
@@ -153,7 +159,7 @@ trapped_door_at(int ttyp, int x, int y)
 
     if (!glyph_is_trap(glyph_at(x, y)))
         return FALSE;
-    if (ttyp != BEAR_TRAP || (Hallucination && rn2(20)))
+    if (ttyp != TRAPPED_DOOR || (Hallucination && rn2(20)))
         return FALSE;
     lev = &levl[x][y];
     if (!IS_DOOR(lev->typ))
@@ -851,14 +857,16 @@ sense_trap(struct trap *trap, xchar x, xchar y, int src_cursed)
     } else if (trap) {
         map_trap(trap, 1);
         trap->tseen = 1;
-    } else { /* trapped door or trapped chest */
-        struct trap temp_trap; /* fake trap */
-
-        (void) memset((genericptr_t) &temp_trap, 0, sizeof temp_trap);
-        temp_trap.tx = x;
-        temp_trap.ty = y;
-        temp_trap.ttyp = BEAR_TRAP; /* some kind of trap */
-        map_trap(&temp_trap, 1);
+    } else {
+        /*
+         * OBSOLETE; this was for trapped door or trapped chest
+         * but those are handled by 'if (trap) {map_trap()}' now
+         * and this block of code shouldn't be reachable anymore.
+         */
+        dummytrap.tx = x;
+        dummytrap.ty = y;
+        dummytrap.ttyp = BEAR_TRAP; /* some kind of trap */
+        map_trap(&dummytrap, 1);
     }
 }
 
@@ -870,8 +878,10 @@ sense_trap(struct trap *trap, xchar x, xchar y, int src_cursed)
    2 if found at some other spot, 3 if both, 0 otherwise; optionally
    update the map to show where such traps were found */
 static int
-detect_obj_traps(struct obj *objlist, boolean show_them,
-                 int how) /* 1 for misleading map feedback */
+detect_obj_traps(
+    struct obj *objlist,
+    boolean show_them,
+    int how) /* 1 for misleading map feedback */
 {
     struct obj *otmp;
     xchar x, y;
@@ -882,12 +892,15 @@ detect_obj_traps(struct obj *objlist, boolean show_them,
      * If so, should they be displayed as objects or as traps?
      */
 
+    dummytrap.ttyp = TRAPPED_CHEST;
     for (otmp = objlist; otmp; otmp = otmp->nobj) {
         if (Is_box(otmp) && otmp->otrapped
             && get_obj_location(otmp, &x, &y, BURIED_TOO | CONTAINED_TOO)) {
             result |= u_at(x, y) ? OTRAP_HERE : OTRAP_THERE;
-            if (show_them)
-                sense_trap((struct trap *) 0, x, y, how);
+            if (show_them) {
+                dummytrap.tx = x, dummytrap.ty = y;
+                sense_trap(&dummytrap, x, y, how);
+            }
         }
         if (Has_contents(otmp))
             result |= detect_obj_traps(otmp->cobj, show_them, how);
@@ -950,6 +963,11 @@ trap_detect(struct obj *sobj) /* null if crystal ball,
     /* door traps */
     for (door = 0; door < g.doorindex; door++) {
         cc = g.doors[door];
+        /* levl[][].doormask and .wall_info both overlay levl[][].flags;
+           the bit in doormask for D_TRAPPED is also a bit in wall_info;
+           secret doors use wall_info so can't be marked as trapped */
+        if (levl[cc.x][cc.y].typ == SDOOR)
+            continue;
         if (levl[cc.x][cc.y].doormask & D_TRAPPED) {
             if (cc.x != u.ux || cc.y != u.uy)
                 goto outtrapmap;
@@ -986,10 +1004,15 @@ trap_detect(struct obj *sobj) /* null if crystal ball,
     for (ttmp = g.ftrap; ttmp; ttmp = ttmp->ntrap)
         sense_trap(ttmp, 0, 0, cursed_src);
 
+    dummytrap.ttyp = TRAPPED_DOOR;
     for (door = 0; door < g.doorindex; door++) {
         cc = g.doors[door];
-        if (levl[cc.x][cc.y].doormask & D_TRAPPED)
-            sense_trap((struct trap *) 0, cc.x, cc.y, cursed_src);
+        if (levl[cc.x][cc.y].typ == SDOOR) /* see above */
+            continue;
+        if (levl[cc.x][cc.y].doormask & D_TRAPPED) {
+            dummytrap.tx = cc.x, dummytrap.ty = cc.y;
+            sense_trap(&dummytrap, cc.x, cc.y, cursed_src);
+        }
     }
 
     /* redisplay hero unless sense_trap() revealed something at <ux,uy> */
@@ -1575,6 +1598,8 @@ openone(int zx, int zy, genericptr_t num)
         }
         /* let it fall to the next cases. could be on trap. */
     }
+    /* note: secret doors can't be trapped; they use levl[][].wall_info;
+       see rm.h for the troublesome overlay of doormask and wall_info */
     if (levl[zx][zy].typ == SDOOR
         || (levl[zx][zy].typ == DOOR
             && (levl[zx][zy].doormask & (D_CLOSED | D_LOCKED)))) {
index 128d68c375492b1d9dd45c70eadcd6276ee8ed27..06ed6e6f3908dab0aa8277e4fd1c417d21dbd5e5 100644 (file)
@@ -145,11 +145,10 @@ monhealthdescr(struct monst *mon, boolean addspace, char *outbuf)
 static void
 trap_description(char *outbuf, int tnum, int x, int y)
 {
-    /* Trap detection displays a bear trap at locations having
-     * a trapped door or trapped container or both.
-     *
-     * TODO: we should create actual trap types for doors and
-     * chests so that they can have their own glyphs and tiles.
+    /*
+     * Trap detection used to display a bear trap at locations having
+     * a trapped door or trapped container or both.  They're semi-real
+     * traps now (defined trap types but not part of ftrap chain).
      */
     if (trapped_chest_at(tnum, x, y))
         Strcpy(outbuf, "trapped chest"); /* might actually be a large box */
@@ -1908,9 +1907,14 @@ doidtrap(void)
     x = u.ux + u.dx;
     y = u.uy + u.dy;
 
-    /* check fake bear trap from confused gold detection */
+    /* trapped doors and chests used to be shown as fake bear traps;
+       they have their own trap types now but aren't part of the ftrap
+       chain; usually they revert to normal door or chest when the hero
+       sees them but player might be using '^' while the hero is blind */
     glyph = glyph_at(x, y);
-    if (glyph_is_trap(glyph) && (tt = glyph_to_trap(glyph)) == BEAR_TRAP) {
+    if (glyph_is_trap(glyph)
+        && ((tt = glyph_to_trap(glyph)) == BEAR_TRAP
+            || tt == TRAPPED_DOOR || tt == TRAPPED_CHEST)) {
         boolean chesttrap = trapped_chest_at(tt, x, y);
 
         if (chesttrap || trapped_door_at(tt, x, y)) {