OSDN Git Service

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