detecting chest and door traps

When confused gold detection finds a door trap or a chest trap, it
puts a bear trap glyph/tile on the map at that location.  (They
disappear once they're within sight.)  Those should be given their
own glyphs so that they can have their own tiles, but this doesn't
do that.  What it does do is describe such fake bear traps as
"trapped door" or "trapped chest" when examined with far-look.
The '^' command--if used while blind so that '^' hasn't disappeared
yet--needs to catch up: it says "I can't see a trap there" when the
adjacent '^' is a fake bear trap.
This commit is contained in:
PatR
2016-05-31 00:08:17 -07:00
parent 7404597ac5
commit 71113a6971
4 changed files with 90 additions and 31 deletions
+3 -1
View File
@@ -272,8 +272,10 @@ reviving one of a stack of N corpses in a shop charged a usage fee for all N;
remaining N-1 were owned by hero if carried but by shop if on floor remaining N-1 were owned by hero if carried but by shop if on floor
gremlin wailing in agony should wake up nearby monsters gremlin wailing in agony should wake up nearby monsters
add more lighting variance to the second bigroom variant add more lighting variance to the second bigroom variant
when getpost was picking a location, typing '^' to move to the next known trap when getpos was picking a location, typing '^' to move to the next known trap
skipped some detected traps if their location was unseen skipped some detected traps if their location was unseen
describe detected door traps and chest traps as trapped door and trapped chest
instead of bear trap; bear trap tile is still used on map though
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
+2
View File
@@ -236,6 +236,8 @@ E void NDECL(decl_init);
/* ### detect.c ### */ /* ### detect.c ### */
E boolean FDECL(trapped_chest_at, (int, int, int));
E boolean FDECL(trapped_door_at, (int, int, int));
E struct obj *FDECL(o_in, (struct obj *, CHAR_P)); E struct obj *FDECL(o_in, (struct obj *, CHAR_P));
E struct obj *FDECL(o_material, (struct obj *, unsigned)); E struct obj *FDECL(o_material, (struct obj *, unsigned));
E int FDECL(gold_detect, (struct obj *)); E int FDECL(gold_detect, (struct obj *));
+74 -29
View File
@@ -22,8 +22,44 @@ STATIC_PTR void FDECL(findone, (int, int, genericptr_t));
STATIC_PTR void FDECL(openone, (int, int, genericptr_t)); STATIC_PTR void FDECL(openone, (int, int, genericptr_t));
STATIC_DCL int FDECL(mfind0, (struct monst *, BOOLEAN_P)); STATIC_DCL int FDECL(mfind0, (struct monst *, BOOLEAN_P));
/* Recursively search obj for an object in class oclass and return 1st found /* this is checking whether a trap symbol represents a trapped chest,
*/ not whether a trapped chest is actually present */
boolean
trapped_chest_at(ttyp, x, y)
int ttyp;
int x, y;
{
if (!glyph_is_trap(glyph_at(x, y)))
return FALSE;
if (ttyp != BEAR_TRAP || (Hallucination && rn2(20)))
return FALSE;
/* presence of any trappable container will do */
return (sobj_at(CHEST, x, y) || sobj_at(LARGE_BOX, x, y)) ? TRUE : FALSE;
}
/* this is checking whether a trap symbol represents a trapped door,
not whether the door here is actually trapped */
boolean
trapped_door_at(ttyp, x, y)
int ttyp;
int x, y;
{
struct rm *lev;
if (!glyph_is_trap(glyph_at(x, y)))
return FALSE;
if (ttyp != BEAR_TRAP || (Hallucination && rn2(20)))
return FALSE;
lev = &levl[x][y];
if (!IS_DOOR(lev->typ))
return FALSE;
if ((lev->doormask & (D_NODOOR | D_BROKEN | D_ISOPEN)) != 0
&& trapped_chest_at(ttyp, x, y))
return FALSE;
return TRUE;
}
/* recursively search obj for an object in class oclass, return 1st found */
struct obj * struct obj *
o_in(obj, oclass) o_in(obj, oclass)
struct obj *obj; struct obj *obj;
@@ -39,7 +75,7 @@ char oclass;
for (otmp = obj->cobj; otmp; otmp = otmp->nobj) for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
if (otmp->oclass == oclass) if (otmp->oclass == oclass)
return otmp; return otmp;
else if (Has_contents(otmp) && (temp = o_in(otmp, oclass))) else if (Has_contents(otmp) && (temp = o_in(otmp, oclass)) != 0)
return temp; return temp;
} }
return (struct obj *) 0; return (struct obj *) 0;
@@ -64,7 +100,7 @@ unsigned material;
if (objects[otmp->otyp].oc_material == material) if (objects[otmp->otyp].oc_material == material)
return otmp; return otmp;
else if (Has_contents(otmp) else if (Has_contents(otmp)
&& (temp = o_material(otmp, material))) && (temp = o_material(otmp, material)) != 0)
return temp; return temp;
} }
return (struct obj *) 0; return (struct obj *) 0;
@@ -179,7 +215,7 @@ register struct obj *sobj;
if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
known = TRUE; known = TRUE;
goto outgoldmap; /* skip further searching */ goto outgoldmap; /* skip further searching */
} else } else {
for (obj = mtmp->minvent; obj; obj = obj->nobj) for (obj = mtmp->minvent; obj; obj = obj->nobj)
if (sobj->blessed && o_material(obj, GOLD)) { if (sobj->blessed && o_material(obj, GOLD)) {
known = TRUE; known = TRUE;
@@ -188,6 +224,7 @@ register struct obj *sobj;
known = TRUE; known = TRUE;
goto outgoldmap; /* skip further searching */ goto outgoldmap; /* skip further searching */
} }
}
} }
/* look for gold objects */ /* look for gold objects */
@@ -208,6 +245,7 @@ register struct obj *sobj;
adjust message if you have gold in your inventory */ adjust message if you have gold in your inventory */
if (sobj) { if (sobj) {
char buf[BUFSZ]; char buf[BUFSZ];
if (youmonst.data == &mons[PM_GOLD_GOLEM]) { if (youmonst.data == &mons[PM_GOLD_GOLEM]) {
Sprintf(buf, "You feel like a million %s!", currency(2L)); Sprintf(buf, "You feel like a million %s!", currency(2L));
} else if (hidden_gold() || money_cnt(invent)) } else if (hidden_gold() || money_cnt(invent))
@@ -232,13 +270,13 @@ outgoldmap:
u.uinwater = u.uburied = 0; u.uinwater = u.uburied = 0;
/* Discover gold locations. */ /* Discover gold locations. */
for (obj = fobj; obj; obj = obj->nobj) { for (obj = fobj; obj; obj = obj->nobj) {
if (sobj->blessed && (temp = o_material(obj, GOLD))) { if (sobj->blessed && (temp = o_material(obj, GOLD)) != 0) {
if (temp != obj) { if (temp != obj) {
temp->ox = obj->ox; temp->ox = obj->ox;
temp->oy = obj->oy; temp->oy = obj->oy;
} }
map_object(temp, 1); map_object(temp, 1);
} else if ((temp = o_in(obj, COIN_CLASS))) { } else if ((temp = o_in(obj, COIN_CLASS)) != 0) {
if (temp != obj) { if (temp != obj) {
temp->ox = obj->ox; temp->ox = obj->ox;
temp->oy = obj->oy; temp->oy = obj->oy;
@@ -251,24 +289,27 @@ outgoldmap:
continue; /* probably overkill here */ continue; /* probably overkill here */
if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
struct obj gold; struct obj gold;
gold = zeroobj; /* ensure oextra is cleared too */ gold = zeroobj; /* ensure oextra is cleared too */
gold.otyp = GOLD_PIECE; gold.otyp = GOLD_PIECE;
gold.quan = (long) rnd(10); /* usually more than 1 */
gold.ox = mtmp->mx; gold.ox = mtmp->mx;
gold.oy = mtmp->my; gold.oy = mtmp->my;
map_object(&gold, 1); map_object(&gold, 1);
} else } else {
for (obj = mtmp->minvent; obj; obj = obj->nobj) for (obj = mtmp->minvent; obj; obj = obj->nobj)
if (sobj->blessed && (temp = o_material(obj, GOLD))) { if (sobj->blessed && (temp = o_material(obj, GOLD)) != 0) {
temp->ox = mtmp->mx; temp->ox = mtmp->mx;
temp->oy = mtmp->my; temp->oy = mtmp->my;
map_object(temp, 1); map_object(temp, 1);
break; break;
} else if ((temp = o_in(obj, COIN_CLASS))) { } else if ((temp = o_in(obj, COIN_CLASS)) != 0) {
temp->ox = mtmp->mx; temp->ox = mtmp->mx;
temp->oy = mtmp->my; temp->oy = mtmp->my;
map_object(temp, 1); map_object(temp, 1);
break; break;
} }
}
} }
newsym(u.ux, u.uy); newsym(u.ux, u.uy);
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied; u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
@@ -505,7 +546,7 @@ int class; /* an object class, 0 for all */
* Map all buried objects first. * Map all buried objects first.
*/ */
for (obj = level.buriedobjlist; obj; obj = obj->nobj) for (obj = level.buriedobjlist; obj; obj = obj->nobj)
if (!class || (otmp = o_in(obj, class))) { if (!class || (otmp = o_in(obj, class)) != 0) {
if (class) { if (class) {
if (otmp != obj) { if (otmp != obj) {
otmp->ox = obj->ox; otmp->ox = obj->ox;
@@ -526,8 +567,8 @@ int class; /* an object class, 0 for all */
for (x = 1; x < COLNO; x++) for (x = 1; x < COLNO; x++)
for (y = 0; y < ROWNO; y++) for (y = 0; y < ROWNO; y++)
for (obj = level.objects[x][y]; obj; obj = obj->nexthere) for (obj = level.objects[x][y]; obj; obj = obj->nexthere)
if ((!class && !boulder) || (otmp = o_in(obj, class)) if ((!class && !boulder) || (otmp = o_in(obj, class)) != 0
|| (otmp = o_in(obj, boulder))) { || (otmp = o_in(obj, boulder)) != 0) {
if (class || boulder) { if (class || boulder) {
if (otmp != obj) { if (otmp != obj) {
otmp->ox = obj->ox; otmp->ox = obj->ox;
@@ -544,8 +585,8 @@ int class; /* an object class, 0 for all */
if (DEADMONSTER(mtmp)) if (DEADMONSTER(mtmp))
continue; continue;
for (obj = mtmp->minvent; obj; obj = obj->nobj) for (obj = mtmp->minvent; obj; obj = obj->nobj)
if ((!class && !boulder) || (otmp = o_in(obj, class)) if ((!class && !boulder) || (otmp = o_in(obj, class)) != 0
|| (otmp = o_in(obj, boulder))) { || (otmp = o_in(obj, boulder)) != 0) {
if (!class && !boulder) if (!class && !boulder)
otmp = obj; otmp = obj;
otmp->ox = mtmp->mx; /* at monster location */ otmp->ox = mtmp->mx; /* at monster location */
@@ -558,8 +599,9 @@ int class; /* an object class, 0 for all */
&& (!class || class == objects[mtmp->mappearance].oc_class)) { && (!class || class == objects[mtmp->mappearance].oc_class)) {
struct obj temp; struct obj temp;
temp.oextra = (struct oextra *) 0; temp = zeroobj;
temp.otyp = mtmp->mappearance; /* needed for obj_to_glyph() */ temp.otyp = mtmp->mappearance; /* needed for obj_to_glyph() */
temp.quan = 1L;
temp.ox = mtmp->mx; temp.ox = mtmp->mx;
temp.oy = mtmp->my; temp.oy = mtmp->my;
temp.corpsenm = PM_TENGU; /* if mimicing a corpse */ temp.corpsenm = PM_TENGU; /* if mimicing a corpse */
@@ -567,8 +609,10 @@ int class; /* an object class, 0 for all */
} else if (findgold(mtmp->minvent) } else if (findgold(mtmp->minvent)
&& (!class || class == COIN_CLASS)) { && (!class || class == COIN_CLASS)) {
struct obj gold; struct obj gold;
gold = zeroobj; /* ensure oextra is cleared too */ gold = zeroobj; /* ensure oextra is cleared too */
gold.otyp = GOLD_PIECE; gold.otyp = GOLD_PIECE;
gold.quan = (long) rnd(10); /* usually more than 1 */
gold.ox = mtmp->mx; gold.ox = mtmp->mx;
gold.oy = mtmp->my; gold.oy = mtmp->my;
map_object(&gold, 1); map_object(&gold, 1);
@@ -585,7 +629,6 @@ int class; /* an object class, 0 for all */
* and the detected object covers a known pool? * and the detected object covers a known pool?
*/ */
docrt(); /* this will correctly reset vision */ docrt(); /* this will correctly reset vision */
if (Underwater) if (Underwater)
under_water(2); under_water(2);
if (u.uburied) if (u.uburied)
@@ -675,7 +718,7 @@ int src_cursed;
if (Hallucination || src_cursed) { if (Hallucination || src_cursed) {
struct obj obj; /* fake object */ struct obj obj; /* fake object */
obj.oextra = (struct oextra *) 0; obj = zeroobj;
if (trap) { if (trap) {
obj.ox = trap->tx; obj.ox = trap->tx;
obj.oy = trap->ty; obj.oy = trap->ty;
@@ -683,7 +726,9 @@ int src_cursed;
obj.ox = x; obj.ox = x;
obj.oy = y; obj.oy = y;
} }
obj.otyp = (src_cursed) ? GOLD_PIECE : random_object(); obj.otyp = !Hallucination ? GOLD_PIECE : random_object();
obj.quan = (long) ((obj.otyp == GOLD_PIECE) ? rnd(10)
: objects[obj.otyp].oc_merge ? rnd(2) : 1);
obj.corpsenm = random_monster(); /* if otyp == CORPSE */ obj.corpsenm = random_monster(); /* if otyp == CORPSE */
map_object(&obj, 1); map_object(&obj, 1);
} else if (trap) { } else if (trap) {
@@ -691,6 +736,8 @@ int src_cursed;
trap->tseen = 1; trap->tseen = 1;
} else { } else {
struct trap temp_trap; /* fake trap */ struct trap temp_trap; /* fake trap */
(void) memset((genericptr_t) &temp_trap, 0, sizeof temp_trap);
temp_trap.tx = x; temp_trap.tx = x;
temp_trap.ty = y; temp_trap.ty = y;
temp_trap.ttyp = BEAR_TRAP; /* some kind of trap */ temp_trap.ttyp = BEAR_TRAP; /* some kind of trap */
@@ -735,8 +782,7 @@ int how; /* 1 for misleading map feedback */
*/ */
int int
trap_detect(sobj) trap_detect(sobj)
register struct obj *sobj; struct obj *sobj; /* null if crystal ball, *scroll if gold detection scroll */
/* sobj is null if crystal ball, *scroll if gold detection scroll */
{ {
register struct trap *ttmp; register struct trap *ttmp;
struct monst *mon; struct monst *mon;
@@ -759,8 +805,7 @@ register struct obj *sobj;
else else
found = TRUE; found = TRUE;
} }
if ((tr = detect_obj_traps(level.buriedobjlist, FALSE, 0)) if ((tr = detect_obj_traps(level.buriedobjlist, FALSE, 0)) != OTRAP_NONE) {
!= OTRAP_NONE) {
if (tr & OTRAP_THERE) if (tr & OTRAP_THERE)
goto outtrapmap; goto outtrapmap;
else else
@@ -798,6 +843,7 @@ register struct obj *sobj;
/* traps exist, but only under me - no separate display required */ /* traps exist, but only under me - no separate display required */
Your("%s itch.", makeplural(body_part(TOE))); Your("%s itch.", makeplural(body_part(TOE)));
return 0; return 0;
outtrapmap: outtrapmap:
cls(); cls();
@@ -993,10 +1039,10 @@ struct obj **optr;
nomul(-rnd(10)); nomul(-rnd(10));
multi_reason = "gazing into a crystal ball"; multi_reason = "gazing into a crystal ball";
nomovemsg = ""; nomovemsg = "";
if (obj->spe <= 0) if (obj->spe <= 0) {
pline_The("vision is unclear."); pline_The("vision is unclear.");
else { } else {
int class; int class, i;
int ret = 0; int ret = 0;
makeknown(CRYSTAL_BALL); makeknown(CRYSTAL_BALL);
@@ -1019,11 +1065,10 @@ struct obj **optr;
case '^': case '^':
ret = trap_detect((struct obj *) 0); ret = trap_detect((struct obj *) 0);
break; break;
default: { default:
int i = rn2(SIZE(level_detects)); i = rn2(SIZE(level_detects));
You_see("%s, %s.", level_detects[i].what, You_see("%s, %s.", level_detects[i].what,
level_distance(level_detects[i].where)); level_distance(level_detects[i].where));
}
ret = 0; ret = 0;
break; break;
} }
+11 -1
View File
@@ -379,7 +379,17 @@ char *buf, *monbuf;
} else if (glyph_is_trap(glyph)) { } else if (glyph_is_trap(glyph)) {
int tnum = what_trap(glyph_to_trap(glyph)); int tnum = what_trap(glyph_to_trap(glyph));
Strcpy(buf, defsyms[trap_to_defsym(tnum)].explanation); /* 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.
*/
if (trapped_chest_at(tnum, x, y))
Strcpy(buf, "trapped chest"); /* might actually be a large box */
else if (trapped_door_at(tnum, x, y))
Strcpy(buf, "trapped door"); /* not "trap door"... */
else
Strcpy(buf, defsyms[trap_to_defsym(tnum)].explanation);
} else if (glyph_is_warning(glyph)) { } else if (glyph_is_warning(glyph)) {
int warnindx = glyph_to_warning(glyph); int warnindx = glyph_to_warning(glyph);