]> granicus.if.org Git - nethack/commitdiff
fix #K105 - earthquake chasms
authorPatR <rankin@nethack.org>
Sun, 5 Jan 2020 09:20:15 +0000 (01:20 -0800)
committerPatR <rankin@nethack.org>
Sun, 5 Jan 2020 09:20:15 +0000 (01:20 -0800)
Drum of earthquake can try to destroy fountains, thrones, altars,
sinks, and graves but it wouldn't do so because maketrap() had been
changed to prevent clobbering furniture with traps.  So you might get
"the throne falls into a chasm" but the throne would remain intact.

Change furniture to be floor before trying to create a pit.  The gist
of the patch is the 'if' after 'do_pit:' and also some changes to the
revealing of hidden monsters.  The rest is reformatting.

doc/fixes37.0
src/music.c

index 66be2e7f870dcfa3b6a88c6301ab589db2169be1..891d8176216787b985dc1e5511c3eb1e06493634 100644 (file)
@@ -1,4 +1,4 @@
-$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.49 $ $NHDT-Date: 1578190894 2020/01/05 02:21:34 $
+$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.50 $ $NHDT-Date: 1578216006 2020/01/05 09:20:06 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -28,6 +28,9 @@ monster wielding Stormbringer or healer's Staff against another monster would
        heal the hero instead of the wielding monster when draining life
 change twoweapon feedback from "not a weapon" to "not a suitable weapon"
 don't allow twoweapon combat if either weapon is a bow, crossbow, or sling
+drum of earthquake feedback reported various things (fountains, thrones, &c)
+       falling into a chasm but they remained intact because trap creation
+       had been changed to not clobber such things (so couldn't make pits)
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 055c407d66cae5660b60b76804acdafda52689b1..2a6123d101d463b16525ceb50c4ebf7cca800357 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 music.c $NHDT-Date: 1573063606 2019/11/06 18:06:46 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.60 $ */
+/* NetHack 3.6 music.c $NHDT-Date: 1578216006 2020/01/05 09:20:06 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.66 $ */
 /*      Copyright (c) 1989 by Jean-Christophe Collet */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -224,16 +224,20 @@ static void
 do_earthquake(force)
 int force;
 {
+    static const char into_a_chasm[] = " into a chasm";
     register int x, y;
     struct monst *mtmp;
     struct obj *otmp;
     struct trap *chasm, *trap_at_u = t_at(u.ux, u.uy);
-    int start_x, start_y, end_x, end_y;
+    int start_x, start_y, end_x, end_y, amsk;
+    aligntyp algn;
     schar filltype;
     unsigned tu_pit = 0;
 
     if (trap_at_u)
         tu_pit = is_pit(trap_at_u->ttyp);
+    if (force > 13) /* sanity precaution; maximum used is actually 10 */
+        force = 13;
     start_x = u.ux - (force * 2);
     start_y = u.uy - (force * 2);
     end_x = u.ux + (force * 2);
@@ -246,180 +250,185 @@ int force;
         for (y = start_y; y <= end_y; y++) {
             if ((mtmp = m_at(x, y)) != 0) {
                 wakeup(mtmp, TRUE); /* peaceful monster will become hostile */
-                if (mtmp->mundetected && is_hider(mtmp->data)) {
+                if (mtmp->mundetected) {
                     mtmp->mundetected = 0;
-                    if (cansee(x, y))
-                        pline("%s is shaken loose from the ceiling!",
-                              Amonnam(mtmp));
-                    else
-                        You_hear("a thumping sound.");
-                    if (x == u.ux && y == u.uy)
-                        You("easily dodge the falling %s.", mon_nam(mtmp));
                     newsym(x, y);
+                    if (ceiling_hider(mtmp->data)) {
+                        if (cansee(x, y))
+                            pline("%s is shaken loose from the ceiling!",
+                                  Amonnam(mtmp));
+                        else if (!is_flyer(mtmp->data))
+                            You_hear("a thump.");
+                    }
                 }
+                if (M_AP_TYPE(mtmp) != M_AP_NOTHING
+                    && M_AP_TYPE(mtmp) != M_AP_MONSTER)
+                    seemimic(mtmp);
             }
-            if (!rn2(14 - force))
-                switch (levl[x][y].typ) {
-                case FOUNTAIN: /* Make the fountain disappear */
-                    if (cansee(x, y))
-                        pline_The("fountain falls into a chasm.");
-                    goto do_pit;
-                case SINK:
-                    if (cansee(x, y))
-                        pline_The("kitchen sink falls into a chasm.");
-                    goto do_pit;
-                case ALTAR:
-                    if (Is_astralevel(&u.uz) || Is_sanctum(&u.uz))
-                        break;
+            if (rn2(14 - force))
+                continue;
 
-                    if (cansee(x, y))
-                        pline_The("altar falls into a chasm.");
-                    goto do_pit;
-                case GRAVE:
-                    if (cansee(x, y))
-                        pline_The("headstone topples into a chasm.");
-                    goto do_pit;
-                case THRONE:
-                    if (cansee(x, y))
-                        pline_The("throne falls into a chasm.");
-                    /*FALLTHRU*/
-                case ROOM:
-                case CORR: /* Try to make a pit */
+            switch (levl[x][y].typ) {
+            case FOUNTAIN: /* make the fountain disappear */
+                if (cansee(x, y))
+                    pline_The("fountain falls%s.", into_a_chasm);
+                goto do_pit;
+            case SINK:
+                if (cansee(x, y))
+                    pline_The("kitchen sink falls%s.", into_a_chasm);
+                goto do_pit;
+            case ALTAR:
+                if (Is_astralevel(&u.uz) || Is_sanctum(&u.uz))
+                    break;
+                /* no need to check for high altar here; we've just
+                   excluded those */
+                amsk = altarmask_at(x, y);
+                algn = Amask2align(amsk & AM_MASK);
+                if (cansee(x, y))
+                    pline_The("%s altar falls%s.",
+                              align_str(algn), into_a_chasm);
+                goto do_pit;
+            case GRAVE:
+                if (cansee(x, y))
+                    pline_The("headstone topples%s.", into_a_chasm);
+                goto do_pit;
+            case THRONE:
+                if (cansee(x, y))
+                    pline_The("throne falls%s.", into_a_chasm);
+                /*FALLTHRU*/
+            case ROOM:
+            case CORR: /* Try to make a pit */
  do_pit:
-                    chasm = maketrap(x, y, PIT);
-                    if (!chasm)
-                        break; /* no pit if portal at that location */
-                    chasm->tseen = 1;
-
-                    /* TODO:
-                     * This ought to be split into a separate routine to
-                     * reduce indentation and the consequent line-wraps.
-                     */
-
-                    levl[x][y].doormask = 0;
-                    /*
-                     * Let liquid flow into the newly created chasm.
-                     * Adjust corresponding code in apply.c for
-                     * exploding wand of digging if you alter this sequence.
-                     */
-                    filltype = fillholetyp(x, y, FALSE);
-                    if (filltype != ROOM) {
-                        levl[x][y].typ = filltype; /* flags set via doormask */
-                        liquid_flow(x, y, filltype, chasm, (char *) 0);
-                    }
-
-                    mtmp = m_at(x, y);
+                /* maketrap() won't replace furniture with a trap,
+                   so remove the furniture first */
+                if (levl[x][y].typ != CORR) {
+                    if (levl[x][y].typ != DOOR)
+                        levl[x][y].typ = ROOM;
+                    levl[x][y].flags = 0; /* clear doormask (D_NODOOR) or
+                                           * altarmask or looted throne */
+                    levl[x][y].horizontal = 0; /* clear blessed fountain,
+                                                * disturbed grave */
+                }
+                chasm = maketrap(x, y, PIT);
+                if (!chasm)
+                    break; /* no pit if portal at that location */
+                chasm->tseen = 1;
+
+                /* Let liquid flow into the newly created chasm.
+                   Adjust corresponding code in apply.c for exploding
+                   wand of digging if you alter this sequence. */
+                filltype = fillholetyp(x, y, FALSE);
+                if (filltype != ROOM) {
+                    levl[x][y].typ = filltype; /* flags set via doormask */
+                    liquid_flow(x, y, filltype, chasm, (char *) 0);
+                }
 
-                    if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
-                        if (cansee(x, y))
-                            pline("KADOOM!  The boulder falls into a chasm%s!",
-                                  (x == u.ux && y == u.uy) ? " below you"
-                                                           : "");
-                        if (mtmp)
-                            mtmp->mtrapped = 0;
-                        obj_extract_self(otmp);
-                        (void) flooreffects(otmp, x, y, "");
-                        break;
-                    }
+                mtmp = m_at(x, y); /* (redundant?) */
+                if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
+                    if (cansee(x, y))
+                        pline("KADOOM!  The boulder falls into a chasm%s!",
+                              (x == u.ux && y == u.uy) ? " below you" : "");
+                    if (mtmp)
+                        mtmp->mtrapped = 0;
+                    obj_extract_self(otmp);
+                    (void) flooreffects(otmp, x, y, "");
+                    break; /* from switch, not loop */
+                }
 
-                    /* We have to check whether monsters or player
-                       falls in a chasm... */
-                    if (mtmp) {
-                        if (!is_flyer(mtmp->data)
-                            && !is_clinger(mtmp->data)) {
-                            boolean m_already_trapped = mtmp->mtrapped;
-
-                            mtmp->mtrapped = 1;
-                            if (!m_already_trapped) { /* suppress messages */
-                                if (cansee(x, y))
-                                    pline("%s falls into a chasm!",
-                                          Monnam(mtmp));
-                                else if (humanoid(mtmp->data))
-                                    You_hear("a scream!");
-                            }
-                            /* Falling is okay for falling down
-                                within a pit from jostling too */
-                            mselftouch(mtmp, "Falling, ", TRUE);
-                            if (!DEADMONSTER(mtmp)) {
-                                mtmp->mhp -= rnd(m_already_trapped ? 4 : 6);
-                                if (DEADMONSTER(mtmp)) {
-                                    if (!cansee(x, y)) {
-                                        pline("It is destroyed!");
-                                    } else {
-                                        You("destroy %s!",
-                                            mtmp->mtame
-                                              ? x_monnam(mtmp, ARTICLE_THE,
-                                                         "poor",
-                                                         has_mname(mtmp)
-                                                           ? SUPPRESS_SADDLE
-                                                           : 0,
-                                                         FALSE)
-                                              : mon_nam(mtmp));
-                                    }
-                                    xkilled(mtmp, XKILL_NOMSG);
+                /* We have to check whether monsters or player
+                   falls in a chasm... */
+                if (mtmp) {
+                    if (!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) {
+                        boolean m_already_trapped = mtmp->mtrapped;
+
+                        mtmp->mtrapped = 1;
+                        if (!m_already_trapped) { /* suppress messages */
+                            if (cansee(x, y))
+                                pline("%s falls into a chasm!", Monnam(mtmp));
+                            else if (humanoid(mtmp->data))
+                                You_hear("a scream!");
+                        }
+                        /* Falling is okay for falling down
+                           within a pit from jostling too */
+                        mselftouch(mtmp, "Falling, ", TRUE);
+                        if (!DEADMONSTER(mtmp)) {
+                            mtmp->mhp -= rnd(m_already_trapped ? 4 : 6);
+                            if (DEADMONSTER(mtmp)) {
+                                if (!cansee(x, y)) {
+                                    pline("It is destroyed!");
+                                } else {
+                                    You("destroy %s!",
+                                        mtmp->mtame
+                                         ? x_monnam(mtmp, ARTICLE_THE, "poor",
+                                                    has_mname(mtmp)
+                                                     ? SUPPRESS_SADDLE : 0,
+                                                    FALSE)
+                                         : mon_nam(mtmp));
                                 }
+                                xkilled(mtmp, XKILL_NOMSG);
                             }
                         }
-                    } else if (x == u.ux && y == u.uy) {
-                        if (u.utrap && u.utraptype == TT_BURIEDBALL) {
-                            /* Note:  the chain should break if a pit gets
-                               created at the buried ball's location, which
-                               is not necessarily here.  But if we don't do
-                               things this way, entering the new pit below
-                               will override current trap anyway, but too
-                               late to get Lev and Fly handling. */
-                            Your("chain breaks!");
-                            reset_utrap(TRUE);
+                    }
+                } else if (x == u.ux && y == u.uy) {
+                    if (u.utrap && u.utraptype == TT_BURIEDBALL) {
+                        /* Note:  the chain should break if a pit gets
+                           created at the buried ball's location, which
+                           is not necessarily here.  But if we don't do
+                           things this way, entering the new pit below
+                           will override current trap anyway, but too
+                           late to get Lev and Fly handling. */
+                        Your("chain breaks!");
+                        reset_utrap(TRUE);
+                    }
+                    if (Levitation || Flying || is_clinger(g.youmonst.data)) {
+                        if (!tu_pit) { /* no pit here previously */
+                            pline("A chasm opens up under you!");
+                            You("don't fall in!");
                         }
-                        if (Levitation || Flying
-                            || is_clinger(g.youmonst.data)) {
-                            if (!tu_pit) { /* no pit here previously */
-                                pline("A chasm opens up under you!");
-                                You("don't fall in!");
-                            }
-                        } else if (!tu_pit || !u.utrap
-                                   || (u.utrap && u.utraptype != TT_PIT)) {
-                            /* no pit here previously, or you were
-                               not in it even if there was */
-                            You("fall into a chasm!");
-                            set_utrap(rn1(6, 2), TT_PIT);
-                            losehp(Maybe_Half_Phys(rnd(6)),
-                                   "fell into a chasm", NO_KILLER_PREFIX);
-                            selftouch("Falling, you");
-                        } else if (u.utrap && u.utraptype == TT_PIT) {
-                            boolean keepfooting =
+                    } else if (!tu_pit || !u.utrap || u.utraptype != TT_PIT) {
+                        /* no pit here previously, or you were
+                           not in it even if there was */
+                        You("fall into a chasm!");
+                        set_utrap(rn1(6, 2), TT_PIT);
+                        losehp(Maybe_Half_Phys(rnd(6)),
+                               "fell into a chasm", NO_KILLER_PREFIX);
+                        selftouch("Falling, you");
+                    } else if (u.utrap && u.utraptype == TT_PIT) {
+                        boolean keepfooting =
                                 ((Fumbling && !rn2(5))
                                  || (!rnl(Role_if(PM_ARCHEOLOGIST) ? 3 : 9))
                                  || ((ACURR(A_DEX) > 7) && rn2(5)));
 
-                            You("are jostled around violently!");
-                            set_utrap(rn1(6, 2), TT_PIT);
-                            losehp(Maybe_Half_Phys(rnd(keepfooting ? 2 : 4)),
-                                   "hurt in a chasm", NO_KILLER_PREFIX);
-                            if (keepfooting)
-                                exercise(A_DEX, TRUE);
-                            else
-                                selftouch(
-                                    (Upolyd && (slithy(g.youmonst.data)
-                                                || nolimbs(g.youmonst.data)))
-                                        ? "Shaken, you"
-                                        : "Falling down, you");
-                        }
-                    } else
-                        newsym(x, y);
-                    break;
-                case DOOR: /* Make the door collapse */
-                    if (levl[x][y].doormask == D_NODOOR)
-                        goto do_pit;
-                    if (cansee(x, y))
-                        pline_The("door collapses.");
-                    if (*in_rooms(x, y, SHOPBASE))
-                        add_damage(x, y, 0L);
-                    levl[x][y].doormask = D_NODOOR;
-                    unblock_point(x, y);
+                        You("are jostled around violently!");
+                        set_utrap(rn1(6, 2), TT_PIT);
+                        losehp(Maybe_Half_Phys(rnd(keepfooting ? 2 : 4)),
+                               "hurt in a chasm", NO_KILLER_PREFIX);
+                        if (keepfooting)
+                            exercise(A_DEX, TRUE);
+                        else
+                            selftouch((Upolyd && (slithy(g.youmonst.data)
+                                                  || nolimbs(g.youmonst.data)))
+                                      ? "Shaken, you"
+                                      : "Falling down, you");
+                    }
+                } else {
                     newsym(x, y);
-                    break;
                 }
+                break;
+            case DOOR: /* make the door collapse */
+                if (levl[x][y].doormask == D_NODOOR)
+                    goto do_pit;
+                /* TODO:  if door is trapped, the trap should explode;
+                   forcing D_NODOOR just makes trap silently go away */
+                if (cansee(x, y))
+                    pline_The("door collapses.");
+                if (*in_rooms(x, y, SHOPBASE))
+                    add_damage(x, y, 0L);
+                levl[x][y].doormask = D_NODOOR;
+                unblock_point(x, y);
+                newsym(x, y);
+                break;
+            }
         }
 }