detection revamp

Change most instances of detection to offer the player a chance to
move the cursor around on the map so that the getpos() autodescribe
feature can explain things that might go away as soon as the
current detection completes.  The few instances that don't offer
such a chance are the ones where everything which has been revealed
will still be there once the action finishes (such as regular magic
mapping and blessed/persistent monster detection).

There were quite a lot of inconsistencies in things like handling
for detection while swallowed or underwater.  I didn't keep track
of them to distinguish between 3.6.0, current dev code, or my patch
in progess.  They should be much more consistent now but without a
comprehensive fixes36.1 entry.

Blessed clairvoyance (divination spells at skilled or expert) now
shows monsters as well as terrain.  I first had it like that for
any clairvoyance, but having getpos/autodescribe kick in every 15
or 30 turns once you have the amulet--or pay the appropriate amount
to a temple preist--was nearly unplayable.  When it only follows an
explicit spell cast it is not intrusive.
This commit is contained in:
PatR
2016-06-02 01:08:34 -07:00
parent a5d57430be
commit 894d6c6859
7 changed files with 334 additions and 154 deletions
+9 -4
View File
@@ -280,6 +280,8 @@ thrown potion that killed peaceful monster would cause "the <mon> gets argry"
after the message about it being killed after the message about it being killed
when poly'd into a hider and engulfed, attempt to hide via #monster was blocked when poly'd into a hider and engulfed, attempt to hide via #monster was blocked
but feedback said "can't hide while held" rather than "while engulfed" but feedback said "can't hide while held" rather than "while engulfed"
various monster/object/food/gold/trap detections were inconsistent in how they
behaved if performed while engulfed or underwater
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
@@ -395,9 +397,12 @@ during end of game disclosure, the vanquished monsters list can be sorted in
one of several ways by answering 'a' to "disclose vanquished monsters?" one of several ways by answering 'a' to "disclose vanquished monsters?"
when #terrain is displaying a censored version of the map (no monsters, &c), when #terrain is displaying a censored version of the map (no monsters, &c),
moving the cursor will display farlook's brief autodescribe feedback moving the cursor will display farlook's brief autodescribe feedback
when monster/object/trap detection temporarily clears the map to highlight the
results of such detection, farlook autodescibe can be used to view it
interrupt a multi turn action if hp or pw is restored to maximum interrupt a multi turn action if hp or pw is restored to maximum
pressing d or D when cursor positioning targets doors and doorways pressing d or D when cursor positioning targets doors and doorways
pressing x or X when cursor positioning targets possibly unexplored location pressing x or X when cursor positioning targets possibly unexplored location
(potentially useful when using '_' [not mouse] to invoke travel)
Platform- and/or Interface-Specific New Features Platform- and/or Interface-Specific New Features
@@ -420,10 +425,10 @@ X11: status display split into three columns to accomodate Stone/Deaf/Lev/&c;
NetHack Community Patches (or Variation) Included NetHack Community Patches (or Variation) Included
------------------------------------------------- -------------------------------------------------
Malcolm Ryan's improved tin opener Malcolm Ryan's improved tin opener
Ray Chason's keyboard may stop responding after locking or unlocking a door when Ray Chason's keyboard may stop responding after locking or unlocking a door
using altkeyhandler=nhraykey.dll when using altkeyhandler=nhraykey.dll
Ray Chason's fix: window interfaces that support transparency may give away unseen Ray Chason's fix: window interfaces that support transparency may give away
parts of the map unseen parts of the map
Ray Chason's xprname should honor iflags.menu_tab_sep Ray Chason's xprname should honor iflags.menu_tab_sep
Ray Chason's punctuation for "That foo is really a mimic." Ray Chason's punctuation for "That foo is really a mimic."
Ray Chason's proper background tiles for lava and water Ray Chason's proper background tiles for lava and water
+1 -1
View File
@@ -248,7 +248,7 @@ E int FDECL(trap_detect, (struct obj *));
E const char *FDECL(level_distance, (d_level *)); E const char *FDECL(level_distance, (d_level *));
E void FDECL(use_crystal_ball, (struct obj **)); E void FDECL(use_crystal_ball, (struct obj **));
E void NDECL(do_mapping); E void NDECL(do_mapping);
E void NDECL(do_vicinity_map); E void FDECL(do_vicinity_map, (struct obj *));
E void FDECL(cvt_sdoor_to_door, (struct rm *)); E void FDECL(cvt_sdoor_to_door, (struct rm *));
#ifdef USE_TRAMPOLI #ifdef USE_TRAMPOLI
E void FDECL(findone, (int, int, genericptr_t)); E void FDECL(findone, (int, int, genericptr_t));
+5 -4
View File
@@ -187,10 +187,11 @@ struct instance_flags {
int override_ID; /* true to force full identification of objects */ int override_ID; /* true to force full identification of objects */
int suppress_price; /* controls doname() for unpaid objects */ int suppress_price; /* controls doname() for unpaid objects */
int terrainmode; /* for getpos()'s autodescribe when #terrain is active */ int terrainmode; /* for getpos()'s autodescribe when #terrain is active */
#define TER_MAP 0x01 #define TER_MAP 0x01
#define TER_TRP 0x02 #define TER_TRP 0x02
#define TER_OBJ 0x04 #define TER_OBJ 0x04
#define TER_MON 0x08 #define TER_MON 0x08
#define TER_DETECT 0x10 /* detect_foo magic rather than #terrain */
coord travelcc; /* coordinates for travel_cache */ coord travelcc; /* coordinates for travel_cache */
boolean window_inited; /* true if init_nhwindows() completed */ boolean window_inited; /* true if init_nhwindows() completed */
boolean vision_inited; /* true if vision is ready */ boolean vision_inited; /* true if vision is ready */
+1 -1
View File
@@ -370,7 +370,7 @@ boolean resuming;
clear_bypasses(); clear_bypasses();
if ((u.uhave.amulet || Clairvoyant) && !In_endgame(&u.uz) if ((u.uhave.amulet || Clairvoyant) && !In_endgame(&u.uz)
&& !BClairvoyant && !(moves % 15) && !rn2(2)) && !BClairvoyant && !(moves % 15) && !rn2(2))
do_vicinity_map(); do_vicinity_map((struct obj *) 0);
if (u.utrap && u.utraptype == TT_LAVA) if (u.utrap && u.utraptype == TT_LAVA)
sink_into_lava(); sink_into_lava();
/* when/if hero escapes from lava, he can't just stay there */ /* when/if hero escapes from lava, he can't just stay there */
+275 -126
View File
@@ -12,6 +12,10 @@
extern boolean known; /* from read.c */ extern boolean known; /* from read.c */
STATIC_DCL boolean NDECL(unconstrain_map);
STATIC_DCL void NDECL(reconstrain_map);
STATIC_DCL void FDECL(browse_map, (int, const char *));
STATIC_DCL void FDECL(map_monst, (struct monst *, BOOLEAN_P));
STATIC_DCL void FDECL(do_dknown_of, (struct obj *)); STATIC_DCL void FDECL(do_dknown_of, (struct obj *));
STATIC_DCL boolean FDECL(check_map_spot, (int, int, CHAR_P, unsigned)); STATIC_DCL boolean FDECL(check_map_spot, (int, int, CHAR_P, unsigned));
STATIC_DCL boolean FDECL(clear_stale_map, (CHAR_P, unsigned)); STATIC_DCL boolean FDECL(clear_stale_map, (CHAR_P, unsigned));
@@ -22,6 +26,62 @@ 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));
/* bring hero out from underwater or underground or being engulfed;
return True iff any change occurred */
STATIC_OVL boolean
unconstrain_map()
{
boolean res = u.uinwater || u.uburied || u.uswallow;
/* bring Underwater, buried, or swallowed hero to normal map */
iflags.save_uinwater = u.uinwater, u.uinwater = 0;
iflags.save_uburied = u.uburied, u.uburied = 0;
iflags.save_uswallow = u.uswallow, u.uswallow = 0;
return res;
}
/* put hero back underwater or underground or engulfed */
STATIC_OVL void
reconstrain_map()
{
u.uinwater = iflags.save_uinwater, iflags.save_uinwater = 0;
u.uburied = iflags.save_uburied, iflags.save_uburied = 0;
u.uswallow = iflags.save_uswallow, iflags.save_uswallow = 0;
}
/* use getpos()'s 'autodescribe' to view whatever is currently shown on map */
STATIC_DCL void
browse_map(ter_typ, ter_explain)
int ter_typ;
const char *ter_explain;
{
coord dummy_pos; /* don't care whether player actually picks a spot */
dummy_pos.x = u.ux, dummy_pos.y = u.uy; /* starting spot for getpos() */
iflags.autodescribe = TRUE;
iflags.terrainmode = ter_typ;
getpos(&dummy_pos, FALSE, ter_explain);
iflags.terrainmode = 0;
/* leave iflags.autodescribe 'on' even if previously 'off' */
}
/* extracted from monster_detection() so can be shared by do_vicinity_map() */
STATIC_DCL void
map_monst(mtmp, showtail)
struct monst *mtmp;
boolean showtail;
{
if (def_monsyms[(int) mtmp->data->mlet].sym == ' ')
show_glyph(mtmp->mx, mtmp->my, detected_mon_to_glyph(mtmp));
else
show_glyph(mtmp->mx, mtmp->my,
mtmp->mtame ? pet_to_glyph(mtmp) : mon_to_glyph(mtmp));
if (showtail && mtmp->data == &mons[PM_LONG_WORM])
detect_wsegs(mtmp, 0);
}
/* this is checking whether a trap symbol represents a trapped chest, /* this is checking whether a trap symbol represents a trapped chest,
not whether a trapped chest is actually present */ not whether a trapped chest is actually present */
boolean boolean
@@ -29,12 +89,42 @@ trapped_chest_at(ttyp, x, y)
int ttyp; int ttyp;
int x, y; int x, y;
{ {
struct monst *mtmp;
struct obj *otmp;
if (!glyph_is_trap(glyph_at(x, y))) if (!glyph_is_trap(glyph_at(x, y)))
return FALSE; return FALSE;
if (ttyp != BEAR_TRAP || (Hallucination && rn2(20))) if (ttyp != BEAR_TRAP || (Hallucination && rn2(20)))
return FALSE; return FALSE;
/* presence of any trappable container will do */
return (sobj_at(CHEST, x, y) || sobj_at(LARGE_BOX, x, y)) ? TRUE : FALSE; /*
* TODO? We should check containers recursively like the trap
* detecting routine does. Chests and large boxes do not nest in
* themselves or each other, but could be contained inside statues.
*
* For farlook, we should also check for buried containers, but
* for '^' command to examine adjacent trap glyph, we shouldn't.
*/
/* on map, presence of any trappable container will do */
if (sobj_at(CHEST, x, y) || sobj_at(LARGE_BOX, x, y))
return TRUE;
/* in inventory, we need to find one which is actually trapped */
if (x == u.ux && y == u.uy) {
for (otmp = invent; otmp; otmp = otmp->nobj)
if (Is_box(otmp) && otmp->otrapped)
return TRUE;
if (u.usteed) { /* steed isn't on map so won't be found by m_at() */
for (otmp = u.usteed->minvent; otmp; otmp = otmp->nobj)
if (Is_box(otmp) && otmp->otrapped)
return TRUE;
}
}
if ((mtmp = m_at(x, y)) != 0)
for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
if (Is_box(otmp) && otmp->otrapped)
return TRUE;
return FALSE;
} }
/* this is checking whether a trap symbol represents a trapped door, /* this is checking whether a trap symbol represents a trapped door,
@@ -202,27 +292,34 @@ register struct obj *sobj;
{ {
register struct obj *obj; register struct obj *obj;
register struct monst *mtmp; register struct monst *mtmp;
struct obj *temp; struct obj gold, *temp = 0;
boolean stale; boolean stale, ugold = FALSE, steedgold = FALSE;
int ter_typ = TER_DETECT | TER_OBJ;
known = stale = known = stale = clear_stale_map(COIN_CLASS,
clear_stale_map(COIN_CLASS, (unsigned) (sobj->blessed ? GOLD : 0)); (unsigned) (sobj->blessed ? GOLD : 0));
/* look for gold carried by monsters (might be in a container) */ /* look for gold carried by monsters (might be in a container) */
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) if (DEADMONSTER(mtmp))
continue; /* probably not needed in this case but... */ continue; /* probably not needed in this case but... */
if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
known = TRUE; if (mtmp == u.usteed) {
goto outgoldmap; /* skip further searching */ steedgold = TRUE;
} else {
known = TRUE;
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; || o_in(obj, COIN_CLASS)) {
goto outgoldmap; if (mtmp == u.usteed) {
} else if (o_in(obj, COIN_CLASS)) { steedgold = TRUE;
known = TRUE; } else {
goto outgoldmap; /* skip further searching */ known = TRUE;
goto outgoldmap; /* skip further searching */
}
} }
} }
} }
@@ -246,13 +343,21 @@ register struct obj *sobj;
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 (money_cnt(invent) || hidden_gold())
Strcpy(buf, Strcpy(buf,
"You feel worried about your future financial situation."); "You feel worried about your future financial situation.");
else if (steedgold)
Sprintf(buf, "You feel interested in %s financial situation.",
s_suffix(x_monnam(u.usteed,
u.usteed->mtame ? ARTICLE_YOUR
: ARTICLE_THE,
(char *) 0,
SUPPRESS_SADDLE, FALSE)));
else else
Strcpy(buf, "You feel materially poor."); Strcpy(buf, "You feel materially poor.");
strange_feeling(sobj, buf); strange_feeling(sobj, buf);
} }
return 1; return 1;
@@ -266,8 +371,7 @@ register struct obj *sobj;
outgoldmap: outgoldmap:
cls(); cls();
iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied; (void) unconstrain_map();
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)) != 0) { if (sobj->blessed && (temp = o_material(obj, GOLD)) != 0) {
@@ -283,19 +387,21 @@ outgoldmap:
} }
map_object(temp, 1); map_object(temp, 1);
} }
if (temp && temp->ox == u.ux && temp->oy == u.uy)
ugold = TRUE;
} }
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) if (DEADMONSTER(mtmp))
continue; /* probably overkill here */ continue; /* probably overkill here */
temp = 0;
if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
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.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);
temp = &gold;
} 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)) != 0) { if (sobj->blessed && (temp = o_material(obj, GOLD)) != 0) {
@@ -310,13 +416,19 @@ outgoldmap:
break; break;
} }
} }
if (temp && temp->ox == u.ux && temp->oy == u.uy)
ugold = TRUE;
}
if (!ugold) {
newsym(u.ux, u.uy);
ter_typ |= TER_MON; /* so autodescribe will recognize hero */
} }
newsym(u.ux, u.uy);
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
iflags.save_uinwater = iflags.save_uburied = 0;
You_feel("very greedy, and sense gold!"); You_feel("very greedy, and sense gold!");
exercise(A_WIS, TRUE); exercise(A_WIS, TRUE);
display_nhwindow(WIN_MAP, TRUE);
browse_map(ter_typ, "gold");
reconstrain_map();
docrt(); docrt();
if (Underwater) if (Underwater)
under_water(2); under_water(2);
@@ -339,6 +451,8 @@ register struct obj *sobj;
const char *what = confused ? something : "food"; const char *what = confused ? something : "food";
stale = clear_stale_map(oclass, 0); stale = clear_stale_map(oclass, 0);
if (u.usteed) /* some situations leave steed with stale coordinates */
u.usteed->mx = u.ux, u.usteed->my = u.uy;
for (obj = fobj; obj; obj = obj->nobj) for (obj = fobj; obj; obj = obj->nobj)
if (o_in(obj, oclass)) { if (o_in(obj, oclass)) {
@@ -347,12 +461,14 @@ register struct obj *sobj;
else else
ct++; ct++;
} }
for (mtmp = fmon; mtmp && !ct; mtmp = mtmp->nmon) { for (mtmp = fmon; mtmp && (!ct || !ctu); mtmp = mtmp->nmon) {
/* no DEADMONSTER(mtmp) check needed since dmons never have inventory /* no DEADMONSTER(mtmp) check needed -- dmons never have inventory */
*/
for (obj = mtmp->minvent; obj; obj = obj->nobj) for (obj = mtmp->minvent; obj; obj = obj->nobj)
if (o_in(obj, oclass)) { if (o_in(obj, oclass)) {
ct++; if (mtmp->mx == u.ux && mtmp->my == u.uy)
ctu++; /* steed or an engulfer with inventory */
else
ct++;
break; break;
} }
} }
@@ -369,6 +485,7 @@ register struct obj *sobj;
} }
} else if (sobj) { } else if (sobj) {
char buf[BUFSZ]; char buf[BUFSZ];
Sprintf(buf, "Your %s twitches%s.", body_part(NOSE), Sprintf(buf, "Your %s twitches%s.", body_part(NOSE),
(sobj->blessed && !u.uedibility) (sobj->blessed && !u.uedibility)
? " then starts to tingle" ? " then starts to tingle"
@@ -394,10 +511,11 @@ register struct obj *sobj;
} }
} else { } else {
struct obj *temp; struct obj *temp;
int ter_typ = TER_DETECT | TER_OBJ;
known = TRUE; known = TRUE;
cls(); cls();
iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied; (void) unconstrain_map();
u.uinwater = u.uburied = 0;
for (obj = fobj; obj; obj = obj->nobj) for (obj = fobj; obj; obj = obj->nobj)
if ((temp = o_in(obj, oclass)) != 0) { if ((temp = o_in(obj, oclass)) != 0) {
if (temp != obj) { if (temp != obj) {
@@ -407,8 +525,7 @@ register struct obj *sobj;
map_object(temp, 1); map_object(temp, 1);
} }
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
/* no DEADMONSTER(mtmp) check needed since dmons never have /* no DEADMONSTER() check needed -- dmons never have inventory */
* inventory */
for (obj = mtmp->minvent; obj; obj = obj->nobj) for (obj = mtmp->minvent; obj; obj = obj->nobj)
if ((temp = o_in(obj, oclass)) != 0) { if ((temp = o_in(obj, oclass)) != 0) {
temp->ox = mtmp->mx; temp->ox = mtmp->mx;
@@ -416,9 +533,10 @@ register struct obj *sobj;
map_object(temp, 1); map_object(temp, 1);
break; /* skip rest of this monster's inventory */ break; /* skip rest of this monster's inventory */
} }
newsym(u.ux, u.uy); if (!ctu) {
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied; newsym(u.ux, u.uy);
iflags.save_uinwater = iflags.save_uburied = 0; ter_typ |= TER_MON; /* for autodescribe of self */
}
if (sobj) { if (sobj) {
if (sobj->blessed) { if (sobj->blessed) {
Your("%s %s to tingle and you smell %s.", body_part(NOSE), Your("%s %s to tingle and you smell %s.", body_part(NOSE),
@@ -428,8 +546,11 @@ register struct obj *sobj;
Your("%s tingles and you smell %s.", body_part(NOSE), what); Your("%s tingles and you smell %s.", body_part(NOSE), what);
} else } else
You("sense %s.", what); You("sense %s.", what);
display_nhwindow(WIN_MAP, TRUE);
exercise(A_WIS, TRUE); exercise(A_WIS, TRUE);
browse_map(ter_typ, "food");
reconstrain_map();
docrt(); docrt();
if (Underwater) if (Underwater)
under_water(2); under_water(2);
@@ -459,7 +580,7 @@ int class; /* an object class, 0 for all */
int ct = 0, ctu = 0; int ct = 0, ctu = 0;
register struct obj *obj, *otmp = (struct obj *) 0; register struct obj *obj, *otmp = (struct obj *) 0;
register struct monst *mtmp; register struct monst *mtmp;
int sym, boulder = 0; int sym, boulder = 0, ter_typ = TER_DETECT | TER_OBJ;
if (class < 0 || class >= MAXOCLASSES) { if (class < 0 || class >= MAXOCLASSES) {
impossible("object_detect: illegal class %d", class); impossible("object_detect: illegal class %d", class);
@@ -509,6 +630,9 @@ int class; /* an object class, 0 for all */
do_dknown_of(obj); do_dknown_of(obj);
} }
if (u.usteed)
u.usteed->mx = u.ux, u.usteed->my = u.uy;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) if (DEADMONSTER(mtmp))
continue; continue;
@@ -540,8 +664,7 @@ int class; /* an object class, 0 for all */
cls(); cls();
iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied; (void) unconstrain_map();
u.uinwater = u.uburied = 0;
/* /*
* Map all buried objects first. * Map all buried objects first.
*/ */
@@ -618,16 +741,18 @@ int class; /* an object class, 0 for all */
map_object(&gold, 1); map_object(&gold, 1);
} }
} }
if (!glyph_is_object(glyph_at(u.ux, u.uy))) {
newsym(u.ux, u.uy); newsym(u.ux, u.uy);
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied; ter_typ |= TER_MON;
iflags.save_uinwater = iflags.save_uburied = 0; }
You("detect the %s of %s.", ct ? "presence" : "absence", stuff); You("detect the %s of %s.", ct ? "presence" : "absence", stuff);
display_nhwindow(WIN_MAP, TRUE);
/* if (!ct)
* What are we going to do when the hero does an object detect while blind display_nhwindow(WIN_MAP, TRUE);
* and the detected object covers a known pool? else
*/ browse_map(ter_typ, "object");
reconstrain_map();
docrt(); /* this will correctly reset vision */ docrt(); /* this will correctly reset vision */
if (Underwater) if (Underwater)
under_water(2); under_water(2);
@@ -668,26 +793,19 @@ int mclass; /* monster class, 0 for all */
: "You feel threatened."); : "You feel threatened.");
return 1; return 1;
} else { } else {
boolean woken = FALSE; boolean unconstrained, woken = FALSE;
unsigned swallowed = u.uswallow; /* before unconstrain_map() */
cls(); cls();
unconstrained = unconstrain_map();
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) if (DEADMONSTER(mtmp))
continue; continue;
if (!mclass || mtmp->data->mlet == mclass if (!mclass || mtmp->data->mlet == mclass
|| (mtmp->data == &mons[PM_LONG_WORM] || (mtmp->data == &mons[PM_LONG_WORM]
&& mclass == S_WORM_TAIL)) && mclass == S_WORM_TAIL))
if (mtmp->mx > 0) { map_monst(mtmp, TRUE);
if (mclass && def_monsyms[mclass].sym == ' ')
show_glyph(mtmp->mx, mtmp->my,
detected_mon_to_glyph(mtmp));
else
show_glyph(mtmp->mx, mtmp->my,
mtmp->mtame ? pet_to_glyph(mtmp) : mon_to_glyph(mtmp));
/* don't be stingy - display entire worm */
if (mtmp->data == &mons[PM_LONG_WORM])
detect_wsegs(mtmp, 0);
}
if (otmp && otmp->cursed if (otmp && otmp->cursed
&& (mtmp->msleeping || !mtmp->mcanmove)) { && (mtmp->msleeping || !mtmp->mcanmove)) {
mtmp->msleeping = mtmp->mfrozen = 0; mtmp->msleeping = mtmp->mfrozen = 0;
@@ -695,12 +813,25 @@ int mclass; /* monster class, 0 for all */
woken = TRUE; woken = TRUE;
} }
} }
display_self(); if (!swallowed)
display_self();
You("sense the presence of monsters."); You("sense the presence of monsters.");
if (woken) if (woken)
pline("Monsters sense the presence of you."); pline("Monsters sense the presence of you.");
display_nhwindow(WIN_MAP, TRUE);
docrt(); if ((otmp && otmp->blessed) && !unconstrained) {
/* persistent detection--just show updated map */
display_nhwindow(WIN_MAP, TRUE);
} else {
/* one-shot detection--allow player to move cursor around and
get autodescribe feedback */
EDetect_monsters |= I_SPECIAL;
browse_map(TER_DETECT | TER_MON, "monster of interest");
EDetect_monsters &= ~I_SPECIAL;
}
reconstrain_map();
docrt(); /* redraw the screen to remove unseen monsters from map */
if (Underwater) if (Underwater)
under_water(2); under_water(2);
if (u.uburied) if (u.uburied)
@@ -734,7 +865,7 @@ int src_cursed;
} else if (trap) { } else if (trap) {
map_trap(trap, 1); map_trap(trap, 1);
trap->tseen = 1; trap->tseen = 1;
} else { } else { /* trapped door or trapped chest */
struct trap temp_trap; /* fake trap */ struct trap temp_trap; /* fake trap */
(void) memset((genericptr_t) &temp_trap, 0, sizeof temp_trap); (void) memset((genericptr_t) &temp_trap, 0, sizeof temp_trap);
@@ -762,6 +893,11 @@ int how; /* 1 for misleading map feedback */
xchar x, y; xchar x, y;
int result = OTRAP_NONE; int result = OTRAP_NONE;
/*
* TODO? Display locations of unarmed land mine and beartrap objects.
* If so, should they be displayed as objects or as traps?
*/
for (otmp = objlist; otmp; otmp = otmp->nobj) { for (otmp = objlist; otmp; otmp = otmp->nobj) {
if (Is_box(otmp) && otmp->otrapped if (Is_box(otmp) && otmp->otrapped
&& get_obj_location(otmp, &x, &y, BURIED_TOO | CONTAINED_TOO)) { && get_obj_location(otmp, &x, &y, BURIED_TOO | CONTAINED_TOO)) {
@@ -786,11 +922,14 @@ struct obj *sobj; /* null if crystal ball, *scroll if gold detection scroll */
{ {
register struct trap *ttmp; register struct trap *ttmp;
struct monst *mon; struct monst *mon;
int door, glyph, tr; int door, glyph, tr, ter_typ = TER_DETECT | TER_TRP;
int cursed_src = sobj && sobj->cursed; int cursed_src = sobj && sobj->cursed;
boolean found = FALSE; boolean found = FALSE;
coord cc; coord cc;
if (u.usteed)
u.usteed->mx = u.ux, u.usteed->my = u.uy;
/* floor/ceiling traps */ /* floor/ceiling traps */
for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) { for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
if (ttmp->tx != u.ux || ttmp->ty != u.uy) if (ttmp->tx != u.ux || ttmp->ty != u.uy)
@@ -847,9 +986,7 @@ struct obj *sobj; /* null if crystal ball, *scroll if gold detection scroll */
outtrapmap: outtrapmap:
cls(); cls();
iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied; (void) unconstrain_map();
u.uinwater = u.uburied = 0;
/* show chest traps first, so that subsequent floor trap display /* show chest traps first, so that subsequent floor trap display
will override if both types are present at the same location */ will override if both types are present at the same location */
(void) detect_obj_traps(fobj, TRUE, cursed_src); (void) detect_obj_traps(fobj, TRUE, cursed_src);
@@ -872,15 +1009,16 @@ outtrapmap:
/* redisplay hero unless sense_trap() revealed something at <ux,uy> */ /* redisplay hero unless sense_trap() revealed something at <ux,uy> */
glyph = glyph_at(u.ux, u.uy); glyph = glyph_at(u.ux, u.uy);
if (!(glyph_is_trap(glyph) || glyph_is_object(glyph))) if (!(glyph_is_trap(glyph) || glyph_is_object(glyph))) {
newsym(u.ux, u.uy); newsym(u.ux, u.uy);
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied; ter_typ |= TER_MON; /* for autodescribe at <u.ux,u.uy> */
iflags.save_uinwater = iflags.save_uburied = 0; }
You_feel("%s.", cursed_src ? "very greedy" : "entrapped"); You_feel("%s.", cursed_src ? "very greedy" : "entrapped");
/* wait for user to respond, then reset map display to normal */
display_nhwindow(WIN_MAP, TRUE); browse_map(ter_typ, "trap of interest");
docrt();
reconstrain_map();
docrt(); /* redraw the screen to remove unseen traps from the map */
if (Underwater) if (Underwater)
under_water(2); under_water(2);
if (u.uburied) if (u.uburied)
@@ -1132,40 +1270,67 @@ void
do_mapping() do_mapping()
{ {
register int zx, zy; register int zx, zy;
boolean unconstrained;
iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied; unconstrained = unconstrain_map();
u.uinwater = u.uburied = 0;
for (zx = 1; zx < COLNO; zx++) for (zx = 1; zx < COLNO; zx++)
for (zy = 0; zy < ROWNO; zy++) for (zy = 0; zy < ROWNO; zy++)
show_map_spot(zx, zy); show_map_spot(zx, zy);
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
iflags.save_uinwater = iflags.save_uburied = 0; if (!level.flags.hero_memory || unconstrained) {
if (!level.flags.hero_memory || Underwater) {
flush_screen(1); /* flush temp screen */ flush_screen(1); /* flush temp screen */
display_nhwindow(WIN_MAP, TRUE); /* wait */ /* browse_map() instead of display_nhwindow(WIN_MAP, TRUE) */
browse_map(TER_DETECT | TER_MAP | TER_TRP | TER_OBJ,
"anything of interest");
docrt(); docrt();
} }
reconstrain_map();
exercise(A_WIS, TRUE); exercise(A_WIS, TRUE);
} }
/* clairvoyance */
void void
do_vicinity_map() do_vicinity_map(sobj)
struct obj *sobj; /* scroll--actually fake spellbook--object */
{ {
register int zx, zy; register int zx, zy;
int lo_y = (u.uy - 5 < 0 ? 0 : u.uy - 5), struct monst *mtmp;
hi_y = (u.uy + 6 > ROWNO ? ROWNO : u.uy + 6), boolean unconstrained, refresh = FALSE, mdetected = FALSE,
lo_x = (u.ux - 9 < 1 ? 1 : u.ux - 9), /* avoid column 0 */ extended = (sobj && sobj->blessed);
hi_x = (u.ux + 10 > COLNO ? COLNO : u.ux + 10); int lo_y = ((u.uy - 5 < 0) ? 0 : u.uy - 5),
hi_y = ((u.uy + 6 >= ROWNO) ? ROWNO - 1 : u.uy + 6),
lo_x = ((u.ux - 9 < 1) ? 1 : u.ux - 9), /* avoid column 0 */
hi_x = ((u.ux + 10 >= COLNO) ? COLNO - 1 : u.ux + 10),
ter_typ = TER_DETECT | TER_MAP | TER_TRP | TER_OBJ;
for (zx = lo_x; zx < hi_x; zx++) unconstrained = unconstrain_map();
for (zy = lo_y; zy < hi_y; zy++) for (zx = lo_x; zx <= hi_x; zx++)
for (zy = lo_y; zy <= hi_y; zy++) {
show_map_spot(zx, zy); show_map_spot(zx, zy);
if (!level.flags.hero_memory || Underwater) { if (extended && (mtmp = m_at(zx, zy)) != 0
&& mtmp->mx == zx && mtmp->my == zy) { /* skip worm tails */
int oldglyph = glyph_at(zx, zy);
map_monst(mtmp, FALSE);
if (glyph_at(zx, zy) != oldglyph)
mdetected = TRUE;
}
}
if (!level.flags.hero_memory || unconstrained || mdetected) {
flush_screen(1); /* flush temp screen */ flush_screen(1); /* flush temp screen */
display_nhwindow(WIN_MAP, TRUE); /* wait */ if (extended || glyph_is_monster(glyph_at(u.ux, u.uy)))
docrt(); ter_typ |= TER_MON;
if (extended)
EDetect_monsters |= I_SPECIAL;
browse_map(ter_typ, "anything of interest");
EDetect_monsters &= ~I_SPECIAL;
refresh = TRUE;
} }
reconstrain_map();
if (refresh)
docrt();
} }
/* convert a secret door into a normal door */ /* convert a secret door into a normal door */
@@ -1379,12 +1544,10 @@ boolean via_warning;
exercise(A_WIS, TRUE); exercise(A_WIS, TRUE);
if (!canspotmon(mtmp)) { if (!canspotmon(mtmp)) {
if (glyph_is_invisible(levl[x][y].glyph)) { if (glyph_is_invisible(levl[x][y].glyph)) {
/* found invisible monster in a square /* Found invisible monster in a square which already has
* which already has an 'I' in it. * an 'I' in it. Logically, this should still take time
* Logically, this should still take * and lead to a return 1, but if we did that the player
* time and lead to a return(1), but * would keep finding the same monster every turn.
* if we did that the player would keep
* finding the same monster every turn.
*/ */
return -1; return -1;
} else { } else {
@@ -1392,18 +1555,16 @@ boolean via_warning;
map_invisible(x, y); map_invisible(x, y);
} }
} else if (!sensemon(mtmp)) } else if (!sensemon(mtmp))
You("find %s.", mtmp->mtame You("find %s.",
? y_monnam(mtmp) mtmp->mtame ? y_monnam(mtmp) : a_monnam(mtmp));
: a_monnam(mtmp));
return 1; return 1;
} }
if (!canspotmon(mtmp)) { if (!canspotmon(mtmp)) {
if (mtmp->mundetected if (mtmp->mundetected
&& (is_hider(mtmp->data) && (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL))
|| mtmp->data->mlet == S_EEL))
if (via_warning) { if (via_warning) {
Your("warning senses cause you to take a second %s.", Your("warning senses cause you to take a second %s.",
Blind ? "to check nearby" : "look close by"); Blind ? "to check nearby" : "look close by");
display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */ display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
} }
mtmp->mundetected = 0; mtmp->mundetected = 0;
@@ -1418,10 +1579,10 @@ dosearch0(aflag)
register int aflag; /* intrinsic autosearch vs explicit searching */ register int aflag; /* intrinsic autosearch vs explicit searching */
{ {
#ifdef GCC_BUG #ifdef GCC_BUG
/* some versions of gcc seriously muck up nested loops. if you get strange /* Some old versions of gcc seriously muck up nested loops. If you get
crashes while searching in a version compiled with gcc, try putting * strange crashes while searching in a version compiled with gcc, try
#define GCC_BUG in *conf.h (or adding -DGCC_BUG to CFLAGS in the * putting #define GCC_BUG in *conf.h (or adding -DGCC_BUG to CFLAGS in
makefile). * the makefile).
*/ */
volatile xchar x, y; volatile xchar x, y;
#else #else
@@ -1566,21 +1727,16 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */
} else { } else {
int x, y, glyph, levl_glyph, default_glyph; int x, y, glyph, levl_glyph, default_glyph;
uchar seenv; uchar seenv;
unsigned save_swallowed;
struct monst *mtmp; struct monst *mtmp;
struct trap *t; struct trap *t;
coord pos;
char buf[BUFSZ]; char buf[BUFSZ];
/* there is a TER_MAP bit too; we always show map regardless of it */ /* there is a TER_MAP bit too; we always show map regardless of it */
boolean keep_traps = (which_subset & TER_TRP) !=0, boolean keep_traps = (which_subset & TER_TRP) !=0,
keep_objs = (which_subset & TER_OBJ) != 0, keep_objs = (which_subset & TER_OBJ) != 0,
keep_mons = (which_subset & TER_MON) != 0; /* not used */ keep_mons = (which_subset & TER_MON) != 0; /* not used */
unsigned swallowed = u.uswallow; /* before unconstrain_map() */
save_swallowed = u.uswallow; if (unconstrain_map())
iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
u.uinwater = u.uburied = 0;
u.uswallow = 0;
if (iflags.save_uinwater || iflags.save_uburied)
docrt(); docrt();
default_glyph = cmap_to_glyph(level.flags.arboreal ? S_tree : S_stone); default_glyph = cmap_to_glyph(level.flags.arboreal ? S_tree : S_stone);
/* for 'full', show the actual terrain for the entire level, /* for 'full', show the actual terrain for the entire level,
@@ -1605,8 +1761,8 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */
glyph, which will never be a monster (unless it is glyph, which will never be a monster (unless it is
the invisible monster glyph, which is handled like the invisible monster glyph, which is handled like
an object, replacing any object or trap at its spot) */ an object, replacing any object or trap at its spot) */
glyph = !save_swallowed ? glyph_at(x, y) : levl_glyph; glyph = !swallowed ? glyph_at(x, y) : levl_glyph;
if (keep_mons && x == u.ux && y == u.uy && save_swallowed) if (keep_mons && x == u.ux && y == u.uy && swallowed)
glyph = mon_to_glyph(u.ustuck); glyph = mon_to_glyph(u.ustuck);
else if (((glyph_is_monster(glyph) else if (((glyph_is_monster(glyph)
|| glyph_is_warning(glyph)) && !keep_mons) || glyph_is_warning(glyph)) && !keep_mons)
@@ -1676,17 +1832,10 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */
/* allow player to move cursor around and get autodescribe feedback /* allow player to move cursor around and get autodescribe feedback
based on what is visible now rather than what is on 'real' map */ based on what is visible now rather than what is on 'real' map */
pos.x = u.ux, pos.y = u.uy; which_subset |= TER_MAP; /* guarantee non-zero */
iflags.autodescribe = TRUE; browse_map(which_subset, "anything of interest");
iflags.terrainmode = which_subset | TER_MAP; /* guaranteed non-zero */
getpos(&pos, FALSE, "anything of interest");
iflags.terrainmode = 0;
/* leave iflags.autodescribe 'on' even if it was previously 'off' */
u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied; reconstrain_map();
iflags.save_uinwater = iflags.save_uburied = 0;
if (save_swallowed)
u.uswallow = 1;
docrt(); /* redraw the screen, restoring regular map */ docrt(); /* redraw the screen, restoring regular map */
if (Underwater) if (Underwater)
under_water(2); under_water(2);
+37 -15
View File
@@ -74,11 +74,13 @@ char *outbuf;
mons[u.umonnum].mname, plname); mons[u.umonnum].mname, plname);
if (u.usteed) if (u.usteed)
Sprintf(eos(outbuf), ", mounted on %s", y_monnam(u.usteed)); Sprintf(eos(outbuf), ", mounted on %s", y_monnam(u.usteed));
if (u.uundetected || (Upolyd && youmonst.m_ap_type))
mhidden_description(&youmonst, FALSE, eos(outbuf));
return outbuf; return outbuf;
} }
/* describe a hidden monster; used for look_at during extended monster /* describe a hidden monster; used for look_at during extended monster
detection and for probing */ detection and for probing; also when looking at self */
void void
mhidden_description(mon, altmon, outbuf) mhidden_description(mon, altmon, outbuf)
struct monst *mon; struct monst *mon;
@@ -86,8 +88,10 @@ boolean altmon; /* for probing: if mimicking a monster, say so */
char *outbuf; char *outbuf;
{ {
struct obj *otmp; struct obj *otmp;
boolean fakeobj; boolean fakeobj, isyou = (mon == &youmonst);
int x = mon->mx, y = mon->my, glyph = levl[x][y].glyph; int x = isyou ? u.ux : mon->mx, y = isyou ? u.uy : mon->my,
glyph = (level.flags.hero_memory && !isyou) ? levl[x][y].glyph
: glyph_at(x, y);
*outbuf = '\0'; *outbuf = '\0';
if (mon->m_ap_type == M_AP_FURNITURE if (mon->m_ap_type == M_AP_FURNITURE
@@ -113,7 +117,7 @@ char *outbuf;
if (altmon) if (altmon)
Sprintf(outbuf, ", masquerading as %s", Sprintf(outbuf, ", masquerading as %s",
an(mons[mon->mappearance].mname)); an(mons[mon->mappearance].mname));
} else if (mon->mundetected) { } else if (isyou ? u.uundetected : mon->mundetected) {
Strcpy(outbuf, ", hiding"); Strcpy(outbuf, ", hiding");
if (hides_under(mon->data)) { if (hides_under(mon->data)) {
Strcat(outbuf, " under "); Strcat(outbuf, " under ");
@@ -141,10 +145,16 @@ struct obj **obj_p;
{ {
boolean fakeobj = FALSE; boolean fakeobj = FALSE;
struct monst *mtmp; struct monst *mtmp;
struct obj *otmp = vobj_at(x, y); struct obj *otmp;
int glyphotyp = glyph_to_obj(glyph); int glyphotyp = glyph_to_obj(glyph);
*obj_p = (struct obj *) 0; *obj_p = (struct obj *) 0;
/* TODO: check inside containers in case glyph came from detection */
if ((otmp = sobj_at(glyphotyp, x, y)) == 0)
for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj)
if (otmp->ox == x && otmp->oy == y && otmp->otyp == glyphotyp)
break;
/* there might be a mimic here posing as an object */ /* there might be a mimic here posing as an object */
mtmp = m_at(x, y); mtmp = m_at(x, y);
if (mtmp && is_obj_mappear(mtmp, (unsigned) glyphotyp)) if (mtmp && is_obj_mappear(mtmp, (unsigned) glyphotyp))
@@ -194,7 +204,9 @@ int x, y, glyph;
} else } else
Strcpy(buf, something); /* sanity precaution */ Strcpy(buf, something); /* sanity precaution */
if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR) if (otmp && otmp->where == OBJ_BURIED)
Strcat(buf, " (buried)");
else if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR)
Strcat(buf, " embedded in stone"); Strcat(buf, " embedded in stone");
else if (IS_WALL(levl[x][y].typ) || levl[x][y].typ == SDOOR) else if (IS_WALL(levl[x][y].typ) || levl[x][y].typ == SDOOR)
Strcat(buf, " embedded in a wall"); Strcat(buf, " embedded in a wall");
@@ -229,9 +241,14 @@ int x, y;
? "peaceful " ? "peaceful "
: "", : "",
name); name);
if (u.ustuck == mtmp) if (u.ustuck == mtmp) {
Strcat(buf, (Upolyd && sticks(youmonst.data)) if (u.uswallow || iflags.save_uswallow) /* monster detection */
? ", being held" : ", holding you"); Strcat(buf, is_animal(mtmp->data)
? ", swallowing you" : ", engulfing you");
else
Strcat(buf, (Upolyd && sticks(youmonst.data))
? ", being held" : ", holding you");
}
if (mtmp->mleashed) if (mtmp->mleashed)
Strcat(buf, ", leashed to you"); Strcat(buf, ", leashed to you");
@@ -328,6 +345,7 @@ char *buf, *monbuf;
buf[0] = monbuf[0] = '\0'; buf[0] = monbuf[0] = '\0';
glyph = glyph_at(x, y); glyph = glyph_at(x, y);
if (u.ux == x && u.uy == y && canspotself() if (u.ux == x && u.uy == y && canspotself()
&& !(iflags.save_uswallow && glyph == mon_to_glyph(u.ustuck))
&& (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0)) { && (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0)) {
/* fill in buf[] */ /* fill in buf[] */
(void) self_lookat(buf); (void) self_lookat(buf);
@@ -342,7 +360,8 @@ char *buf, *monbuf;
(even if you could also see yourself via other means). (even if you could also see yourself via other means).
Sensing self while blind or swallowed is treated as if it Sensing self while blind or swallowed is treated as if it
were by normal vision (cf canseeself()). */ were by normal vision (cf canseeself()). */
if ((Invisible || u.uundetected) && !Blind && !u.uswallow) { if ((Invisible || u.uundetected) && !Blind
&& !(u.uswallow || iflags.save_uswallow)) {
unsigned how = 0; unsigned how = 0;
if (Infravision) if (Infravision)
@@ -702,10 +721,15 @@ const char **firstmatch;
* submerged will always both be False and skip this code.) * submerged will always both be False and skip this code.)
*/ */
x_str = 0; x_str = 0;
if (looked && (u.uswallow || submerged) && distu(cc.x, cc.y) > 2) { if (!looked) {
; /* skip special handling */
} else if (((u.uswallow || submerged) && distu(cc.x, cc.y) > 2)
/* detection showing some category, so mostly background */
|| ((iflags.terrainmode & (TER_DETECT | TER_MAP)) == TER_DETECT
&& glyph == cmap_to_glyph(S_stone))) {
x_str = unreconnoitered; x_str = unreconnoitered;
need_to_look = FALSE; need_to_look = FALSE;
} else if (looked && u.uswallow && is_swallow_sym(sym)) { } else if (is_swallow_sym(sym)) {
x_str = mon_interior; x_str = mon_interior;
need_to_look = TRUE; /* for specific monster type */ need_to_look = TRUE; /* for specific monster type */
} }
@@ -943,9 +967,7 @@ coord *click_cc;
if (quick) { if (quick) {
from_screen = TRUE; /* yes, we want to use the cursor */ from_screen = TRUE; /* yes, we want to use the cursor */
i = 'y'; i = 'y';
} } else {
if (i != 'y') {
menu_item *pick_list = (menu_item *) 0; menu_item *pick_list = (menu_item *) 0;
winid win; winid win;
anything any; anything any;
+6 -3
View File
@@ -1136,6 +1136,7 @@ boolean atme;
case SPE_INVISIBILITY: case SPE_INVISIBILITY:
(void) peffects(pseudo); (void) peffects(pseudo);
break; break;
/* end of potion-like spells */
case SPE_CURE_BLINDNESS: case SPE_CURE_BLINDNESS:
healup(0, 0, FALSE, TRUE); healup(0, 0, FALSE, TRUE);
@@ -1151,10 +1152,12 @@ boolean atme;
(void) make_familiar((struct obj *) 0, u.ux, u.uy, FALSE); (void) make_familiar((struct obj *) 0, u.ux, u.uy, FALSE);
break; break;
case SPE_CLAIRVOYANCE: case SPE_CLAIRVOYANCE:
if (!BClairvoyant) if (!BClairvoyant) {
do_vicinity_map(); if (role_skill >= P_SKILLED)
pseudo->blessed = 1; /* detect monsters as well as map */
do_vicinity_map(pseudo);
/* at present, only one thing blocks clairvoyance */ /* at present, only one thing blocks clairvoyance */
else if (uarmh && uarmh->otyp == CORNUTHAUM) } else if (uarmh && uarmh->otyp == CORNUTHAUM)
You("sense a pointy hat on top of your %s.", body_part(HEAD)); You("sense a pointy hat on top of your %s.", body_part(HEAD));
break; break;
case SPE_PROTECTION: case SPE_PROTECTION: