show trapped doors,chests as themselves \

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.
This commit is contained in:
PatR
2022-04-27 17:16:23 -07:00
parent 281d959b8b
commit 4ab68767bf
3 changed files with 56 additions and 23 deletions

View 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

View 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)))) {

View 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)) {