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:
+9
-4
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user