OSDN Git Service

add translation
[jnethack/source.git] / src / pager.c
1 /* NetHack 3.6  pager.c $NHDT-Date: 1448482543 2015/11/25 20:15:43 $  $NHDT-Branch: master $:$NHDT-Revision: 1.86 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016            */
8 /* JNetHack may be freely redistributed.  See license for details. */
9
10 /* This file contains the command routines dowhatis() and dohelp() and */
11 /* a few other help related facilities */
12
13 #include "hack.h"
14 #include "dlb.h"
15
16 STATIC_DCL boolean FDECL(is_swallow_sym, (int));
17 STATIC_DCL int FDECL(append_str, (char *, const char *));
18 STATIC_DCL void FDECL(look_at_object, (char *, int, int, int));
19 STATIC_DCL void FDECL(look_at_monster, (char *, char *,
20                                         struct monst *, int, int));
21 STATIC_DCL struct permonst *FDECL(lookat, (int, int, char *, char *));
22 STATIC_DCL void FDECL(checkfile, (char *, struct permonst *,
23                                   BOOLEAN_P, BOOLEAN_P));
24 STATIC_DCL void FDECL(look_all, (BOOLEAN_P,BOOLEAN_P));
25 STATIC_DCL boolean FDECL(help_menu, (int *));
26 STATIC_DCL void NDECL(docontact);
27 #ifdef PORT_HELP
28 extern void NDECL(port_help);
29 #endif
30
31 /* Returns "true" for characters that could represent a monster's stomach. */
32 STATIC_OVL boolean
33 is_swallow_sym(c)
34 int c;
35 {
36     int i;
37
38     for (i = S_sw_tl; i <= S_sw_br; i++)
39         if ((int) showsyms[i] == c)
40             return TRUE;
41     return FALSE;
42 }
43
44 /*
45  * Append new_str to the end of buf if new_str doesn't already exist as
46  * a substring of buf.  Return 1 if the string was appended, 0 otherwise.
47  * It is expected that buf is of size BUFSZ.
48  */
49 STATIC_OVL int
50 append_str(buf, new_str)
51 char *buf;
52 const char *new_str;
53 {
54     int space_left; /* space remaining in buf */
55
56     if (strstri(buf, new_str))
57         return 0;
58
59     space_left = BUFSZ - strlen(buf) - 1;
60 #if 0 /*JP*/
61     (void) strncat(buf, " or ", space_left);
62     (void) strncat(buf, new_str, space_left - 4);
63 #else
64     (void) strncat(buf, "\82Ü\82½\82Í", space_left);
65     (void) strncat(buf, new_str, space_left - 6);
66 #endif
67     return 1;
68 }
69
70 /* shared by monster probing (via query_objlist!) as well as lookat() */
71 char *
72 self_lookat(outbuf)
73 char *outbuf;
74 {
75     char race[QBUFSZ];
76
77     /* include race with role unless polymorphed */
78     race[0] = '\0';
79     if (!Upolyd)
80 /*JP
81         Sprintf(race, "%s ", urace.adj);
82 */
83         Sprintf(race, "%s", urace.adj);
84 #if 0 /*JP*/
85     Sprintf(outbuf, "%s%s%s called %s",
86             /* being blinded may hide invisibility from self */
87             (Invis && (senseself() || !Blind)) ? "invisible " : "", race,
88             mons[u.umonnum].mname, plname);
89 #else
90     Sprintf(outbuf, "%s%s%s\82Æ\82¢\82¤\96¼\82Ì%s",
91             (Invis && (senseself() || !Blind)) ? "\8ep\82Ì\8c©\82¦\82È\82¢" : "", race,
92             plname,
93             mons[u.umonnum].mname);
94 #endif
95     if (u.usteed)
96 /*JP
97         Sprintf(eos(outbuf), ", mounted on %s", y_monnam(u.usteed));
98 */
99         Sprintf(eos(outbuf), "\81C%s\82É\8fæ\82Á\82Ä\82¢\82é", y_monnam(u.usteed));
100     return outbuf;
101 }
102
103 /* extracted from lookat(); also used by namefloorobj() */
104 boolean
105 object_from_map(glyph, x, y, obj_p)
106 int glyph, x, y;
107 struct obj **obj_p;
108 {
109     boolean fakeobj = FALSE;
110     struct monst *mtmp;
111     struct obj *otmp = vobj_at(x, y);
112     int glyphotyp = glyph_to_obj(glyph);
113
114     *obj_p = (struct obj *) 0;
115     /* there might be a mimic here posing as an object */
116     mtmp = m_at(x, y);
117     if (mtmp && is_obj_mappear(mtmp, (unsigned) glyphotyp))
118         otmp = 0;
119     else
120         mtmp = 0;
121
122     if (!otmp || otmp->otyp != glyphotyp) {
123         /* this used to exclude STRANGE_OBJECT; now caller deals with it */
124         otmp = mksobj(glyphotyp, FALSE, FALSE);
125         if (!otmp)
126             return FALSE;
127         fakeobj = TRUE;
128         if (otmp->oclass == COIN_CLASS)
129             otmp->quan = 2L; /* to force pluralization */
130         else if (otmp->otyp == SLIME_MOLD)
131             otmp->spe = context.current_fruit; /* give it a type */
132         if (mtmp && has_mcorpsenm(mtmp)) /* mimic as corpse/statue */
133             otmp->corpsenm = MCORPSENM(mtmp);
134     }
135     /* if located at adjacent spot, mark it as having been seen up close */
136     if (otmp && distu(x, y) <= 2 && !Blind && !Hallucination)
137         otmp->dknown = 1;
138
139     *obj_p = otmp;
140     return fakeobj; /* when True, caller needs to dealloc *obj_p */
141 }
142
143 STATIC_OVL void
144 look_at_object(buf, x, y, glyph)
145 char *buf; /* output buffer */
146 int x, y, glyph;
147 {
148     struct obj *otmp = 0;
149     boolean fakeobj = object_from_map(glyph, x, y, &otmp);
150
151     if (otmp) {
152         Strcpy(buf, (otmp->otyp != STRANGE_OBJECT)
153                      ? distant_name(otmp, xname)
154                      : obj_descr[STRANGE_OBJECT].oc_name);
155         if (fakeobj)
156             dealloc_obj(otmp), otmp = 0;
157     } else
158         Strcpy(buf, something); /* sanity precaution */
159
160     if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR)
161 /*JP
162         Strcat(buf, " embedded in stone");
163 */
164         Strcat(buf, "\81C\8aâ\82É\96\84\82ß\82±\82Ü\82ê\82Ä\82¢\82é");
165     else if (IS_WALL(levl[x][y].typ) || levl[x][y].typ == SDOOR)
166 /*JP
167         Strcat(buf, " embedded in a wall");
168 */
169         Strcat(buf, "\81C\95Ç\82É\96\84\82ß\82±\82Ü\82ê\82Ä\82¢\82é");
170     else if (closed_door(x, y))
171 /*JP
172         Strcat(buf, " embedded in a door");
173 */
174         Strcat(buf, "\81C\94à\82É\96\84\82ß\82±\82Ü\82ê\82Ä\82¢\82é");
175     else if (is_pool(x, y))
176       /*JP 3.4.3 \82±\82Ì\95\94\95ª\82Í\95¨\91Ì\82É\82µ\82©\8eg\82í\82ê\82È\82¢ */
177 /*JP
178         Strcat(buf, " in water");
179 */
180         Strcat(buf, "\81C\90\85\92\86\82É\82 \82é");
181     else if (is_lava(x, y))
182 #if 0 /*JP*/
183         Strcat(buf, " in molten lava"); /* [can this ever happen?] */
184 #else
185         Strcat(buf, "\81C\97n\8aâ\82Ì\92\86\82É\82 \82é");        /* [can this ever happen?] */
186 #endif
187     return;
188 }
189
190 STATIC_OVL void
191 look_at_monster(buf, monbuf, mtmp, x, y)
192 char *buf, *monbuf; /* buf: output, monbuf: optional output */
193 struct monst *mtmp;
194 int x, y;
195 {
196     char *name, monnambuf[BUFSZ];
197     boolean accurate = !Hallucination;
198
199     if (mtmp->data == &mons[PM_COYOTE] && accurate)
200         name = coyotename(mtmp, monnambuf);
201     else
202         name = distant_monnam(mtmp, ARTICLE_NONE, monnambuf);
203
204 #if 0 /*JP*/
205     Sprintf(buf, "%s%s%s",
206             (mtmp->mx != x || mtmp->my != y)
207                 ? ((mtmp->isshk && accurate) ? "tail of " : "tail of a ")
208                 : "",
209             (mtmp->mtame && accurate)
210                 ? "tame "
211                 : (mtmp->mpeaceful && accurate)
212                     ? "peaceful "
213                     : "",
214             name);
215 #else
216     Sprintf(buf, "%s%s%s",
217             (mtmp->mtame && accurate) ? "\8eè\82È\82¸\82¯\82ç\82ê\82½" :
218             (mtmp->mpeaceful && accurate) ? "\97F\8dD\93I\82È" : "",
219             name,
220             (mtmp->mx != x || mtmp->my != y) ?
221             ((mtmp->isshk && accurate)
222              ? "\82Ì\90K\94ö" : "\82Ì\90K\94ö") : "");
223 #endif
224     if (u.ustuck == mtmp)
225         Strcat(buf, (Upolyd && sticks(youmonst.data))
226 /*JP
227                      ? ", being held" : ", holding you");
228 */
229                      ? "\81C\82 \82È\82½\82ª\92Í\82Ü\82¦\82Ä\82¢\82é" : "\81C\82 \82È\82½\82ð\92Í\82Ü\82¦\82Ä\82¢\82é");
230     if (mtmp->mleashed)
231 /*JP
232         Strcat(buf, ", leashed to you");
233 */
234         Strcat(buf, "\81C\95R\82Å\8c\8b\82Î\82ê\82Ä\82¢\82é");
235
236     if (mtmp->mtrapped && cansee(mtmp->mx, mtmp->my)) {
237         struct trap *t = t_at(mtmp->mx, mtmp->my);
238         int tt = t ? t->ttyp : NO_TRAP;
239
240         /* newsym lets you know of the trap, so mention it here */
241         if (tt == BEAR_TRAP || tt == PIT || tt == SPIKED_PIT || tt == WEB)
242 /*JP
243             Sprintf(eos(buf), ", trapped in %s",
244 */
245             Sprintf(eos(buf), ", %s\82É\95ß\82Ü\82Á\82Ä\82¢\82é",
246                     an(defsyms[trap_to_defsym(tt)].explanation));
247     }
248
249     if (monbuf) {
250         unsigned how_seen = howmonseen(mtmp);
251
252         monbuf[0] = '\0';
253         if (how_seen != 0 && how_seen != MONSEEN_NORMAL) {
254             if (how_seen & MONSEEN_NORMAL) {
255 /*JP
256                 Strcat(monbuf, "normal vision");
257 */
258                 Strcat(monbuf, "\92Ê\8fí\82Ì\8e\8b\8ao");
259                 how_seen &= ~MONSEEN_NORMAL;
260                 /* how_seen can't be 0 yet... */
261                 if (how_seen)
262                     Strcat(monbuf, ", ");
263             }
264             if (how_seen & MONSEEN_SEEINVIS) {
265 /*JP
266                 Strcat(monbuf, "see invisible");
267 */
268                 Strcat(monbuf, "\8c©\82¦\82È\82¢\82à\82Ì\82ð\8c©\82é\8e\8b\8ao");
269                 how_seen &= ~MONSEEN_SEEINVIS;
270                 if (how_seen)
271                     Strcat(monbuf, ", ");
272             }
273             if (how_seen & MONSEEN_INFRAVIS) {
274 /*JP
275                 Strcat(monbuf, "infravision");
276 */
277                 Strcat(monbuf, "\90Ô\8aO\90ü\82ª\8c©\82¦\82é\8e\8b\8ao");
278                 how_seen &= ~MONSEEN_INFRAVIS;
279                 if (how_seen)
280                     Strcat(monbuf, ", ");
281             }
282             if (how_seen & MONSEEN_TELEPAT) {
283 /*JP
284                 Strcat(monbuf, "telepathy");
285 */
286                 Strcat(monbuf, "\83e\83\8c\83p\83V\81[");
287                 how_seen &= ~MONSEEN_TELEPAT;
288                 if (how_seen)
289                     Strcat(monbuf, ", ");
290             }
291             if (how_seen & MONSEEN_XRAYVIS) {
292                 /* Eyes of the Overworld */
293 /*JP
294                 Strcat(monbuf, "astral vision");
295 */
296                 Strcat(monbuf, "\90¸\90_\82É\82æ\82é\8e\8b\8ao");
297                 how_seen &= ~MONSEEN_XRAYVIS;
298                 if (how_seen)
299                     Strcat(monbuf, ", ");
300             }
301             if (how_seen & MONSEEN_DETECT) {
302 /*JP
303                 Strcat(monbuf, "monster detection");
304 */
305                 Strcat(monbuf, "\89ö\95¨\82ð\94­\8c©\82·\82é\94\\97Í");
306                 how_seen &= ~MONSEEN_DETECT;
307                 if (how_seen)
308                     Strcat(monbuf, ", ");
309             }
310             if (how_seen & MONSEEN_WARNMON) {
311                 if (Hallucination)
312 /*JP
313                     Strcat(monbuf, "paranoid delusion");
314 */
315                     Strcat(monbuf, "\95Î\8e·\93I\96Ï\91z");
316                 else
317 /*JP
318                     Sprintf(eos(monbuf), "warned of %s",
319 */
320                     Sprintf(eos(monbuf), "%s\82ð\8cx\8d\90\82µ\82Ä\82¢\82é",
321                             makeplural(mtmp->data->mname));
322                 how_seen &= ~MONSEEN_WARNMON;
323                 if (how_seen)
324                     Strcat(monbuf, ", ");
325             }
326             /* should have used up all the how_seen bits by now */
327             if (how_seen) {
328                 impossible("lookat: unknown method of seeing monster");
329                 Sprintf(eos(monbuf), "(%u)", how_seen);
330             }
331         } /* seen by something other than normal vision */
332     } /* monbuf is non-null */
333 }
334
335 /*
336  * Return the name of the glyph found at (x,y).
337  * If not hallucinating and the glyph is a monster, also monster data.
338  */
339 STATIC_OVL struct permonst *
340 lookat(x, y, buf, monbuf)
341 int x, y;
342 char *buf, *monbuf;
343 {
344     struct monst *mtmp = (struct monst *) 0;
345     struct permonst *pm = (struct permonst *) 0;
346     int glyph;
347
348     buf[0] = monbuf[0] = '\0';
349     glyph = glyph_at(x, y);
350     if (u.ux == x && u.uy == y && canspotself()) {
351         /* fill in buf[] */
352         (void) self_lookat(buf);
353
354         /* file lookup can't distinguish between "gnomish wizard" monster
355            and correspondingly named player character, always picking the
356            former; force it to find the general "wizard" entry instead */
357         if (Role_if(PM_WIZARD) && Race_if(PM_GNOME) && !Upolyd)
358             pm = &mons[PM_WIZARD];
359
360         /* When you see yourself normally, no explanation is appended
361            (even if you could also see yourself via other means).
362            Sensing self while blind or swallowed is treated as if it
363            were by normal vision (cf canseeself()). */
364         if ((Invisible || u.uundetected) && !Blind && !u.uswallow) {
365             unsigned how = 0;
366
367             if (Infravision)
368                 how |= 1;
369             if (Unblind_telepat)
370                 how |= 2;
371             if (Detect_monsters)
372                 how |= 4;
373
374             if (how)
375 #if 0 /*JP*/
376                 Sprintf(
377                     eos(buf), " [seen: %s%s%s%s%s]",
378                     (how & 1) ? "infravision" : "",
379                     /* add comma if telep and infrav */
380                     ((how & 3) > 2) ? ", " : "", (how & 2) ? "telepathy" : "",
381                     /* add comma if detect and (infrav or telep or both) */
382                     ((how & 7) > 4) ? ", " : "",
383                     (how & 4) ? "monster detection" : "");
384 #else
385                 Sprintf(
386                     eos(buf), " [\8a´\92m: %s%s%s%s%s]",
387                     (how & 1) ? "\90Ô\8aO\90ü" : "",
388                     /* add comma if telep and infrav */
389                     ((how & 3) > 2) ? ", " : "", (how & 2) ? "\83e\83\8c\83p\83V\81[" : "",
390                     /* add comma if detect and (infrav or telep or both) */
391                     ((how & 7) > 4) ? ", " : "",
392                     (how & 4) ? "\89ö\95¨\8a´\92m" : "");
393 #endif
394         }
395     } else if (u.uswallow) {
396         /* all locations when swallowed other than the hero are the monster */
397 #if 0 /*JP*/
398         Sprintf(buf, "interior of %s",
399                 Blind ? "a monster" : a_monnam(u.ustuck));
400 #else
401         Sprintf(buf, "%s\82Ì\93à\95\94",
402                 Blind ? "\89ö\95¨" : a_monnam(u.ustuck));
403 #endif
404         pm = u.ustuck->data;
405     } else if (glyph_is_monster(glyph)) {
406         bhitpos.x = x;
407         bhitpos.y = y;
408         if ((mtmp = m_at(x, y)) != 0) {
409             look_at_monster(buf, monbuf, mtmp, x, y);
410             pm = mtmp->data;
411         }
412     } else if (glyph_is_object(glyph)) {
413         look_at_object(buf, x, y, glyph); /* fill in buf[] */
414     } else if (glyph_is_trap(glyph)) {
415         int tnum = what_trap(glyph_to_trap(glyph));
416
417         Strcpy(buf, defsyms[trap_to_defsym(tnum)].explanation);
418     } else if (!glyph_is_cmap(glyph)) {
419 /*JP
420         Strcpy(buf, "unexplored area");
421 */
422         Strcpy(buf, "\96¢\92T\8dõ\82Ì\8fê\8f\8a");
423     } else
424         switch (glyph_to_cmap(glyph)) {
425         case S_altar:
426 /*JP
427             Sprintf(buf, "%s %saltar",
428 */
429             Sprintf(buf, "%s%s\8dÕ\92d",
430                     /* like endgame high priests, endgame high altars
431                        are only recognizable when immediately adjacent */
432                     (Is_astralevel(&u.uz) && distu(x, y) > 2)
433 /*JP
434                         ? "aligned"
435 */
436                         ? "\91®\90«\82Ì"
437                         : align_str(
438                               Amask2align(levl[x][y].altarmask & ~AM_SHRINE)),
439                     ((levl[x][y].altarmask & AM_SHRINE)
440                      && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
441 /*JP
442                         ? "high "
443 */
444                         ? "\8d\82\88Ê\82Ì"
445                         : "");
446             break;
447         case S_ndoor:
448             if (is_drawbridge_wall(x, y) >= 0)
449 /*JP
450                 Strcpy(buf, "open drawbridge portcullis");
451 */
452                 Strcpy(buf,"\8aJ\82¢\82Ä\82¢\82é\92µ\82Ë\8b´");
453             else if ((levl[x][y].doormask & ~D_TRAPPED) == D_BROKEN)
454 /*JP
455                 Strcpy(buf, "broken door");
456 */
457                 Strcpy(buf,"\89ó\82ê\82½\94à");
458             else
459 /*JP
460                 Strcpy(buf, "doorway");
461 */
462                 Strcpy(buf,"\8fo\93ü\82è\8cû");
463             break;
464         case S_cloud:
465             Strcpy(buf,
466 /*JP
467                    Is_airlevel(&u.uz) ? "cloudy area" : "fog/vapor cloud");
468 */
469                    Is_airlevel(&u.uz) ? "\93Ü\82Á\82Ä\82¢\82é\8fê\8f\8a" : "\96¶/\8fö\8bC\82Ì\89_");
470             break;
471         case S_stone:
472             if (!levl[x][y].seenv) {
473 /*JP
474                 Strcpy(buf, "unexplored");
475 */
476                 Strcpy(buf, "\96¢\92T\8dõ");
477                 break;
478             } else if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR) {
479 /*JP
480                 Strcpy(buf, "stone");
481 */
482                 Strcpy(buf, "\8aâ\94Õ");
483                 break;
484             }
485             /*else FALLTHRU*/
486         default:
487             Strcpy(buf, defsyms[glyph_to_cmap(glyph)].explanation);
488             break;
489         }
490
491     return (pm && !Hallucination) ? pm : (struct permonst *) 0;
492 }
493
494 /*
495  * Look in the "data" file for more info.  Called if the user typed in the
496  * whole name (user_typed_name == TRUE), or we've found a possible match
497  * with a character/glyph and flags.help is TRUE.
498  *
499  * NOTE: when (user_typed_name == FALSE), inp is considered read-only and
500  *       must not be changed directly, e.g. via lcase(). We want to force
501  *       lcase() for data.base lookup so that we can have a clean key.
502  *       Therefore, we create a copy of inp _just_ for data.base lookup.
503  */
504 STATIC_OVL void
505 checkfile(inp, pm, user_typed_name, without_asking)
506 char *inp;
507 struct permonst *pm;
508 boolean user_typed_name, without_asking;
509 {
510     dlb *fp;
511     char buf[BUFSZ], newstr[BUFSZ];
512     char *ep, *dbase_str;
513     unsigned long txt_offset = 0L;
514     int chk_skip;
515     boolean found_in_file = FALSE, skipping_entry = FALSE;
516     winid datawin = WIN_ERR;
517
518     fp = dlb_fopen(DATAFILE, "r");
519     if (!fp) {
520 #if 0 /*JP*/
521         pline("Cannot open data file!");
522 #else
523         pline("\83f\81[\83^\83t\83@\83C\83\8b\82ð\8aJ\82¯\82È\82¢\81I");
524 #endif
525         return;
526     }
527
528     /*
529      * If someone passed us garbage, prevent fault.
530      */
531     if (!inp || (inp && strlen(inp) > (BUFSZ - 1))) {
532         pline("bad do_look buffer passed!");
533         return;
534     }
535
536     /* To prevent the need for entries in data.base like *ngel to account
537      * for Angel and angel, make the lookup string the same for both
538      * user_typed_name and picked name.
539      */
540     if (pm != (struct permonst *) 0 && !user_typed_name)
541         dbase_str = strcpy(newstr, pm->mname);
542     else
543         dbase_str = strcpy(newstr, inp);
544     (void) lcase(dbase_str);
545
546     if (!strncmp(dbase_str, "interior of ", 12))
547         dbase_str += 12;
548     if (!strncmp(dbase_str, "a ", 2))
549         dbase_str += 2;
550     else if (!strncmp(dbase_str, "an ", 3))
551         dbase_str += 3;
552     else if (!strncmp(dbase_str, "the ", 4))
553         dbase_str += 4;
554     if (!strncmp(dbase_str, "tame ", 5))
555         dbase_str += 5;
556     else if (!strncmp(dbase_str, "peaceful ", 9))
557         dbase_str += 9;
558     if (!strncmp(dbase_str, "invisible ", 10))
559         dbase_str += 10;
560     if (!strncmp(dbase_str, "saddled ", 8))
561         dbase_str += 8;
562     if (!strncmp(dbase_str, "statue of ", 10))
563         dbase_str[6] = '\0';
564     else if (!strncmp(dbase_str, "figurine of ", 12))
565         dbase_str[8] = '\0';
566
567     /* Make sure the name is non-empty. */
568     if (*dbase_str) {
569         /* adjust the input to remove "named " and convert to lower case */
570         char *alt = 0; /* alternate description */
571
572         if ((ep = strstri(dbase_str, " named ")) != 0)
573             alt = ep + 7;
574         else
575             ep = strstri(dbase_str, " called ");
576         if (!ep)
577             ep = strstri(dbase_str, ", ");
578         if (ep && ep > dbase_str)
579             *ep = '\0';
580
581         /*
582          * If the object is named, then the name is the alternate description;
583          * otherwise, the result of makesingular() applied to the name is.
584          * This
585          * isn't strictly optimal, but named objects of interest to the user
586          * will usually be found under their name, rather than under their
587          * object type, so looking for a singular form is pointless.
588          */
589         if (!alt)
590             alt = makesingular(dbase_str);
591
592         /* skip first record; read second */
593         txt_offset = 0L;
594         if (!dlb_fgets(buf, BUFSZ, fp) || !dlb_fgets(buf, BUFSZ, fp)) {
595             impossible("can't read 'data' file");
596             (void) dlb_fclose(fp);
597             return;
598         } else if (sscanf(buf, "%8lx\n", &txt_offset) < 1 || txt_offset == 0L)
599             goto bad_data_file;
600
601         /* look for the appropriate entry */
602         while (dlb_fgets(buf, BUFSZ, fp)) {
603             if (*buf == '.')
604                 break; /* we passed last entry without success */
605
606             if (digit(*buf)) {
607                 /* a number indicates the end of current entry */
608                 skipping_entry = FALSE;
609             } else if (!skipping_entry) {
610                 if (!(ep = index(buf, '\n')))
611                     goto bad_data_file;
612                 *ep = 0;
613                 /* if we match a key that begins with "~", skip this entry */
614                 chk_skip = (*buf == '~') ? 1 : 0;
615                 if (pmatch(&buf[chk_skip], dbase_str)
616                     || (alt && pmatch(&buf[chk_skip], alt))) {
617                     if (chk_skip) {
618                         skipping_entry = TRUE;
619                         continue;
620                     } else {
621                         found_in_file = TRUE;
622                         break;
623                     }
624                 }
625             }
626         }
627     }
628
629     if (found_in_file) {
630         long entry_offset;
631         int entry_count;
632         int i;
633
634         /* skip over other possible matches for the info */
635         do {
636             if (!dlb_fgets(buf, BUFSZ, fp))
637                 goto bad_data_file;
638         } while (!digit(*buf));
639         if (sscanf(buf, "%ld,%d\n", &entry_offset, &entry_count) < 2) {
640         bad_data_file:
641             impossible("'data' file in wrong format or corrupted");
642             /* window will exist if we came here from below via 'goto' */
643             if (datawin != WIN_ERR)
644                 destroy_nhwindow(datawin);
645             (void) dlb_fclose(fp);
646             return;
647         }
648
649 /*JP
650         if (user_typed_name || without_asking || yn("More info?") == 'y') {
651 */
652         if (user_typed_name || without_asking || yn("\8fÚ\8d×\82ð\8c©\82é\81H") == 'y') {
653             if (dlb_fseek(fp, (long) txt_offset + entry_offset, SEEK_SET)
654                 < 0) {
655 /*JP
656                 pline("? Seek error on 'data' file!");
657 */
658                 pline("'data'\83t\83@\83C\83\8b\82Ì\83V\81[\83N\83G\83\89\81[\81I");
659                 (void) dlb_fclose(fp);
660                 return;
661             }
662             datawin = create_nhwindow(NHW_MENU);
663             for (i = 0; i < entry_count; i++) {
664                 if (!dlb_fgets(buf, BUFSZ, fp))
665                     goto bad_data_file;
666                 if ((ep = index(buf, '\n')) != 0)
667                     *ep = 0;
668                 if (index(buf + 1, '\t') != 0)
669                     (void) tabexpand(buf + 1);
670                 putstr(datawin, 0, buf + 1);
671             }
672             display_nhwindow(datawin, FALSE);
673             destroy_nhwindow(datawin);
674         }
675     } else if (user_typed_name)
676 /*JP
677         pline("I don't have any information on those things.");
678 */
679         pline("\82»\82ñ\82È\96¼\91O\82Í\95·\82¢\82½\82±\82Æ\82ª\82È\82¢\81D");
680
681     (void) dlb_fclose(fp);
682 }
683
684 int
685 do_screen_description(cc, looked, sym, out_str, firstmatch)
686 coord cc;
687 boolean looked;
688 int sym;
689 char *out_str;
690 const char **firstmatch;
691 {
692     boolean need_to_look = FALSE;
693     int glyph = NO_GLYPH;
694     static char look_buf[BUFSZ];
695     char prefix[BUFSZ];
696     int found = 0; /* count of matching syms found */
697     int i, alt_i;
698     int skipped_venom = 0;
699     boolean hit_trap;
700     const char *x_str;
701 /*JP
702     static const char *mon_interior = "the interior of a monster";
703 */
704     static const char *mon_interior = "\89ö\95¨\82Ì\93à\95\94";
705
706     if (looked) {
707         int oc;
708         unsigned os;
709
710         glyph = glyph_at(cc.x, cc.y);
711         /* Convert glyph at selected position to a symbol for use below. */
712         (void) mapglyph(glyph, &sym, &oc, &os, cc.x, cc.y);
713
714         Sprintf(prefix, "%s        ", encglyph(glyph));
715     } else
716         Sprintf(prefix, "%c        ", sym);
717
718     /*
719      * Check all the possibilities, saving all explanations in a buffer.
720      * When all have been checked then the string is printed.
721      */
722
723     /*
724      * Special case: if identifying from the screen, and we're swallowed,
725      * and looking at something other than our own symbol, then just say
726      * "the interior of a monster".
727      */
728     if (u.uswallow && looked
729         && (is_swallow_sym(sym) || (int) showsyms[S_stone] == sym)) {
730         if (!found) {
731             Sprintf(out_str, "%s%s", prefix, mon_interior);
732             *firstmatch = mon_interior;
733         } else {
734             found += append_str(out_str, mon_interior);
735         }
736         need_to_look = TRUE;
737         goto didlook;
738     }
739
740     /* Check for monsters */
741     for (i = 0; i < MAXMCLASSES; i++) {
742         if (sym == (looked ? showsyms[i + SYM_OFF_M] : def_monsyms[i].sym)
743             && def_monsyms[i].explain) {
744             need_to_look = TRUE;
745             if (!found) {
746                 Sprintf(out_str, "%s%s", prefix, an(def_monsyms[i].explain));
747                 *firstmatch = def_monsyms[i].explain;
748                 found++;
749             } else {
750                 found += append_str(out_str, an(def_monsyms[i].explain));
751             }
752         }
753     }
754     /* handle '@' as a special case if it refers to you and you're
755        playing a character which isn't normally displayed by that
756        symbol; firstmatch is assumed to already be set for '@' */
757     if ((looked ? (sym == showsyms[S_HUMAN + SYM_OFF_M]
758                    && cc.x == u.ux && cc.y == u.uy)
759                 : (sym == def_monsyms[S_HUMAN].sym && !flags.showrace))
760         && !(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
761 #if 0 /*JP*/
762         found += append_str(out_str, "you"); /* tack on "or you" */
763 #else
764         found += append_str(out_str, "\82 \82È\82½"); /* tack on "or you" */
765 #endif
766
767     /* Now check for objects */
768     for (i = 1; i < MAXOCLASSES; i++) {
769         if (sym == (looked ? showsyms[i + SYM_OFF_O] : def_oc_syms[i].sym)) {
770             need_to_look = TRUE;
771             if (looked && i == VENOM_CLASS) {
772                 skipped_venom++;
773                 continue;
774             }
775             if (!found) {
776                 Sprintf(out_str, "%s%s", prefix, an(def_oc_syms[i].explain));
777                 *firstmatch = def_oc_syms[i].explain;
778                 found++;
779             } else {
780                 found += append_str(out_str, an(def_oc_syms[i].explain));
781             }
782         }
783     }
784
785     if (sym == DEF_INVISIBLE) {
786         if (!found) {
787             Sprintf(out_str, "%s%s", prefix, an(invisexplain));
788             *firstmatch = invisexplain;
789             found++;
790         } else {
791             found += append_str(out_str, an(invisexplain));
792         }
793     }
794
795 #define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
796 #define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
797
798     /* Now check for graphics symbols */
799     alt_i = (sym == (looked ? showsyms[0] : defsyms[0].sym)) ? 0 : (2 + 1);
800     for (hit_trap = FALSE, i = 0; i < MAXPCHARS; i++) {
801         /* when sym is the default background character, we process
802            i == 0 three times: unexplored, stone, dark part of a room */
803         if (alt_i < 2) {
804 /*JP
805             x_str = !alt_i++ ? "unexplored" : "stone";
806 */
807             x_str = !alt_i++ ? "\96¢\92T\8dõ" : "\8aâ\94Õ";
808             i = 0; /* for second iteration, undo loop increment */
809             /* alt_i is now 1 or 2 */
810         } else {
811             if (alt_i++ == 2)
812                 i = 0; /* undo loop increment */
813             x_str = defsyms[i].explanation;
814             /* alt_i is now 3 or more and no longer of interest */
815         }
816         if (sym == (looked ? showsyms[i] : defsyms[i].sym) && *x_str) {
817 #if 0 /*JP*//*\93ú\96{\8cê\82É\82Í\8aÖ\8cW\82È\82¢*/
818             /* avoid "an unexplored", "an stone", "an air", "a water",
819                "a floor of a room", "a dark part of a room";
820                article==2 => "the", 1 => "an", 0 => (none) */
821             int article = strstri(x_str, " of a room") ? 2
822                           : !(alt_i <= 2
823                               || strcmp(x_str, "air") == 0
824                               || strcmp(x_str, "water") == 0);
825
826 #endif
827             if (!found) {
828                 if (is_cmap_trap(i)) {
829 /*JP
830                     Sprintf(out_str, "%sa trap", prefix);
831 */
832                     Sprintf(out_str, "%sã©", prefix);
833                     hit_trap = TRUE;
834                 } else {
835 #if 0 /*JP*/
836                     Sprintf(out_str, "%s%s", prefix,
837                             article == 2 ? the(x_str)
838                             : article == 1 ? an(x_str) : x_str);
839 #else
840                     Sprintf(out_str, "%s%s", prefix, x_str);
841 #endif
842                 }
843                 *firstmatch = x_str;
844                 found++;
845             } else if (!u.uswallow && !(hit_trap && is_cmap_trap(i))
846                        && !(found >= 3 && is_cmap_drawbridge(i))
847                        /* don't mention vibrating square outside of Gehennom
848                           unless this happens to be one (hallucination?) */
849                        && (i != S_vibrating_square || Inhell
850                            || (looked && glyph_is_trap(glyph)
851                                && glyph_to_trap(glyph) == VIBRATING_SQUARE))) {
852 #if 0 /*JP*/
853                 found += append_str(out_str, (article == 2) ? the(x_str)
854                                              : (article == 1) ? an(x_str)
855                                                : x_str);
856 #else
857                 found += append_str(out_str, x_str);
858 #endif
859                 if (is_cmap_trap(i))
860                     hit_trap = TRUE;
861             }
862
863             if (i == S_altar || is_cmap_trap(i))
864                 need_to_look = TRUE;
865         }
866     }
867
868     /* Now check for warning symbols */
869     for (i = 1; i < WARNCOUNT; i++) {
870         x_str = def_warnsyms[i].explanation;
871         if (sym == (looked ? warnsyms[i] : def_warnsyms[i].sym)) {
872             if (!found) {
873                 Sprintf(out_str, "%s%s", prefix, def_warnsyms[i].explanation);
874                 *firstmatch = def_warnsyms[i].explanation;
875                 found++;
876             } else {
877                 found += append_str(out_str, def_warnsyms[i].explanation);
878             }
879             /* Kludge: warning trumps boulders on the display.
880                Reveal the boulder too or player can get confused */
881             if (looked && sobj_at(BOULDER, cc.x, cc.y))
882                 Strcat(out_str, " co-located with a boulder");
883             break; /* out of for loop*/
884         }
885     }
886
887     /* if we ignored venom and list turned out to be short, put it back */
888     if (skipped_venom && found < 2) {
889         x_str = def_oc_syms[VENOM_CLASS].explain;
890         if (!found) {
891             Sprintf(out_str, "%s%s", prefix, an(x_str));
892             *firstmatch = x_str;
893             found++;
894         } else {
895             found += append_str(out_str, an(x_str));
896         }
897     }
898
899     /* handle optional boulder symbol as a special case */
900     if (iflags.bouldersym && sym == iflags.bouldersym) {
901         if (!found) {
902 /*JP
903             *firstmatch = "boulder";
904 */
905             *firstmatch = "\8aâ";
906             Sprintf(out_str, "%s%s", prefix, an(*firstmatch));
907             found++;
908         } else {
909 /*JP
910             found += append_str(out_str, "boulder");
911 */
912             found += append_str(out_str, "\8aâ");
913         }
914     }
915
916     /*
917      * If we are looking at the screen, follow multiple possibilities or
918      * an ambiguous explanation by something more detailed.
919      */
920  didlook:
921     if (looked) {
922         if (found > 1 || need_to_look) {
923             char monbuf[BUFSZ];
924             char temp_buf[BUFSZ];
925
926             (void) lookat(cc.x, cc.y, look_buf, monbuf);
927             *firstmatch = look_buf;
928             if (*(*firstmatch)) {
929                 Sprintf(temp_buf, " (%s)", *firstmatch);
930                 (void) strncat(out_str, temp_buf,
931                                BUFSZ - strlen(out_str) - 1);
932                 found = 1; /* we have something to look up */
933             }
934             if (monbuf[0]) {
935                 Sprintf(temp_buf, " [seen: %s]", monbuf);
936                 (void) strncat(out_str, temp_buf,
937                                BUFSZ - strlen(out_str) - 1);
938             }
939         }
940     }
941
942     return found;
943 }
944
945 /* getpos() return values */
946 #define LOOK_TRADITIONAL 0 /* '.' -- ask about "more info?" */
947 #define LOOK_QUICK 1       /* ',' -- skip "more info?" */
948 #define LOOK_ONCE 2        /* ';' -- skip and stop looping */
949 #define LOOK_VERBOSE 3     /* ':' -- show more info w/o asking */
950
951 /* also used by getpos hack in do_name.c */
952 /*JP
953 const char what_is_an_unknown_object[] = "an unknown object";
954 */
955 const char what_is_an_unknown_object[] = "\93ä\82Ì\95¨\91Ì";
956
957 int
958 do_look(mode, click_cc)
959 int mode;
960 coord *click_cc;
961 {
962     boolean quick = (mode == 1); /* use cursor; don't search for "more info" */
963     boolean clicklook = (mode == 2); /* right mouse-click method */
964     char out_str[BUFSZ];
965     const char *firstmatch = 0;
966     struct permonst *pm = 0;
967     int i = '\0', ans = 0;
968     int sym;              /* typed symbol or converted glyph */
969     int found;            /* count of matching syms found */
970     coord cc;             /* screen pos of unknown glyph */
971     boolean save_verbose; /* saved value of flags.verbose */
972     boolean from_screen;  /* question from the screen */
973
974     if (!clicklook) {
975         if (quick) {
976             from_screen = TRUE; /* yes, we want to use the cursor */
977             i = 'y';
978         }
979
980         if (i != 'y') {
981             menu_item *pick_list = (menu_item *) 0;
982             winid win;
983             anything any;
984
985             any = zeroany;
986             win = create_nhwindow(NHW_MENU);
987             start_menu(win);
988             any.a_char = '/';
989             /* 'y' and 'n' to keep backwards compatibility with previous
990                versions: "Specify unknown object by cursor?" */
991             add_menu(win, NO_GLYPH, &any,
992                      flags.lootabc ? 0 : any.a_char, 'y', ATR_NONE,
993 /*JP
994                      "something on the map", MENU_UNSELECTED);
995 */
996                      "\92n\90}\8fã\82É\82 \82é\82à\82Ì", MENU_UNSELECTED);
997             any.a_char = 'i';
998             add_menu(win, NO_GLYPH, &any,
999                      flags.lootabc ? 0 : any.a_char, 0, ATR_NONE,
1000 /*JP
1001                      "something you're carrying", MENU_UNSELECTED);
1002 */
1003                      "\82 \82È\82½\82ª\8e\9d\82Á\82Ä\82¢\82é\82à\82Ì", MENU_UNSELECTED);
1004             any.a_char = '?';
1005             add_menu(win, NO_GLYPH, &any,
1006                      flags.lootabc ? 0 : any.a_char, 'n', ATR_NONE,
1007 /*JP
1008                      "something else (by symbol or name)", MENU_UNSELECTED);
1009 */
1010                      "\82»\82ê\88È\8aO(\83V\83\93\83{\83\8b\82©\96¼\91O\82Å\8ew\92è)", MENU_UNSELECTED);
1011             if (!u.uswallow && !Hallucination) {
1012                 any = zeroany;
1013                 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
1014                          "", MENU_UNSELECTED);
1015                 /* these options work sensibly for the swallowed case,
1016                    but there's no reason for the player to use them then;
1017                    objects work fine when hallucinating, but screen
1018                    symbol/monster class letter doesn't match up with
1019                    bogus monster type, so suppress when hallucinating */
1020                 any.a_char = 'm';
1021                 add_menu(win, NO_GLYPH, &any,
1022                          flags.lootabc ? 0 : any.a_char, 0, ATR_NONE,
1023 /*JP
1024                          "nearby monsters", MENU_UNSELECTED);
1025 */
1026                          "\8bß\82­\82É\82¢\82é\89ö\95¨", MENU_UNSELECTED);
1027                 any.a_char = 'M';
1028                 add_menu(win, NO_GLYPH, &any,
1029                          flags.lootabc ? 0 : any.a_char, 0, ATR_NONE,
1030 /*JP
1031                          "all monsters shown on map", MENU_UNSELECTED);
1032 */
1033                          "\92n\90}\8fã\82É\82¢\82é\91S\82Ä\82Ì\89ö\95¨", MENU_UNSELECTED);
1034                 any.a_char = 'o';
1035                 add_menu(win, NO_GLYPH, &any,
1036                          flags.lootabc ? 0 : any.a_char, 0, ATR_NONE,
1037 /*JP
1038                          "nearby objects", MENU_UNSELECTED);
1039 */
1040                          "\8bß\82­\82É\82 \82é\82à\82Ì", MENU_UNSELECTED);
1041                 any.a_char = 'O';
1042                 add_menu(win, NO_GLYPH, &any,
1043                          flags.lootabc ? 0 : any.a_char, 0, ATR_NONE,
1044 /*JP
1045                          "all objects shown on map", MENU_UNSELECTED);
1046 */
1047                          "\92n\90}\8fã\82É\82 \82é\91S\82Ä\82Ì\82à\82Ì", MENU_UNSELECTED);
1048             }
1049 /*JP
1050             end_menu(win, "What do you want to look at:");
1051 */
1052             end_menu(win, "\89½\82ð\8c©\82é\81H");
1053             if (select_menu(win, PICK_ONE, &pick_list) > 0) {
1054                 i = pick_list->item.a_char;
1055                 free((genericptr_t) pick_list);
1056             }
1057             destroy_nhwindow(win);
1058         }
1059
1060         switch (i) {
1061         default:
1062         case 'q':
1063             return 0;
1064         case 'y':
1065         case '/':
1066             from_screen = TRUE;
1067             sym = 0;
1068             cc.x = u.ux;
1069             cc.y = u.uy;
1070             break;
1071         case 'i':
1072           {
1073             char invlet;
1074             struct obj *invobj;
1075
1076             invlet = display_inventory((const char *) 0, TRUE);
1077             if (!invlet || invlet == '\033')
1078                 return 0;
1079             *out_str = '\0';
1080             for (invobj = invent; invobj; invobj = invobj->nobj)
1081                 if (invobj->invlet == invlet) {
1082                     strcpy(out_str, singular(invobj, xname));
1083                     break;
1084                 }
1085             if (*out_str)
1086                 checkfile(out_str, pm, TRUE, TRUE);
1087             return 0;
1088           }
1089         case '?':
1090             from_screen = FALSE;
1091 /*JP
1092             getlin("Specify what? (type the word)", out_str);
1093 */
1094             getlin("\89½\82ð\92²\82×\82é\81H(\95\8e\9a\82ð\93ü\82ê\82Ä\82Ë)", out_str);
1095             if (out_str[0] == '\0' || out_str[0] == '\033')
1096                 return 0;
1097
1098             if (out_str[1]) { /* user typed in a complete string */
1099                 checkfile(out_str, pm, TRUE, TRUE);
1100                 return 0;
1101             }
1102             sym = out_str[0];
1103             break;
1104         case 'm':
1105             look_all(TRUE, TRUE); /* list nearby monsters */
1106             return 0;
1107         case 'M':
1108             look_all(FALSE, TRUE); /* list all monsters */
1109             return 0;
1110         case 'o':
1111             look_all(TRUE, FALSE); /* list nearby objects */
1112             return 0;
1113         case 'O':
1114             look_all(FALSE, FALSE); /* list all objects */
1115             return 0;
1116         }
1117     } else { /* clicklook */
1118         cc.x = click_cc->x;
1119         cc.y = click_cc->y;
1120         sym = 0;
1121         from_screen = FALSE;
1122     }
1123
1124     /* Save the verbose flag, we change it later. */
1125     save_verbose = flags.verbose;
1126     flags.verbose = flags.verbose && !quick;
1127     /*
1128      * The user typed one letter, or we're identifying from the screen.
1129      */
1130     do {
1131         /* Reset some variables. */
1132         pm = (struct permonst *) 0;
1133         found = 0;
1134         out_str[0] = '\0';
1135
1136         if (from_screen || clicklook) {
1137             if (from_screen) {
1138                 if (flags.verbose)
1139 #if 0 /*JP*/
1140                     pline("Please move the cursor to %s.",
1141                           what_is_an_unknown_object);
1142 #else
1143                     pline("\83J\81[\83\\83\8b\82ð\95¨\91Ì\82É\88Ú\93®\82µ\82Ä\82­\82¾\82³\82¢\81D");
1144 #endif
1145                 else
1146 /*JP
1147                     pline("Pick an object.");
1148 */
1149                     pline("\95¨\91Ì\82ð\8ew\92è\82µ\82Ä\82­\82¾\82³\82¢\81D");
1150
1151                 ans = getpos(&cc, quick, what_is_an_unknown_object);
1152                 if (ans < 0 || cc.x < 0) {
1153                     flags.verbose = save_verbose;
1154                     return 0; /* done */
1155                 }
1156                 flags.verbose = FALSE; /* only print long question once */
1157             }
1158         }
1159
1160         found = do_screen_description(cc, (from_screen || clicklook), sym,
1161                                       out_str, &firstmatch);
1162
1163         /* Finally, print out our explanation. */
1164         if (found) {
1165             /* Used putmixed() because there may be an encoded glyph present
1166              */
1167             putmixed(WIN_MESSAGE, 0, out_str);
1168
1169             /* check the data file for information about this thing */
1170             if (found == 1 && ans != LOOK_QUICK && ans != LOOK_ONCE
1171                 && (ans == LOOK_VERBOSE || (flags.help && !quick))
1172                 && !clicklook) {
1173                 char temp_buf[BUFSZ];
1174
1175                 Strcpy(temp_buf, firstmatch);
1176                 checkfile(temp_buf, pm, FALSE,
1177                           (boolean) (ans == LOOK_VERBOSE));
1178             }
1179         } else {
1180 /*JP
1181             pline("I've never heard of such things.");
1182 */
1183             pline("\82»\82ñ\82È\96¼\91O\82Í\95·\82¢\82½\82±\82Æ\82ª\82È\82¢\81D");
1184         }
1185
1186     } while (from_screen && !quick && ans != LOOK_ONCE && !clicklook);
1187
1188     flags.verbose = save_verbose;
1189     return 0;
1190 }
1191
1192 STATIC_OVL void
1193 look_all(nearby, do_mons)
1194 boolean nearby; /* True => within BOLTLIM, False => entire map */
1195 boolean do_mons; /* True => monsters, False => objects */
1196 {
1197     winid win;
1198     int x, y, lo_x, lo_y, hi_x, hi_y, glyph, count = 0;
1199     char buf[BUFSZ], outbuf[BUFSZ], coordbuf[12], fmt[12]; /* "%02d,%02d" */
1200
1201     /* row,column orientation rather than cartesian x,y */
1202     Sprintf(fmt, "%%%sd,%%%sd",
1203             (ROWNO <= 100) ? "02" : (ROWNO <= 1000) ? "03" : "",
1204             (COLNO <= 100) ? "02" : (COLNO <= 1000) ? "03" : "");
1205
1206     win = create_nhwindow(NHW_TEXT);
1207     lo_y = nearby ? max(u.uy - BOLT_LIM, 0) : 0;
1208     lo_x = nearby ? max(u.ux - BOLT_LIM, 1) : 1;
1209     hi_y = nearby ? min(u.uy + BOLT_LIM, ROWNO - 1) : ROWNO - 1;
1210     hi_x = nearby ? min(u.ux + BOLT_LIM, COLNO - 1) : COLNO - 1;
1211     for (y = lo_y; y <= hi_y; y++) {
1212         for (x = lo_x; x <= hi_x; x++) {
1213             buf[0] = '\0';
1214             glyph = glyph_at(x, y);
1215             if (do_mons) {
1216                 if (glyph_is_monster(glyph)) {
1217                     struct monst *mtmp;
1218
1219                     bhitpos.x = x; /* [is this actually necessary?] */
1220                     bhitpos.y = y;
1221                     if (x == u.ux && y == u.uy && canspotself()) {
1222                         (void) self_lookat(buf);
1223                         ++count;
1224                     } else if ((mtmp = m_at(x, y)) != 0) {
1225                         look_at_monster(buf, (char *) 0, mtmp, x, y);
1226                         ++count;
1227                     }
1228                 } else if (glyph_is_invisible(glyph)) {
1229                     /* remembered, unseen, creature */
1230                     Strcpy(buf, invisexplain);
1231                     ++count;
1232                 } else if (glyph_is_warning(glyph)) {
1233                     int warnindx = glyph_to_warning(glyph);
1234
1235                     Strcpy(buf, def_warnsyms[warnindx].explanation);
1236                     ++count;
1237                 }
1238             } else { /* !do_mons */
1239                 if (glyph_is_object(glyph)) {
1240                     look_at_object(buf, x, y, glyph);
1241                     ++count;
1242                 }
1243             }
1244             if (*buf) {
1245                 if (count == 1) {
1246                     char which[12];
1247
1248                     Strcpy(which, do_mons ? "monsters" : "objects");
1249                     if (nearby) {
1250                         Sprintf(coordbuf, fmt, u.uy, u.ux);
1251                         Sprintf(outbuf, "%s currently shown near %s:",
1252                                 upstart(which), coordbuf);
1253                     } else
1254                         Sprintf(outbuf, "All %s currently shown on the map:",
1255                                 which);
1256                     putstr(win, 0, outbuf);
1257                     putstr(win, 0, "");
1258                 }
1259                 Sprintf(coordbuf, fmt, y, x);
1260                 /* prefix: "C  row,column  " */
1261                 Sprintf(outbuf, "%s  %s  ", encglyph(glyph), coordbuf);
1262                 /* guard against potential overflow */
1263                 buf[sizeof buf - 1 - strlen(outbuf)] = '\0';
1264                 Strcat(outbuf, buf);
1265                 putmixed(win, 0, outbuf);
1266             }
1267         }
1268     }
1269     if (count)
1270         display_nhwindow(win, TRUE);
1271     else
1272 #if 0 /*JP*/
1273         pline("No %s are currently shown %s.",
1274               do_mons ? "monsters" : "objects",
1275               nearby ? "nearby" : "on the map");
1276 #else
1277         pline("\8d¡\82Ì\82Æ\82±\82ë%s\82É%s\81D",
1278               nearby ? "\8bß\82­" : "\92n\90}\8fã",
1279               do_mons ? "\89ö\95¨\82Í\82¢\82È\82¢" : "\82à\82Ì\82Í\82È\82¢");
1280 #endif
1281     destroy_nhwindow(win);
1282 }
1283
1284 /* the '/' command */
1285 int
1286 dowhatis()
1287 {
1288     return do_look(0, (coord *) 0);
1289 }
1290
1291 /* the ';' command */
1292 int
1293 doquickwhatis()
1294 {
1295     return do_look(1, (coord *) 0);
1296 }
1297
1298 /* the '^' command */
1299 int
1300 doidtrap()
1301 {
1302     register struct trap *trap;
1303     int x, y, tt;
1304
1305     if (!getdir("^"))
1306         return 0;
1307     x = u.ux + u.dx;
1308     y = u.uy + u.dy;
1309     for (trap = ftrap; trap; trap = trap->ntrap)
1310         if (trap->tx == x && trap->ty == y) {
1311             if (!trap->tseen)
1312                 break;
1313             tt = trap->ttyp;
1314             if (u.dz) {
1315                 if (u.dz < 0 ? (tt == TRAPDOOR || tt == HOLE)
1316                              : tt == ROCKTRAP)
1317                     break;
1318             }
1319             tt = what_trap(tt);
1320 #if 0 /*JP*/
1321             pline("That is %s%s%s.",
1322                   an(defsyms[trap_to_defsym(tt)].explanation),
1323                   !trap->madeby_u
1324                      ? ""
1325                      : (tt == WEB)
1326                         ? " woven"
1327                         /* trap doors & spiked pits can't be made by
1328                            player, and should be considered at least
1329                            as much "set" as "dug" anyway */
1330                         : (tt == HOLE || tt == PIT)
1331                            ? " dug"
1332                            : " set",
1333                   !trap->madeby_u ? "" : " by you");
1334 #else
1335             pline("\82»\82ê\82Í%s%s\82¾\81D",
1336                   !trap->madeby_u
1337                      ? ""
1338                      : (tt == WEB)
1339                         ? "\82 \82È\82½\82ª\92£\82Á\82½"
1340                         : (tt == HOLE || tt == PIT)
1341                            ? "\82 \82È\82½\82ª\8c@\82Á\82½"
1342                            : "\82 \82È\82½\82ª\8ed\8a|\82¯\82½",
1343                   defsyms[trap_to_defsym(tt)].explanation);
1344 #endif
1345             return 0;
1346         }
1347 /*JP
1348     pline("I can't see a trap there.");
1349 */
1350     pline("\82»\82±\82É\82Íã©\82Í\82Ý\82 \82½\82ç\82È\82¢\81D");
1351     return 0;
1352 }
1353
1354 char *
1355 dowhatdoes_core(q, cbuf)
1356 char q;
1357 char *cbuf;
1358 {
1359     dlb *fp;
1360     char bufr[BUFSZ];
1361     register char *buf = &bufr[6], *ep, ctrl, meta;
1362
1363     fp = dlb_fopen(CMDHELPFILE, "r");
1364     if (!fp) {
1365 #if 0 /*JP*/
1366         pline("Cannot open data file!");
1367 #else
1368         pline("\83f\81[\83^\83t\83@\83C\83\8b\82ð\8aJ\82¯\82È\82¢\81I");
1369 #endif
1370         return 0;
1371     }
1372
1373     ctrl = ((q <= '\033') ? (q - 1 + 'A') : 0);
1374     meta = ((0x80 & q) ? (0x7f & q) : 0);
1375     while (dlb_fgets(buf, BUFSZ - 6, fp)) {
1376         if ((ctrl && *buf == '^' && *(buf + 1) == ctrl)
1377             || (meta && *buf == 'M' && *(buf + 1) == '-'
1378                 && *(buf + 2) == meta) || *buf == q) {
1379             ep = index(buf, '\n');
1380             if (ep)
1381                 *ep = 0;
1382             if (ctrl && buf[2] == '\t') {
1383                 buf = bufr + 1;
1384                 (void) strncpy(buf, "^?      ", 8);
1385                 buf[1] = ctrl;
1386             } else if (meta && buf[3] == '\t') {
1387                 buf = bufr + 2;
1388                 (void) strncpy(buf, "M-?     ", 8);
1389                 buf[2] = meta;
1390             } else if (buf[1] == '\t') {
1391                 buf = bufr;
1392                 buf[0] = q;
1393                 (void) strncpy(buf + 1, "       ", 7);
1394             }
1395             (void) dlb_fclose(fp);
1396             Strcpy(cbuf, buf);
1397             return cbuf;
1398         }
1399     }
1400     (void) dlb_fclose(fp);
1401     return (char *) 0;
1402 }
1403
1404 int
1405 dowhatdoes()
1406 {
1407     char bufr[BUFSZ];
1408     char q, *reslt;
1409
1410 #if defined(UNIX) || defined(VMS)
1411     introff();
1412 #endif
1413 /*JP
1414     q = yn_function("What command?", (char *) 0, '\0');
1415 */
1416     q = yn_function("\82Ç\82¤\82¢\82¤\83R\83}\83\93\83h\81H", (char *) 0, '\0');
1417 #if defined(UNIX) || defined(VMS)
1418     intron();
1419 #endif
1420     reslt = dowhatdoes_core(q, bufr);
1421     if (reslt)
1422         pline1(reslt);
1423     else
1424 /*JP
1425         pline("I've never heard of such commands.");
1426 */
1427         pline("\82»\82ñ\82È\83R\83}\83\93\83h\82Í\95·\82¢\82½\82±\82Æ\82ª\82È\82¢\81D");
1428     return 0;
1429 }
1430
1431 void
1432 docontact()
1433 {
1434     winid cwin = create_nhwindow(NHW_TEXT);
1435     char buf[BUFSZ];
1436
1437     if (sysopt.support) {
1438         /*XXX overflow possibilities*/
1439         Sprintf(buf, "To contact local support, %s", sysopt.support);
1440         putstr(cwin, 0, buf);
1441         putstr(cwin, 0, "");
1442     } else if (sysopt.fmtd_wizard_list) { /* formatted SYSCF WIZARDS */
1443         Sprintf(buf, "To contact local support, contact %s.",
1444                 sysopt.fmtd_wizard_list);
1445         putstr(cwin, 0, buf);
1446         putstr(cwin, 0, "");
1447     }
1448     putstr(cwin, 0, "To contact the NetHack development team directly,");
1449     /*XXX overflow possibilities*/
1450     Sprintf(buf, "see the 'Contact' form on our website or email <%s>.",
1451             DEVTEAM_EMAIL);
1452     putstr(cwin, 0, buf);
1453     putstr(cwin, 0, "");
1454     putstr(cwin, 0, "For more information on NetHack, or to report a bug,");
1455     Sprintf(buf, "visit our website \"%s\".", DEVTEAM_URL);
1456     putstr(cwin, 0, buf);
1457     display_nhwindow(cwin, FALSE);
1458     destroy_nhwindow(cwin);
1459 }
1460
1461 /* data for help_menu() */
1462 static const char *help_menu_items[] = {
1463 #if 0 /*JP*/
1464     /*  0*/ "About NetHack (version information).",
1465     /*  1*/ "Long description of the game and commands.",
1466     /*  2*/ "List of game commands.",
1467     /*  3*/ "Concise history of NetHack.",
1468     /*  4*/ "Info on a character in the game display.",
1469     /*  5*/ "Info on what a given key does.",
1470     /*  6*/ "List of game options.",
1471     /*  7*/ "Longer explanation of game options.",
1472     /*  8*/ "List of extended commands.",
1473     /*  9*/ "The NetHack license.",
1474     /* 10*/ "Support information.",
1475 #ifdef PORT_HELP
1476     "%s-specific help and commands.",
1477 #define PORT_HELP_ID 100
1478 #define WIZHLP_SLOT 12
1479 #else
1480 #define WIZHLP_SLOT 11
1481 #endif
1482     "List of wizard-mode commands.", "", (char *) 0
1483 #else /*JP*/
1484     /*  0*/ "NetHack\82É\82Â\82¢\82Ä(\83o\81[\83W\83\87\83\93\8fî\95ñ)",
1485     /*  1*/ "\83Q\81[\83\80\82¨\82æ\82Ñ\83R\83}\83\93\83h\82Ì\89ð\90à(\92·\95¶)",
1486     /*  2*/ "\83R\83}\83\93\83h\88ê\97\97",
1487     /*  3*/ "NetHack\82Ì\8aÈ\92P\82È\97ð\8ej",
1488     /*  4*/ "\89æ\96Ê\82É\95\\8e¦\82³\82ê\82é\95\8e\9a\82Ì\90à\96¾",
1489     /*  5*/ "\82±\82Ì\83L\81[\82ª\89½\82ð\88Ó\96¡\82·\82é\82©\82Ì\90à\96¾",
1490     /*  6*/ "\83Q\81[\83\80\82Ì\83I\83v\83V\83\87\83\93\88ê\97\97",
1491     /*  7*/ "\83Q\81[\83\80\82Ì\83I\83v\83V\83\87\83\93\88ê\97\97(\92·\95¶)",
1492     /*  8*/ "\8ag\92£\83R\83}\83\93\83h\88ê\97\97",
1493     /*  9*/ "NetHack\82Ì\83\89\83C\83Z\83\93\83X",
1494     /* 10*/ "\83T\83|\81[\83g\8fî\95ñ",
1495 #ifdef PORT_HELP
1496     "%s\82É\93Á\97L\82Ì\83w\83\8b\83v\82¨\82æ\82Ñ\83R\83}\83\93\83h",
1497 #define PORT_HELP_ID 100
1498 #define WIZHLP_SLOT 12
1499 #else
1500 #define WIZHLP_SLOT 11
1501 #endif
1502     "\83E\83B\83U\81[\83h\83\82\81[\83h\82Ì\83R\83}\83\93\83h\88ê\97\97", "", (char *) 0
1503 #endif /*JP*/
1504 };
1505
1506 STATIC_OVL boolean
1507 help_menu(sel)
1508 int *sel;
1509 {
1510     winid tmpwin = create_nhwindow(NHW_MENU);
1511 #ifdef PORT_HELP
1512     char helpbuf[QBUFSZ];
1513 #endif
1514     int i, n;
1515     menu_item *selected;
1516     anything any;
1517
1518     any = zeroany; /* zero all bits */
1519     start_menu(tmpwin);
1520     if (!wizard)
1521         help_menu_items[WIZHLP_SLOT] = "",
1522         help_menu_items[WIZHLP_SLOT + 1] = (char *) 0;
1523     for (i = 0; help_menu_items[i]; i++)
1524 #ifdef PORT_HELP
1525         /* port-specific line has a %s in it for the PORT_ID */
1526         if (help_menu_items[i][0] == '%') {
1527             Sprintf(helpbuf, help_menu_items[i], PORT_ID);
1528             any.a_int = PORT_HELP_ID + 1;
1529             add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, helpbuf,
1530                      MENU_UNSELECTED);
1531         } else
1532 #endif
1533         {
1534             any.a_int = (*help_menu_items[i]) ? i + 1 : 0;
1535             add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
1536                      help_menu_items[i], MENU_UNSELECTED);
1537         }
1538 /*JP
1539     end_menu(tmpwin, "Select one item:");
1540 */
1541     end_menu(tmpwin, "\91I\82ñ\82Å\82­\82¾\82³\82¢\81F");
1542     n = select_menu(tmpwin, PICK_ONE, &selected);
1543     destroy_nhwindow(tmpwin);
1544     if (n > 0) {
1545         *sel = selected[0].item.a_int - 1;
1546         free((genericptr_t) selected);
1547         return TRUE;
1548     }
1549     return FALSE;
1550 }
1551
1552 /* the '?' command */
1553 int
1554 dohelp()
1555 {
1556     int sel = 0;
1557
1558     if (help_menu(&sel)) {
1559         switch (sel) {
1560         case 0:
1561             (void) doextversion();
1562             break;
1563         case 1:
1564             display_file(HELP, TRUE);
1565             break;
1566         case 2:
1567             display_file(SHELP, TRUE);
1568             break;
1569         case 3:
1570             (void) dohistory();
1571             break;
1572         case 4:
1573             (void) dowhatis();
1574             break;
1575         case 5:
1576             (void) dowhatdoes();
1577             break;
1578         case 6:
1579             option_help();
1580             break;
1581         case 7:
1582             display_file(OPTIONFILE, TRUE);
1583             break;
1584         case 8:
1585             (void) doextlist();
1586             break;
1587         case 9:
1588             display_file(LICENSE, TRUE);
1589             break;
1590         case 10:
1591             (void) docontact();
1592             break;
1593 #ifdef PORT_HELP
1594         case PORT_HELP_ID:
1595             port_help();
1596             break;
1597 #endif
1598         default:
1599             /* handle slot 11 or 12 */
1600             display_file(DEBUGHELP, TRUE);
1601             break;
1602         }
1603     }
1604     return 0;
1605 }
1606
1607 /* the 'V' command; also a choice for '?' */
1608 int
1609 dohistory()
1610 {
1611     display_file(HISTORY, TRUE);
1612     return 0;
1613 }
1614
1615 /*pager.c*/