OSDN Git Service

update year to 2020
[jnethack/source.git] / src / detect.c
1 /* NetHack 3.6  detect.c        $NHDT-Date: 1575245054 2019/12/02 00:04:14 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.100 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2018. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /*
7  * Detection routines, including crystal ball, magic mapping, and search
8  * command.
9  */
10
11 /* JNetHack Copyright */
12 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
13 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020            */
14 /* JNetHack may be freely redistributed.  See license for details. */
15
16 #include "hack.h"
17 #include "artifact.h"
18
19 extern boolean known; /* from read.c */
20
21 STATIC_DCL boolean NDECL(unconstrain_map);
22 STATIC_DCL void NDECL(reconstrain_map);
23 STATIC_DCL void FDECL(browse_map, (int, const char *));
24 STATIC_DCL void FDECL(map_monst, (struct monst *, BOOLEAN_P));
25 STATIC_DCL void FDECL(do_dknown_of, (struct obj *));
26 STATIC_DCL boolean FDECL(check_map_spot, (int, int, CHAR_P, unsigned));
27 STATIC_DCL boolean FDECL(clear_stale_map, (CHAR_P, unsigned));
28 STATIC_DCL void FDECL(sense_trap, (struct trap *, XCHAR_P, XCHAR_P, int));
29 STATIC_DCL int FDECL(detect_obj_traps, (struct obj *, BOOLEAN_P, int));
30 STATIC_DCL void FDECL(show_map_spot, (int, int));
31 STATIC_PTR void FDECL(findone, (int, int, genericptr_t));
32 STATIC_PTR void FDECL(openone, (int, int, genericptr_t));
33 STATIC_DCL int FDECL(mfind0, (struct monst *, BOOLEAN_P));
34 STATIC_DCL int FDECL(reveal_terrain_getglyph, (int, int, int,
35                                                unsigned, int, int));
36
37 /* bring hero out from underwater or underground or being engulfed;
38    return True iff any change occurred */
39 STATIC_OVL boolean
40 unconstrain_map()
41 {
42     boolean res = u.uinwater || u.uburied || u.uswallow;
43
44     /* bring Underwater, buried, or swallowed hero to normal map */
45     iflags.save_uinwater = u.uinwater, u.uinwater = 0;
46     iflags.save_uburied  = u.uburied,  u.uburied  = 0;
47     iflags.save_uswallow = u.uswallow, u.uswallow = 0;
48
49     return res;
50 }
51
52 /* put hero back underwater or underground or engulfed */
53 STATIC_OVL void
54 reconstrain_map()
55 {
56     u.uinwater = iflags.save_uinwater, iflags.save_uinwater = 0;
57     u.uburied  = iflags.save_uburied,  iflags.save_uburied  = 0;
58     u.uswallow = iflags.save_uswallow, iflags.save_uswallow = 0;
59 }
60
61 /* use getpos()'s 'autodescribe' to view whatever is currently shown on map */
62 STATIC_DCL void
63 browse_map(ter_typ, ter_explain)
64 int ter_typ;
65 const char *ter_explain;
66 {
67     coord dummy_pos; /* don't care whether player actually picks a spot */
68     boolean save_autodescribe;
69
70     dummy_pos.x = u.ux, dummy_pos.y = u.uy; /* starting spot for getpos() */
71     save_autodescribe = iflags.autodescribe;
72     iflags.autodescribe = TRUE;
73     iflags.terrainmode = ter_typ;
74     getpos(&dummy_pos, FALSE, ter_explain);
75     iflags.terrainmode = 0;
76     iflags.autodescribe = save_autodescribe;
77 }
78
79 /* extracted from monster_detection() so can be shared by do_vicinity_map() */
80 STATIC_DCL void
81 map_monst(mtmp, showtail)
82 struct monst *mtmp;
83 boolean showtail;
84 {
85     if (def_monsyms[(int) mtmp->data->mlet].sym == ' ')
86         show_glyph(mtmp->mx, mtmp->my,
87                    detected_mon_to_glyph(mtmp, newsym_rn2));
88     else
89         show_glyph(mtmp->mx, mtmp->my, mtmp->mtame
90                    ? pet_to_glyph(mtmp, newsym_rn2)
91                    : mon_to_glyph(mtmp, newsym_rn2));
92
93     if (showtail && mtmp->data == &mons[PM_LONG_WORM])
94         detect_wsegs(mtmp, 0);
95 }
96
97 /* this is checking whether a trap symbol represents a trapped chest,
98    not whether a trapped chest is actually present */
99 boolean
100 trapped_chest_at(ttyp, x, y)
101 int ttyp;
102 int x, y;
103 {
104     struct monst *mtmp;
105     struct obj *otmp;
106
107     if (!glyph_is_trap(glyph_at(x, y)))
108         return FALSE;
109     if (ttyp != BEAR_TRAP || (Hallucination && rn2(20)))
110         return FALSE;
111
112     /*
113      * TODO?  We should check containers recursively like the trap
114      * detecting routine does.  Chests and large boxes do not nest in
115      * themselves or each other, but could be contained inside statues.
116      *
117      * For farlook, we should also check for buried containers, but
118      * for '^' command to examine adjacent trap glyph, we shouldn't.
119      */
120
121     /* on map, presence of any trappable container will do */
122     if (sobj_at(CHEST, x, y) || sobj_at(LARGE_BOX, x, y))
123         return TRUE;
124     /* in inventory, we need to find one which is actually trapped */
125     if (x == u.ux && y == u.uy) {
126         for (otmp = invent; otmp; otmp = otmp->nobj)
127             if (Is_box(otmp) && otmp->otrapped)
128                 return TRUE;
129         if (u.usteed) { /* steed isn't on map so won't be found by m_at() */
130             for (otmp = u.usteed->minvent; otmp; otmp = otmp->nobj)
131                 if (Is_box(otmp) && otmp->otrapped)
132                     return TRUE;
133         }
134     }
135     if ((mtmp = m_at(x, y)) != 0)
136         for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
137             if (Is_box(otmp) && otmp->otrapped)
138                 return TRUE;
139     return FALSE;
140 }
141
142 /* this is checking whether a trap symbol represents a trapped door,
143    not whether the door here is actually trapped */
144 boolean
145 trapped_door_at(ttyp, x, y)
146 int ttyp;
147 int x, y;
148 {
149     struct rm *lev;
150
151     if (!glyph_is_trap(glyph_at(x, y)))
152         return FALSE;
153     if (ttyp != BEAR_TRAP || (Hallucination && rn2(20)))
154         return FALSE;
155     lev = &levl[x][y];
156     if (!IS_DOOR(lev->typ))
157         return FALSE;
158     if ((lev->doormask & (D_NODOOR | D_BROKEN | D_ISOPEN)) != 0
159          && trapped_chest_at(ttyp, x, y))
160         return FALSE;
161     return TRUE;
162 }
163
164 /* recursively search obj for an object in class oclass, return 1st found */
165 struct obj *
166 o_in(obj, oclass)
167 struct obj *obj;
168 char oclass;
169 {
170     register struct obj *otmp;
171     struct obj *temp;
172
173     if (obj->oclass == oclass)
174         return obj;
175     /*
176      * Note:  we exclude SchroedingersBox because the corpse it contains
177      * isn't necessarily a corpse yet.  Resolving the status would lead
178      * to complications if it turns out to be a live cat.  We know that
179      * that Box can't contain anything else because putting something in
180      * would resolve the cat/corpse situation and convert to ordinary box.
181      */
182     if (Has_contents(obj) && !SchroedingersBox(obj)) {
183         for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
184             if (otmp->oclass == oclass)
185                 return otmp;
186             else if (Has_contents(otmp) && (temp = o_in(otmp, oclass)) != 0)
187                 return temp;
188     }
189     return (struct obj *) 0;
190 }
191
192 /* Recursively search obj for an object made of specified material.
193  * Return first found.
194  */
195 struct obj *
196 o_material(obj, material)
197 struct obj *obj;
198 unsigned material;
199 {
200     register struct obj *otmp;
201     struct obj *temp;
202
203     if (objects[obj->otyp].oc_material == material)
204         return obj;
205
206     if (Has_contents(obj)) {
207         for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
208             if (objects[otmp->otyp].oc_material == material)
209                 return otmp;
210             else if (Has_contents(otmp)
211                      && (temp = o_material(otmp, material)) != 0)
212                 return temp;
213     }
214     return (struct obj *) 0;
215 }
216
217 STATIC_OVL void
218 do_dknown_of(obj)
219 struct obj *obj;
220 {
221     struct obj *otmp;
222
223     obj->dknown = 1;
224     if (Has_contents(obj)) {
225         for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
226             do_dknown_of(otmp);
227     }
228 }
229
230 /* Check whether the location has an outdated object displayed on it. */
231 STATIC_OVL boolean
232 check_map_spot(x, y, oclass, material)
233 int x, y;
234 char oclass;
235 unsigned material;
236 {
237     int glyph;
238     register struct obj *otmp;
239     register struct monst *mtmp;
240
241     glyph = glyph_at(x, y);
242     if (glyph_is_object(glyph)) {
243         /* there's some object shown here */
244         if (oclass == ALL_CLASSES) {
245             return (boolean) !(level.objects[x][y] /* stale if nothing here */
246                                || ((mtmp = m_at(x, y)) != 0 && mtmp->minvent));
247         } else {
248             if (material
249                 && objects[glyph_to_obj(glyph)].oc_material == material) {
250                 /* object shown here is of interest because material matches */
251                 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
252                     if (o_material(otmp, GOLD))
253                         return FALSE;
254                 /* didn't find it; perhaps a monster is carrying it */
255                 if ((mtmp = m_at(x, y)) != 0) {
256                     for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
257                         if (o_material(otmp, GOLD))
258                             return FALSE;
259                 }
260                 /* detection indicates removal of this object from the map */
261                 return TRUE;
262             }
263             if (oclass && objects[glyph_to_obj(glyph)].oc_class == oclass) {
264                 /* obj shown here is of interest because its class matches */
265                 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
266                     if (o_in(otmp, oclass))
267                         return FALSE;
268                 /* didn't find it; perhaps a monster is carrying it */
269                 if ((mtmp = m_at(x, y)) != 0) {
270                     for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
271                         if (o_in(otmp, oclass))
272                             return FALSE;
273                 }
274                 /* detection indicates removal of this object from the map */
275                 return TRUE;
276             }
277         }
278     }
279     return FALSE;
280 }
281
282 /*
283  * When doing detection, remove stale data from the map display (corpses
284  * rotted away, objects carried away by monsters, etc) so that it won't
285  * reappear after the detection has completed.  Return true if noticeable
286  * change occurs.
287  */
288 STATIC_OVL boolean
289 clear_stale_map(oclass, material)
290 char oclass;
291 unsigned material;
292 {
293     register int zx, zy;
294     boolean change_made = FALSE;
295
296     for (zx = 1; zx < COLNO; zx++)
297         for (zy = 0; zy < ROWNO; zy++)
298             if (check_map_spot(zx, zy, oclass, material)) {
299                 unmap_object(zx, zy);
300                 change_made = TRUE;
301             }
302
303     return change_made;
304 }
305
306 /* look for gold, on the floor or in monsters' possession */
307 int
308 gold_detect(sobj)
309 register struct obj *sobj;
310 {
311     register struct obj *obj;
312     register struct monst *mtmp;
313     struct obj gold, *temp = 0;
314     boolean stale, ugold = FALSE, steedgold = FALSE;
315     int ter_typ = TER_DETECT | TER_OBJ;
316
317     known = stale = clear_stale_map(COIN_CLASS,
318                                     (unsigned) (sobj->blessed ? GOLD : 0));
319
320     /* look for gold carried by monsters (might be in a container) */
321     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
322         if (DEADMONSTER(mtmp))
323             continue; /* probably not needed in this case but... */
324         if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
325             if (mtmp == u.usteed) {
326                 steedgold = TRUE;
327             } else {
328                 known = TRUE;
329                 goto outgoldmap; /* skip further searching */
330             }
331         } else {
332             for (obj = mtmp->minvent; obj; obj = obj->nobj)
333                 if ((sobj->blessed && o_material(obj, GOLD))
334                     || o_in(obj, COIN_CLASS)) {
335                     if (mtmp == u.usteed) {
336                         steedgold = TRUE;
337                     } else {
338                         known = TRUE;
339                         goto outgoldmap; /* skip further searching */
340                     }
341                 }
342         }
343     }
344
345     /* look for gold objects */
346     for (obj = fobj; obj; obj = obj->nobj) {
347         if (sobj->blessed && o_material(obj, GOLD)) {
348             known = TRUE;
349             if (obj->ox != u.ux || obj->oy != u.uy)
350                 goto outgoldmap;
351         } else if (o_in(obj, COIN_CLASS)) {
352             known = TRUE;
353             if (obj->ox != u.ux || obj->oy != u.uy)
354                 goto outgoldmap;
355         }
356     }
357
358     if (!known) {
359         /* no gold found on floor or monster's inventory.
360            adjust message if you have gold in your inventory */
361         if (sobj) {
362             char buf[BUFSZ];
363
364             if (youmonst.data == &mons[PM_GOLD_GOLEM])
365 /*JP
366                 Sprintf(buf, "You feel like a million %s!", currency(2L));
367 */
368                 Strcpy(buf, "\82 \82È\82½\82Í\8bà\8e\9d\82¿\82É\82È\82Á\82½\82æ\82¤\82É\8a´\82\82½\81I");
369             else if (money_cnt(invent) || hidden_gold())
370                 Strcpy(buf,
371 /*JP
372                    "You feel worried about your future financial situation.");
373 */
374                    "\82 \82È\82½\82Í\8f«\97\88\82Ì\8co\8dÏ\8fó\8bµ\82ª\90S\94z\82É\82È\82Á\82½\81D");
375             else if (steedgold)
376 #if 0 /*JP:T*/
377                 Sprintf(buf, "You feel interested in %s financial situation.",
378                         s_suffix(x_monnam(u.usteed,
379                                           u.usteed->mtame ? ARTICLE_YOUR
380                                                           : ARTICLE_THE,
381                                           (char *) 0,
382                                           SUPPRESS_SADDLE, FALSE)));
383 #else
384                 Sprintf(buf, "\82 \82È\82½\82Í%s\82Ì\8co\8dÏ\8fó\8bµ\82É\8b»\96¡\82ª\8fo\82Ä\82«\82½\81D",
385                         x_monnam(u.usteed,
386                                           u.usteed->mtame ? ARTICLE_YOUR
387                                                           : ARTICLE_THE,
388                                           (char *) 0,
389                                           SUPPRESS_SADDLE, FALSE));
390 #endif
391             else
392 /*JP
393                 Strcpy(buf, "You feel materially poor.");
394 */
395                 Strcpy(buf, "\82 \82È\82½\82Í\82Ð\82à\82\82³\82ð\8a´\82\82½\81D");
396
397             strange_feeling(sobj, buf);
398         }
399         return 1;
400     }
401     /* only under me - no separate display required */
402     if (stale)
403         docrt();
404 /*JP
405     You("notice some gold between your %s.", makeplural(body_part(FOOT)));
406 */
407     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));
408     return 0;
409
410  outgoldmap:
411     cls();
412
413     (void) unconstrain_map();
414     /* Discover gold locations. */
415     for (obj = fobj; obj; obj = obj->nobj) {
416         if (sobj->blessed && (temp = o_material(obj, GOLD)) != 0) {
417             if (temp != obj) {
418                 temp->ox = obj->ox;
419                 temp->oy = obj->oy;
420             }
421             map_object(temp, 1);
422         } else if ((temp = o_in(obj, COIN_CLASS)) != 0) {
423             if (temp != obj) {
424                 temp->ox = obj->ox;
425                 temp->oy = obj->oy;
426             }
427             map_object(temp, 1);
428         }
429         if (temp && temp->ox == u.ux && temp->oy == u.uy)
430             ugold = TRUE;
431     }
432     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
433         if (DEADMONSTER(mtmp))
434             continue; /* probably overkill here */
435         temp = 0;
436         if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
437             gold = zeroobj; /* ensure oextra is cleared too */
438             gold.otyp = GOLD_PIECE;
439             gold.quan = (long) rnd(10); /* usually more than 1 */
440             gold.ox = mtmp->mx;
441             gold.oy = mtmp->my;
442             map_object(&gold, 1);
443             temp = &gold;
444         } else {
445             for (obj = mtmp->minvent; obj; obj = obj->nobj)
446                 if (sobj->blessed && (temp = o_material(obj, GOLD)) != 0) {
447                     temp->ox = mtmp->mx;
448                     temp->oy = mtmp->my;
449                     map_object(temp, 1);
450                     break;
451                 } else if ((temp = o_in(obj, COIN_CLASS)) != 0) {
452                     temp->ox = mtmp->mx;
453                     temp->oy = mtmp->my;
454                     map_object(temp, 1);
455                     break;
456                 }
457         }
458         if (temp && temp->ox == u.ux && temp->oy == u.uy)
459             ugold = TRUE;
460     }
461     if (!ugold) {
462         newsym(u.ux, u.uy);
463         ter_typ |= TER_MON; /* so autodescribe will recognize hero */
464     }
465 /*JP
466     You_feel("very greedy, and sense gold!");
467 */
468     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");
469     exercise(A_WIS, TRUE);
470
471 /*JP
472     browse_map(ter_typ, "gold");
473 */
474     browse_map(ter_typ, "\8bà");
475
476     reconstrain_map();
477     docrt();
478     if (Underwater)
479         under_water(2);
480     if (u.uburied)
481         under_ground(2);
482     return 0;
483 }
484
485 /* returns 1 if nothing was detected, 0 if something was detected */
486 int
487 food_detect(sobj)
488 register struct obj *sobj;
489 {
490     register struct obj *obj;
491     register struct monst *mtmp;
492     register int ct = 0, ctu = 0;
493     boolean confused = (Confusion || (sobj && sobj->cursed)), stale;
494     char oclass = confused ? POTION_CLASS : FOOD_CLASS;
495 /*JP
496     const char *what = confused ? something : "food";
497 */
498     const char *what = confused ? "\83n\83\89\83w\83\8a" : "\90H\82×\95¨";
499
500     stale = clear_stale_map(oclass, 0);
501     if (u.usteed) /* some situations leave steed with stale coordinates */
502         u.usteed->mx = u.ux, u.usteed->my = u.uy;
503
504     for (obj = fobj; obj; obj = obj->nobj)
505         if (o_in(obj, oclass)) {
506             if (obj->ox == u.ux && obj->oy == u.uy)
507                 ctu++;
508             else
509                 ct++;
510         }
511     for (mtmp = fmon; mtmp && (!ct || !ctu); mtmp = mtmp->nmon) {
512         /* no DEADMONSTER(mtmp) check needed -- dmons never have inventory */
513         for (obj = mtmp->minvent; obj; obj = obj->nobj)
514             if (o_in(obj, oclass)) {
515                 if (mtmp->mx == u.ux && mtmp->my == u.uy)
516                     ctu++; /* steed or an engulfer with inventory */
517                 else
518                     ct++;
519                 break;
520             }
521     }
522
523     if (!ct && !ctu) {
524         known = stale && !confused;
525         if (stale) {
526             docrt();
527 /*JP
528             You("sense a lack of %s nearby.", what);
529 */
530             You("%s\82ª\8c¸\82Á\82Ä\82¢\82é\82Ì\82É\8bC\82ª\82Â\82¢\82½\81D",what);
531             if (sobj && sobj->blessed) {
532                 if (!u.uedibility)
533 /*JP
534                     Your("%s starts to tingle.", body_part(NOSE));
535 */
536                     Your("%s\82ª\82Ò\82­\82Á\82Æ\93®\82¢\82½\81D", body_part(NOSE));
537                 u.uedibility = 1;
538             }
539         } else if (sobj) {
540             char buf[BUFSZ];
541
542 #if 0 /*JP:T*/
543             Sprintf(buf, "Your %s twitches%s.", body_part(NOSE),
544                     (sobj->blessed && !u.uedibility)
545                         ? " then starts to tingle"
546                         : "");
547 #else
548             Sprintf(buf, "\82 \82È\82½\82Ì%s\82ª\82Ð\82­\82Ð\82­\82Æ\93®\82¢%s\81D", body_part(NOSE),
549                     (sobj->blessed && !u.uedibility)
550                         ? "\82Ä\81C\82¤\82¸\82¤\82¸\82µ\82¾\82µ\82½"
551                         : "\82½");
552 #endif
553             if (sobj->blessed && !u.uedibility) {
554                 boolean savebeginner = flags.beginner;
555
556                 flags.beginner = FALSE; /* prevent non-delivery of message */
557                 strange_feeling(sobj, buf);
558                 flags.beginner = savebeginner;
559                 u.uedibility = 1;
560             } else
561                 strange_feeling(sobj, buf);
562         }
563         return !stale;
564     } else if (!ct) {
565         known = TRUE;
566 /*JP
567         You("%s %s nearby.", sobj ? "smell" : "sense", what);
568 */
569         You("\8bß\82­\82Å%s%s\81D", what, sobj ? "\82Ì\82É\82¨\82¢\82ð\82©\82¢\82¾" : "\82ð\8a´\92m\82µ\82½");
570         if (sobj && sobj->blessed) {
571             if (!u.uedibility)
572 /*JP
573                 pline("Your %s starts to tingle.", body_part(NOSE));
574 */
575                 pline("\82 \82È\82½\82Ì%s\82ª\82¤\82¸\82¤\82¸\82µ\82¾\82µ\82½\81D", body_part(NOSE));
576             u.uedibility = 1;
577         }
578     } else {
579         struct obj *temp;
580         int ter_typ = TER_DETECT | TER_OBJ;
581
582         known = TRUE;
583         cls();
584         (void) unconstrain_map();
585         for (obj = fobj; obj; obj = obj->nobj)
586             if ((temp = o_in(obj, oclass)) != 0) {
587                 if (temp != obj) {
588                     temp->ox = obj->ox;
589                     temp->oy = obj->oy;
590                 }
591                 map_object(temp, 1);
592             }
593         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
594             /* no DEADMONSTER() check needed -- dmons never have inventory */
595             for (obj = mtmp->minvent; obj; obj = obj->nobj)
596                 if ((temp = o_in(obj, oclass)) != 0) {
597                     temp->ox = mtmp->mx;
598                     temp->oy = mtmp->my;
599                     map_object(temp, 1);
600                     break; /* skip rest of this monster's inventory */
601                 }
602         if (!ctu) {
603             newsym(u.ux, u.uy);
604             ter_typ |= TER_MON; /* for autodescribe of self */
605         }
606         if (sobj) {
607             if (sobj->blessed) {
608 #if 0 /*JP:T*/
609                 Your("%s %s to tingle and you smell %s.", body_part(NOSE),
610                      u.uedibility ? "continues" : "starts", what);
611 #else
612                 Your("%s\82Í\82¤\82¸\82¤\82¸\82µ%s\81C%s\82Ì\93õ\82¢\82ð\9ak\82¬\82Æ\82Á\82½\81D", body_part(NOSE),
613                      u.uedibility ? "\91±\82¯" : "\8en\82ß", what);
614 #endif
615                 u.uedibility = 1;
616             } else
617 /*JP
618                 Your("%s tingles and you smell %s.", body_part(NOSE), what);
619 */
620                 Your("%s\82Í\82¤\82¸\82¤\82¸\82µ\81C%s\82Ì\93õ\82¢\82ð\9ak\82¬\82Æ\82Á\82½\81D", body_part(NOSE), what);
621         } else
622 /*JP
623             You("sense %s.", what);
624 */
625             You("%s\82ð\8a´\92m\82µ\82½\81D", what);
626         exercise(A_WIS, TRUE);
627
628 /*JP
629         browse_map(ter_typ, "food");
630 */
631         browse_map(ter_typ, "\90H\97¿");
632
633         reconstrain_map();
634         docrt();
635         if (Underwater)
636             under_water(2);
637         if (u.uburied)
638             under_ground(2);
639     }
640     return 0;
641 }
642
643 /*
644  * Used for scrolls, potions, spells, and crystal balls.  Returns:
645  *
646  *      1 - nothing was detected
647  *      0 - something was detected
648  */
649 int
650 object_detect(detector, class)
651 struct obj *detector; /* object doing the detecting */
652 int class;            /* an object class, 0 for all */
653 {
654     register int x, y;
655     char stuff[BUFSZ];
656     int is_cursed = (detector && detector->cursed);
657     int do_dknown = (detector && (detector->oclass == POTION_CLASS
658                                   || detector->oclass == SPBOOK_CLASS)
659                      && detector->blessed);
660     int ct = 0, ctu = 0;
661     register struct obj *obj, *otmp = (struct obj *) 0;
662     register struct monst *mtmp;
663     int sym, boulder = 0, ter_typ = TER_DETECT | TER_OBJ;
664
665     if (class < 0 || class >= MAXOCLASSES) {
666         impossible("object_detect:  illegal class %d", class);
667         class = 0;
668     }
669
670     /* Special boulder symbol check - does the class symbol happen
671      * to match showsyms[SYM_BOULDER + SYM_OFF_X] which is user-defined.
672      * If so, that means we aren't sure what they really wanted to
673      * detect. Rather than trump anything, show both possibilities.
674      * We can exclude checking the buried obj chain for boulders below.
675      */
676     sym = class ? def_oc_syms[class].sym : 0;
677     if (sym && showsyms[SYM_BOULDER + SYM_OFF_X] && sym == showsyms[SYM_BOULDER + SYM_OFF_X])
678         boulder = ROCK_CLASS;
679
680     if (Hallucination || (Confusion && class == SCROLL_CLASS))
681         Strcpy(stuff, something);
682     else
683 /*JP
684         Strcpy(stuff, class ? def_oc_syms[class].name : "objects");
685 */
686         Strcpy(stuff, class ? def_oc_syms[class].name : "\95¨\91Ì");
687     if (boulder && class != ROCK_CLASS)
688 /*JP
689         Strcat(stuff, " and/or large stones");
690 */
691         Strcat(stuff, "\82Æ\8b\90\8aâ");
692
693     if (do_dknown)
694         for (obj = invent; obj; obj = obj->nobj)
695             do_dknown_of(obj);
696
697     for (obj = fobj; obj; obj = obj->nobj) {
698         if ((!class && !boulder) || o_in(obj, class) || o_in(obj, boulder)) {
699             if (obj->ox == u.ux && obj->oy == u.uy)
700                 ctu++;
701             else
702                 ct++;
703         }
704         if (do_dknown)
705             do_dknown_of(obj);
706     }
707
708     for (obj = level.buriedobjlist; obj; obj = obj->nobj) {
709         if (!class || o_in(obj, class)) {
710             if (obj->ox == u.ux && obj->oy == u.uy)
711                 ctu++;
712             else
713                 ct++;
714         }
715         if (do_dknown)
716             do_dknown_of(obj);
717     }
718
719     if (u.usteed)
720         u.usteed->mx = u.ux, u.usteed->my = u.uy;
721
722     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
723         if (DEADMONSTER(mtmp))
724             continue;
725         for (obj = mtmp->minvent; obj; obj = obj->nobj) {
726             if ((!class && !boulder) || o_in(obj, class)
727                 || o_in(obj, boulder))
728                 ct++;
729             if (do_dknown)
730                 do_dknown_of(obj);
731         }
732         if ((is_cursed && M_AP_TYPE(mtmp) == M_AP_OBJECT
733              && (!class || class == objects[mtmp->mappearance].oc_class))
734             || (findgold(mtmp->minvent) && (!class || class == COIN_CLASS))) {
735             ct++;
736             break;
737         }
738     }
739
740     if (!clear_stale_map(!class ? ALL_CLASSES : class, 0) && !ct) {
741         if (!ctu) {
742             if (detector)
743 /*JP
744                 strange_feeling(detector, "You feel a lack of something.");
745 */
746                 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");
747             return 1;
748         }
749
750 /*JP
751         You("sense %s nearby.", stuff);
752 */
753         You("\8bß\82­\82Ì%s\82ð\8a´\92m\82µ\82½\81D", stuff);
754         return 0;
755     }
756
757     cls();
758
759     (void) unconstrain_map();
760     /*
761      *  Map all buried objects first.
762      */
763     for (obj = level.buriedobjlist; obj; obj = obj->nobj)
764         if (!class || (otmp = o_in(obj, class)) != 0) {
765             if (class) {
766                 if (otmp != obj) {
767                     otmp->ox = obj->ox;
768                     otmp->oy = obj->oy;
769                 }
770                 map_object(otmp, 1);
771             } else
772                 map_object(obj, 1);
773         }
774     /*
775      * If we are mapping all objects, map only the top object of a pile or
776      * the first object in a monster's inventory.  Otherwise, go looking
777      * for a matching object class and display the first one encountered
778      * at each location.
779      *
780      * Objects on the floor override buried objects.
781      */
782     for (x = 1; x < COLNO; x++)
783         for (y = 0; y < ROWNO; y++)
784             for (obj = level.objects[x][y]; obj; obj = obj->nexthere)
785                 if ((!class && !boulder) || (otmp = o_in(obj, class)) != 0
786                     || (otmp = o_in(obj, boulder)) != 0) {
787                     if (class || boulder) {
788                         if (otmp != obj) {
789                             otmp->ox = obj->ox;
790                             otmp->oy = obj->oy;
791                         }
792                         map_object(otmp, 1);
793                     } else
794                         map_object(obj, 1);
795                     break;
796                 }
797
798     /* Objects in the monster's inventory override floor objects. */
799     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
800         if (DEADMONSTER(mtmp))
801             continue;
802         for (obj = mtmp->minvent; obj; obj = obj->nobj)
803             if ((!class && !boulder) || (otmp = o_in(obj, class)) != 0
804                 || (otmp = o_in(obj, boulder)) != 0) {
805                 if (!class && !boulder)
806                     otmp = obj;
807                 otmp->ox = mtmp->mx; /* at monster location */
808                 otmp->oy = mtmp->my;
809                 map_object(otmp, 1);
810                 break;
811             }
812         /* Allow a mimic to override the detected objects it is carrying. */
813         if (is_cursed && M_AP_TYPE(mtmp) == M_AP_OBJECT
814             && (!class || class == objects[mtmp->mappearance].oc_class)) {
815             struct obj temp;
816
817             temp = zeroobj;
818             temp.otyp = mtmp->mappearance; /* needed for obj_to_glyph() */
819             temp.quan = 1L;
820             temp.ox = mtmp->mx;
821             temp.oy = mtmp->my;
822             temp.corpsenm = PM_TENGU; /* if mimicing a corpse */
823             map_object(&temp, 1);
824         } else if (findgold(mtmp->minvent)
825                    && (!class || class == COIN_CLASS)) {
826             struct obj gold;
827
828             gold = zeroobj; /* ensure oextra is cleared too */
829             gold.otyp = GOLD_PIECE;
830             gold.quan = (long) rnd(10); /* usually more than 1 */
831             gold.ox = mtmp->mx;
832             gold.oy = mtmp->my;
833             map_object(&gold, 1);
834         }
835     }
836     if (!glyph_is_object(glyph_at(u.ux, u.uy))) {
837         newsym(u.ux, u.uy);
838         ter_typ |= TER_MON;
839     }
840 /*JP
841     You("detect the %s of %s.", ct ? "presence" : "absence", stuff);
842 */
843     You("%s%s\81D", stuff, ct ? "\82ð\94­\8c©\82µ\82½" : "\82Í\89½\82à\82È\82¢\82±\82Æ\82ª\82í\82©\82Á\82½" );
844
845     if (!ct)
846         display_nhwindow(WIN_MAP, TRUE);
847     else
848 /*JP
849         browse_map(ter_typ, "object");
850 */
851         browse_map(ter_typ, "\95¨\91Ì");
852
853     reconstrain_map();
854     docrt(); /* this will correctly reset vision */
855     if (Underwater)
856         under_water(2);
857     if (u.uburied)
858         under_ground(2);
859     return 0;
860 }
861
862 /*
863  * Used by: crystal balls, potions, fountains
864  *
865  * Returns 1 if nothing was detected.
866  * Returns 0 if something was detected.
867  */
868 int
869 monster_detect(otmp, mclass)
870 register struct obj *otmp; /* detecting object (if any) */
871 int mclass;                /* monster class, 0 for all */
872 {
873     register struct monst *mtmp;
874     int mcnt = 0;
875
876     /* Note: This used to just check fmon for a non-zero value
877      * but in versions since 3.3.0 fmon can test TRUE due to the
878      * presence of dmons, so we have to find at least one
879      * with positive hit-points to know for sure.
880      */
881     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
882         if (!DEADMONSTER(mtmp)) {
883             mcnt++;
884             break;
885         }
886
887     if (!mcnt) {
888         if (otmp)
889             strange_feeling(otmp, Hallucination
890 /*JP
891                                       ? "You get the heebie jeebies."
892 */
893                                       ? "\82 \82È\82½\82Í\8bà\92¹\82Ì\89Ä\82Å\83L\83\93\83`\83\87\81[\82µ\82½\81D"
894 /*JP
895                                       : "You feel threatened.");
896 */
897                                       : "\82 \82È\82½\82Í\8b°\95|\82Å\82¼\82­\82Á\82Æ\82µ\82½\81D");
898         return 1;
899     } else {
900         boolean unconstrained, woken = FALSE;
901         unsigned swallowed = u.uswallow; /* before unconstrain_map() */
902
903         cls();
904         unconstrained = unconstrain_map();
905         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
906             if (DEADMONSTER(mtmp))
907                 continue;
908             if (!mclass || mtmp->data->mlet == mclass
909                 || (mtmp->data == &mons[PM_LONG_WORM]
910                     && mclass == S_WORM_TAIL))
911                 map_monst(mtmp, TRUE);
912
913             if (otmp && otmp->cursed
914                 && (mtmp->msleeping || !mtmp->mcanmove)) {
915                 mtmp->msleeping = mtmp->mfrozen = 0;
916                 mtmp->mcanmove = 1;
917                 woken = TRUE;
918             }
919         }
920         if (!swallowed)
921             display_self();
922 /*JP
923         You("sense the presence of monsters.");
924 */
925         You("\89ö\95¨\82Ì\91\8dÝ\82ð\9ak\82¬\82Â\82¯\82½\81D");
926         if (woken)
927 /*JP
928             pline("Monsters sense the presence of you.");
929 */
930             pline("\89ö\95¨\82Í\82 \82È\82½\82Ì\91\8dÝ\82ð\9ak\82¬\82Â\82¯\82½\81D");
931
932         if ((otmp && otmp->blessed) && !unconstrained) {
933             /* persistent detection--just show updated map */
934             display_nhwindow(WIN_MAP, TRUE);
935         } else {
936             /* one-shot detection--allow player to move cursor around and
937                get autodescribe feedback */
938             EDetect_monsters |= I_SPECIAL;
939 /*JP
940             browse_map(TER_DETECT | TER_MON, "monster of interest");
941 */
942             browse_map(TER_DETECT | TER_MON, "\8aÖ\90S\82Ì\82 \82é\89ö\95¨");
943             EDetect_monsters &= ~I_SPECIAL;
944         }
945
946         reconstrain_map();
947         docrt(); /* redraw the screen to remove unseen monsters from map */
948         if (Underwater)
949             under_water(2);
950         if (u.uburied)
951             under_ground(2);
952     }
953     return 0;
954 }
955
956 STATIC_OVL void
957 sense_trap(trap, x, y, src_cursed)
958 struct trap *trap;
959 xchar x, y;
960 int src_cursed;
961 {
962     if (Hallucination || src_cursed) {
963         struct obj obj; /* fake object */
964
965         obj = zeroobj;
966         if (trap) {
967             obj.ox = trap->tx;
968             obj.oy = trap->ty;
969         } else {
970             obj.ox = x;
971             obj.oy = y;
972         }
973         obj.otyp = !Hallucination ? GOLD_PIECE : random_object(rn2);
974         obj.quan = (long) ((obj.otyp == GOLD_PIECE) ? rnd(10)
975                            : objects[obj.otyp].oc_merge ? rnd(2) : 1);
976         obj.corpsenm = random_monster(rn2); /* if otyp == CORPSE */
977         map_object(&obj, 1);
978     } else if (trap) {
979         map_trap(trap, 1);
980         trap->tseen = 1;
981     } else { /* trapped door or trapped chest */
982         struct trap temp_trap; /* fake trap */
983
984         (void) memset((genericptr_t) &temp_trap, 0, sizeof temp_trap);
985         temp_trap.tx = x;
986         temp_trap.ty = y;
987         temp_trap.ttyp = BEAR_TRAP; /* some kind of trap */
988         map_trap(&temp_trap, 1);
989     }
990 }
991
992 #define OTRAP_NONE 0  /* nothing found */
993 #define OTRAP_HERE 1  /* found at hero's location */
994 #define OTRAP_THERE 2 /* found at any other location */
995
996 /* check a list of objects for chest traps; return 1 if found at <ux,uy>,
997    2 if found at some other spot, 3 if both, 0 otherwise; optionally
998    update the map to show where such traps were found */
999 STATIC_OVL int
1000 detect_obj_traps(objlist, show_them, how)
1001 struct obj *objlist;
1002 boolean show_them;
1003 int how; /* 1 for misleading map feedback */
1004 {
1005     struct obj *otmp;
1006     xchar x, y;
1007     int result = OTRAP_NONE;
1008
1009     /*
1010      * TODO?  Display locations of unarmed land mine and beartrap objects.
1011      * If so, should they be displayed as objects or as traps?
1012      */
1013
1014     for (otmp = objlist; otmp; otmp = otmp->nobj) {
1015         if (Is_box(otmp) && otmp->otrapped
1016             && get_obj_location(otmp, &x, &y, BURIED_TOO | CONTAINED_TOO)) {
1017             result |= (x == u.ux && y == u.uy) ? OTRAP_HERE : OTRAP_THERE;
1018             if (show_them)
1019                 sense_trap((struct trap *) 0, x, y, how);
1020         }
1021         if (Has_contents(otmp))
1022             result |= detect_obj_traps(otmp->cobj, show_them, how);
1023     }
1024     return result;
1025 }
1026
1027 /* the detections are pulled out so they can
1028  * also be used in the crystal ball routine
1029  * returns 1 if nothing was detected
1030  * returns 0 if something was detected
1031  */
1032 int
1033 trap_detect(sobj)
1034 struct obj *sobj; /* null if crystal ball, *scroll if gold detection scroll */
1035 {
1036     register struct trap *ttmp;
1037     struct monst *mon;
1038     int door, glyph, tr, ter_typ = TER_DETECT | TER_TRP;
1039     int cursed_src = sobj && sobj->cursed;
1040     boolean found = FALSE;
1041     coord cc;
1042
1043     if (u.usteed)
1044         u.usteed->mx = u.ux, u.usteed->my = u.uy;
1045
1046     /* floor/ceiling traps */
1047     for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
1048         if (ttmp->tx != u.ux || ttmp->ty != u.uy)
1049             goto outtrapmap;
1050         else
1051             found = TRUE;
1052     }
1053     /* chest traps (might be buried or carried) */
1054     if ((tr = detect_obj_traps(fobj, FALSE, 0)) != OTRAP_NONE) {
1055         if (tr & OTRAP_THERE)
1056             goto outtrapmap;
1057         else
1058             found = TRUE;
1059     }
1060     if ((tr = detect_obj_traps(level.buriedobjlist, FALSE, 0)) != OTRAP_NONE) {
1061         if (tr & OTRAP_THERE)
1062             goto outtrapmap;
1063         else
1064             found = TRUE;
1065     }
1066     for (mon = fmon; mon; mon = mon->nmon) {
1067         if (DEADMONSTER(mon))
1068             continue;
1069         if ((tr = detect_obj_traps(mon->minvent, FALSE, 0)) != OTRAP_NONE) {
1070             if (tr & OTRAP_THERE)
1071                 goto outtrapmap;
1072             else
1073                 found = TRUE;
1074         }
1075     }
1076     if (detect_obj_traps(invent, FALSE, 0) != OTRAP_NONE)
1077         found = TRUE;
1078     /* door traps */
1079     for (door = 0; door < doorindex; door++) {
1080         cc = doors[door];
1081         if (levl[cc.x][cc.y].doormask & D_TRAPPED) {
1082             if (cc.x != u.ux || cc.y != u.uy)
1083                 goto outtrapmap;
1084             else
1085                 found = TRUE;
1086         }
1087     }
1088     if (!found) {
1089         char buf[BUFSZ];
1090
1091 /*JP
1092         Sprintf(buf, "Your %s stop itching.", makeplural(body_part(TOE)));
1093 */
1094         Sprintf(buf, "\82 \82È\82½\82Ì%s\82Ì\82Þ\82¸\82Þ\82¸\82Í\82¨\82³\82Ü\82Á\82½\81D", makeplural(body_part(TOE)));
1095         strange_feeling(sobj, buf);
1096         return 1;
1097     }
1098     /* traps exist, but only under me - no separate display required */
1099 /*JP
1100     Your("%s itch.", makeplural(body_part(TOE)));
1101 */
1102     Your("%s\82Í\82Þ\82¸\82Þ\82¸\82µ\82½\81D", makeplural(body_part(TOE)));
1103     return 0;
1104
1105  outtrapmap:
1106     cls();
1107
1108     (void) unconstrain_map();
1109     /* show chest traps first, so that subsequent floor trap display
1110        will override if both types are present at the same location */
1111     (void) detect_obj_traps(fobj, TRUE, cursed_src);
1112     (void) detect_obj_traps(level.buriedobjlist, TRUE, cursed_src);
1113     for (mon = fmon; mon; mon = mon->nmon) {
1114         if (DEADMONSTER(mon))
1115             continue;
1116         (void) detect_obj_traps(mon->minvent, TRUE, cursed_src);
1117     }
1118     (void) detect_obj_traps(invent, TRUE, cursed_src);
1119
1120     for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
1121         sense_trap(ttmp, 0, 0, cursed_src);
1122
1123     for (door = 0; door < doorindex; door++) {
1124         cc = doors[door];
1125         if (levl[cc.x][cc.y].doormask & D_TRAPPED)
1126             sense_trap((struct trap *) 0, cc.x, cc.y, cursed_src);
1127     }
1128
1129     /* redisplay hero unless sense_trap() revealed something at <ux,uy> */
1130     glyph = glyph_at(u.ux, u.uy);
1131     if (!(glyph_is_trap(glyph) || glyph_is_object(glyph))) {
1132         newsym(u.ux, u.uy);
1133         ter_typ |= TER_MON; /* for autodescribe at <u.ux,u.uy> */
1134     }
1135 /*JP
1136     You_feel("%s.", cursed_src ? "very greedy" : "entrapped");
1137 */
1138     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È");
1139
1140 /*JP
1141     browse_map(ter_typ, "trap of interest");
1142 */
1143     browse_map(ter_typ, "\8aÖ\90S\82Ì\82 \82éã©");
1144
1145     reconstrain_map();
1146     docrt(); /* redraw the screen to remove unseen traps from the map */
1147     if (Underwater)
1148         under_water(2);
1149     if (u.uburied)
1150         under_ground(2);
1151     return 0;
1152 }
1153
1154 const char *
1155 level_distance(where)
1156 d_level *where;
1157 {
1158     register schar ll = depth(&u.uz) - depth(where);
1159     register boolean indun = (u.uz.dnum == where->dnum);
1160
1161     if (ll < 0) {
1162         if (ll < (-8 - rn2(3)))
1163             if (!indun)
1164 /*JP
1165                 return "far away";
1166 */
1167                 return "\82Í\82é\82©\94Þ\95û\82É";
1168             else
1169 /*JP
1170                 return "far below";
1171 */
1172                 return "\82Í\82é\82©\89º\95û\82É";
1173         else if (ll < -1)
1174             if (!indun)
1175 /*JP
1176                 return "away below you";
1177 */
1178                 return "\82¸\82Á\82Æ\89º\95û\82É";
1179             else
1180 /*JP
1181                 return "below you";
1182 */
1183                 return "\89º\95û\82É";
1184         else if (!indun)
1185 /*JP
1186             return "in the distance";
1187 */
1188             return "\89\93\82­\82É";
1189         else
1190 /*JP
1191             return "just below";
1192 */
1193             return "\90^\89º\82É";
1194     } else if (ll > 0) {
1195         if (ll > (8 + rn2(3)))
1196             if (!indun)
1197 /*JP
1198                 return "far away";
1199 */
1200                 return "\82Í\82é\82©\94Þ\95û\82É";
1201             else
1202 /*JP
1203                 return "far above";
1204 */
1205                 return "\82Í\82é\82©\8fã\95û\82É";
1206         else if (ll > 1)
1207             if (!indun)
1208 /*JP
1209                 return "away above you";
1210 */
1211                 return "\82¸\82Á\82Æ\8fã\95û\82É";
1212             else
1213 /*JP
1214                 return "above you";
1215 */
1216                 return "\8fã\95û\82É";
1217         else if (!indun)
1218 /*JP
1219             return "in the distance";
1220 */
1221             return "\89\93\82­\82É";
1222         else
1223 /*JP
1224             return "just above";
1225 */
1226             return "\90^\8fã\82É";
1227     } else if (!indun)
1228 /*JP
1229         return "in the distance";
1230 */
1231         return "\89\93\82­\82É";
1232     else
1233 /*JP
1234         return "near you";
1235 */
1236         return "\8bß\82­\82É";
1237 }
1238
1239 static const struct {
1240     const char *what;
1241     d_level *where;
1242 } level_detects[] = {
1243 /*JP
1244     { "Delphi", &oracle_level },
1245 */
1246     { "\83f\83\8b\83t\83@\83C", &oracle_level },
1247 /*JP
1248     { "Medusa's lair", &medusa_level },
1249 */
1250     { "\83\81\83f\83\85\81[\83T\82Ì\8fZ\82Ý\82©", &medusa_level },
1251 /*JP
1252     { "a castle", &stronghold_level },
1253 */
1254     { "\8fé", &stronghold_level },
1255 /*JP
1256     { "the Wizard of Yendor's tower", &wiz1_level },
1257 */
1258     { "\83C\83F\83\93\83_\81[\82Ì\96\82\96@\8eg\82¢\82Ì\93\83", &wiz1_level },
1259 };
1260
1261 void
1262 use_crystal_ball(optr)
1263 struct obj **optr;
1264 {
1265     char ch;
1266     int oops;
1267     struct obj *obj = *optr;
1268
1269     if (Blind) {
1270 /*JP
1271         pline("Too bad you can't see %s.", the(xname(obj)));
1272 */
1273         pline("\82È\82ñ\82Ä\82±\82Æ\82¾\81D%s\82ð\8c©\82é\82±\82Æ\82ª\82Å\82«\82È\82¢\81D", the(xname(obj)));
1274         return;
1275     }
1276     oops = (rnd(20) > ACURR(A_INT) || obj->cursed);
1277     if (oops && (obj->spe > 0)) {
1278         switch (rnd(obj->oartifact ? 4 : 5)) {
1279         case 1:
1280 /*JP
1281             pline("%s too much to comprehend!", Tobjnam(obj, "are"));
1282 */
1283             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));
1284             break;
1285         case 2:
1286 /*JP
1287             pline("%s you!", Tobjnam(obj, "confuse"));
1288 */
1289             pline("%s\82ð\94`\82¢\82Ä\82é\82Æ\82Ó\82ç\82Â\82¢\82Ä\82«\82½\81I", xname(obj));
1290             make_confused((HConfusion & TIMEOUT) + (long) rnd(100), FALSE);
1291             break;
1292         case 3:
1293             if (!resists_blnd(&youmonst)) {
1294 /*JP
1295                 pline("%s your vision!", Tobjnam(obj, "damage"));
1296 */
1297                 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));
1298                 make_blinded((Blinded & TIMEOUT) + (long) rnd(100), FALSE);
1299                 if (!Blind)
1300                     Your1(vision_clears);
1301             } else {
1302 /*JP
1303                 pline("%s your vision.", Tobjnam(obj, "assault"));
1304 */
1305                 pline("%s\82ª\82 \82È\82½\82Ì\8e\8b\8aE\82É\94\97\82Á\82Ä\82«\82½\81D", xname(obj));
1306 /*JP
1307                 You("are unaffected!");
1308 */
1309                 pline("\82µ\82©\82µ\81C\82 \82È\82½\82Í\89e\8b¿\82ð\8eó\82¯\82È\82©\82Á\82½\81I");
1310             }
1311             break;
1312         case 4:
1313 /*JP
1314             pline("%s your mind!", Tobjnam(obj, "zap"));
1315 */
1316             pline("%s\82ð\94`\82¢\82Ä\82¢\82é\82Æ\8cÜ\8a´\82ª\82¨\82©\82µ\82­\82È\82Á\82Ä\82«\82½\81I", xname(obj));
1317             (void) make_hallucinated(
1318                 (HHallucination & TIMEOUT) + (long) rnd(100), FALSE, 0L);
1319             break;
1320         case 5:
1321 /*JP
1322             pline("%s!", Tobjnam(obj, "explode"));
1323 */
1324             pline("%s\82Í\94\9a\94­\82µ\82½\81I", xname(obj));
1325             useup(obj);
1326             *optr = obj = 0; /* it's gone */
1327             /* physical damage cause by the shards and force */
1328 /*JP
1329             losehp(Maybe_Half_Phys(rnd(30)), "exploding crystal ball",
1330 */
1331             losehp(Maybe_Half_Phys(rnd(30)), "\90\85\8f»\8bÊ\82Ì\94\9a\94­\82Å",
1332                    KILLED_BY_AN);
1333             break;
1334         }
1335         if (obj)
1336             consume_obj_charge(obj, TRUE);
1337         return;
1338     }
1339
1340     if (Hallucination) {
1341         if (!obj->spe) {
1342 /*JP
1343             pline("All you see is funky %s haze.", hcolor((char *) 0));
1344 */
1345             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));
1346         } else {
1347             switch (rnd(6)) {
1348             case 1:
1349 /*JP
1350                 You("grok some groovy globs of incandescent lava.");
1351 */
1352                 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");
1353                 break;
1354             case 2:
1355 #if 0 /*JP:T*/
1356                 pline("Whoa!  Psychedelic colors, %s!",
1357                       poly_gender() == 1 ? "babe" : "dude");
1358 #else
1359                 pline("\83\8f\81[\83I\81I\83\89\83\8a\82Á\82Ä\82é\82©\82¢\81H%s\81I",
1360                       poly_gender() == 1 ? "\83x\83C\83r\81[" : "\83\86\81[");
1361 #endif
1362                 break;
1363             case 3:
1364 /*JP
1365                 pline_The("crystal pulses with sinister %s light!",
1366 */
1367                 pline("\90\85\8f»\82Í\95s\8bg\82È%s\83p\83\8b\83X\82ð\94­\82µ\82½\81I", 
1368                           hcolor((char *) 0));
1369                 break;
1370             case 4:
1371 /*JP
1372                 You_see("goldfish swimming above fluorescent rocks.");
1373 */
1374                 You("\8cu\8cõ\8aâ\82Ì\8fã\82ð\8bà\8b\9b\82ª\89j\82¢\82Å\82¢\82é\82Ì\82ð\8c©\82½\81D");
1375                 break;
1376             case 5:
1377 #if 0 /*JP:T*/
1378                 You_see(
1379                     "tiny snowflakes spinning around a miniature farmhouse.");
1380 #else
1381                     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");
1382 #endif
1383                 break;
1384             default:
1385 /*JP
1386                 pline("Oh wow... like a kaleidoscope!");
1387 */
1388                 pline("\83\8f\81[\83I\81D\96\9c\89Ø\8b¾\82Ì\82æ\82¤\82¾\81I");
1389                 break;
1390             }
1391             consume_obj_charge(obj, TRUE);
1392         }
1393         return;
1394     }
1395
1396     /* read a single character */
1397     if (flags.verbose)
1398 /*JP
1399         You("may look for an object or monster symbol.");
1400 */
1401         You("\95¨\91Ì\82â\89ö\95¨\82Ì\8bL\8d\86\82ð\92T\82¹\82é\81D");
1402 /*JP
1403     ch = yn_function("What do you look for?", (char *) 0, '\0');
1404 */
1405     ch = yn_function("\89½\82ð\92T\82µ\82Ü\82·\82©\81H", (char *)0, '\0');
1406     /* Don't filter out ' ' here; it has a use */
1407     if ((ch != def_monsyms[S_GHOST].sym) && index(quitchars, ch)) {
1408         if (flags.verbose)
1409             pline1(Never_mind);
1410         return;
1411     }
1412 /*JP
1413     You("peer into %s...", the(xname(obj)));
1414 */
1415     You("%s\82ð\94`\82«\82±\82ñ\82¾\81D\81D\81D", the(xname(obj)));
1416     nomul(-rnd(10));
1417 /*JP
1418     multi_reason = "gazing into a crystal ball";
1419 */
1420     multi_reason = "\90\85\8f»\8b\85\82ð\94`\82«\8d\9e\82ñ\82Å\82¢\82é\8e\9e\82É";
1421     nomovemsg = "";
1422     if (obj->spe <= 0) {
1423 /*JP
1424         pline_The("vision is unclear.");
1425 */
1426         pline("\89f\91\9c\82Í\95s\91N\96¾\82¾\82Á\82½\81D");
1427     } else {
1428         int class, i;
1429         int ret = 0;
1430
1431         makeknown(CRYSTAL_BALL);
1432         consume_obj_charge(obj, TRUE);
1433
1434         /* special case: accept ']' as synonym for mimic
1435          * we have to do this before the def_char_to_objclass check
1436          */
1437         if (ch == DEF_MIMIC_DEF)
1438             ch = DEF_MIMIC;
1439
1440         if ((class = def_char_to_objclass(ch)) != MAXOCLASSES)
1441             ret = object_detect((struct obj *) 0, class);
1442         else if ((class = def_char_to_monclass(ch)) != MAXMCLASSES)
1443             ret = monster_detect((struct obj *) 0, class);
1444         else if (showsyms[SYM_BOULDER + SYM_OFF_X]
1445                  && (ch == showsyms[SYM_BOULDER + SYM_OFF_X]))
1446             ret = object_detect((struct obj *) 0, ROCK_CLASS);
1447         else
1448             switch (ch) {
1449             case '^':
1450                 ret = trap_detect((struct obj *) 0);
1451                 break;
1452             default:
1453                 i = rn2(SIZE(level_detects));
1454 #if 0 /*JP:T*/
1455                 You_see("%s, %s.", level_detects[i].what,
1456                         level_distance(level_detects[i].where));
1457 #else
1458                 You_see("%s\82ð%s\8c©\82½\81D", level_detects[i].what,
1459                         level_distance(level_detects[i].where));
1460 #endif
1461                 ret = 0;
1462                 break;
1463             }
1464
1465         if (ret) {
1466             if (!rn2(100)) /* make them nervous */
1467 /*JP
1468                 You_see("the Wizard of Yendor gazing out at you.");
1469 */
1470                 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");
1471             else
1472 /*JP
1473                 pline_The("vision is unclear.");
1474 */
1475                 pline("\89f\91\9c\82Í\95s\91N\96¾\82É\82È\82Á\82½\81D");
1476         }
1477     }
1478     return;
1479 }
1480
1481 STATIC_OVL void
1482 show_map_spot(x, y)
1483 register int x, y;
1484 {
1485     struct rm *lev;
1486     struct trap *t;
1487     int oldglyph;
1488
1489     if (Confusion && rn2(7))
1490         return;
1491     lev = &levl[x][y];
1492
1493     lev->seenv = SVALL;
1494
1495     /* Secret corridors are found, but not secret doors. */
1496     if (lev->typ == SCORR) {
1497         lev->typ = CORR;
1498         unblock_point(x, y);
1499     }
1500
1501     /*
1502      * Force the real background, then if it's not furniture and there's
1503      * a known trap there, display the trap, else if there was an object
1504      * shown there, redisplay the object.  So during mapping, furniture
1505      * takes precedence over traps, which take precedence over objects,
1506      * opposite to how normal vision behaves.
1507      */
1508     oldglyph = glyph_at(x, y);
1509     if (level.flags.hero_memory) {
1510         magic_map_background(x, y, 0);
1511         newsym(x, y); /* show it, if not blocked */
1512     } else {
1513         magic_map_background(x, y, 1); /* display it */
1514     }
1515     if (!IS_FURNITURE(lev->typ)) {
1516         if ((t = t_at(x, y)) != 0 && t->tseen) {
1517             map_trap(t, 1);
1518         } else if (glyph_is_trap(oldglyph) || glyph_is_object(oldglyph)) {
1519             show_glyph(x, y, oldglyph);
1520             if (level.flags.hero_memory)
1521                 lev->glyph = oldglyph;
1522         }
1523     }
1524 }
1525
1526 void
1527 do_mapping()
1528 {
1529     register int zx, zy;
1530     boolean unconstrained;
1531
1532     unconstrained = unconstrain_map();
1533     for (zx = 1; zx < COLNO; zx++)
1534         for (zy = 0; zy < ROWNO; zy++)
1535             show_map_spot(zx, zy);
1536
1537     if (!level.flags.hero_memory || unconstrained) {
1538         flush_screen(1);                 /* flush temp screen */
1539         /* browse_map() instead of display_nhwindow(WIN_MAP, TRUE) */
1540 #if 0 /*JP:T*/
1541         browse_map(TER_DETECT | TER_MAP | TER_TRP | TER_OBJ,
1542                    "anything of interest");
1543 #else
1544         browse_map(TER_DETECT | TER_MAP | TER_TRP | TER_OBJ,
1545                    "\8aÖ\90S\82Ì\82 \82é\82à\82Ì");
1546 #endif
1547         docrt();
1548     }
1549     reconstrain_map();
1550     exercise(A_WIS, TRUE);
1551 }
1552
1553 /* clairvoyance */
1554 void
1555 do_vicinity_map(sobj)
1556 struct obj *sobj; /* scroll--actually fake spellbook--object */
1557 {
1558     register int zx, zy;
1559     struct monst *mtmp;
1560     struct obj *otmp;
1561     long save_EDetect_mons;
1562     char save_viz_uyux;
1563     boolean unconstrained, refresh = FALSE,
1564             mdetected = FALSE, odetected = FALSE,
1565             /* fake spellbook 'sobj' implies hero has cast the spell;
1566                when book is blessed, casting is skilled or expert level;
1567                if already clairvoyant, non-skilled spell acts like skilled */
1568             extended = (sobj && (sobj->blessed || Clairvoyant));
1569     int newglyph, oldglyph,
1570         lo_y = ((u.uy - 5 < 0) ? 0 : u.uy - 5),
1571         hi_y = ((u.uy + 6 >= ROWNO) ? ROWNO - 1 : u.uy + 6),
1572         lo_x = ((u.ux - 9 < 1) ? 1 : u.ux - 9), /* avoid column 0 */
1573         hi_x = ((u.ux + 10 >= COLNO) ? COLNO - 1 : u.ux + 10),
1574         ter_typ = TER_DETECT | TER_MAP | TER_TRP | TER_OBJ;
1575
1576     /*
1577      * 3.6.0 attempted to emphasize terrain over transient map
1578      * properties (monsters and objects) but that led to problems.
1579      * Notably, known trap would be displayed instead of a monster
1580      * on or in it and then the display remained that way after the
1581      * clairvoyant snapshot finished.  That could have been fixed by
1582      * issuing --More-- and then regular vision update, but we want
1583      * to avoid that when having a clairvoyant episode every N turns
1584      * (from donating to a temple priest or by carrying the Amulet).
1585      * Unlike when casting the spell, it is much too intrustive when
1586      * in the midst of walking around or combatting monsters.
1587      *
1588      * As of 3.6.2, show terrain, then object, then monster like regular
1589      * map updating, except in this case the map locations get marked
1590      * as seen from every direction rather than just from direction of
1591      * hero.  Skilled spell marks revealed objects as 'seen up close'
1592      * (but for piles, only the top item) and shows monsters as if
1593      * detected.  Non-skilled and timed clairvoyance reveals non-visible
1594      * monsters as 'remembered, unseen'.
1595      */
1596
1597     /* if hero is engulfed, show engulfer at <u.ux,u.uy> */
1598     save_viz_uyux = viz_array[u.uy][u.ux];
1599     if (u.uswallow)
1600         viz_array[u.uy][u.ux] |= IN_SIGHT; /* <x,y> are reversed to [y][x] */
1601     save_EDetect_mons = EDetect_monsters;
1602     /* for skilled spell, getpos() scanning of the map will display all
1603        monsters within range; otherwise, "unseen creature" will be shown */
1604     EDetect_monsters |= I_SPECIAL;
1605     unconstrained = unconstrain_map();
1606     for (zx = lo_x; zx <= hi_x; zx++)
1607         for (zy = lo_y; zy <= hi_y; zy++) {
1608             oldglyph = glyph_at(zx, zy);
1609             /* this will remove 'remembered, unseen mon' (and objects) */
1610             show_map_spot(zx, zy);
1611             /* if there are any objects here, see the top one */
1612             if (OBJ_AT(zx, zy)) {
1613                 /* not vobj_at(); this is not vision-based access;
1614                    unlike object detection, we don't notice buried items */
1615                 otmp = level.objects[zx][zy];
1616                 if (extended)
1617                     otmp->dknown = 1;
1618                 map_object(otmp, TRUE);
1619                 newglyph = glyph_at(zx, zy);
1620                 /* if otmp is underwater, we'll need to redisplay the water */
1621                 if (newglyph != oldglyph && covers_objects(zx, zy))
1622                     odetected = TRUE;
1623             }
1624             /* if there is a monster here, see or detect it,
1625                possibly as "remembered, unseen monster" */
1626             if ((mtmp = m_at(zx, zy)) != 0
1627                 && mtmp->mx == zx && mtmp->my == zy) { /* skip worm tails */
1628                 /* if we're going to offer browse_map()/getpos() scanning of
1629                    the map and we're not doing extended/blessed clairvoyance
1630                    (hence must be swallowed or underwater), show "unseen
1631                    creature" unless map already displayed a monster here */
1632                 if ((unconstrained || !level.flags.hero_memory)
1633                     && !extended && (zx != u.ux || zy != u.uy)
1634                     && !glyph_is_monster(oldglyph))
1635                     map_invisible(zx, zy);
1636                 else
1637                     map_monst(mtmp, FALSE);
1638                 newglyph = glyph_at(zx, zy);
1639                 if (extended && newglyph != oldglyph
1640                     && !glyph_is_invisible(newglyph))
1641                     mdetected = TRUE;
1642             }
1643         }
1644
1645     if (!level.flags.hero_memory || unconstrained || mdetected || odetected) {
1646         flush_screen(1);                 /* flush temp screen */
1647         /* the getpos() prompt from browse_map() is only shown when
1648            flags.verbose is set, but make this unconditional so that
1649            not-verbose users become aware of the prompting situation */
1650 /*JP
1651         You("sense your surroundings.");
1652 */
1653         You("\82Ü\82í\82è\82Ì\82à\82Ì\82ð\8a´\92m\82µ\82½\81D");
1654         if (extended || glyph_is_monster(glyph_at(u.ux, u.uy)))
1655             ter_typ |= TER_MON;
1656 /*JP
1657         browse_map(ter_typ, "anything of interest");
1658 */
1659         browse_map(ter_typ, "\8aÖ\90S\82Ì\82 \82é\82à\82Ì");
1660         refresh = TRUE;
1661     }
1662     reconstrain_map();
1663     EDetect_monsters = save_EDetect_mons;
1664     viz_array[u.uy][u.ux] = save_viz_uyux;
1665
1666     /* replace monsters with remembered,unseen monster, then run
1667        see_monsters() to update visible ones and warned-of ones */
1668     for (zx = lo_x; zx <= hi_x; zx++)
1669         for (zy = lo_y; zy <= hi_y; zy++) {
1670             if (zx == u.ux && zy == u.uy)
1671                 continue;
1672             newglyph = glyph_at(zx, zy);
1673             if (glyph_is_monster(newglyph)
1674                 && glyph_to_mon(newglyph) != PM_LONG_WORM_TAIL) {
1675                 /* map_invisible() was unconditional here but that made
1676                    remembered objects be forgotten for the case where a
1677                    monster is immediately redrawn by see_monsters() */
1678                 if ((mtmp = m_at(zx, zy)) == 0 || !canspotmon(mtmp))
1679                     map_invisible(zx, zy);
1680             }
1681         }
1682     see_monsters();
1683
1684     if (refresh)
1685         docrt();
1686 }
1687
1688 /* convert a secret door into a normal door */
1689 void
1690 cvt_sdoor_to_door(lev)
1691 struct rm *lev;
1692 {
1693     int newmask = lev->doormask & ~WM_MASK;
1694
1695     if (Is_rogue_level(&u.uz))
1696         /* rogue didn't have doors, only doorways */
1697         newmask = D_NODOOR;
1698     else
1699         /* newly exposed door is closed */
1700         if (!(newmask & D_LOCKED))
1701         newmask |= D_CLOSED;
1702
1703     lev->typ = DOOR;
1704     lev->doormask = newmask;
1705 }
1706
1707 /* find something at one location; it should find all somethings there
1708    since it is used for magical detection rather than physical searching */
1709 STATIC_PTR void
1710 findone(zx, zy, num)
1711 int zx, zy;
1712 genericptr_t num;
1713 {
1714     register struct trap *ttmp;
1715     register struct monst *mtmp;
1716
1717     /*
1718      * This used to use if/else-if/else-if/else/end-if but that only
1719      * found the first hidden thing at the location.  Two hidden things
1720      * at the same spot is uncommon, but it's possible for an undetected
1721      * monster to be hiding at the location of an unseen trap.
1722      */
1723
1724     if (levl[zx][zy].typ == SDOOR) {
1725         cvt_sdoor_to_door(&levl[zx][zy]); /* .typ = DOOR */
1726         magic_map_background(zx, zy, 0);
1727         newsym(zx, zy);
1728         (*(int *) num)++;
1729     } else if (levl[zx][zy].typ == SCORR) {
1730         levl[zx][zy].typ = CORR;
1731         unblock_point(zx, zy);
1732         magic_map_background(zx, zy, 0);
1733         newsym(zx, zy);
1734         (*(int *) num)++;
1735     }
1736
1737     if ((ttmp = t_at(zx, zy)) != 0 && !ttmp->tseen
1738         /* [shouldn't successful 'find' reveal and activate statue traps?] */
1739         && ttmp->ttyp != STATUE_TRAP) {
1740         ttmp->tseen = 1;
1741         newsym(zx, zy);
1742         (*(int *) num)++;
1743     }
1744
1745     if ((mtmp = m_at(zx, zy)) != 0
1746         /* brings hidden monster out of hiding even if already sensed */
1747         && (!canspotmon(mtmp) || mtmp->mundetected || M_AP_TYPE(mtmp))) {
1748         if (M_AP_TYPE(mtmp)) {
1749             seemimic(mtmp);
1750             (*(int *) num)++;
1751         } else if (mtmp->mundetected && (is_hider(mtmp->data)
1752                                          || hides_under(mtmp->data)
1753                                          || mtmp->data->mlet == S_EEL)) {
1754             mtmp->mundetected = 0;
1755             newsym(zx, zy);
1756             (*(int *) num)++;
1757         }
1758         if (!canspotmon(mtmp) && !glyph_is_invisible(levl[zx][zy].glyph))
1759             map_invisible(zx, zy);
1760     } else if (unmap_invisible(zx, zy)) {
1761         (*(int *) num)++;
1762     }
1763 }
1764
1765 STATIC_PTR void
1766 openone(zx, zy, num)
1767 int zx, zy;
1768 genericptr_t num;
1769 {
1770     register struct trap *ttmp;
1771     register struct obj *otmp;
1772     int *num_p = (int *) num;
1773
1774     if (OBJ_AT(zx, zy)) {
1775         for (otmp = level.objects[zx][zy]; otmp; otmp = otmp->nexthere) {
1776             if (Is_box(otmp) && otmp->olocked) {
1777                 otmp->olocked = 0;
1778                 (*num_p)++;
1779             }
1780         }
1781         /* let it fall to the next cases. could be on trap. */
1782     }
1783     if (levl[zx][zy].typ == SDOOR
1784         || (levl[zx][zy].typ == DOOR
1785             && (levl[zx][zy].doormask & (D_CLOSED | D_LOCKED)))) {
1786         if (levl[zx][zy].typ == SDOOR)
1787             cvt_sdoor_to_door(&levl[zx][zy]); /* .typ = DOOR */
1788         if (levl[zx][zy].doormask & D_TRAPPED) {
1789             if (distu(zx, zy) < 3)
1790 /*JP
1791                 b_trapped("door", 0);
1792 */
1793                 b_trapped("\94à", 0);
1794             else
1795 #if 0 /*JP:T*/
1796                 Norep("You %s an explosion!",
1797                       cansee(zx, zy) ? "see" : (!Deaf ? "hear"
1798                                                       : "feel the shock of"));
1799 #else
1800                 Norep("\82 \82È\82½\82Í\94\9a\94­%s\81I",
1801                       cansee(zx, zy) ? "\82ð\8c©\82½" : (!Deaf ? "\89¹\82ð\95·\82¢\82½"
1802                                                          : "\82Ì\8fÕ\8c\82\82ð\8a´\82\82½"));
1803 #endif
1804             wake_nearto(zx, zy, 11 * 11);
1805             levl[zx][zy].doormask = D_NODOOR;
1806         } else
1807             levl[zx][zy].doormask = D_ISOPEN;
1808         unblock_point(zx, zy);
1809         newsym(zx, zy);
1810         (*num_p)++;
1811     } else if (levl[zx][zy].typ == SCORR) {
1812         levl[zx][zy].typ = CORR;
1813         unblock_point(zx, zy);
1814         newsym(zx, zy);
1815         (*num_p)++;
1816     } else if ((ttmp = t_at(zx, zy)) != 0) {
1817         struct monst *mon;
1818         boolean dummy; /* unneeded "you notice it arg" */
1819
1820         if (!ttmp->tseen && ttmp->ttyp != STATUE_TRAP) {
1821             ttmp->tseen = 1;
1822             newsym(zx, zy);
1823             (*num_p)++;
1824         }
1825         mon = (zx == u.ux && zy == u.uy) ? &youmonst : m_at(zx, zy);
1826         if (openholdingtrap(mon, &dummy)
1827             || openfallingtrap(mon, TRUE, &dummy))
1828             (*num_p)++;
1829     } else if (find_drawbridge(&zx, &zy)) {
1830         /* make sure it isn't an open drawbridge */
1831         open_drawbridge(zx, zy);
1832         (*num_p)++;
1833     }
1834 }
1835
1836 /* returns number of things found */
1837 int
1838 findit()
1839 {
1840     int num = 0;
1841
1842     if (u.uswallow)
1843         return 0;
1844     do_clear_area(u.ux, u.uy, BOLT_LIM, findone, (genericptr_t) &num);
1845     return num;
1846 }
1847
1848 /* returns number of things found and opened */
1849 int
1850 openit()
1851 {
1852     int num = 0;
1853
1854     if (u.uswallow) {
1855         if (is_animal(u.ustuck->data)) {
1856             if (Blind)
1857 /*JP
1858                 pline("Its mouth opens!");
1859 */
1860                 pline("\89½\8eÒ\82©\82Ì\8cû\82ª\8aJ\82¢\82½\81I");
1861             else
1862 /*JP
1863                 pline("%s opens its mouth!", Monnam(u.ustuck));
1864 */
1865                 pline("%s\82Í\8cû\82ð\8aJ\82¢\82½\81I", Monnam(u.ustuck));
1866         }
1867         expels(u.ustuck, u.ustuck->data, TRUE);
1868         return -1;
1869     }
1870
1871     do_clear_area(u.ux, u.uy, BOLT_LIM, openone, (genericptr_t) &num);
1872     return num;
1873 }
1874
1875 /* callback hack for overriding vision in do_clear_area() */
1876 boolean
1877 detecting(func)
1878 void FDECL((*func), (int, int, genericptr_t));
1879 {
1880     return (func == findone || func == openone);
1881 }
1882
1883 void
1884 find_trap(trap)
1885 struct trap *trap;
1886 {
1887     int tt = what_trap(trap->ttyp, rn2);
1888     boolean cleared = FALSE;
1889
1890     trap->tseen = 1;
1891     exercise(A_WIS, TRUE);
1892     feel_newsym(trap->tx, trap->ty);
1893
1894     /* The "Hallucination ||" is to preserve 3.6.1 behaviour, but this
1895        behaviour might need a rework in the hallucination case
1896        (e.g. to not prompt if any trap glyph appears on the square). */
1897     if (Hallucination ||
1898         levl[trap->tx][trap->ty].glyph !=
1899         trap_to_glyph(trap, rn2_on_display_rng)) {
1900         /* There's too much clutter to see your find otherwise */
1901         cls();
1902         map_trap(trap, 1);
1903         display_self();
1904         cleared = TRUE;
1905     }
1906
1907 /*JP
1908     You("find %s.", an(defsyms[trap_to_defsym(tt)].explanation));
1909 */
1910     You("%s\82ð\8c©\82Â\82¯\82½\81D", defsyms[trap_to_defsym(tt)].explanation);
1911
1912     if (cleared) {
1913         display_nhwindow(WIN_MAP, TRUE); /* wait */
1914         docrt();
1915     }
1916 }
1917
1918 STATIC_OVL int
1919 mfind0(mtmp, via_warning)
1920 struct monst *mtmp;
1921 boolean via_warning;
1922 {
1923     int x = mtmp->mx, y = mtmp->my;
1924     boolean found_something = FALSE;
1925
1926     if (via_warning && !warning_of(mtmp))
1927         return -1;
1928
1929     if (M_AP_TYPE(mtmp)) {
1930         seemimic(mtmp);
1931         found_something = TRUE;
1932     } else {
1933         /* this used to only be executed if a !canspotmon() test passed
1934            but that failed to bring sensed monsters out of hiding */
1935         found_something = !canspotmon(mtmp);
1936         if (mtmp->mundetected && (is_hider(mtmp->data)
1937                                   || hides_under(mtmp->data)
1938                                   || mtmp->data->mlet == S_EEL)) {
1939             if (via_warning) {
1940 #if 0 /*JP:T*/
1941                 Your("warning senses cause you to take a second %s.",
1942                      Blind ? "to check nearby" : "look close by");
1943 #else
1944                 Your("\8cx\89ú\90S\82ª%s\82µ\82Î\82ç\82­\82©\82©\82Á\82½\81D",
1945                      Blind ? "\82Ü\82í\82è\82ð\92²\82×\82é\82Ì\82É" : "\8bß\82­\82ð\8c©\82é\82Ì\82É");
1946 #endif
1947                 display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
1948             }
1949             mtmp->mundetected = 0;
1950             found_something = TRUE;
1951         }
1952         newsym(x, y);
1953     }
1954
1955     if (found_something) {
1956         if (!canspotmon(mtmp) && glyph_is_invisible(levl[x][y].glyph))
1957             return -1; /* Found invisible monster in square which already has
1958                         * 'I' in it.  Logically, this should still take time
1959                         * and lead to `return 1', but if we did that the hero
1960                         * would keep finding the same monster every turn. */
1961         exercise(A_WIS, TRUE);
1962         if (!canspotmon(mtmp)) {
1963             map_invisible(x, y);
1964 /*JP
1965             You_feel("an unseen monster!");
1966 */
1967             You("\8c©\82¦\82È\82¢\89ö\95¨\82Ì\8bC\94z\82ð\8a´\82\82½\81I");
1968         } else if (!sensemon(mtmp)) {
1969 #if 0 /*JP:T*/
1970             You("find %s.", mtmp->mtame ? y_monnam(mtmp) : a_monnam(mtmp));
1971 #else
1972             You("%s\82ð\8c©\82Â\82¯\82½\81D", mtmp->mtame ? y_monnam(mtmp) : a_monnam(mtmp));
1973 #endif
1974         }
1975         return 1;
1976     }
1977     return 0;
1978 }
1979
1980 int
1981 dosearch0(aflag)
1982 register int aflag; /* intrinsic autosearch vs explicit searching */
1983 {
1984 #ifdef GCC_BUG
1985     /* Some old versions of gcc seriously muck up nested loops.  If you get
1986      * strange crashes while searching in a version compiled with gcc, try
1987      * putting #define GCC_BUG in *conf.h (or adding -DGCC_BUG to CFLAGS in
1988      * the makefile).
1989      */
1990     volatile xchar x, y;
1991 #else
1992     register xchar x, y;
1993 #endif
1994     register struct trap *trap;
1995     register struct monst *mtmp;
1996
1997     if (u.uswallow) {
1998         if (!aflag)
1999 /*JP
2000             pline("What are you looking for?  The exit?");
2001 */
2002             pline("\89½\82ð\92T\82·\82ñ\82¾\82¢\81H\94ñ\8fí\8cû\81H");
2003     } else {
2004         int fund = (uwep && uwep->oartifact
2005                     && spec_ability(uwep, SPFX_SEARCH)) ? uwep->spe : 0;
2006
2007         if (ublindf && ublindf->otyp == LENSES && !Blind)
2008             fund += 2; /* JDS: lenses help searching */
2009         if (fund > 5)
2010             fund = 5;
2011         for (x = u.ux - 1; x < u.ux + 2; x++)
2012             for (y = u.uy - 1; y < u.uy + 2; y++) {
2013                 if (!isok(x, y))
2014                     continue;
2015                 if (x == u.ux && y == u.uy)
2016                     continue;
2017
2018                 if (Blind && !aflag)
2019                     feel_location(x, y);
2020                 if (levl[x][y].typ == SDOOR) {
2021                     if (rnl(7 - fund))
2022                         continue;
2023                     cvt_sdoor_to_door(&levl[x][y]); /* .typ = DOOR */
2024                     exercise(A_WIS, TRUE);
2025                     nomul(0);
2026                     feel_location(x, y); /* make sure it shows up */
2027 /*JP
2028                     You("find a hidden door.");
2029 */
2030                     You("\89B\82³\82ê\82½\94à\82ð\8c©\82Â\82¯\82½\81D");
2031                 } else if (levl[x][y].typ == SCORR) {
2032                     if (rnl(7 - fund))
2033                         continue;
2034                     levl[x][y].typ = CORR;
2035                     unblock_point(x, y); /* vision */
2036                     exercise(A_WIS, TRUE);
2037                     nomul(0);
2038                     feel_newsym(x, y); /* make sure it shows up */
2039 /*JP
2040                     You("find a hidden passage.");
2041 */
2042                     You("\89B\82³\82ê\82½\92Ê\98H\82ð\8c©\82Â\82¯\82½\81D");
2043                 } else {
2044                     /* Be careful not to find anything in an SCORR or SDOOR */
2045                     if ((mtmp = m_at(x, y)) != 0 && !aflag) {
2046                         int mfres = mfind0(mtmp, 0);
2047
2048                         if (mfres == -1)
2049                             continue;
2050                         else if (mfres > 0)
2051                             return mfres;
2052                     }
2053
2054                     /* see if an invisible monster has moved--if Blind,
2055                      * feel_location() already did it
2056                      */
2057                     if (!aflag && !mtmp && !Blind)
2058                         (void) unmap_invisible(x, y);
2059
2060                     if ((trap = t_at(x, y)) && !trap->tseen && !rnl(8)) {
2061                         nomul(0);
2062                         if (trap->ttyp == STATUE_TRAP) {
2063                             if (activate_statue_trap(trap, x, y, FALSE))
2064                                 exercise(A_WIS, TRUE);
2065                             return 1;
2066                         } else {
2067                             find_trap(trap);
2068                         }
2069                     }
2070                 }
2071             }
2072     }
2073     return 1;
2074 }
2075
2076 /* the 's' command -- explicit searching */
2077 int
2078 dosearch()
2079 {
2080     return dosearch0(0);
2081 }
2082
2083 void
2084 warnreveal()
2085 {
2086     int x, y;
2087     struct monst *mtmp;
2088
2089     for (x = u.ux - 1; x <= u.ux + 1; x++)
2090         for (y = u.uy - 1; y <= u.uy + 1; y++) {
2091             if (!isok(x, y) || (x == u.ux && y == u.uy))
2092                 continue;
2093             if ((mtmp = m_at(x, y)) != 0
2094                 && warning_of(mtmp) && mtmp->mundetected)
2095                 (void) mfind0(mtmp, 1); /* via_warning */
2096         }
2097 }
2098
2099 /* Pre-map the sokoban levels */
2100 void
2101 sokoban_detect()
2102 {
2103     register int x, y;
2104     register struct trap *ttmp;
2105     register struct obj *obj;
2106
2107     /* Map the background and boulders */
2108     for (x = 1; x < COLNO; x++)
2109         for (y = 0; y < ROWNO; y++) {
2110             levl[x][y].seenv = SVALL;
2111             levl[x][y].waslit = TRUE;
2112             map_background(x, y, 1);
2113             if ((obj = sobj_at(BOULDER, x, y)) != 0)
2114                 map_object(obj, 1);
2115         }
2116
2117     /* Map the traps */
2118     for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
2119         ttmp->tseen = 1;
2120         map_trap(ttmp, 1);
2121         /* set sokoban_rules when there is at least one pit or hole */
2122         if (ttmp->ttyp == PIT || ttmp->ttyp == HOLE)
2123             Sokoban = 1;
2124     }
2125 }
2126
2127 STATIC_DCL int
2128 reveal_terrain_getglyph(x, y, full, swallowed, default_glyph, which_subset)
2129 int x, y, full;
2130 unsigned swallowed;
2131 int default_glyph, which_subset;
2132 {
2133     int glyph, levl_glyph;
2134     uchar seenv;
2135     boolean keep_traps = (which_subset & TER_TRP) !=0,
2136             keep_objs = (which_subset & TER_OBJ) != 0,
2137             keep_mons = (which_subset & TER_MON) != 0;
2138     struct monst *mtmp;
2139     struct trap *t;
2140
2141     /* for 'full', show the actual terrain for the entire level,
2142        otherwise what the hero remembers for seen locations with
2143        monsters, objects, and/or traps removed as caller dictates */
2144     seenv = (full || level.flags.hero_memory)
2145               ? levl[x][y].seenv : cansee(x, y) ? SVALL : 0;
2146     if (full) {
2147         levl[x][y].seenv = SVALL;
2148         glyph = back_to_glyph(x, y);
2149         levl[x][y].seenv = seenv;
2150     } else {
2151         levl_glyph = level.flags.hero_memory
2152               ? levl[x][y].glyph
2153               : seenv ? back_to_glyph(x, y): default_glyph;
2154         /* glyph_at() returns the displayed glyph, which might
2155            be a monster.  levl[][].glyph contains the remembered
2156            glyph, which will never be a monster (unless it is
2157            the invisible monster glyph, which is handled like
2158            an object, replacing any object or trap at its spot) */
2159         glyph = !swallowed ? glyph_at(x, y) : levl_glyph;
2160         if (keep_mons && x == u.ux && y == u.uy && swallowed)
2161             glyph = mon_to_glyph(u.ustuck, rn2_on_display_rng);
2162         else if (((glyph_is_monster(glyph)
2163                    || glyph_is_warning(glyph)) && !keep_mons)
2164                  || glyph_is_swallow(glyph))
2165             glyph = levl_glyph;
2166         if (((glyph_is_object(glyph) && !keep_objs)
2167              || glyph_is_invisible(glyph))
2168             && keep_traps && !covers_traps(x, y)) {
2169             if ((t = t_at(x, y)) != 0 && t->tseen)
2170                 glyph = trap_to_glyph(t, rn2_on_display_rng);
2171         }
2172         if ((glyph_is_object(glyph) && !keep_objs)
2173             || (glyph_is_trap(glyph) && !keep_traps)
2174             || glyph_is_invisible(glyph)) {
2175             if (!seenv) {
2176                 glyph = default_glyph;
2177             } else if (lastseentyp[x][y] == levl[x][y].typ) {
2178                 glyph = back_to_glyph(x, y);
2179             } else {
2180                 /* look for a mimic here posing as furniture;
2181                    if we don't find one, we'll have to fake it */
2182                 if ((mtmp = m_at(x, y)) != 0
2183                     && M_AP_TYPE(mtmp) == M_AP_FURNITURE) {
2184                     glyph = cmap_to_glyph(mtmp->mappearance);
2185                 } else {
2186                     /* we have a topology type but we want a screen
2187                        symbol in order to derive a glyph; some screen
2188                        symbols need the flags field of levl[][] in
2189                        addition to the type (to disambiguate STAIRS to
2190                        S_upstair or S_dnstair, for example; current
2191                        flags might not be intended for remembered type,
2192                        but we've got no other choice) */
2193                     schar save_typ = levl[x][y].typ;
2194
2195                     levl[x][y].typ = lastseentyp[x][y];
2196                     glyph = back_to_glyph(x, y);
2197                     levl[x][y].typ = save_typ;
2198                 }
2199             }
2200         }
2201     }
2202     if (glyph == cmap_to_glyph(S_darkroom))
2203         glyph = cmap_to_glyph(S_room); /* FIXME: dirty hack */
2204     return glyph;
2205 }
2206
2207 #ifdef DUMPLOG
2208 void
2209 dump_map()
2210 {
2211     int x, y, glyph, skippedrows, lastnonblank;
2212     int subset = TER_MAP | TER_TRP | TER_OBJ | TER_MON;
2213     int default_glyph = cmap_to_glyph(level.flags.arboreal ? S_tree : S_stone);
2214     char buf[BUFSZ];
2215     boolean blankrow, toprow;
2216
2217     /*
2218      * Squeeze out excess vertial space when dumping the map.
2219      * If there are any blank map rows at the top, suppress them
2220      * (our caller has already printed a separator).  If there is
2221      * more than one blank map row at the bottom, keep just one.
2222      * Any blank rows within the middle of the map are kept.
2223      * Note: putstr() with winid==0 is for dumplog.
2224      */
2225     skippedrows = 0;
2226     toprow = TRUE;
2227     for (y = 0; y < ROWNO; y++) {
2228         blankrow = TRUE; /* assume blank until we discover otherwise */
2229         lastnonblank = -1; /* buf[] index rather than map's x */
2230         for (x = 1; x < COLNO; x++) {
2231             int ch, color;
2232             unsigned special;
2233
2234             glyph = reveal_terrain_getglyph(x, y, FALSE, u.uswallow,
2235                                             default_glyph, subset);
2236             (void) mapglyph(glyph, &ch, &color, &special, x, y, 0);
2237             buf[x - 1] = ch;
2238             if (ch != ' ') {
2239                 blankrow = FALSE;
2240                 lastnonblank = x - 1;
2241             }
2242         }
2243         if (!blankrow) {
2244             buf[lastnonblank + 1] = '\0';
2245             if (toprow) {
2246                 skippedrows = 0;
2247                 toprow = FALSE;
2248             }
2249             for (x = 0; x < skippedrows; x++)
2250                 putstr(0, 0, "");
2251             putstr(0, 0, buf); /* map row #y */
2252             skippedrows = 0;
2253         } else {
2254             ++skippedrows;
2255         }
2256     }
2257     if (skippedrows)
2258         putstr(0, 0, "");
2259 }
2260 #endif /* DUMPLOG */
2261
2262 /* idea from crawl; show known portion of map without any monsters,
2263    objects, or traps occluding the view of the underlying terrain */
2264 void
2265 reveal_terrain(full, which_subset)
2266 int full; /* wizard|explore modes allow player to request full map */
2267 int which_subset; /* when not full, whether to suppress objs and/or traps */
2268 {
2269     if ((Hallucination || Stunned || Confusion) && !full) {
2270 /*JP
2271         You("are too disoriented for this.");
2272 */
2273         You("\8d¬\97\90\82µ\82Ä\82¢\82é\82Ì\82Å\82»\82ê\82Í\82Å\82«\82È\82¢\81D");
2274     } else {
2275         int x, y, glyph, default_glyph;
2276         char buf[BUFSZ];
2277         /* there is a TER_MAP bit too; we always show map regardless of it */
2278         boolean keep_traps = (which_subset & TER_TRP) !=0,
2279                 keep_objs = (which_subset & TER_OBJ) != 0,
2280                 keep_mons = (which_subset & TER_MON) != 0; /* not used */
2281         unsigned swallowed = u.uswallow; /* before unconstrain_map() */
2282
2283         if (unconstrain_map())
2284             docrt();
2285         default_glyph = cmap_to_glyph(level.flags.arboreal ? S_tree : S_stone);
2286
2287         for (x = 1; x < COLNO; x++)
2288             for (y = 0; y < ROWNO; y++) {
2289                 glyph = reveal_terrain_getglyph(x,y, full, swallowed,
2290                                                 default_glyph, which_subset);
2291                 show_glyph(x, y, glyph);
2292             }
2293
2294         /* hero's location is not highlighted, but getpos() starts with
2295            cursor there, and after moving it anywhere '@' moves it back */
2296         flush_screen(1);
2297         if (full) {
2298 /*JP
2299             Strcpy(buf, "underlying terrain");
2300 */
2301             Strcpy(buf, "\89º\82É\82 \82é\92n\8c`");
2302         } else {
2303 /*JP
2304             Strcpy(buf, "known terrain");
2305 */
2306             Strcpy(buf, "\92m\82Á\82Ä\82¢\82é\92n\8c`");
2307             if (keep_traps)
2308 #if 0 /*JP*/
2309                 Sprintf(eos(buf), "%s traps",
2310                         (keep_objs || keep_mons) ? "," : " and");
2311 #else
2312                 Strcat(buf, "\82Æã©");
2313 #endif
2314             if (keep_objs)
2315 #if 0 /*JP*/
2316                 Sprintf(eos(buf), "%s%s objects",
2317                         (keep_traps || keep_mons) ? "," : "",
2318                         keep_mons ? "" : " and");
2319 #else
2320                 Strcat(buf, "\82Æ\95¨\91Ì");
2321 #endif
2322             if (keep_mons)
2323 #if 0 /*JP*/
2324                 Sprintf(eos(buf), "%s and monsters",
2325                         (keep_traps || keep_objs) ? "," : "");
2326 #else
2327                 Strcat(buf, "\82Æ\89ö\95¨");
2328 #endif
2329         }
2330 /*JP
2331         pline("Showing %s only...", buf);
2332 */
2333         pline("%s\82¾\82¯\82ð\8c©\82é\81D\81D\81D", buf);
2334
2335         /* allow player to move cursor around and get autodescribe feedback
2336            based on what is visible now rather than what is on 'real' map */
2337         which_subset |= TER_MAP; /* guarantee non-zero */
2338 /*JP
2339         browse_map(which_subset, "anything of interest");
2340 */
2341         browse_map(which_subset, "\8aÖ\90S\82Ì\82 \82é\82à\82Ì");
2342
2343         reconstrain_map();
2344         docrt(); /* redraw the screen, restoring regular map */
2345         if (Underwater)
2346             under_water(2);
2347         if (u.uburied)
2348             under_ground(2);
2349     }
2350     return;
2351 }
2352
2353 /*detect.c*/