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

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