fix #K105 - earthquake chasms

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.
This commit is contained in:
PatR
2020-01-05 01:20:15 -08:00
parent 4b2ba5acc7
commit 5292ab5de0
2 changed files with 173 additions and 161 deletions
+4 -1
View 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 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 heal the hero instead of the wielding monster when draining life
change twoweapon feedback from "not a weapon" to "not a suitable weapon" 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 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 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
+169 -160
View 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 */ /* Copyright (c) 1989 by Jean-Christophe Collet */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -224,16 +224,20 @@ static void
do_earthquake(force) do_earthquake(force)
int force; int force;
{ {
static const char into_a_chasm[] = " into a chasm";
register int x, y; register int x, y;
struct monst *mtmp; struct monst *mtmp;
struct obj *otmp; struct obj *otmp;
struct trap *chasm, *trap_at_u = t_at(u.ux, u.uy); 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; schar filltype;
unsigned tu_pit = 0; unsigned tu_pit = 0;
if (trap_at_u) if (trap_at_u)
tu_pit = is_pit(trap_at_u->ttyp); 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_x = u.ux - (force * 2);
start_y = u.uy - (force * 2); start_y = u.uy - (force * 2);
end_x = u.ux + (force * 2); end_x = u.ux + (force * 2);
@@ -246,180 +250,185 @@ int force;
for (y = start_y; y <= end_y; y++) { for (y = start_y; y <= end_y; y++) {
if ((mtmp = m_at(x, y)) != 0) { if ((mtmp = m_at(x, y)) != 0) {
wakeup(mtmp, TRUE); /* peaceful monster will become hostile */ wakeup(mtmp, TRUE); /* peaceful monster will become hostile */
if (mtmp->mundetected && is_hider(mtmp->data)) { if (mtmp->mundetected) {
mtmp->mundetected = 0; 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); newsym(x, y);
} if (ceiling_hider(mtmp->data)) {
}
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 (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 */
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);
if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
if (cansee(x, y)) if (cansee(x, y))
pline("KADOOM! The boulder falls into a chasm%s!", pline("%s is shaken loose from the ceiling!",
(x == u.ux && y == u.uy) ? " below you" Amonnam(mtmp));
: ""); else if (!is_flyer(mtmp->data))
if (mtmp) You_hear("a thump.");
mtmp->mtrapped = 0;
obj_extract_self(otmp);
(void) flooreffects(otmp, x, y, "");
break;
} }
}
if (M_AP_TYPE(mtmp) != M_AP_NOTHING
&& M_AP_TYPE(mtmp) != M_AP_MONSTER)
seemimic(mtmp);
}
if (rn2(14 - force))
continue;
/* We have to check whether monsters or player switch (levl[x][y].typ) {
falls in a chasm... */ case FOUNTAIN: /* make the fountain disappear */
if (mtmp) { if (cansee(x, y))
if (!is_flyer(mtmp->data) pline_The("fountain falls%s.", into_a_chasm);
&& !is_clinger(mtmp->data)) { goto do_pit;
boolean m_already_trapped = mtmp->mtrapped; 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:
/* 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;
mtmp->mtrapped = 1; /* Let liquid flow into the newly created chasm.
if (!m_already_trapped) { /* suppress messages */ Adjust corresponding code in apply.c for exploding
if (cansee(x, y)) wand of digging if you alter this sequence. */
pline("%s falls into a chasm!", filltype = fillholetyp(x, y, FALSE);
Monnam(mtmp)); if (filltype != ROOM) {
else if (humanoid(mtmp->data)) levl[x][y].typ = filltype; /* flags set via doormask */
You_hear("a scream!"); liquid_flow(x, y, filltype, chasm, (char *) 0);
} }
/* Falling is okay for falling down
within a pit from jostling too */ mtmp = m_at(x, y); /* (redundant?) */
mselftouch(mtmp, "Falling, ", TRUE); if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
if (!DEADMONSTER(mtmp)) { if (cansee(x, y))
mtmp->mhp -= rnd(m_already_trapped ? 4 : 6); pline("KADOOM! The boulder falls into a chasm%s!",
if (DEADMONSTER(mtmp)) { (x == u.ux && y == u.uy) ? " below you" : "");
if (!cansee(x, y)) { if (mtmp)
pline("It is destroyed!"); mtmp->mtrapped = 0;
} else { obj_extract_self(otmp);
You("destroy %s!", (void) flooreffects(otmp, x, y, "");
mtmp->mtame break; /* from switch, not loop */
? x_monnam(mtmp, ARTICLE_THE, }
"poor",
has_mname(mtmp) /* We have to check whether monsters or player
? SUPPRESS_SADDLE falls in a chasm... */
: 0, if (mtmp) {
FALSE) if (!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) {
: mon_nam(mtmp)); boolean m_already_trapped = mtmp->mtrapped;
}
xkilled(mtmp, XKILL_NOMSG); 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) { } else if (x == u.ux && y == u.uy) {
/* Note: the chain should break if a pit gets if (u.utrap && u.utraptype == TT_BURIEDBALL) {
created at the buried ball's location, which /* Note: the chain should break if a pit gets
is not necessarily here. But if we don't do created at the buried ball's location, which
things this way, entering the new pit below is not necessarily here. But if we don't do
will override current trap anyway, but too things this way, entering the new pit below
late to get Lev and Fly handling. */ will override current trap anyway, but too
Your("chain breaks!"); late to get Lev and Fly handling. */
reset_utrap(TRUE); 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 } else if (!tu_pit || !u.utrap || u.utraptype != TT_PIT) {
|| is_clinger(g.youmonst.data)) { /* no pit here previously, or you were
if (!tu_pit) { /* no pit here previously */ not in it even if there was */
pline("A chasm opens up under you!"); You("fall into a chasm!");
You("don't fall in!"); set_utrap(rn1(6, 2), TT_PIT);
} losehp(Maybe_Half_Phys(rnd(6)),
} else if (!tu_pit || !u.utrap "fell into a chasm", NO_KILLER_PREFIX);
|| (u.utrap && u.utraptype != TT_PIT)) { selftouch("Falling, you");
/* no pit here previously, or you were } else if (u.utrap && u.utraptype == TT_PIT) {
not in it even if there was */ boolean keepfooting =
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)) ((Fumbling && !rn2(5))
|| (!rnl(Role_if(PM_ARCHEOLOGIST) ? 3 : 9)) || (!rnl(Role_if(PM_ARCHEOLOGIST) ? 3 : 9))
|| ((ACURR(A_DEX) > 7) && rn2(5))); || ((ACURR(A_DEX) > 7) && rn2(5)));
You("are jostled around violently!"); You("are jostled around violently!");
set_utrap(rn1(6, 2), TT_PIT); set_utrap(rn1(6, 2), TT_PIT);
losehp(Maybe_Half_Phys(rnd(keepfooting ? 2 : 4)), losehp(Maybe_Half_Phys(rnd(keepfooting ? 2 : 4)),
"hurt in a chasm", NO_KILLER_PREFIX); "hurt in a chasm", NO_KILLER_PREFIX);
if (keepfooting) if (keepfooting)
exercise(A_DEX, TRUE); exercise(A_DEX, TRUE);
else else
selftouch( selftouch((Upolyd && (slithy(g.youmonst.data)
(Upolyd && (slithy(g.youmonst.data) || nolimbs(g.youmonst.data)))
|| nolimbs(g.youmonst.data))) ? "Shaken, you"
? "Shaken, you" : "Falling down, you");
: "Falling down, you"); }
} } else {
} 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);
newsym(x, y); 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;
}
} }
} }