items destroyed by exploding chest

From a report by a beta tester 8 years ago:  kicking a chest gave
"THUD!  The chest explodes!" but the chest remained intact.  The
explosion was destroying all floor items at the hero's spot rather
than at the chest's spot.  Fixing that results in the chest being
destroyed because it's one of the items at its own spot.

While fixing that I noticed that delobj() was only protecting the
Amulet and the invocation items from destruction, not Rider corpses.
You could destroy one or more of those by getting a trapped chest's
explosion while using a key at its spot rather than by kicking it
from adjacent.  (Getting the exploding chest result is not easy,
particuarly with positive luck.  I eventually resorted to forcing
it with a debugger.)
This commit is contained in:
PatR
2022-03-27 17:55:52 -07:00
parent c763e26aa7
commit 6a2ff5743a
3 changed files with 22 additions and 12 deletions

View File

@@ -1,4 +1,4 @@
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.849 $ $NHDT-Date: 1648318980 2022/03/26 18:23:00 $
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.851 $ $NHDT-Date: 1648428942 2022/03/28 00:55:42 $
General Fixes and Modified Features
-----------------------------------
@@ -850,6 +850,10 @@ don't stop travel when going past a closed door (eg. when traveling along
a room wall)
some monster corpses can now convey temporary acid or stoning resistance
fix travel getting stuck oscillating between two locations
kicking a trapped chest and getting the exploding chest result destroyed items
at the hero's location rather than the chest's location; because of
that it left the exploded chest intact
it was possible to destroy a Rider corpse with an exploding chest
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 invent.c $NHDT-Date: 1647472704 2022/03/16 23:18:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.355 $ */
/* NetHack 3.7 invent.c $NHDT-Date: 1648428942 2022/03/28 00:55:42 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.359 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1204,10 +1204,9 @@ delobj(struct obj *obj)
{
boolean update_map;
if (obj->otyp == AMULET_OF_YENDOR
|| obj->otyp == CANDELABRUM_OF_INVOCATION
|| obj->otyp == BELL_OF_OPENING
|| obj->otyp == SPE_BOOK_OF_THE_DEAD) {
/* obj_resists(obj,0,0) protects the Amulet, the invocation tools,
and Rider corspes */
if (obj_resists(obj, 0, 0)) {
/* player might be doing something stupid, but we
* can't guarantee that. assume special artifacts
* are indestructible via drawbridges, and exploding

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 trap.c $NHDT-Date: 1646428017 2022/03/04 21:06:57 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.459 $ */
/* NetHack 3.7 trap.c $NHDT-Date: 1648428945 2022/03/28 00:55:45 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.471 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */
@@ -5430,7 +5430,7 @@ chest_trap(
struct monst *shkp = 0;
long loss = 0L;
boolean costly, insider;
register xchar ox = obj->ox, oy = obj->oy;
xchar ox = obj->ox, oy = obj->oy;
/* the obj location need not be that of player */
costly = (costly_spot(ox, oy)
@@ -5446,14 +5446,21 @@ chest_trap(
loss += stolen_value(obj, ox, oy, (boolean) shkp->mpeaceful,
TRUE);
delete_contents(obj);
/*
* Note: the explosion is taking place at the chest's
* location, not necessarily at the hero's. (Simplest
* case: kicking it from one step away and getting the
* chest_trap() outcome.)
*/
/* unpunish() in advance if either ball or chain (or both)
is going to be destroyed */
if (Punished && (u_at(uchain->ox, uchain->oy)
if (Punished && ((uchain->ox == ox && uchain->oy == oy)
|| (uball->where == OBJ_FLOOR
&& u_at(uball->ox, uball->oy))))
&& uball->ox == ox && uball->oy == oy)))
unpunish();
for (otmp = g.level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
/* destroy everything at the spot (the Amulet, the
invocation tools, and Rider corpses will remain intact) */
for (otmp = g.level.objects[ox][oy]; otmp; otmp = otmp2) {
otmp2 = otmp->nexthere;
if (costly)
loss += stolen_value(otmp, otmp->ox, otmp->oy,