1 /* NetHack 3.6 detect.c $NHDT-Date: 1446369464 2015/11/01 09:17:44 $ $NHDT-Branch: master $:$NHDT-Revision: 1.61 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
6 * Detection routines, including crystal ball, magic mapping, and search
10 /* JNetHack Copyright */
11 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
12 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
13 /* JNetHack may be freely redistributed. See license for details. */
18 extern boolean known; /* from read.c */
20 STATIC_DCL void FDECL(do_dknown_of, (struct obj *));
21 STATIC_DCL boolean FDECL(check_map_spot, (int, int, CHAR_P, unsigned));
22 STATIC_DCL boolean FDECL(clear_stale_map, (CHAR_P, unsigned));
23 STATIC_DCL void FDECL(sense_trap, (struct trap *, XCHAR_P, XCHAR_P, int));
24 STATIC_DCL int FDECL(detect_obj_traps, (struct obj *, BOOLEAN_P, int));
25 STATIC_DCL void FDECL(show_map_spot, (int, int));
26 STATIC_PTR void FDECL(findone, (int, int, genericptr_t));
27 STATIC_PTR void FDECL(openone, (int, int, genericptr_t));
29 /* Recursively search obj for an object in class oclass and return 1st found
36 register struct obj *otmp;
39 if (obj->oclass == oclass)
42 if (Has_contents(obj)) {
43 for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
44 if (otmp->oclass == oclass)
46 else if (Has_contents(otmp) && (temp = o_in(otmp, oclass)))
49 return (struct obj *) 0;
52 /* Recursively search obj for an object made of specified material.
56 o_material(obj, material)
60 register struct obj *otmp;
63 if (objects[obj->otyp].oc_material == material)
66 if (Has_contents(obj)) {
67 for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
68 if (objects[otmp->otyp].oc_material == material)
70 else if (Has_contents(otmp)
71 && (temp = o_material(otmp, material)))
74 return (struct obj *) 0;
84 if (Has_contents(obj)) {
85 for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
90 /* Check whether the location has an outdated object displayed on it. */
92 check_map_spot(x, y, oclass, material)
98 register struct obj *otmp;
99 register struct monst *mtmp;
101 glyph = glyph_at(x, y);
102 if (glyph_is_object(glyph)) {
103 /* there's some object shown here */
104 if (oclass == ALL_CLASSES) {
105 return (boolean) !(level.objects[x][y] /* stale if nothing here */
106 || ((mtmp = m_at(x, y)) != 0 && mtmp->minvent));
109 && objects[glyph_to_obj(glyph)].oc_material == material) {
110 /* object shown here is of interest because material matches */
111 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
112 if (o_material(otmp, GOLD))
114 /* didn't find it; perhaps a monster is carrying it */
115 if ((mtmp = m_at(x, y)) != 0) {
116 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
117 if (o_material(otmp, GOLD))
120 /* detection indicates removal of this object from the map */
123 if (oclass && objects[glyph_to_obj(glyph)].oc_class == oclass) {
124 /* obj shown here is of interest because its class matches */
125 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
126 if (o_in(otmp, oclass))
128 /* didn't find it; perhaps a monster is carrying it */
129 if ((mtmp = m_at(x, y)) != 0) {
130 for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
131 if (o_in(otmp, oclass))
134 /* detection indicates removal of this object from the map */
143 * When doing detection, remove stale data from the map display (corpses
144 * rotted away, objects carried away by monsters, etc) so that it won't
145 * reappear after the detection has completed. Return true if noticeable
149 clear_stale_map(oclass, material)
154 boolean change_made = FALSE;
156 for (zx = 1; zx < COLNO; zx++)
157 for (zy = 0; zy < ROWNO; zy++)
158 if (check_map_spot(zx, zy, oclass, material)) {
159 unmap_object(zx, zy);
166 /* look for gold, on the floor or in monsters' possession */
169 register struct obj *sobj;
171 register struct obj *obj;
172 register struct monst *mtmp;
177 clear_stale_map(COIN_CLASS, (unsigned) (sobj->blessed ? GOLD : 0));
179 /* look for gold carried by monsters (might be in a container) */
180 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
181 if (DEADMONSTER(mtmp))
182 continue; /* probably not needed in this case but... */
183 if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
185 goto outgoldmap; /* skip further searching */
187 for (obj = mtmp->minvent; obj; obj = obj->nobj)
188 if (sobj->blessed && o_material(obj, GOLD)) {
191 } else if (o_in(obj, COIN_CLASS)) {
193 goto outgoldmap; /* skip further searching */
197 /* look for gold objects */
198 for (obj = fobj; obj; obj = obj->nobj) {
199 if (sobj->blessed && o_material(obj, GOLD)) {
201 if (obj->ox != u.ux || obj->oy != u.uy)
203 } else if (o_in(obj, COIN_CLASS)) {
205 if (obj->ox != u.ux || obj->oy != u.uy)
211 /* no gold found on floor or monster's inventory.
212 adjust message if you have gold in your inventory */
215 if (youmonst.data == &mons[PM_GOLD_GOLEM]) {
217 Sprintf(buf, "You feel like a million %s!", currency(2L));
219 Strcpy(buf, "
\82 \82È
\82½
\82Í
\8bà
\8e\9d\82¿
\82É
\82È
\82Á
\82½
\82æ
\82¤
\82É
\8a´
\82¶
\82½
\81I");
220 } else if (hidden_gold() || money_cnt(invent))
223 "You feel worried about your future financial situation.");
225 "
\82 \82È
\82½
\82Í
\8f«
\97\88\82Ì
\8co
\8dÏ
\8fó
\8bµ
\82ª
\90S
\94z
\82É
\82È
\82Á
\82½
\81D");
228 Strcpy(buf, "You feel materially poor.");
230 Strcpy(buf, "
\82 \82È
\82½
\82Í
\82Ð
\82à
\82¶
\82³
\82ð
\8a´
\82¶
\82½
\81D");
231 strange_feeling(sobj, buf);
235 /* only under me - no separate display required */
239 You("notice some gold between your %s.", makeplural(body_part(FOOT)));
241 You("%s
\82Ì
\8aÔ
\82É
\8bà
\89Ý
\82ª
\97\8e\82¿
\82Ä
\82¢
\82é
\82±
\82Æ
\82É
\8bC
\82ª
\82Â
\82¢
\82½
\81D", body_part(FOOT));
247 iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
248 u.uinwater = u.uburied = 0;
249 /* Discover gold locations. */
250 for (obj = fobj; obj; obj = obj->nobj) {
251 if (sobj->blessed && (temp = o_material(obj, GOLD))) {
257 } else if ((temp = o_in(obj, COIN_CLASS))) {
265 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
266 if (DEADMONSTER(mtmp))
267 continue; /* probably overkill here */
268 if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
270 gold = zeroobj; /* ensure oextra is cleared too */
271 gold.otyp = GOLD_PIECE;
274 map_object(&gold, 1);
276 for (obj = mtmp->minvent; obj; obj = obj->nobj)
277 if (sobj->blessed && (temp = o_material(obj, GOLD))) {
282 } else if ((temp = o_in(obj, COIN_CLASS))) {
290 u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
292 You_feel("very greedy, and sense gold!");
294 You("
\82Ç
\82ñ
\97~
\82É
\82È
\82Á
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81C
\82»
\82µ
\82Ä
\8bà
\89Ý
\82Ì
\88Ê
\92u
\82ð
\8a´
\92m
\82µ
\82½
\81I");
295 exercise(A_WIS, TRUE);
296 display_nhwindow(WIN_MAP, TRUE);
305 /* returns 1 if nothing was detected */
306 /* returns 0 if something was detected */
309 register struct obj *sobj;
311 register struct obj *obj;
312 register struct monst *mtmp;
313 register int ct = 0, ctu = 0;
314 boolean confused = (Confusion || (sobj && sobj->cursed)), stale;
315 char oclass = confused ? POTION_CLASS : FOOD_CLASS;
317 const char *what = confused ? something : "food";
319 const char *what = confused ? "
\83n
\83\89\83w
\83\8a" : "
\90H
\82×
\95¨";
321 stale = clear_stale_map(oclass, 0);
323 for (obj = fobj; obj; obj = obj->nobj)
324 if (o_in(obj, oclass)) {
325 if (obj->ox == u.ux && obj->oy == u.uy)
330 for (mtmp = fmon; mtmp && !ct; mtmp = mtmp->nmon) {
331 /* no DEADMONSTER(mtmp) check needed since dmons never have inventory
333 for (obj = mtmp->minvent; obj; obj = obj->nobj)
334 if (o_in(obj, oclass)) {
341 known = stale && !confused;
345 You("sense a lack of %s nearby.", what);
347 You("%s
\82ª
\8c¸
\82Á
\82Ä
\82¢
\82é
\82Ì
\82É
\8bC
\82ª
\82Â
\82¢
\82½
\81D",what);
348 if (sobj && sobj->blessed) {
351 Your("%s starts to tingle.", body_part(NOSE));
353 Your("%s
\82ª
\82Ò
\82
\82Á
\82Æ
\93®
\82¢
\82½
\81D", body_part(NOSE));
359 Sprintf(buf, "Your %s twitches%s.", body_part(NOSE),
360 (sobj->blessed && !u.uedibility)
361 ? " then starts to tingle"
364 Sprintf(buf, "
\82 \82È
\82½
\82Ì%s
\82ª
\82Ð
\82
\82Ð
\82
\82Æ
\93®
\82¢%s
\81D", body_part(NOSE),
365 (sobj->blessed && !u.uedibility)
366 ? "
\82Ä
\81C
\82¤
\82¸
\82¤
\82¸
\82µ
\82¾
\82µ
\82½"
369 if (sobj->blessed && !u.uedibility) {
370 boolean savebeginner = flags.beginner;
372 flags.beginner = FALSE; /* prevent non-delivery of message */
373 strange_feeling(sobj, buf);
374 flags.beginner = savebeginner;
377 strange_feeling(sobj, buf);
383 You("%s %s nearby.", sobj ? "smell" : "sense", what);
385 You("
\8bß
\82
\82Å%s%s
\81D", what, sobj ? "
\82Ì
\82É
\82¨
\82¢
\82ð
\82©
\82¢
\82¾" : "
\82ð
\8a´
\92m
\82µ
\82½");
386 if (sobj && sobj->blessed) {
389 pline("Your %s starts to tingle.", body_part(NOSE));
391 pline("
\82 \82È
\82½
\82Ì%s
\82ª
\82¤
\82¸
\82¤
\82¸
\82µ
\82¾
\82µ
\82½
\81D", body_part(NOSE));
398 iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
399 u.uinwater = u.uburied = 0;
400 for (obj = fobj; obj; obj = obj->nobj)
401 if ((temp = o_in(obj, oclass)) != 0) {
408 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
409 /* no DEADMONSTER(mtmp) check needed since dmons never have
411 for (obj = mtmp->minvent; obj; obj = obj->nobj)
412 if ((temp = o_in(obj, oclass)) != 0) {
416 break; /* skip rest of this monster's inventory */
419 u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
423 Your("%s %s to tingle and you smell %s.", body_part(NOSE),
424 u.uedibility ? "continues" : "starts", what);
426 Your("%s
\82Í
\82¤
\82¸
\82¤
\82¸
\82µ%s
\81C%s
\82Ì
\93õ
\82¢
\82ð
\9ak
\82¬
\82Æ
\82Á
\82½
\81D", body_part(NOSE),
427 u.uedibility ? "
\91±
\82¯" : "
\8en
\82ß", what);
432 Your("%s tingles and you smell %s.", body_part(NOSE), what);
434 Your("%s
\82Í
\82¤
\82¸
\82¤
\82¸
\82µ
\81C%s
\82Ì
\93õ
\82¢
\82ð
\9ak
\82¬
\82Æ
\82Á
\82½
\81D", body_part(NOSE), what);
437 You("sense %s.", what);
439 You("%s
\82ð
\8a´
\92m
\82µ
\82½
\81D", what);
440 display_nhwindow(WIN_MAP, TRUE);
441 exercise(A_WIS, TRUE);
452 * Used for scrolls, potions, spells, and crystal balls. Returns:
454 * 1 - nothing was detected
455 * 0 - something was detected
458 object_detect(detector, class)
459 struct obj *detector; /* object doing the detecting */
460 int class; /* an object class, 0 for all */
464 int is_cursed = (detector && detector->cursed);
465 int do_dknown = (detector && (detector->oclass == POTION_CLASS
466 || detector->oclass == SPBOOK_CLASS)
467 && detector->blessed);
469 register struct obj *obj, *otmp = (struct obj *) 0;
470 register struct monst *mtmp;
471 int sym, boulder = 0;
473 if (class < 0 || class >= MAXOCLASSES) {
474 impossible("object_detect: illegal class %d", class);
478 /* Special boulder symbol check - does the class symbol happen
479 * to match iflags.bouldersym which is a user-defined?
480 * If so, that means we aren't sure what they really wanted to
481 * detect. Rather than trump anything, show both possibilities.
482 * We can exclude checking the buried obj chain for boulders below.
484 sym = class ? def_oc_syms[class].sym : 0;
485 if (sym && iflags.bouldersym && sym == iflags.bouldersym)
486 boulder = ROCK_CLASS;
488 if (Hallucination || (Confusion && class == SCROLL_CLASS))
489 Strcpy(stuff, something);
492 Strcpy(stuff, class ? def_oc_syms[class].name : "objects");
494 Strcpy(stuff, class ? def_oc_syms[class].name : "
\95¨
\91Ì");
495 if (boulder && class != ROCK_CLASS)
497 Strcat(stuff, " and/or large stones");
499 Strcat(stuff, "
\82Æ
\8b\90\8aâ");
502 for (obj = invent; obj; obj = obj->nobj)
505 for (obj = fobj; obj; obj = obj->nobj) {
506 if ((!class && !boulder) || o_in(obj, class) || o_in(obj, boulder)) {
507 if (obj->ox == u.ux && obj->oy == u.uy)
516 for (obj = level.buriedobjlist; obj; obj = obj->nobj) {
517 if (!class || o_in(obj, class)) {
518 if (obj->ox == u.ux && obj->oy == u.uy)
527 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
528 if (DEADMONSTER(mtmp))
530 for (obj = mtmp->minvent; obj; obj = obj->nobj) {
531 if ((!class && !boulder) || o_in(obj, class)
532 || o_in(obj, boulder))
537 if ((is_cursed && mtmp->m_ap_type == M_AP_OBJECT
538 && (!class || class == objects[mtmp->mappearance].oc_class))
539 || (findgold(mtmp->minvent) && (!class || class == COIN_CLASS))) {
545 if (!clear_stale_map(!class ? ALL_CLASSES : class, 0) && !ct) {
549 strange_feeling(detector, "You feel a lack of something.");
551 strange_feeling(detector, "
\82 \82È
\82½
\82Í
\89½
\82©
\82ª
\8c\87\96R
\82µ
\82Ä
\82¢
\82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D");
556 You("sense %s nearby.", stuff);
558 You("
\8bß
\82
\82Ì%s
\82ð
\8a´
\92m
\82µ
\82½
\81D", stuff);
564 iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
565 u.uinwater = u.uburied = 0;
567 * Map all buried objects first.
569 for (obj = level.buriedobjlist; obj; obj = obj->nobj)
570 if (!class || (otmp = o_in(obj, class))) {
581 * If we are mapping all objects, map only the top object of a pile or
582 * the first object in a monster's inventory. Otherwise, go looking
583 * for a matching object class and display the first one encountered
586 * Objects on the floor override buried objects.
588 for (x = 1; x < COLNO; x++)
589 for (y = 0; y < ROWNO; y++)
590 for (obj = level.objects[x][y]; obj; obj = obj->nexthere)
591 if ((!class && !boulder) || (otmp = o_in(obj, class))
592 || (otmp = o_in(obj, boulder))) {
593 if (class || boulder) {
604 /* Objects in the monster's inventory override floor objects. */
605 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
606 if (DEADMONSTER(mtmp))
608 for (obj = mtmp->minvent; obj; obj = obj->nobj)
609 if ((!class && !boulder) || (otmp = o_in(obj, class))
610 || (otmp = o_in(obj, boulder))) {
611 if (!class && !boulder)
613 otmp->ox = mtmp->mx; /* at monster location */
618 /* Allow a mimic to override the detected objects it is carrying. */
619 if (is_cursed && mtmp->m_ap_type == M_AP_OBJECT
620 && (!class || class == objects[mtmp->mappearance].oc_class)) {
623 temp.oextra = (struct oextra *) 0;
624 temp.otyp = mtmp->mappearance; /* needed for obj_to_glyph() */
627 temp.corpsenm = PM_TENGU; /* if mimicing a corpse */
628 map_object(&temp, 1);
629 } else if (findgold(mtmp->minvent)
630 && (!class || class == COIN_CLASS)) {
632 gold = zeroobj; /* ensure oextra is cleared too */
633 gold.otyp = GOLD_PIECE;
636 map_object(&gold, 1);
641 u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
643 You("detect the %s of %s.", ct ? "presence" : "absence", stuff);
645 You("%s%s
\81D", stuff, ct ? "
\82ð
\94
\8c©
\82µ
\82½" : "
\82Í
\89½
\82à
\82È
\82¢
\82±
\82Æ
\82ª
\82í
\82©
\82Á
\82½" );
646 display_nhwindow(WIN_MAP, TRUE);
648 * What are we going to do when the hero does an object detect while blind
649 * and the detected object covers a known pool?
651 docrt(); /* this will correctly reset vision */
661 * Used by: crystal balls, potions, fountains
663 * Returns 1 if nothing was detected.
664 * Returns 0 if something was detected.
667 monster_detect(otmp, mclass)
668 register struct obj *otmp; /* detecting object (if any) */
669 int mclass; /* monster class, 0 for all */
671 register struct monst *mtmp;
674 /* Note: This used to just check fmon for a non-zero value
675 * but in versions since 3.3.0 fmon can test TRUE due to the
676 * presence of dmons, so we have to find at least one
677 * with positive hit-points to know for sure.
679 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
680 if (!DEADMONSTER(mtmp)) {
687 strange_feeling(otmp, Hallucination
689 ? "You get the heebie jeebies."
691 ? "
\82 \82È
\82½
\82Í
\8bà
\92¹
\82Ì
\89Ä
\82Å
\83L
\83\93\83`
\83\87\81[
\82µ
\82½
\81D"
693 : "You feel threatened.");
695 : "
\82 \82È
\82½
\82Í
\8b°
\95|
\82Å
\82¼
\82
\82Á
\82Æ
\82µ
\82½
\81D");
698 boolean woken = FALSE;
701 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
702 if (DEADMONSTER(mtmp))
704 if (!mclass || mtmp->data->mlet == mclass
705 || (mtmp->data == &mons[PM_LONG_WORM]
706 && mclass == S_WORM_TAIL))
708 if (mclass && def_monsyms[mclass].sym == ' ')
709 show_glyph(mtmp->mx, mtmp->my,
710 detected_mon_to_glyph(mtmp));
712 show_glyph(mtmp->mx, mtmp->my,
713 mtmp->mtame ? pet_to_glyph(mtmp) : mon_to_glyph(mtmp));
714 /* don't be stingy - display entire worm */
715 if (mtmp->data == &mons[PM_LONG_WORM])
716 detect_wsegs(mtmp, 0);
718 if (otmp && otmp->cursed
719 && (mtmp->msleeping || !mtmp->mcanmove)) {
720 mtmp->msleeping = mtmp->mfrozen = 0;
727 You("sense the presence of monsters.");
729 You("
\89ö
\95¨
\82Ì
\91¶
\8dÝ
\82ð
\9ak
\82¬
\82Â
\82¯
\82½
\81D");
732 pline("Monsters sense the presence of you.");
734 pline("
\89ö
\95¨
\82Í
\82 \82È
\82½
\82Ì
\91¶
\8dÝ
\82ð
\9ak
\82¬
\82Â
\82¯
\82½
\81D");
735 display_nhwindow(WIN_MAP, TRUE);
746 sense_trap(trap, x, y, src_cursed)
751 if (Hallucination || src_cursed) {
752 struct obj obj; /* fake object */
754 obj.oextra = (struct oextra *) 0;
762 obj.otyp = (src_cursed) ? GOLD_PIECE : random_object();
763 obj.corpsenm = random_monster(); /* if otyp == CORPSE */
769 struct trap temp_trap; /* fake trap */
772 temp_trap.ttyp = BEAR_TRAP; /* some kind of trap */
773 map_trap(&temp_trap, 1);
777 #define OTRAP_NONE 0 /* nothing found */
778 #define OTRAP_HERE 1 /* found at hero's location */
779 #define OTRAP_THERE 2 /* found at any other location */
781 /* check a list of objects for chest traps; return 1 if found at <ux,uy>,
782 2 if found at some other spot, 3 if both, 0 otherwise; optionally
783 update the map to show where such traps were found */
785 detect_obj_traps(objlist, show_them, how)
788 int how; /* 1 for misleading map feedback */
792 int result = OTRAP_NONE;
794 for (otmp = objlist; otmp; otmp = otmp->nobj) {
795 if (Is_box(otmp) && otmp->otrapped
796 && get_obj_location(otmp, &x, &y, BURIED_TOO | CONTAINED_TOO)) {
797 result |= (x == u.ux && y == u.uy) ? OTRAP_HERE : OTRAP_THERE;
799 sense_trap((struct trap *) 0, x, y, how);
801 if (Has_contents(otmp))
802 result |= detect_obj_traps(otmp->cobj, show_them, how);
807 /* the detections are pulled out so they can
808 * also be used in the crystal ball routine
809 * returns 1 if nothing was detected
810 * returns 0 if something was detected
814 register struct obj *sobj;
815 /* sobj is null if crystal ball, *scroll if gold detection scroll */
817 register struct trap *ttmp;
820 int cursed_src = sobj && sobj->cursed;
821 boolean found = FALSE;
824 /* floor/ceiling traps */
825 for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
826 if (ttmp->tx != u.ux || ttmp->ty != u.uy)
831 /* chest traps (might be buried or carried) */
832 if ((tr = detect_obj_traps(fobj, FALSE, 0)) != OTRAP_NONE) {
833 if (tr & OTRAP_THERE)
838 if ((tr = detect_obj_traps(level.buriedobjlist, FALSE, 0))
840 if (tr & OTRAP_THERE)
845 for (mon = fmon; mon; mon = mon->nmon) {
846 if (DEADMONSTER(mon))
848 if ((tr = detect_obj_traps(mon->minvent, FALSE, 0)) != OTRAP_NONE) {
849 if (tr & OTRAP_THERE)
855 if (detect_obj_traps(invent, FALSE, 0) != OTRAP_NONE)
858 for (door = 0; door < doorindex; door++) {
860 if (levl[cc.x][cc.y].doormask & D_TRAPPED) {
861 if (cc.x != u.ux || cc.y != u.uy)
871 Sprintf(buf, "Your %s stop itching.", makeplural(body_part(TOE)));
873 Sprintf(buf, "
\82 \82È
\82½
\82Ì%s
\82Ì
\82Þ
\82¸
\82Þ
\82¸
\82Í
\82¨
\82³
\82Ü
\82Á
\82½
\81D", makeplural(body_part(TOE)));
874 strange_feeling(sobj, buf);
877 /* traps exist, but only under me - no separate display required */
879 Your("%s itch.", makeplural(body_part(TOE)));
881 Your("%s
\82Í
\82Þ
\82¸
\82Þ
\82¸
\82µ
\82½
\81D", makeplural(body_part(TOE)));
886 iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
887 u.uinwater = u.uburied = 0;
889 /* show chest traps first, so that subsequent floor trap display
890 will override if both types are present at the same location */
891 (void) detect_obj_traps(fobj, TRUE, cursed_src);
892 (void) detect_obj_traps(level.buriedobjlist, TRUE, cursed_src);
893 for (mon = fmon; mon; mon = mon->nmon) {
894 if (DEADMONSTER(mon))
896 (void) detect_obj_traps(mon->minvent, TRUE, cursed_src);
898 (void) detect_obj_traps(invent, TRUE, cursed_src);
900 for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
901 sense_trap(ttmp, 0, 0, cursed_src);
903 for (door = 0; door < doorindex; door++) {
905 if (levl[cc.x][cc.y].doormask & D_TRAPPED)
906 sense_trap((struct trap *) 0, cc.x, cc.y, cursed_src);
909 /* redisplay hero unless sense_trap() revealed something at <ux,uy> */
910 glyph = glyph_at(u.ux, u.uy);
911 if (!(glyph_is_trap(glyph) || glyph_is_object(glyph)))
913 u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
916 You_feel("%s.", cursed_src ? "very greedy" : "entrapped");
918 You("%s
\8bC
\8e\9d\82É
\82È
\82Á
\82½
\81D", cursed_src ? "
\82Æ
\82Ä
\82à
\82Ç
\82ñ
\97~
\82È" : "
\82¾
\82Ü
\82³
\82ê
\82Ä
\82¢
\82é
\82æ
\82¤
\82È");
919 /* wait for user to respond, then reset map display to normal */
920 display_nhwindow(WIN_MAP, TRUE);
930 level_distance(where)
933 register schar ll = depth(&u.uz) - depth(where);
934 register boolean indun = (u.uz.dnum == where->dnum);
937 if (ll < (-8 - rn2(3)))
942 return "
\82Í
\82é
\82©
\94Þ
\95û
\82É";
947 return "
\82Í
\82é
\82©
\89º
\95û
\82É";
951 return "away below you";
953 return "
\82¸
\82Á
\82Æ
\89º
\95û
\82É";
958 return "
\89º
\95û
\82É";
961 return "in the distance";
963 return "
\89\93\82
\82É";
968 return "
\90^
\89º
\82É";
970 if (ll > (8 + rn2(3)))
975 return "
\82Í
\82é
\82©
\94Þ
\95û
\82É";
980 return "
\82Í
\82é
\82©
\8fã
\95û
\82É";
984 return "away above you";
986 return "
\82¸
\82Á
\82Æ
\8fã
\95û
\82É";
991 return "
\8fã
\95û
\82É";
994 return "in the distance";
996 return "
\89\93\82
\82É";
1001 return "
\90^
\8fã
\82É";
1004 return "in the distance";
1006 return "
\89\93\82
\82É";
1011 return "
\8bß
\82
\82É";
1014 static const struct {
1017 } level_detects[] = {
1019 { "Delphi", &oracle_level },
1021 { "
\83f
\83\8b\83t
\83@
\83C", &oracle_level },
1023 { "Medusa's lair", &medusa_level },
1025 { "
\83\81\83f
\83\85\81[
\83T
\82Ì
\8fZ
\82Ý
\82©", &medusa_level },
1027 { "a castle", &stronghold_level },
1029 { "
\8fé", &stronghold_level },
1031 { "the Wizard of Yendor's tower", &wiz1_level },
1033 { "
\83C
\83F
\83\93\83_
\81[
\82Ì
\96\82\96@
\8eg
\82¢
\82Ì
\93\83", &wiz1_level },
1037 use_crystal_ball(optr)
1042 struct obj *obj = *optr;
1046 pline("Too bad you can't see %s.", the(xname(obj)));
1048 pline("
\82È
\82ñ
\82Ä
\82±
\82Æ
\82¾
\81D%s
\82ð
\8c©
\82é
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D", the(xname(obj)));
1051 oops = (rnd(20) > ACURR(A_INT) || obj->cursed);
1052 if (oops && (obj->spe > 0)) {
1053 switch (rnd(obj->oartifact ? 4 : 5)) {
1056 pline("%s too much to comprehend!", Tobjnam(obj, "are"));
1058 pline("%s
\82ð
\94`
\82¢
\82½
\82ª
\89½
\82Ì
\82±
\82Æ
\82¾
\82©
\82³
\82Á
\82Ï
\82è
\82í
\82©
\82ç
\82È
\82©
\82Á
\82½
\81I", xname(obj));
1062 pline("%s you!", Tobjnam(obj, "confuse"));
1064 pline("%s
\82ð
\94`
\82¢
\82Ä
\82é
\82Æ
\82Ó
\82ç
\82Â
\82¢
\82Ä
\82«
\82½
\81I", xname(obj));
1065 make_confused((HConfusion & TIMEOUT) + (long) rnd(100), FALSE);
1068 if (!resists_blnd(&youmonst)) {
1070 pline("%s your vision!", Tobjnam(obj, "damage"));
1072 pline("%s
\82ð
\94`
\82¢
\82Ä
\82¢
\82é
\82Æ
\8e\8b\8ao
\82ª
\82¨
\82©
\82µ
\82
\82È
\82Á
\82Ä
\82«
\82½
\81I", xname(obj));
1073 make_blinded((Blinded & TIMEOUT) + (long) rnd(100), FALSE);
1075 Your1(vision_clears);
1078 pline("%s your vision.", Tobjnam(obj, "assault"));
1080 pline("%s
\82ª
\82 \82È
\82½
\82Ì
\8e\8b\8aE
\82É
\94\97\82Á
\82Ä
\82«
\82½
\81D", xname(obj));
1082 You("are unaffected!");
1084 pline("
\82µ
\82©
\82µ
\81C
\82 \82È
\82½
\82Í
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82©
\82Á
\82½
\81I");
1089 pline("%s your mind!", Tobjnam(obj, "zap"));
1091 pline("%s
\82ð
\94`
\82¢
\82Ä
\82¢
\82é
\82Æ
\8cÜ
\8a´
\82ª
\82¨
\82©
\82µ
\82
\82È
\82Á
\82Ä
\82«
\82½
\81I", xname(obj));
1092 (void) make_hallucinated(
1093 (HHallucination & TIMEOUT) + (long) rnd(100), FALSE, 0L);
1097 pline("%s!", Tobjnam(obj, "explode"));
1099 pline("%s
\82Í
\94\9a\94
\82µ
\82½
\81I", xname(obj));
1101 *optr = obj = 0; /* it's gone */
1102 /* physical damage cause by the shards and force */
1104 losehp(Maybe_Half_Phys(rnd(30)), "exploding crystal ball",
1106 losehp(Maybe_Half_Phys(rnd(30)), "
\90\85\8f»
\8bÊ
\82Ì
\94\9a\94
\82Å",
1111 consume_obj_charge(obj, TRUE);
1115 if (Hallucination) {
1118 pline("All you see is funky %s haze.", hcolor((char *) 0));
1120 pline("
\82¨
\82¨
\81I
\83t
\83@
\83\93\83L
\81[
\83\82\83\93\83L
\81[
\82È%s
\82à
\82â
\82ª
\8c©
\82¦
\82é
\81D", hcolor((char *)0));
1125 You("grok some groovy globs of incandescent lava.");
1127 You("
\90\85\96å
\82Ì
\8c®
\82ð
\82à
\82Á
\82½
\90\85\8cË
\89©
\96å
\82ª
\95Ç
\82Ì
\89e
\82É
\89B
\82ê
\82Ä
\82¢
\82é
\82Ì
\82ª
\8c©
\82¦
\82½
\81D");
1131 pline("Whoa! Psychedelic colors, %s!",
1132 poly_gender() == 1 ? "babe" : "dude");
1134 pline("
\83\8f\81[
\83I
\81I
\83\89\83\8a\82Á
\82Ä
\82é
\82©
\82¢
\81H%s
\81I",
1135 poly_gender() == 1 ? "
\83x
\83C
\83r
\81[" : "
\83\86\81[");
1140 pline_The("crystal pulses with sinister %s light!",
1142 pline("
\90\85\8f»
\82Í
\95s
\8bg
\82È%s
\83p
\83\8b\83X
\82ð
\94
\82µ
\82½
\81I",
1143 hcolor((char *) 0));
1147 You_see("goldfish swimming above fluorescent rocks.");
1149 You("
\8cu
\8cõ
\8aâ
\82Ì
\8fã
\82ð
\8bà
\8b\9b\82ª
\89j
\82¢
\82Å
\82¢
\82é
\82Ì
\82ð
\8c©
\82½
\81D");
1154 "tiny snowflakes spinning around a miniature farmhouse.");
1156 You("
\8f¬
\82³
\82¢
\90á
\95Ð
\82ª
\83~
\83j
\83`
\83\85\83A
\82Ì
\94_
\89Æ
\82Ì
\89Æ
\82Ì
\82Ü
\82í
\82è
\82ð
\95\91\82Á
\82Ä
\82é
\82Ì
\82ð
\8c©
\82½
\81D");
1161 pline("Oh wow... like a kaleidoscope!");
1163 pline("
\83\8f\81[
\83I
\81D
\96\9c\89Ø
\8b¾
\82Ì
\82æ
\82¤
\82¾
\81I");
1166 consume_obj_charge(obj, TRUE);
1171 /* read a single character */
1174 You("may look for an object or monster symbol.");
1176 You("
\95¨
\91Ì
\82â
\89ö
\95¨
\82Ì
\8bL
\8d\86\82ð
\92T
\82¹
\82é
\81D");
1178 ch = yn_function("What do you look for?", (char *) 0, '\0');
1180 ch = yn_function("
\89½
\82ð
\92T
\82µ
\82Ü
\82·
\82©
\81H", (char *)0, '\0');
1181 /* Don't filter out ' ' here; it has a use */
1182 if ((ch != def_monsyms[S_GHOST].sym) && index(quitchars, ch)) {
1188 You("peer into %s...", the(xname(obj)));
1190 You("%s
\82ð
\94`
\82«
\82±
\82ñ
\82¾
\81D
\81D
\81D", the(xname(obj)));
1193 multi_reason = "gazing into a crystal ball";
1195 multi_reason = "
\90\85\8f»
\8b\85\82ð
\94`
\82«
\8d\9e\82ñ
\82Å
\82¢
\82é
\8e\9e\82É";
1199 pline_The("vision is unclear.");
1201 pline("
\89f
\91\9c\82Í
\95s
\91N
\96¾
\82¾
\82Á
\82½
\81D");
1206 makeknown(CRYSTAL_BALL);
1207 consume_obj_charge(obj, TRUE);
1209 /* special case: accept ']' as synonym for mimic
1210 * we have to do this before the def_char_to_objclass check
1212 if (ch == DEF_MIMIC_DEF)
1215 if ((class = def_char_to_objclass(ch)) != MAXOCLASSES)
1216 ret = object_detect((struct obj *) 0, class);
1217 else if ((class = def_char_to_monclass(ch)) != MAXMCLASSES)
1218 ret = monster_detect((struct obj *) 0, class);
1219 else if (iflags.bouldersym && (ch == iflags.bouldersym))
1220 ret = object_detect((struct obj *) 0, ROCK_CLASS);
1224 ret = trap_detect((struct obj *) 0);
1227 int i = rn2(SIZE(level_detects));
1229 You_see("%s, %s.", level_detects[i].what,
1230 level_distance(level_detects[i].where));
1232 You_see("%s
\82ð%s
\8c©
\82½
\81D", level_detects[i].what,
1233 level_distance(level_detects[i].where));
1241 if (!rn2(100)) /* make them nervous */
1243 You_see("the Wizard of Yendor gazing out at you.");
1245 You("
\83C
\83F
\83\93\83_
\81[
\82Ì
\96\82\96@
\8eg
\82¢
\82ª
\82 \82È
\82½
\82ð
\82É
\82ç
\82ñ
\82Å
\82¢
\82é
\82Ì
\82ð
\8c©
\82½
\81D");
1248 pline_The("vision is unclear.");
1250 pline("
\89f
\91\9c\82Í
\95s
\91N
\96¾
\82É
\82È
\82Á
\82½
\81D");
1264 if (Confusion && rn2(7))
1270 /* Secret corridors are found, but not secret doors. */
1271 if (lev->typ == SCORR) {
1273 unblock_point(x, y);
1277 * Force the real background, then if it's not furniture and there's
1278 * a known trap there, display the trap, else if there was an object
1279 * shown there, redisplay the object. So during mapping, furniture
1280 * takes precedence over traps, which take precedence over objects,
1281 * opposite to how normal vision behaves.
1283 oldglyph = glyph_at(x, y);
1284 if (level.flags.hero_memory) {
1285 magic_map_background(x, y, 0);
1286 newsym(x, y); /* show it, if not blocked */
1288 magic_map_background(x, y, 1); /* display it */
1290 if (!IS_FURNITURE(lev->typ)) {
1291 if ((t = t_at(x, y)) != 0 && t->tseen) {
1293 } else if (glyph_is_trap(oldglyph) || glyph_is_object(oldglyph)) {
1294 show_glyph(x, y, oldglyph);
1295 if (level.flags.hero_memory)
1296 lev->glyph = oldglyph;
1304 register int zx, zy;
1306 iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
1307 u.uinwater = u.uburied = 0;
1308 for (zx = 1; zx < COLNO; zx++)
1309 for (zy = 0; zy < ROWNO; zy++)
1310 show_map_spot(zx, zy);
1311 u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
1312 if (!level.flags.hero_memory || Underwater) {
1313 flush_screen(1); /* flush temp screen */
1314 display_nhwindow(WIN_MAP, TRUE); /* wait */
1317 exercise(A_WIS, TRUE);
1323 register int zx, zy;
1324 int lo_y = (u.uy - 5 < 0 ? 0 : u.uy - 5),
1325 hi_y = (u.uy + 6 > ROWNO ? ROWNO : u.uy + 6),
1326 lo_x = (u.ux - 9 < 1 ? 1 : u.ux - 9), /* avoid column 0 */
1327 hi_x = (u.ux + 10 > COLNO ? COLNO : u.ux + 10);
1329 for (zx = lo_x; zx < hi_x; zx++)
1330 for (zy = lo_y; zy < hi_y; zy++)
1331 show_map_spot(zx, zy);
1333 if (!level.flags.hero_memory || Underwater) {
1334 flush_screen(1); /* flush temp screen */
1335 display_nhwindow(WIN_MAP, TRUE); /* wait */
1340 /* convert a secret door into a normal door */
1342 cvt_sdoor_to_door(lev)
1345 int newmask = lev->doormask & ~WM_MASK;
1347 if (Is_rogue_level(&u.uz))
1348 /* rogue didn't have doors, only doorways */
1351 /* newly exposed door is closed */
1352 if (!(newmask & D_LOCKED))
1353 newmask |= D_CLOSED;
1356 lev->doormask = newmask;
1360 findone(zx, zy, num)
1364 register struct trap *ttmp;
1365 register struct monst *mtmp;
1367 if (levl[zx][zy].typ == SDOOR) {
1368 cvt_sdoor_to_door(&levl[zx][zy]); /* .typ = DOOR */
1369 magic_map_background(zx, zy, 0);
1372 } else if (levl[zx][zy].typ == SCORR) {
1373 levl[zx][zy].typ = CORR;
1374 unblock_point(zx, zy);
1375 magic_map_background(zx, zy, 0);
1378 } else if ((ttmp = t_at(zx, zy)) != 0) {
1379 if (!ttmp->tseen && ttmp->ttyp != STATUE_TRAP) {
1384 } else if ((mtmp = m_at(zx, zy)) != 0) {
1385 if (mtmp->m_ap_type) {
1389 if (mtmp->mundetected
1390 && (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL)) {
1391 mtmp->mundetected = 0;
1395 if (!canspotmon(mtmp) && !glyph_is_invisible(levl[zx][zy].glyph))
1396 map_invisible(zx, zy);
1397 } else if (glyph_is_invisible(levl[zx][zy].glyph)) {
1398 unmap_object(zx, zy);
1405 openone(zx, zy, num)
1409 register struct trap *ttmp;
1410 register struct obj *otmp;
1411 int *num_p = (int *) num;
1413 if (OBJ_AT(zx, zy)) {
1414 for (otmp = level.objects[zx][zy]; otmp; otmp = otmp->nexthere) {
1415 if (Is_box(otmp) && otmp->olocked) {
1420 /* let it fall to the next cases. could be on trap. */
1422 if (levl[zx][zy].typ == SDOOR
1423 || (levl[zx][zy].typ == DOOR
1424 && (levl[zx][zy].doormask & (D_CLOSED | D_LOCKED)))) {
1425 if (levl[zx][zy].typ == SDOOR)
1426 cvt_sdoor_to_door(&levl[zx][zy]); /* .typ = DOOR */
1427 if (levl[zx][zy].doormask & D_TRAPPED) {
1428 if (distu(zx, zy) < 3)
1430 b_trapped("door", 0);
1432 b_trapped("
\94à", 0);
1435 Norep("You %s an explosion!",
1436 cansee(zx, zy) ? "see" : (!Deaf ? "hear"
1437 : "feel the shock of"));
1439 Norep("
\82 \82È
\82½
\82Í
\94\9a\94%s
\81I",
1440 cansee(zx, zy) ? "
\82ð
\8c©
\82½" : (!Deaf ? "
\89¹
\82ð
\95·
\82¢
\82½"
1441 : "
\82Ì
\8fÕ
\8c\82\82ð
\8a´
\82¶
\82½"));
1443 wake_nearto(zx, zy, 11 * 11);
1444 levl[zx][zy].doormask = D_NODOOR;
1446 levl[zx][zy].doormask = D_ISOPEN;
1447 unblock_point(zx, zy);
1450 } else if (levl[zx][zy].typ == SCORR) {
1451 levl[zx][zy].typ = CORR;
1452 unblock_point(zx, zy);
1455 } else if ((ttmp = t_at(zx, zy)) != 0) {
1457 boolean dummy; /* unneeded "you notice it arg" */
1459 if (!ttmp->tseen && ttmp->ttyp != STATUE_TRAP) {
1464 mon = (zx == u.ux && zy == u.uy) ? &youmonst : m_at(zx, zy);
1465 if (openholdingtrap(mon, &dummy)
1466 || openfallingtrap(mon, TRUE, &dummy))
1468 } else if (find_drawbridge(&zx, &zy)) {
1469 /* make sure it isn't an open drawbridge */
1470 open_drawbridge(zx, zy);
1475 /* returns number of things found */
1483 do_clear_area(u.ux, u.uy, BOLT_LIM, findone, (genericptr_t) &num);
1487 /* returns number of things found and opened */
1494 if (is_animal(u.ustuck->data)) {
1497 pline("Its mouth opens!");
1499 pline("
\89½
\8eÒ
\82©
\82Ì
\8cû
\82ª
\8aJ
\82¢
\82½
\81I");
1502 pline("%s opens its mouth!", Monnam(u.ustuck));
1504 pline("%s
\82Í
\8cû
\82ð
\8aJ
\82¢
\82½
\81I", Monnam(u.ustuck));
1506 expels(u.ustuck, u.ustuck->data, TRUE);
1510 do_clear_area(u.ux, u.uy, BOLT_LIM, openone, (genericptr_t) &num);
1514 /* callback hack for overriding vision in do_clear_area() */
1517 void FDECL((*func), (int, int, genericptr_t));
1519 return (func == findone || func == openone);
1526 int tt = what_trap(trap->ttyp);
1527 boolean cleared = FALSE;
1530 exercise(A_WIS, TRUE);
1531 feel_newsym(trap->tx, trap->ty);
1533 if (levl[trap->tx][trap->ty].glyph != trap_to_glyph(trap)) {
1534 /* There's too much clutter to see your find otherwise */
1542 You("find %s.", an(defsyms[trap_to_defsym(tt)].explanation));
1544 You("%s
\82ð
\8c©
\82Â
\82¯
\82½
\81D", defsyms[trap_to_defsym(tt)].explanation);
1547 display_nhwindow(WIN_MAP, TRUE); /* wait */
1554 register int aflag; /* intrinsic autosearch vs explicit searching */
1557 /* some versions of gcc seriously muck up nested loops. if you get strange
1558 crashes while searching in a version compiled with gcc, try putting
1559 #define GCC_BUG in *conf.h (or adding -DGCC_BUG to CFLAGS in the
1562 volatile xchar x, y;
1564 register xchar x, y;
1566 register struct trap *trap;
1567 register struct monst *mtmp;
1572 pline("What are you looking for? The exit?");
1574 pline("
\89½
\82ð
\92T
\82·
\82ñ
\82¾
\82¢
\81H
\94ñ
\8fí
\8cû
\81H");
1576 int fund = (uwep && uwep->oartifact
1577 && spec_ability(uwep, SPFX_SEARCH)) ? uwep->spe : 0;
1579 if (ublindf && ublindf->otyp == LENSES && !Blind)
1580 fund += 2; /* JDS: lenses help searching */
1583 for (x = u.ux - 1; x < u.ux + 2; x++)
1584 for (y = u.uy - 1; y < u.uy + 2; y++) {
1587 if (x == u.ux && y == u.uy)
1590 if (Blind && !aflag)
1591 feel_location(x, y);
1592 if (levl[x][y].typ == SDOOR) {
1595 cvt_sdoor_to_door(&levl[x][y]); /* .typ = DOOR */
1596 exercise(A_WIS, TRUE);
1598 feel_location(x, y); /* make sure it shows up */
1600 You("find a hidden door.");
1602 You("
\89B
\82³
\82ê
\82½
\94à
\82ð
\8c©
\82Â
\82¯
\82½
\81D");
1603 } else if (levl[x][y].typ == SCORR) {
1606 levl[x][y].typ = CORR;
1607 unblock_point(x, y); /* vision */
1608 exercise(A_WIS, TRUE);
1610 feel_location(x, y); /* make sure it shows up */
1612 You("find a hidden passage.");
1614 You("
\89B
\82³
\82ê
\82½
\92Ê
\98H
\82ð
\8c©
\82Â
\82¯
\82½
\81D");
1616 /* Be careful not to find anything in an SCORR or SDOOR */
1617 if ((mtmp = m_at(x, y)) != 0 && !aflag) {
1618 if (mtmp->m_ap_type) {
1621 exercise(A_WIS, TRUE);
1622 if (!canspotmon(mtmp)) {
1623 if (glyph_is_invisible(levl[x][y].glyph)) {
1624 /* found invisible monster in a square
1625 * which already has an 'I' in it.
1626 * Logically, this should still take
1627 * time and lead to a return(1), but
1628 * if we did that the player would keep
1629 * finding the same monster every turn.
1634 You_feel("an unseen monster!");
1636 You("
\8c©
\82¦
\82È
\82¢
\89ö
\95¨
\82Ì
\8bC
\94z
\82ð
\8a´
\82¶
\82½
\81I");
1637 map_invisible(x, y);
1639 } else if (!sensemon(mtmp))
1641 You("find %s.", mtmp->mtame
1643 You("%s
\82ð
\8c©
\82Â
\82¯
\82½
\81D", mtmp->mtame
1648 if (!canspotmon(mtmp)) {
1649 if (mtmp->mundetected
1650 && (is_hider(mtmp->data)
1651 || mtmp->data->mlet == S_EEL))
1652 mtmp->mundetected = 0;
1658 /* see if an invisible monster has moved--if Blind,
1659 * feel_location() already did it
1661 if (!aflag && !mtmp && !Blind
1662 && glyph_is_invisible(levl[x][y].glyph)) {
1667 if ((trap = t_at(x, y)) && !trap->tseen && !rnl(8)) {
1669 if (trap->ttyp == STATUE_TRAP) {
1670 if (activate_statue_trap(trap, x, y, FALSE))
1671 exercise(A_WIS, TRUE);
1683 /* the 's' command -- explicit searching */
1687 return dosearch0(0);
1690 /* Pre-map the sokoban levels */
1695 register struct trap *ttmp;
1696 register struct obj *obj;
1698 /* Map the background and boulders */
1699 for (x = 1; x < COLNO; x++)
1700 for (y = 0; y < ROWNO; y++) {
1701 levl[x][y].seenv = SVALL;
1702 levl[x][y].waslit = TRUE;
1703 map_background(x, y, 1);
1704 if ((obj = sobj_at(BOULDER, x, y)) != 0)
1709 for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
1712 /* set sokoban_rules when there is at least one pit or hole */
1713 if (ttmp->ttyp == PIT || ttmp->ttyp == HOLE)
1718 /* idea from crawl; show known portion of map without any monsters,
1719 objects, or traps occluding the view of the underlying terrain */
1721 reveal_terrain(full, which_subset)
1722 int full; /* wizard|explore modes allow player to request full map */
1723 int which_subset; /* when not full, whether to suppress objs and/or traps */
1725 if ((Hallucination || Stunned || Confusion) && !full) {
1727 You("are too disoriented for this.");
1729 You("
\8d¬
\97\90\82µ
\82Ä
\82¢
\82é
\82Ì
\82Å
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
1731 int x, y, glyph, levl_glyph, default_glyph;
1733 unsigned save_swallowed;
1737 boolean keep_traps = (which_subset & 1) !=0,
1738 keep_objs = (which_subset & 2) != 0,
1739 keep_mons = (which_subset & 4) != 0; /* actually always 0 */
1741 save_swallowed = u.uswallow;
1742 iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied;
1743 u.uinwater = u.uburied = 0;
1745 default_glyph = cmap_to_glyph(level.flags.arboreal ? S_tree : S_stone);
1746 /* for 'full', show the actual terrain for the entire level,
1747 otherwise what the hero remembers for seen locations with
1748 monsters, objects, and/or traps removed as caller dictates */
1749 for (x = 1; x < COLNO; x++)
1750 for (y = 0; y < ROWNO; y++) {
1751 seenv = (full || level.flags.hero_memory)
1752 ? levl[x][y].seenv : cansee(x, y) ? SVALL : 0;
1754 levl[x][y].seenv = SVALL;
1755 glyph = back_to_glyph(x, y);
1756 levl[x][y].seenv = seenv;
1758 levl_glyph = level.flags.hero_memory
1761 ? back_to_glyph(x, y)
1763 /* glyph_at() returns the displayed glyph, which might
1764 be a monster. levl[][].glyph contains the remembered
1765 glyph, which will never be a monster (unless it is
1766 the invisible monster glyph, which is handled like
1767 an object, replacing any object or trap at its spot) */
1768 glyph = !save_swallowed ? glyph_at(x, y) : levl_glyph;
1769 if (keep_mons && x == u.ux && y == u.uy && save_swallowed)
1770 glyph = mon_to_glyph(u.ustuck);
1771 else if (((glyph_is_monster(glyph)
1772 || glyph_is_warning(glyph)) && !keep_mons)
1773 || glyph_is_swallow(glyph))
1775 if (((glyph_is_object(glyph) && !keep_objs)
1776 || glyph_is_invisible(glyph))
1777 && keep_traps && !covers_traps(x, y)) {
1778 if ((t = t_at(x, y)) != 0 && t->tseen)
1779 glyph = trap_to_glyph(t);
1781 if ((glyph_is_object(glyph) && !keep_objs)
1782 || (glyph_is_trap(glyph) && !keep_traps)
1783 || glyph_is_invisible(glyph)) {
1785 glyph = default_glyph;
1786 } else if (lastseentyp[x][y] == levl[x][y].typ) {
1787 glyph = back_to_glyph(x, y);
1789 /* look for a mimic here posing as furniture;
1790 if we don't find one, we'll have to fake it */
1791 if ((mtmp = m_at(x, y)) != 0
1792 && mtmp->m_ap_type == M_AP_FURNITURE) {
1793 glyph = cmap_to_glyph(mtmp->mappearance);
1795 /* we have a topology type but we want a
1796 screen symbol in order to derive a glyph;
1797 some screen symbols need the flags field
1798 of levl[][] in addition to the type
1799 (to disambiguate STAIRS to S_upstair or
1800 S_dnstair, for example; current flags
1801 might not be intended for remembered
1802 type, but we've got no other choice) */
1803 schar save_typ = levl[x][y].typ;
1805 levl[x][y].typ = lastseentyp[x][y];
1806 glyph = back_to_glyph(x, y);
1807 levl[x][y].typ = save_typ;
1812 show_glyph(x, y, glyph);
1815 /* [TODO: highlight hero's location somehow] */
1816 u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied;
1822 Strcpy(buf, "underlying terrain");
1824 Strcpy(buf, "
\89º
\82É
\82 \82é
\92n
\8c`");
1827 Strcpy(buf, "known terrain");
1829 Strcpy(buf, "
\92m
\82Á
\82Ä
\82¢
\82é
\92n
\8c`");
1832 Sprintf(eos(buf), "%s traps",
1833 (keep_objs || keep_mons) ? "," : " and");
1835 Strcat(buf, "
\82Æã©");
1839 Sprintf(eos(buf), "%s%s objects",
1840 (keep_traps || keep_mons) ? "," : "",
1841 keep_mons ? "" : " and");
1843 Strcat(buf, "
\82Æ
\95¨
\91Ì");
1847 Sprintf(eos(buf), "%s and monsters",
1848 (keep_traps || keep_objs) ? "," : "");
1850 Strcat(buf, "
\82Æ
\89ö
\95¨");
1854 pline("Showing %s only...", buf);
1856 pline("%s
\82¾
\82¯
\82ð
\8c©
\82é
\81D
\81D
\81D", buf);
1857 display_nhwindow(WIN_MAP, TRUE); /* give "--More--" prompt */
1858 docrt(); /* redraw the screen, restoring regular map */