]> granicus.if.org Git - nethack/commitdiff
Cancellation explodes magical traps
authorPasi Kallinen <paxed@alt.org>
Fri, 28 Jan 2022 06:30:08 +0000 (08:30 +0200)
committerPasi Kallinen <paxed@alt.org>
Fri, 28 Jan 2022 06:30:08 +0000 (08:30 +0200)
doc/fixes37.0
include/objclass.h
include/trap.h
src/dig.c
src/explode.c
src/mkmaze.c
src/sp_lev.c
src/trap.c
src/zap.c

index 5bc61aa90fec6540441a4522b47989767285569b..a56a947e13ae138950b40cf7d2fbda36ede38916 100644 (file)
@@ -1365,6 +1365,7 @@ drinking blessed potion of full healing heals wounded legs, either hero's or
        steed's (when riding, wounded leg injury applies to steed, not hero)
 drinking uncursed potion of full healing or blessed potion of extra healing
        heal hero's wounded legs when not riding; no effect on steed if riding
+cancellation explodes most magical traps
 
 
 Platform- and/or Interface-Specific New Features
index 1180017523665c62e18092d0f5b795257b06352a..2eccd95fc0cf6304bdaf3c00f7cb45bb17388537 100644 (file)
@@ -147,6 +147,7 @@ enum objclass_syms {
 
 #define BURNING_OIL (MAXOCLASSES + 1) /* Can be used as input to explode.   */
 #define MON_EXPLODE (MAXOCLASSES + 2) /* Exploding monster (e.g. gas spore) */
+#define TRAP_EXPLODE (MAXOCLASSES + 3)
 
 #if 0 /* moved to decl.h so that makedefs.c won't see them */
 extern const struct class_sym
index 59cb01f948ecafa5dcba141674c94f96b8a3d492..60e4aa9e4d4ecd8c16b8bfe831555aebd6773747 100644 (file)
@@ -84,6 +84,13 @@ enum trap_types {
 
 #define is_pit(ttyp) ((ttyp) == PIT || (ttyp) == SPIKED_PIT)
 #define is_hole(ttyp)  ((ttyp) == HOLE || (ttyp) == TRAPDOOR)
+#define undestroyable_trap(ttyp) ((ttyp) == MAGIC_PORTAL         \
+                                  || (ttyp) == VIBRATING_SQUARE)
+#define is_magical_trap(ttyp) ((ttyp) == TELEP_TRAP     \
+                               || (ttyp) == LEVEL_TELEP \
+                               || (ttyp) == MAGIC_TRAP  \
+                               || (ttyp) == ANTI_MAGIC  \
+                               || (ttyp) == POLY_TRAP)
 /* "transportation" traps */
 #define is_xport(ttyp) ((ttyp) >= TELEP_TRAP && (ttyp) <= MAGIC_PORTAL)
 
index e6a12c90252b3463cd19d35ab38b0604608340aa..454d8cc51e9ca5f15f36a855f0b3f6a2ae851cb6 100644 (file)
--- a/src/dig.c
+++ b/src/dig.c
@@ -207,8 +207,7 @@ dig_check(struct monst *madeby, boolean verbose, int x, int y)
     } else if ((IS_ROCK(levl[x][y].typ) && levl[x][y].typ != SDOOR
                 && (levl[x][y].wall_info & W_NONDIGGABLE) != 0)
                || (ttmp
-                   && (ttmp->ttyp == MAGIC_PORTAL
-                       || ttmp->ttyp == VIBRATING_SQUARE
+                   && (undestroyable_trap(ttmp->ttyp)
                        || (!Can_dig_down(&u.uz) && !levl[x][y].candig)))) {
         if (verbose)
             pline_The("%s here is too hard to %s.", surface(x, y), verb);
@@ -790,8 +789,7 @@ dighole(boolean pit_only, boolean by_magic, coord *cc)
     nohole = (!Can_dig_down(&u.uz) && !lev->candig);
     old_typ = lev->typ;
 
-    if ((ttmp && (ttmp->ttyp == MAGIC_PORTAL
-                  || ttmp->ttyp == VIBRATING_SQUARE || nohole))
+    if ((ttmp && (undestroyable_trap(ttmp->ttyp) || nohole))
         || (IS_ROCK(old_typ) && old_typ != SDOOR
             && (lev->wall_info & W_NONDIGGABLE) != 0)) {
         pline_The("%s %shere is too hard to dig in.", surface(dig_x, dig_y),
index c10eea0244a1b266d1668f3f61476e487d350807..84da15f952457a6867e3d06fdbacdf864cae2c7a 100644 (file)
@@ -314,7 +314,7 @@ explode(
 
         tmp_at(DISP_END, 0); /* clear the explosion */
     } else {
-        if (olet == MON_EXPLODE) {
+        if (olet == MON_EXPLODE || olet == TRAP_EXPLODE) {
             str = "explosion";
             generic = TRUE;
         }
index 32ef3bc9bdffab5deb0445f8f7342df0abc46b8f..f4aa66f3de514bfb66cc847d7dd43f843c8a3b0d 100644 (file)
@@ -320,7 +320,7 @@ put_lregion_here(
                It might still fail if there's a dungeon feature here. */
             struct trap *t = t_at(x, y);
 
-            if (t && t->ttyp != MAGIC_PORTAL && t->ttyp != VIBRATING_SQUARE)
+            if (t && !undestroyable_trap(t->ttyp))
                 deltrap(t);
             if (bad_location(x, y, nlx, nly, nhx, nhy))
                 return FALSE;
index 0187679faa04c362aee96d7f1ff8e2b0d1377304..7efbb091a3a12596bf5d60742aa9b2c669af54a8 100644 (file)
@@ -5256,8 +5256,7 @@ ensure_way_out(void)
     }
 
     while (ttmp) {
-        if ((ttmp->ttyp == MAGIC_PORTAL || ttmp->ttyp == VIBRATING_SQUARE
-             || is_hole(ttmp->ttyp))
+        if ((undestroyable_trap(ttmp->ttyp) || is_hole(ttmp->ttyp))
             && !selection_getpoint(ttmp->tx, ttmp->ty, ov))
             selection_floodfill(ov, ttmp->tx, ttmp->ty, TRUE);
         ttmp = ttmp->ntrap;
index 32ddde59038ad9033cdd6fa4245bc44f4102130c..ba07f096ed10830a120f19eefb4930ec580a97e6 100644 (file)
@@ -346,7 +346,7 @@ maketrap(int x, int y, int typ)
     struct rm *lev = &levl[x][y];
 
     if ((ttmp = t_at(x, y)) != 0) {
-        if (ttmp->ttyp == MAGIC_PORTAL || ttmp->ttyp == VIBRATING_SQUARE)
+        if (undestroyable_trap(ttmp->ttyp))
             return (struct trap *) 0;
         oldplace = TRUE;
         if (u.utrap && x == u.ux && y == u.uy
@@ -2441,7 +2441,7 @@ dotrap(register struct trap* trap, unsigned int trflags)
                 trapname(ttype, FALSE));
             return;
         }
-        if (!Fumbling && ttype != MAGIC_PORTAL && ttype != VIBRATING_SQUARE
+        if (!Fumbling && !undestroyable_trap(ttype)
             && ttype != ANTI_MAGIC && !forcebungle && !plunged
             && !conj_pit && !adj_pit
             && (!rn2(5) || (is_pit(ttype)
index ae0080418f14d7eba8a77ecd3a75024e302e7d91..dcecbe39c33fd42099d4f250e393f81bf8d8d9ff 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -21,6 +21,7 @@ static void zhitu(int, int, const char *, xchar, xchar);
 static void revive_egg(struct obj *);
 static boolean zap_steed(struct obj *);
 static void skiprange(int, int *, int *);
+static void maybe_explode_trap(struct trap *, struct obj *);
 static int zap_hit(int, int);
 static void disintegrate_mon(struct monst *, int, const char *);
 static int adtyp_to_prop(int);
@@ -3138,6 +3139,10 @@ zap_updown(struct obj *obj) /* wand or spell */
                 break;
             }
         }
+
+        maybe_explode_trap(ttmp, obj);
+        /* note: ttmp might be now gone */
+
     } else if (u.dz < 0) {
         /* zapping upward */
 
@@ -3335,6 +3340,34 @@ skiprange(int range, int *skipstart, int *skipend)
         *skipend = tmp - 1;
 }
 
+/* maybe explode a trap hit by object otmp's effect;
+   cancellation beam hitting a magical trap causes an explosion.
+   might delete the trap.  */
+static void
+maybe_explode_trap(struct trap *ttmp, struct obj *otmp)
+{
+    if (!ttmp || !otmp)
+        return;
+    if (otmp->otyp == WAN_CANCELLATION || otmp->otyp == SPE_CANCELLATION) {
+        xchar x = ttmp->tx, y = ttmp->ty;
+
+        if (undestroyable_trap(ttmp->ttyp)) {
+            shieldeff(x, y);
+            if (cansee(x, y)) {
+                ttmp->tseen = 1;
+                newsym(x, y);
+            }
+        } else if (is_magical_trap(ttmp->ttyp)) {
+            if (!Deaf)
+                pline("Kaboom!");
+            explode(x, y, -WAN_CANCELLATION,
+                    20+d(3,6), TRAP_EXPLODE, EXPL_MAGICAL);
+            deltrap(ttmp);
+            newsym(x, y);
+        }
+    }
+}
+
 /*
  *  Called for the following distance effects:
  *      when a weapon is thrown (weapon == THROWN_WEAPON)
@@ -3468,6 +3501,9 @@ bhit(int ddx, int ddy, int range,  /* direction and range */
                 learnwand(obj);
         }
 
+        if (weapon == ZAPPED_WAND)
+            maybe_explode_trap(t_at(g.bhitpos.x, g.bhitpos.y), obj);
+
         mtmp = m_at(g.bhitpos.x, g.bhitpos.y);
 
         /*