OSDN Git Service

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