OSDN Git Service

#37449 (2.2.0.56) 日記にWIZ/ARTIFACT_INFO出力を実装。 / Implement diary to WIZ/ARTIFACT_INFO.
[hengband/hengband.git] / src / cmd4.c
1 /*!
2  * @file cmd4.c
3  * @brief プレイヤーのインターフェイスに関するコマンドの実装 / Interface commands
4  * @date 2014/01/02
5  * @author
6  * <pre>
7  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
8  * This software may be copied and distributed for educational, research,
9  * and not for profit purposes provided that this copyright and statement
10  * are included in all such copies.  Other copyrights may also apply.
11  * </pre>
12  * @details
13  * <pre>
14  * A set of functions to maintain automatic dumps of various kinds.
15  * -Mogami-
16  * remove_auto_dump(orig_file, mark)
17  *     Remove the old automatic dump of type "mark".
18  * auto_dump_printf(fmt, ...)
19  *     Dump a formatted string using fprintf().
20  * open_auto_dump(buf, mark)
21  *     Open a file, remove old dump, and add new header.
22  * close_auto_dump(void)
23  *     Add a footer, and close the file.
24  *    The dump commands of original Angband simply add new lines to
25  * existing files; these files will become bigger and bigger unless
26  * an user deletes some or all of these files by hand at some
27  * point.
28  *     These three functions automatically delete old dumped lines 
29  * before adding new ones.  Since there are various kinds of automatic 
30  * dumps in a single file, we add a header and a footer with a type 
31  * name for every automatic dump, and kill old lines only when the 
32  * lines have the correct type of header and footer.
33  *     We need to be quite paranoid about correctness; the user might 
34  * (mistakenly) edit the file by hand, and see all their work come
35  * to nothing on the next auto dump otherwise.  The current code only 
36  * detects changes by noting inconsistencies between the actual number 
37  * of lines and the number written in the footer.  Note that this will 
38  * not catch single-line edits.
39  * </pre>
40  */
41
42 #include "angband.h"
43
44
45
46 /*
47  */
48
49 /*
50  *  Mark strings for auto dump
51  */
52 static char auto_dump_header[] = "# vvvvvvv== %s ==vvvvvvv";
53 static char auto_dump_footer[] = "# ^^^^^^^== %s ==^^^^^^^";
54
55 /*
56  * Variables for auto dump
57  */
58 static FILE *auto_dump_stream;
59 static cptr auto_dump_mark;
60 static int auto_dump_line_num;
61
62
63 /*!
64  * @brief prf出力内容を消去する /
65  * Remove old lines automatically generated before.
66  * @param orig_file 消去を行うファイル名
67  */
68 static void remove_auto_dump(cptr orig_file)
69 {
70         FILE *tmp_fff, *orig_fff;
71
72         char tmp_file[1024];
73         char buf[1024];
74         bool between_mark = FALSE;
75         bool changed = FALSE;
76         int line_num = 0;
77         long header_location = 0;
78         char header_mark_str[80];
79         char footer_mark_str[80];
80         size_t mark_len;
81
82         /* Prepare a header/footer mark string */
83         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
84         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
85
86         mark_len = strlen(footer_mark_str);
87
88         /* Open an old dump file in read-only mode */
89         orig_fff = my_fopen(orig_file, "r");
90
91         /* If original file does not exist, nothing to do */
92         if (!orig_fff) return;
93
94         /* Open a new (temporary) file */
95         tmp_fff = my_fopen_temp(tmp_file, 1024);
96
97         if (!tmp_fff)
98         {
99             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
100             msg_print(NULL);
101             return;
102         }
103
104         /* Loop for every line */
105         while (TRUE)
106         {
107                 /* Read a line */
108                 if (my_fgets(orig_fff, buf, sizeof(buf)))
109                 {
110                         /* Read error: Assume End of File */
111
112                         /*
113                          * Was looking for the footer, but not found.
114                          *
115                          * Since automatic dump might be edited by hand,
116                          * it's dangerous to kill these lines.
117                          * Seek back to the next line of the (pseudo) header,
118                          * and read again.
119                          */
120                         if (between_mark)
121                         {
122                                 fseek(orig_fff, header_location, SEEK_SET);
123                                 between_mark = FALSE;
124                                 continue;
125                         }
126
127                         /* Success -- End the loop */
128                         else
129                         {
130                                 break;
131                         }
132                 }
133
134                 /* We are looking for the header mark of automatic dump */
135                 if (!between_mark)
136                 {
137                         /* Is this line a header? */
138                         if (!strcmp(buf, header_mark_str))
139                         {
140                                 /* Memorise seek point of this line */
141                                 header_location = ftell(orig_fff);
142
143                                 /* Initialize counter for number of lines */
144                                 line_num = 0;
145
146                                 /* Look for the footer from now */
147                                 between_mark = TRUE;
148
149                                 /* There are some changes */
150                                 changed = TRUE;
151                         }
152
153                         /* Not a header */
154                         else
155                         {
156                                 /* Copy orginally lines */
157                                 fprintf(tmp_fff, "%s\n", buf);
158                         }
159                 }
160
161                 /* We are looking for the footer mark of automatic dump */
162                 else
163                 {
164                         /* Is this line a footer? */
165                         if (!strncmp(buf, footer_mark_str, mark_len))
166                         {
167                                 int tmp;
168
169                                 /*
170                                  * Compare the number of lines
171                                  *
172                                  * If there is an inconsistency between
173                                  * actual number of lines and the
174                                  * number here, the automatic dump
175                                  * might be edited by hand.  So it's
176                                  * dangerous to kill these lines.
177                                  * Seek back to the next line of the
178                                  * (pseudo) header, and read again.
179                                  */
180                                 if (!sscanf(buf + mark_len, " (%d)", &tmp)
181                                     || tmp != line_num)
182                                 {
183                                         fseek(orig_fff, header_location, SEEK_SET);
184                                 }
185
186                                 /* Look for another header */
187                                 between_mark = FALSE;
188                         }
189
190                         /* Not a footer */
191                         else
192                         {
193                                 /* Ignore old line, and count number of lines */
194                                 line_num++;
195                         }
196                 }
197         }
198
199         /* Close files */
200         my_fclose(orig_fff);
201         my_fclose(tmp_fff);
202
203         /* If there are some changes, overwrite the original file with new one */
204         if (changed)
205         {
206                 /* Copy contents of temporary file */
207
208                 tmp_fff = my_fopen(tmp_file, "r");
209                 orig_fff = my_fopen(orig_file, "w");
210
211                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
212                         fprintf(orig_fff, "%s\n", buf);
213
214                 my_fclose(orig_fff);
215                 my_fclose(tmp_fff);
216         }
217
218         /* Kill the temporary file */
219         fd_kill(tmp_file);
220
221         return;
222 }
223
224
225 /*!
226  * @brief prfファイルのフォーマットに従った内容を出力する /
227  * Dump a formatted line, using "vstrnfmt()".
228  * @param fmt 出力内容
229  */
230 static void auto_dump_printf(cptr fmt, ...)
231 {
232         cptr p;
233         va_list vp;
234
235         char buf[1024];
236
237         /* Begin the Varargs Stuff */
238         va_start(vp, fmt);
239
240         /* Format the args, save the length */
241         (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
242
243         /* End the Varargs Stuff */
244         va_end(vp);
245
246         /* Count number of lines */
247         for (p = buf; *p; p++)
248         {
249                 if (*p == '\n') auto_dump_line_num++;
250         }
251
252         /* Dump it */
253         fprintf(auto_dump_stream, "%s", buf);
254 }
255
256
257 /*!
258  * @brief prfファイルをファイルオープンする /
259  * Open file to append auto dump.
260  * @param buf ファイル名
261  * @param mark 出力するヘッダマーク
262  * @return ファイルポインタを取得できたらTRUEを返す
263  */
264 static bool open_auto_dump(cptr buf, cptr mark)
265 {
266
267         char header_mark_str[80];
268
269         /* Save the mark string */
270         auto_dump_mark = mark;
271
272         /* Prepare a header mark string */
273         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
274
275         /* Remove old macro dumps */
276         remove_auto_dump(buf);
277
278         /* Append to the file */
279         auto_dump_stream = my_fopen(buf, "a");
280
281         /* Failure */
282         if (!auto_dump_stream) {
283                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
284                 msg_print(NULL);
285
286                 /* Failed */
287                 return FALSE;
288         }
289
290         /* Start dumping */
291         fprintf(auto_dump_stream, "%s\n", header_mark_str);
292
293         /* Initialize counter */
294         auto_dump_line_num = 0;
295
296         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
297                                            "# *Warning!*  The lines below are an automatic dump.\n"));
298         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n", 
299                                            "# Don't edit them; changes will be deleted and replaced automatically.\n"));
300         /* Success */
301         return TRUE;
302 }
303
304 /*!
305  * @brief prfファイルをファイルクローズする /
306  * Append foot part and close auto dump.
307  * @return なし
308  */
309 static void close_auto_dump(void)
310 {
311         char footer_mark_str[80];
312
313         /* Prepare a footer mark string */
314         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
315
316         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
317                                            "# *Warning!*  The lines below are an automatic dump.\n"));
318         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n", 
319                                            "# Don't edit them; changes will be deleted and replaced automatically.\n"));
320         /* End of dump */
321         fprintf(auto_dump_stream, "%s (%d)\n", footer_mark_str, auto_dump_line_num);
322
323         /* Close */
324         my_fclose(auto_dump_stream);
325
326         return;
327 }
328
329
330 #ifndef JP
331
332 /*!
333  * @brief Return suffix of ordinal number
334  * @param num number
335  * @return pointer of suffix string.
336  */
337 cptr get_ordinal_number_suffix(int num)
338 {
339         num = ABS(num) % 100;
340         switch (num % 10)
341         {
342         case 1:
343                 return (num == 11) ? "th" : "st";
344         case 2:
345                 return (num == 12) ? "th" : "nd";
346         case 3:
347                 return (num == 13) ? "th" : "rd";
348         default:
349                 return "th";
350         }
351 }
352 #endif
353
354
355 /*!
356  * @brief 日記にメッセージを追加する /
357  * Take note to the diary.
358  * @param type 日記内容のID
359  * @param num 日記内容のIDに応じた数値
360  * @param note 日記内容のIDに応じた文字列参照ポインタ
361  * @return エラーID
362  */
363 errr do_cmd_write_nikki(int type, int num, cptr note)
364 {
365         int day, hour, min;
366         FILE *fff = NULL;
367         char file_name[80];
368         char buf[1024];
369         cptr note_level = "";
370         bool do_level = TRUE;
371         char note_level_buf[40];
372         int q_idx;
373
374         static bool disable_nikki = FALSE;
375
376         extract_day_hour_min(&day, &hour, &min);
377
378         if (disable_nikki) return(-1);
379
380         if (type == NIKKI_FIX_QUEST_C ||
381             type == NIKKI_FIX_QUEST_F ||
382             type == NIKKI_RAND_QUEST_C ||
383             type == NIKKI_RAND_QUEST_F ||
384             type == NIKKI_TO_QUEST)
385         {
386                 int old_quest;
387
388                 old_quest = p_ptr->inside_quest;
389                 p_ptr->inside_quest = (quest[num].type == QUEST_TYPE_RANDOM) ? 0 : num;
390
391                 /* Get the quest text */
392                 init_flags = INIT_NAME_ONLY;
393
394                 process_dungeon_file("q_info.txt", 0, 0, 0, 0);
395
396                 /* Reset the old quest number */
397                 p_ptr->inside_quest = old_quest;
398         }
399
400         /* different filne name to avoid mixing */
401         sprintf(file_name,_("playrecord-%s.txt", "playrec-%s.txt"),savefile_base);
402
403         /* Build the filename */
404         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
405
406         /* File type is "TEXT" */
407         FILE_TYPE(FILE_TYPE_TEXT);
408
409         fff = my_fopen(buf, "a");
410
411         /* Failure */
412         if (!fff)
413         {
414                 msg_format(_("%s を開くことができませんでした。プレイ記録を一時停止します。", "Failed to open %s. Play-Record is disabled temporally."), buf);
415                 msg_format(NULL);
416                 disable_nikki=TRUE;
417                 return (-1);
418         }
419
420         q_idx = quest_number(dun_level);
421
422         if (write_level)
423         {
424                 if (p_ptr->inside_arena)
425                         note_level = _("アリーナ:", "Arane:");
426                 else if (!dun_level)
427                         note_level = _("地上:", "Surface:");
428                 else if (q_idx && (is_fixed_quest_idx(q_idx)
429                          && !((q_idx == QUEST_OBERON) || (q_idx == QUEST_SERPENT))))
430                         note_level = _("クエスト:", "Quest:");
431                 else
432                 {
433 #ifdef JP
434                         sprintf(note_level_buf, "%d階(%s):", dun_level, d_name+d_info[dungeon_type].name);
435 #else
436                         sprintf(note_level_buf, "%s L%d:", d_name+d_info[dungeon_type].name, dun_level);
437 #endif
438                         note_level = note_level_buf;
439                 }
440         }
441
442         switch(type)
443         {
444                 case NIKKI_HIGAWARI:
445                 {
446                         if (day < MAX_DAYS) fprintf(fff, _("%d日目\n", "Day %d\n"), day);
447                         else fputs(_("*****日目\n", "Day *****\n"), fff);
448                         do_level = FALSE;
449                         break;
450                 }
451                 case NIKKI_BUNSHOU:
452                 {
453                         if (num)
454                         {
455                                 fprintf(fff, "%s\n",note);
456                                 do_level = FALSE;
457                         }
458                         else
459                                 fprintf(fff, " %2d:%02d %20s %s\n",hour, min, note_level, note);
460                         break;
461                 }
462                 case NIKKI_ART:
463                 {
464                         fprintf(fff, _(" %2d:%02d %20s %sを発見した。\n", " %2d:%02d %20s discovered %s.\n"), hour, min, note_level, note);
465                         break;
466                 }
467                 case NIKKI_ART_SCROLL:
468                 {
469                         fprintf(fff, _(" %2d:%02d %20s 巻物によって%sを生成した。\n", " %2d:%02d %20s created %s by scroll.\n"), hour, min, note_level, note);
470                         break;
471                 }
472                 case NIKKI_UNIQUE:
473                 {
474                         fprintf(fff, _(" %2d:%02d %20s %sを倒した。\n", " %2d:%02d %20s defeated %s.\n"), hour, min, note_level, note);
475                         break;
476                 }
477                 case NIKKI_FIX_QUEST_C:
478                 {
479                         if (quest[num].flags & QUEST_FLAG_SILENT) break;
480                         fprintf(fff, _(" %2d:%02d %20s クエスト「%s」を達成した。\n",
481                                                    " %2d:%02d %20s completed quest '%s'.\n"), hour, min, note_level, quest[num].name);
482                         break;
483                 }
484                 case NIKKI_FIX_QUEST_F:
485                 {
486                         if (quest[num].flags & QUEST_FLAG_SILENT) break;
487                         fprintf(fff, _(" %2d:%02d %20s クエスト「%s」から命からがら逃げ帰った。\n",
488                                                    " %2d:%02d %20s run away from quest '%s'.\n"), hour, min, note_level, quest[num].name);
489                         break;
490                 }
491                 case NIKKI_RAND_QUEST_C:
492                 {
493                         char name[80];
494                         strcpy(name, r_name+r_info[quest[num].r_idx].name);
495                         fprintf(fff, _(" %2d:%02d %20s ランダムクエスト(%s)を達成した。\n",
496                                                    " %2d:%02d %20s completed random quest '%s'\n"), hour, min, note_level, name);
497                         break;
498                 }
499                 case NIKKI_RAND_QUEST_F:
500                 {
501                         char name[80];
502                         strcpy(name, r_name+r_info[quest[num].r_idx].name);
503                         fprintf(fff, _(" %2d:%02d %20s ランダムクエスト(%s)から逃げ出した。\n",
504                                                    " %2d:%02d %20s ran away from quest '%s'.\n"), hour, min, note_level, name);
505                         break;
506                 }
507                 case NIKKI_MAXDEAPTH:
508                 {
509                         fprintf(fff, _(" %2d:%02d %20s %sの最深階%d階に到達した。\n",
510                                                    " %2d:%02d %20s reached level %d of %s for the first time.\n"), hour, min, note_level,
511                                                    _(d_name+d_info[dungeon_type].name, num),
512                                                    _(num, d_name+d_info[dungeon_type].name));
513                         break;
514                 }
515                 case NIKKI_TRUMP:
516                 {
517                         fprintf(fff, _(" %2d:%02d %20s %s%sの最深階を%d階にセットした。\n",
518                                                    " %2d:%02d %20s reset recall level of %s to %d %s.\n"), hour, min, note_level, note,
519                                                    _(d_name + d_info[num].name, max_dlv[num]),
520                                                    _(max_dlv[num], d_name + d_info[num].name));
521                         break;
522                 }
523                 case NIKKI_STAIR:
524                 {
525                         cptr to;
526                         if (q_idx && (is_fixed_quest_idx(q_idx)
527                              && !((q_idx == QUEST_OBERON) || (q_idx == QUEST_SERPENT))))
528                         {
529                                 to = _("地上", "the surface");
530                         }
531                         else
532                         {
533                                 if (!(dun_level+num)) to = _("地上", "the surface");
534                                 else to = format(_("%d階", "level %d"), dun_level+num);
535                         }
536                         fprintf(fff, _(" %2d:%02d %20s %sへ%s。\n", " %2d:%02d %20s %s %s.\n"), hour, min, note_level, _(to, note), _(note, to));
537                         break;
538                 }
539                 case NIKKI_RECALL:
540                 {
541                         if (!num)
542                         fprintf(fff, _(" %2d:%02d %20s 帰還を使って%sの%d階へ下りた。\n", " %2d:%02d %20s recalled to dungeon level %d of %s.\n"), 
543                                                 hour, min, note_level, _(d_name+d_info[dungeon_type].name, max_dlv[dungeon_type]), 
544                                                                                            _(max_dlv[dungeon_type], d_name+d_info[dungeon_type].name));
545                         else
546                                 fprintf(fff, _(" %2d:%02d %20s 帰還を使って地上へと戻った。\n", " %2d:%02d %20s recalled from dungeon to surface.\n"), hour, min, note_level);
547                         break;
548                 }
549                 case NIKKI_TO_QUEST:
550                 {
551                         if (quest[num].flags & QUEST_FLAG_SILENT) break;
552                         fprintf(fff, _(" %2d:%02d %20s クエスト「%s」へと突入した。\n", " %2d:%02d %20s entered the quest '%s'.\n"),
553                                                 hour, min, note_level, quest[num].name);
554                         break;
555                 }
556                 case NIKKI_TELE_LEV:
557                 {
558                         fprintf(fff, _(" %2d:%02d %20s レベル・テレポートで脱出した。\n", " %2d:%02d %20s Got out using teleport level.\n"),
559                                                 hour, min, note_level);
560                         break;
561                 }
562                 case NIKKI_BUY:
563                 {
564                         fprintf(fff, _(" %2d:%02d %20s %sを購入した。\n", " %2d:%02d %20s bought %s.\n"), hour, min, note_level, note);
565                         break;
566                 }
567                 case NIKKI_SELL:
568                 {
569                         fprintf(fff, _(" %2d:%02d %20s %sを売却した。\n", " %2d:%02d %20s sold %s.\n"), hour, min, note_level, note);
570                         break;
571                 }
572                 case NIKKI_ARENA:
573                 {
574                         if (num < 0)
575                         {
576                                 int n = -num;
577                                 fprintf(fff, _(" %2d:%02d %20s 闘技場の%d%s回戦で、%sの前に敗れ去った。\n", " %2d:%02d %20s beaten by %s in the %d%s fight.\n"),
578                                                         hour, min, note_level, _(n, note), _("", n), _(note, get_ordinal_number_suffix(n)));
579                                 break;
580                         }
581                         fprintf(fff, _(" %2d:%02d %20s 闘技場の%d%s回戦(%s)に勝利した。\n", " %2d:%02d %20s won the %d%s fight (%s).\n"),
582                                                 hour, min, note_level, num, _("", get_ordinal_number_suffix(num)), note);
583                         
584                         if (num == MAX_ARENA_MONS)
585                         {
586                                 fprintf(fff, _("                 闘技場のすべての敵に勝利し、チャンピオンとなった。\n",
587                                                            "                 won all fight to become a Chanpion.\n"));
588                                 do_level = FALSE;
589                         }
590                         break;
591                 }
592                 case NIKKI_HANMEI:
593                 {
594                         fprintf(fff, _(" %2d:%02d %20s %sを識別した。\n", " %2d:%02d %20s identified %s.\n"), hour, min, note_level, note);
595                         break;
596                 }
597                 case NIKKI_WIZ_TELE:
598                 {
599                         cptr to;
600                         if (!dun_level)
601                                 to = _("地上", "the surface");
602                         else
603                                 to = format(_("%d階(%s)", "level %d of %s"), dun_level, d_name+d_info[dungeon_type].name);
604
605                         fprintf(fff, _(" %2d:%02d %20s %sへとウィザード・テレポートで移動した。\n",
606                                                    " %2d:%02d %20s wizard-teleport to %s.\n"), hour, min, note_level, to);
607                         break;
608                 }
609                 case NIKKI_PAT_TELE:
610                 {
611                         cptr to;
612                         if (!dun_level)
613                                 to = _("地上", "the surface");
614                         else
615                                 to = format(_("%d階(%s)", "level %d of %s"), dun_level, d_name+d_info[dungeon_type].name);
616
617                         fprintf(fff, _(" %2d:%02d %20s %sへとパターンの力で移動した。\n",
618                                                    " %2d:%02d %20s used Pattern to teleport to %s.\n"), hour, min, note_level, to);
619                         break;
620                 }
621                 case NIKKI_LEVELUP:
622                 {
623                         fprintf(fff, _(" %2d:%02d %20s レベルが%dに上がった。\n", " %2d:%02d %20s reached player level %d.\n"), hour, min, note_level, num);
624                         break;
625                 }
626                 case NIKKI_GAMESTART:
627                 {
628                         time_t ct = time((time_t*)0);
629                         do_level = FALSE;
630                         if (num)
631                         {
632                                 fprintf(fff, "%s %s",note, ctime(&ct));
633                         }
634                         else
635                                 fprintf(fff, " %2d:%02d %20s %s %s",hour, min, note_level, note, ctime(&ct));
636                         break;
637                 }
638                 case NIKKI_NAMED_PET:
639                 {
640                         fprintf(fff, " %2d:%02d %20s ", hour, min, note_level);
641                         switch (num)
642                         {
643                                 case RECORD_NAMED_PET_NAME:
644                                         fprintf(fff, _("%sを旅の友にすることに決めた。\n", "decided to travel together with %s.\n"), note);
645                                         break;
646                                 case RECORD_NAMED_PET_UNNAME:
647                                         fprintf(fff, _("%sの名前を消した。\n", "unnamed %s.\n"), note);
648                                         break;
649                                 case RECORD_NAMED_PET_DISMISS:
650                                         fprintf(fff, _("%sを解放した。\n", "dismissed %s.\n"), note);
651                                         break;
652                                 case RECORD_NAMED_PET_DEATH:
653                                         fprintf(fff, _("%sが死んでしまった。\n", "%s died.\n"), note);
654                                         break;
655                                 case RECORD_NAMED_PET_MOVED:
656                                         fprintf(fff, _("%sをおいて別のマップへ移動した。\n", "moved to another map leaving %s behind.\n"), note);
657                                         break;
658                                 case RECORD_NAMED_PET_LOST_SIGHT:
659                                         fprintf(fff, _("%sとはぐれてしまった。\n", "lost sight of %s.\n"), note);
660                                         break;
661                                 case RECORD_NAMED_PET_DESTROY:
662                                         fprintf(fff, _("%sが*破壊*によって消え去った。\n", "%s was made disappeared by *destruction*.\n"), note);
663                                         break;
664                                 case RECORD_NAMED_PET_EARTHQUAKE:
665                                         fprintf(fff, _("%sが岩石に押し潰された。\n", "%s was crushed by falling rocks.\n"), note);
666                                         break;
667                                 case RECORD_NAMED_PET_GENOCIDE:
668                                         fprintf(fff, _("%sが抹殺によって消え去った。\n", "%s was made disappeared by genocide.\n"), note);
669                                         break;
670                                 case RECORD_NAMED_PET_WIZ_ZAP:
671                                         fprintf(fff, _("%sがデバッグコマンドによって消え去った。\n", "%s was removed by debug command.\n"), note);
672                                         break;
673                                 case RECORD_NAMED_PET_TELE_LEVEL:
674                                         fprintf(fff, _("%sがテレポート・レベルによって消え去った。\n", "%s was made disappeared by teleport level.\n"), note);
675                                         break;
676                                 case RECORD_NAMED_PET_BLAST:
677                                         fprintf(fff, _("%sを爆破した。\n", "blasted %s.\n"), note);
678                                         break;
679                                 case RECORD_NAMED_PET_HEAL_LEPER:
680                                         fprintf(fff, _("%sの病気が治り旅から外れた。\n", "%s was healed and left.\n"), note);
681                                         break;
682                                 case RECORD_NAMED_PET_COMPACT:
683                                         fprintf(fff, _("%sがモンスター情報圧縮によって消え去った。\n", "%s was made disappeared by compacting monsters.\n"), note);
684                                         break;
685                                 case RECORD_NAMED_PET_LOSE_PARENT:
686                                         fprintf(fff, _("%sの召喚者が既にいないため消え去った。\n", "%s disappeared because there does not exist summoner.\n"), note);
687                                         break;
688
689
690                                 default:
691                                         fprintf(fff, "\n");
692                                         break;
693                         }
694                         break;
695                 }
696
697                 case NIKKI_WIZ_ARTIFACT:
698                         fprintf(fff, "WIZ/ARTIFACT_INFO: %s\n", note);
699                         break;
700
701                 default:
702                         break;
703         }
704
705         my_fclose(fff);
706
707         if (do_level) write_level = FALSE;
708
709         return (0);
710 }
711
712
713 #define MAX_SUBTITLE (sizeof(subtitle)/sizeof(subtitle[0]))
714
715 /*!
716  * @brief 日記のタイトル表記と内容出力 /
717  * @return なし
718  * @details
719  * 日記のタイトルは本関数の subtitle ローカル変数で定義されている。
720  */
721 static void do_cmd_disp_nikki(void)
722 {
723         char nikki_title[256];
724         char file_name[80];
725         char buf[1024];
726         char tmp[80];
727 #ifdef JP
728         /*! */
729         static const char subtitle[][30] = {"最強の肉体を求めて",
730                                            "人生それははかない",
731                                            "明日に向かって",
732                                            "棚からぼたもち",
733                                            "あとの祭り",
734                                            "それはいい考えだ",
735                                            "何とでも言え",
736                                            "兎にも角にも",
737                                            "ウソだけど",
738                                            "もはやこれまで",
739                                            "なんでこうなるの",
740                                            "それは無理だ",
741                                            "倒すべき敵はゲ○ツ",
742                                            "ん~?聞こえんなぁ",
743                                            "オレの名を言ってみろ",
744                                            "頭が変になっちゃった",
745                                            "互換しません",
746                                            "せっかくだから",
747                                            "まだまだ甘いね",
748                                            "むごいむごすぎる",
749                                            "こんなもんじゃない",
750                                            "だめだこりゃ",
751                                            "次いってみよう",
752                                            "ちょっとだけよ",
753                                            "哀しき冒険者",
754                                            "野望の果て",
755                                            "無限地獄",
756                                            "神に喧嘩を売る者",
757                                            "未知の世界へ",
758                                            "最高の頭脳を求めて"};
759 #else
760         static const char subtitle[][51] ={"Quest of The World's Toughest Body",
761                                            "Attack is the best form of defence.",
762                                            "Might is right.",
763                                            "An unexpected windfall",
764                                            "A drowning man will catch at a straw",
765                                            "Don't count your chickens before they are hatched.",
766                                            "It is no use crying over spilt milk.",
767                                            "Seeing is believing.",
768                                            "Strike the iron while it is hot.",
769                                            "I don't care what follows.",
770                                            "To dig a well to put out a house on fire.",
771                                            "Tomorrow is another day.",
772                                            "Easy come, easy go.",
773                                            "The more haste, the less speed.",
774                                            "Where there is life, there is hope.",
775                                            "There is no royal road to *WINNER*.",
776                                            "Danger past, God forgotten.",
777                                            "The best thing to do now is to run away.",
778                                            "Life is but an empty dream.",
779                                            "Dead men tell no tales.",
780                                            "A book that remains shut is but a block.",
781                                            "Misfortunes never come singly.",
782                                            "A little knowledge is a dangerous thing.",
783                                            "History repeats itself.",
784                                            "*WINNER* was not built in a day.",
785                                            "Ignorance is bliss.",
786                                            "To lose is to win?",
787                                            "No medicine can cure folly.",
788                                            "All good things come to an end.",
789                                            "M$ Empire strikes back.",
790                                            "To see is to believe",
791                                            "Time is money.",
792                                            "Quest of The World's Greatest Brain"};
793 #endif
794         sprintf(file_name,_("playrecord-%s.txt", "playrec-%s.txt"),savefile_base);
795
796         /* Build the filename */
797         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
798
799         if (p_ptr->pclass == CLASS_WARRIOR || p_ptr->pclass == CLASS_MONK || p_ptr->pclass == CLASS_SAMURAI || p_ptr->pclass == CLASS_BERSERKER)
800                 strcpy(tmp,subtitle[randint0(MAX_SUBTITLE-1)]);
801         else if (p_ptr->pclass == CLASS_MAGE || p_ptr->pclass == CLASS_HIGH_MAGE || p_ptr->pclass == CLASS_SORCERER)
802                 strcpy(tmp,subtitle[randint0(MAX_SUBTITLE-1)+1]);
803         else strcpy(tmp,subtitle[randint0(MAX_SUBTITLE-2)+1]);
804
805 #ifdef JP
806         sprintf(nikki_title, "「%s%s%sの伝説 -%s-」",
807                 ap_ptr->title, ap_ptr->no ? "の" : "", p_ptr->name, tmp);
808 #else
809         sprintf(nikki_title, "Legend of %s %s '%s'",
810                 ap_ptr->title, p_ptr->name, tmp);
811 #endif
812
813         /* Display the file contents */
814         show_file(FALSE, buf, nikki_title, -1, 0);
815 }
816
817 /*!
818  * @brief 日記に任意の内容を表記するコマンドのメインルーチン /
819  * @return なし
820  */
821 static void do_cmd_bunshou(void)
822 {
823         char tmp[80] = "\0";
824         char bunshou[80] = "\0";
825
826         if (get_string(_("内容: ", "diary note: "), tmp, 79))
827         {
828                 strcpy(bunshou, tmp);
829
830                 do_cmd_write_nikki(NIKKI_BUNSHOU, 0, bunshou);
831         }
832 }
833
834 /*!
835  * @brief 最後に取得したアイテムの情報を日記に追加するメインルーチン /
836  * @return なし
837  */
838 static void do_cmd_last_get(void)
839 {
840         char buf[256];
841         s32b turn_tmp;
842
843         if (record_o_name[0] == '\0') return;
844
845         sprintf(buf,_("%sの入手を記録します。", "Do you really want to record getting %s? "),record_o_name);
846         if (!get_check(buf)) return;
847
848         turn_tmp = turn;
849         turn = record_turn;
850         sprintf(buf,_("%sを手に入れた。", "descover %s."), record_o_name);
851         do_cmd_write_nikki(NIKKI_BUNSHOU, 0, buf);
852         turn = turn_tmp;
853 }
854
855 /*!
856  * @brief ファイル中の全日記記録を消去する /
857  * @return なし
858  */
859 static void do_cmd_erase_nikki(void)
860 {
861         char file_name[80];
862         char buf[256];
863         FILE *fff = NULL;
864
865         if (!get_check(_("本当に記録を消去しますか?", "Do you really want to delete all your record? "))) return;
866                 sprintf(file_name,_("playrecord-%s.txt", "playrec-%s.txt"),savefile_base);
867
868         /* Build the filename */
869         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
870
871         /* Remove the file */
872         fd_kill(buf);
873
874         fff = my_fopen(buf, "w");
875         if(fff){
876                 my_fclose(fff);
877                 msg_format(_("記録を消去しました。", "deleted record."));
878         }else{
879                 msg_format(_("%s の消去に失敗しました。", "failed to delete %s."), buf);
880         }
881         msg_print(NULL);
882 }
883
884 /*!
885  * @brief 日記コマンド
886  * @return なし
887  */
888 void do_cmd_nikki(void)
889 {
890         int i;
891
892         /* File type is "TEXT" */
893         FILE_TYPE(FILE_TYPE_TEXT);
894
895         /* Save the screen */
896         screen_save();
897
898         /* Interact until done */
899         while (1)
900         {
901                 /* Clear screen */
902                 Term_clear();
903
904                 /* Ask for a choice */
905                 prt(_("[ 記録の設定 ]", "[ Play Record ]"), 2, 0);
906
907                 /* Give some choices */
908                 prt(_("(1) 記録を見る", "(1) Display your record"), 4, 5);
909                 prt(_("(2) 文章を記録する", "(2) Add record"), 5, 5);
910                 prt(_("(3) 直前に入手又は鑑定したものを記録する", "(3) Record item you last get/identify"), 6, 5);
911                 prt(_("(4) 記録を消去する", "(4) Delete your record"), 7, 5);
912
913                 prt(_("(R) プレイ動画を記録する/中止する", "(R) Record playing movie / or stop it"), 9, 5);
914
915                 /* Prompt */
916                 prt(_("コマンド:", "Command: "), 18, 0);
917
918                 /* Prompt */
919                 i = inkey();
920
921                 /* Done */
922                 if (i == ESCAPE) break;
923
924                 switch (i)
925                 {
926                 case '1':
927                         do_cmd_disp_nikki();
928                         break;
929                 case '2':
930                         do_cmd_bunshou();
931                         break;
932                 case '3':
933                         do_cmd_last_get();
934                         break;
935                 case '4':
936                         do_cmd_erase_nikki();
937                         break;
938                 case 'r': case 'R':
939                         screen_load();
940                         prepare_movie_hooks();
941                         return;
942                 default: /* Unknown option */
943                         bell();
944                 }
945
946                 /* Flush messages */
947                 msg_print(NULL);
948         }
949
950         /* Restore the screen */
951         screen_load();
952 }
953
954 /*!
955  * @brief 画面を再描画するコマンドのメインルーチン
956  * Hack -- redraw the screen
957  * @return なし
958  * @details
959  * <pre>
960  * This command performs various low level updates, clears all the "extra"
961  * windows, does a total redraw of the main window, and requests all of the
962  * interesting updates and redraws that I can think of.
963  *
964  * This command is also used to "instantiate" the results of the user
965  * selecting various things, such as graphics mode, so it must call
966  * the "TERM_XTRA_REACT" hook before redrawing the windows.
967  * </pre>
968  */
969 void do_cmd_redraw(void)
970 {
971         int j;
972
973         term *old = Term;
974
975
976         /* Hack -- react to changes */
977         Term_xtra(TERM_XTRA_REACT, 0);
978
979
980         /* Combine and Reorder the pack (later) */
981         p_ptr->notice |= (PN_COMBINE | PN_REORDER);
982
983
984         /* Update torch */
985         p_ptr->update |= (PU_TORCH);
986
987         /* Update stuff */
988         p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
989
990         /* Forget lite/view */
991         p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
992
993         /* Update lite/view */
994         p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
995
996         /* Update monsters */
997         p_ptr->update |= (PU_MONSTERS);
998
999         /* Redraw everything */
1000         p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
1001
1002         /* Window stuff */
1003         p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER);
1004
1005         /* Window stuff */
1006         p_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT);
1007
1008         update_playtime();
1009
1010         /* Hack -- update */
1011         handle_stuff();
1012
1013         if (p_ptr->prace == RACE_ANDROID) calc_android_exp();
1014
1015
1016         /* Redraw every window */
1017         for (j = 0; j < 8; j++)
1018         {
1019                 /* Dead window */
1020                 if (!angband_term[j]) continue;
1021
1022                 /* Activate */
1023                 Term_activate(angband_term[j]);
1024
1025                 /* Redraw */
1026                 Term_redraw();
1027
1028                 /* Refresh */
1029                 Term_fresh();
1030
1031                 /* Restore */
1032                 Term_activate(old);
1033         }
1034 }
1035
1036
1037 /*!
1038  * @brief 名前を変更するコマンドのメインルーチン
1039  * Hack -- change name
1040  * @return なし
1041  */
1042 void do_cmd_change_name(void)
1043 {
1044         char    c;
1045
1046         int             mode = 0;
1047
1048         char    tmp[160];
1049
1050
1051         /* Save the screen */
1052         screen_save();
1053
1054         /* Forever */
1055         while (1)
1056         {
1057                 update_playtime();
1058
1059                 /* Display the player */
1060                 display_player(mode);
1061
1062                 if (mode == 4)
1063                 {
1064                         mode = 0;
1065                         display_player(mode);
1066                 }
1067
1068                 /* Prompt */
1069 #ifdef JP
1070                 Term_putstr(2, 23, -1, TERM_WHITE,
1071                             "['c'で名前変更, 'f'でファイルへ書出, 'h'でモード変更, ESCで終了]");
1072 #else
1073                 Term_putstr(2, 23, -1, TERM_WHITE,
1074                         "['c' to change name, 'f' to file, 'h' to change mode, or ESC]");
1075 #endif
1076
1077
1078                 /* Query */
1079                 c = inkey();
1080
1081                 /* Exit */
1082                 if (c == ESCAPE) break;
1083
1084                 /* Change name */
1085                 if (c == 'c')
1086                 {
1087                         get_name();
1088
1089                         /* Process the player name */
1090                         process_player_name(FALSE);
1091                 }
1092
1093                 /* File dump */
1094                 else if (c == 'f')
1095                 {
1096                         sprintf(tmp, "%s.txt", player_base);
1097                         if (get_string(_("ファイル名: ", "File name: "), tmp, 80))
1098                         {
1099                                 if (tmp[0] && (tmp[0] != ' '))
1100                                 {
1101                                         file_character(tmp);
1102                                 }
1103                         }
1104                 }
1105
1106                 /* Toggle mode */
1107                 else if (c == 'h')
1108                 {
1109                         mode++;
1110                 }
1111
1112                 /* Oops */
1113                 else
1114                 {
1115                         bell();
1116                 }
1117
1118                 /* Flush messages */
1119                 msg_print(NULL);
1120         }
1121
1122         /* Restore the screen */
1123         screen_load();
1124
1125         /* Redraw everything */
1126         p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
1127
1128         handle_stuff();
1129 }
1130
1131
1132 /*!
1133  * @brief 最近表示されたメッセージを再表示するコマンドのメインルーチン
1134  * Recall the most recent message
1135  * @return なし
1136  */
1137 void do_cmd_message_one(void)
1138 {
1139         /* Recall one message XXX XXX XXX */
1140         prt(format("> %s", message_str(0)), 0, 0);
1141 }
1142
1143
1144 /*!
1145  * @brief メッセージのログを表示するコマンドのメインルーチン
1146  * Recall the most recent message
1147  * @return なし
1148  * @details
1149  * <pre>
1150  * Show previous messages to the user   -BEN-
1151  *
1152  * The screen format uses line 0 and 23 for headers and prompts,
1153  * skips line 1 and 22, and uses line 2 thru 21 for old messages.
1154  *
1155  * This command shows you which commands you are viewing, and allows
1156  * you to "search" for strings in the recall.
1157  *
1158  * Note that messages may be longer than 80 characters, but they are
1159  * displayed using "infinite" length, with a special sub-command to
1160  * "slide" the virtual display to the left or right.
1161  *
1162  * Attempt to only hilite the matching portions of the string.
1163  * </pre>
1164  */
1165 void do_cmd_messages(int num_now)
1166 {
1167         int i, n;
1168
1169         char shower_str[81];
1170         char finder_str[81];
1171         char back_str[81];
1172         cptr shower = NULL;
1173         int wid, hgt;
1174         int num_lines;
1175
1176         /* Get size */
1177         Term_get_size(&wid, &hgt);
1178
1179         /* Number of message lines in a screen */
1180         num_lines = hgt - 4;
1181
1182         /* Wipe finder */
1183         strcpy(finder_str, "");
1184
1185         /* Wipe shower */
1186         strcpy(shower_str, "");
1187
1188         /* Total messages */
1189         n = message_num();
1190
1191         /* Start on first message */
1192         i = 0;
1193
1194         /* Save the screen */
1195         screen_save();
1196
1197         /* Clear screen */
1198         Term_clear();
1199
1200         /* Process requests until done */
1201         while (1)
1202         {
1203                 int j;
1204                 int skey;
1205
1206                 /* Dump up to 20 lines of messages */
1207                 for (j = 0; (j < num_lines) && (i + j < n); j++)
1208                 {
1209                         cptr msg = message_str(i+j);
1210
1211                         /* Dump the messages, bottom to top */
1212                         c_prt((i + j < num_now ? TERM_WHITE : TERM_SLATE), msg, num_lines + 1 - j, 0);
1213
1214                         /* Hilite "shower" */
1215                         if (shower && shower[0])
1216                         {
1217                                 cptr str = msg;
1218
1219                                 /* Display matches */
1220                                 while ((str = my_strstr(str, shower)) != NULL)
1221                                 {
1222                                         int len = strlen(shower);
1223
1224                                         /* Display the match */
1225                                         Term_putstr(str-msg, num_lines + 1 - j, len, TERM_YELLOW, shower);
1226
1227                                         /* Advance */
1228                                         str += len;
1229                                 }
1230                         }
1231                 }
1232
1233                 /* Erase remaining lines */
1234                 for (; j < num_lines; j++)
1235                 {
1236                         Term_erase(0, num_lines + 1 - j, 255);
1237                 }
1238
1239                 /* Display header XXX XXX XXX */
1240 #ifdef JP
1241                 /* translation */
1242                 prt(format("以前のメッセージ %d-%d 全部で(%d)",
1243                            i, i + j - 1, n), 0, 0);
1244 #else
1245                 prt(format("Message Recall (%d-%d of %d)",
1246                            i, i + j - 1, n), 0, 0);
1247 #endif
1248
1249                 /* Display prompt (not very informative) */
1250                 prt(_("[ 'p' で更に古いもの, 'n' で更に新しいもの, '/' で検索, ESC で中断 ]",
1251                           "[Press 'p' for older, 'n' for newer, ..., or ESCAPE]"), hgt - 1, 0);
1252
1253                 /* Get a command */
1254                 skey = inkey_special(TRUE);
1255
1256                 /* Exit on Escape */
1257                 if (skey == ESCAPE) break;
1258
1259                 /* Hack -- Save the old index */
1260                 j = i;
1261
1262                 switch (skey)
1263                 {
1264                 /* Hack -- handle show */
1265                 case '=':
1266                         /* Prompt */
1267                         prt(_("強調: ", "Show: "), hgt - 1, 0);
1268
1269                         /* Get a "shower" string, or continue */
1270                         strcpy(back_str, shower_str);
1271                         if (askfor(shower_str, 80))
1272                         {
1273                                 /* Show it */
1274                                 shower = shower_str[0] ? shower_str : NULL;
1275                         }
1276                         else strcpy(shower_str, back_str);
1277
1278                         /* Okay */
1279                         continue;
1280
1281                 /* Hack -- handle find */
1282                 case '/':
1283                 case KTRL('s'):
1284                         {
1285                                 int z;
1286
1287                                 /* Prompt */
1288                                 prt(_("検索: ", "Find: "), hgt - 1, 0);
1289
1290                                 /* Get a "finder" string, or continue */
1291                                 strcpy(back_str, finder_str);
1292                                 if (!askfor(finder_str, 80))
1293                                 {
1294                                         strcpy(finder_str, back_str);
1295                                         continue;
1296                                 }
1297                                 else if (!finder_str[0])
1298                                 {
1299                                         shower = NULL; /* Stop showing */
1300                                         continue;
1301                                 }
1302
1303                                 /* Show it */
1304                                 shower = finder_str;
1305
1306                                 /* Scan messages */
1307                                 for (z = i + 1; z < n; z++)
1308                                 {
1309                                         cptr msg = message_str(z);
1310
1311                                         /* Search for it */
1312                                         if (my_strstr(msg, finder_str))
1313                                         {
1314                                                 /* New location */
1315                                                 i = z;
1316
1317                                                 /* Done */
1318                                                 break;
1319                                         }
1320                                 }
1321                         }
1322                         break;
1323
1324                 /* Recall 1 older message */
1325                 case SKEY_TOP:
1326                         /* Go to the oldest line */
1327                         i = n - num_lines;
1328                         break;
1329
1330                 /* Recall 1 newer message */
1331                 case SKEY_BOTTOM:
1332                         /* Go to the newest line */
1333                         i = 0;
1334                         break;
1335
1336                 /* Recall 1 older message */
1337                 case '8':
1338                 case SKEY_UP:
1339                 case '\n':
1340                 case '\r':
1341                         /* Go older if legal */
1342                         i = MIN(i + 1, n - num_lines);
1343                         break;
1344
1345                 /* Recall 10 older messages */
1346                 case '+':
1347                         /* Go older if legal */
1348                         i = MIN(i + 10, n - num_lines);
1349                         break;
1350
1351                 /* Recall 20 older messages */
1352                 case 'p':
1353                 case KTRL('P'):
1354                 case ' ':
1355                 case SKEY_PGUP:
1356                         /* Go older if legal */
1357                         i = MIN(i + num_lines, n - num_lines);
1358                         break;
1359
1360                 /* Recall 20 newer messages */
1361                 case 'n':
1362                 case KTRL('N'):
1363                 case SKEY_PGDOWN:
1364                         /* Go newer (if able) */
1365                         i = MAX(0, i - num_lines);
1366                         break;
1367
1368                 /* Recall 10 newer messages */
1369                 case '-':
1370                         /* Go newer (if able) */
1371                         i = MAX(0, i - 10);
1372                         break;
1373
1374                 /* Recall 1 newer messages */
1375                 case '2':
1376                 case SKEY_DOWN:
1377                         /* Go newer (if able) */
1378                         i = MAX(0, i - 1);
1379                         break;
1380                 }
1381
1382                 /* Hack -- Error of some kind */
1383                 if (i == j) bell();
1384         }
1385
1386         /* Restore the screen */
1387         screen_load();
1388 }
1389
1390
1391
1392 /*!
1393  * チートオプションの最大数 / Number of cheating options
1394  */
1395 #define CHEAT_MAX 8
1396
1397 /*!
1398  * チーとオプションの定義テーブル / Cheating options
1399  */
1400 static option_type cheat_info[CHEAT_MAX] =
1401 {
1402         { &cheat_peek,          FALSE,  255,    0x01, 0x00,
1403                 "cheat_peek",           _("アイテムの生成をのぞき見る", "Peek into object creation")
1404         },
1405
1406         { &cheat_hear,          FALSE,  255,    0x02, 0x00,
1407                 "cheat_hear",           _("モンスターの生成をのぞき見る", "Peek into monster creation")
1408         },
1409
1410         { &cheat_room,          FALSE,  255,    0x04, 0x00,
1411                 "cheat_room",           _("ダンジョンの生成をのぞき見る", "Peek into dungeon creation")
1412         },
1413
1414         { &cheat_xtra,          FALSE,  255,    0x08, 0x00,
1415                 "cheat_xtra",           _("その他の事をのぞき見る", "Peek into something else")
1416         },
1417
1418         { &cheat_know,          FALSE,  255,    0x10, 0x00,
1419                 "cheat_know",           _("完全なモンスターの思い出を知る", "Know complete monster info")
1420         },
1421
1422         { &cheat_live,          FALSE,  255,    0x20, 0x00,
1423                 "cheat_live",           _("死を回避することを可能にする", "Allow player to avoid death")
1424         },
1425
1426         { &cheat_save,          FALSE,  255,    0x40, 0x00,
1427                 "cheat_save",           _("死んだ時セーブするか確認する", "Ask for saving death")
1428         },
1429
1430         { &cheat_diary_output,  FALSE,  255,    0x80, 0x00,
1431                 "cheat_diary_output",           _("詳細な情報を日記に出力する", "Output detailed infotmation to diary.")
1432         }
1433
1434
1435 };
1436
1437 /*!
1438  * @brief チートオプションを変更するコマンドのメインルーチン
1439  * Interact with some options for cheating
1440  * @param info 表示メッセージ
1441  * @return なし
1442  */
1443 static void do_cmd_options_cheat(cptr info)
1444 {
1445         char    ch;
1446
1447         int             i, k = 0, n = CHEAT_MAX;
1448
1449         char    buf[80];
1450
1451
1452         /* Clear screen */
1453         Term_clear();
1454
1455         /* Interact with the player */
1456         while (TRUE)
1457         {
1458                 int dir;
1459
1460                 /* Prompt XXX XXX XXX */
1461                 sprintf(buf, _("%s ( リターンで次へ, y/n でセット, ESC で決定 )", "%s (RET to advance, y/n to set, ESC to accept) "), info);
1462
1463                 prt(buf, 0, 0);
1464
1465 #ifdef JP
1466                 /* 詐欺オプションをうっかりいじってしまう人がいるようなので注意 */
1467                 prt("                                 <<  注意  >>", 11, 0);
1468                 prt("      詐欺オプションを一度でも設定すると、スコア記録が残らなくなります!", 12, 0);
1469                 prt("      後に解除してもダメですので、勝利者を目指す方はここのオプションはい", 13, 0);
1470                 prt("      じらないようにして下さい。", 14, 0);
1471 #endif
1472                 /* Display the options */
1473                 for (i = 0; i < n; i++)
1474                 {
1475                         byte a = TERM_WHITE;
1476
1477                         /* Color current option */
1478                         if (i == k) a = TERM_L_BLUE;
1479
1480                         /* Display the option text */
1481                         sprintf(buf, "%-48s: %s (%s)",
1482                             cheat_info[i].o_desc,
1483                             (*cheat_info[i].o_var ? _("はい  ", "yes") : _("いいえ", "no ")),
1484                             cheat_info[i].o_text);
1485                         c_prt(a, buf, i + 2, 0);
1486                 }
1487
1488                 /* Hilite current option */
1489                 move_cursor(k + 2, 50);
1490
1491                 /* Get a key */
1492                 ch = inkey();
1493
1494                 /*
1495                  * HACK - Try to translate the key into a direction
1496                  * to allow using the roguelike keys for navigation.
1497                  */
1498                 dir = get_keymap_dir(ch);
1499                 if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8))
1500                         ch = I2D(dir);
1501
1502                 /* Analyze */
1503                 switch (ch)
1504                 {
1505                         case ESCAPE:
1506                         {
1507                                 return;
1508                         }
1509
1510                         case '-':
1511                         case '8':
1512                         {
1513                                 k = (n + k - 1) % n;
1514                                 break;
1515                         }
1516
1517                         case ' ':
1518                         case '\n':
1519                         case '\r':
1520                         case '2':
1521                         {
1522                                 k = (k + 1) % n;
1523                                 break;
1524                         }
1525
1526                         case 'y':
1527                         case 'Y':
1528                         case '6':
1529                         {
1530                                 if(!p_ptr->noscore)
1531                                 do_cmd_write_nikki(NIKKI_BUNSHOU, 0,
1532                                                         _("詐欺オプションをONにして、スコアを残せなくなった。", "give up sending score to use cheating options."));
1533                                 p_ptr->noscore |= (cheat_info[k].o_set * 256 + cheat_info[k].o_bit);
1534                                 (*cheat_info[k].o_var) = TRUE;
1535                                 k = (k + 1) % n;
1536                                 break;
1537                         }
1538
1539                         case 'n':
1540                         case 'N':
1541                         case '4':
1542                         {
1543                                 (*cheat_info[k].o_var) = FALSE;
1544                                 k = (k + 1) % n;
1545                                 break;
1546                         }
1547
1548                         case '?':
1549                         {
1550                                 strnfmt(buf, sizeof(buf), _("joption.txt#%s", "option.txt#%s"), cheat_info[k].o_text);
1551                                 /* Peruse the help file */
1552                                 (void)show_file(TRUE, buf, NULL, 0, 0);
1553
1554                                 Term_clear(); 
1555                                 break;
1556                         }
1557
1558                         default:
1559                         {
1560                                 bell();
1561                                 break;
1562                         }
1563                 }
1564         }
1565 }
1566
1567
1568 /*!
1569  * 自動セーブオプションテーブル
1570  */
1571 static option_type autosave_info[2] =
1572 {
1573         { &autosave_l,      FALSE, 255, 0x01, 0x00,
1574             "autosave_l",    _("新しい階に入る度に自動セーブする", "Autosave when entering new levels") },
1575
1576         { &autosave_t,      FALSE, 255, 0x02, 0x00,
1577             "autosave_t",   _("一定ターン毎に自動セーブする", "Timed autosave") },
1578 };
1579
1580 /*!
1581  * @brief セーブ頻度ターンの次の値を返す
1582  * @param current 現在のセーブ頻度ターン値
1583  * @return 次のセーブ頻度ターン値
1584  */
1585 static s16b toggle_frequency(s16b current)
1586 {
1587         switch (current)
1588         {
1589         case 0: return 50;
1590         case 50: return 100;
1591         case 100: return 250;
1592         case 250: return 500;
1593         case 500: return 1000;
1594         case 1000: return 2500;
1595         case 2500: return 5000;
1596         case 5000: return 10000;
1597         case 10000: return 25000;
1598         default: return 0;
1599         }
1600 }
1601
1602
1603 /*!
1604  * @brief 自動セーブオプションを変更するコマンドのメインルーチン
1605  * @param info 表示メッセージ
1606  * @return なし
1607  */
1608 static void do_cmd_options_autosave(cptr info)
1609 {
1610         char    ch;
1611
1612         int     i, k = 0, n = 2;
1613
1614         char    buf[80];
1615
1616
1617         /* Clear screen */
1618         Term_clear();
1619
1620         /* Interact with the player */
1621         while (TRUE)
1622         {
1623                 /* Prompt XXX XXX XXX */
1624                 sprintf(buf, _("%s ( リターンで次へ, y/n でセット, F で頻度を入力, ESC で決定 ) ", 
1625                                            "%s (RET to advance, y/n to set, 'F' for frequency, ESC to accept) "), info);
1626
1627                 prt(buf, 0, 0);
1628
1629                 /* Display the options */
1630                 for (i = 0; i < n; i++)
1631                 {
1632                         byte a = TERM_WHITE;
1633
1634                         /* Color current option */
1635                         if (i == k) a = TERM_L_BLUE;
1636
1637                         /* Display the option text */
1638                         sprintf(buf, "%-48s: %s (%s)",
1639                             autosave_info[i].o_desc,
1640                             (*autosave_info[i].o_var ? _("はい  ", "yes") : _("いいえ", "no ")),
1641                             autosave_info[i].o_text);
1642                         c_prt(a, buf, i + 2, 0);
1643                 }
1644                 prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"),  autosave_freq), 5, 0);
1645
1646                 /* Hilite current option */
1647                 move_cursor(k + 2, 50);
1648
1649                 /* Get a key */
1650                 ch = inkey();
1651
1652                 /* Analyze */
1653                 switch (ch)
1654                 {
1655                         case ESCAPE:
1656                         {
1657                                 return;
1658                         }
1659
1660                         case '-':
1661                         case '8':
1662                         {
1663                                 k = (n + k - 1) % n;
1664                                 break;
1665                         }
1666
1667                         case ' ':
1668                         case '\n':
1669                         case '\r':
1670                         case '2':
1671                         {
1672                                 k = (k + 1) % n;
1673                                 break;
1674                         }
1675
1676                         case 'y':
1677                         case 'Y':
1678                         case '6':
1679                         {
1680
1681                                 (*autosave_info[k].o_var) = TRUE;
1682                                 k = (k + 1) % n;
1683                                 break;
1684                         }
1685
1686                         case 'n':
1687                         case 'N':
1688                         case '4':
1689                         {
1690                                 (*autosave_info[k].o_var) = FALSE;
1691                                 k = (k + 1) % n;
1692                                 break;
1693                         }
1694
1695                         case 'f':
1696                         case 'F':
1697                         {
1698                                 autosave_freq = toggle_frequency(autosave_freq);
1699                                 prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0);
1700                                 break;
1701                         }
1702
1703                         case '?':
1704                         {
1705                                 (void)show_file(TRUE, _("joption.txt#Autosave", "option.txt#Autosave"), NULL, 0, 0);
1706                                 Term_clear(); 
1707                                 break;
1708                         }
1709
1710                         default:
1711                         {
1712                                 bell();
1713                                 break;
1714                         }
1715                 }
1716         }
1717 }
1718
1719
1720 /*!
1721  * @brief 標準オプションを変更するコマンドのサブルーチン /
1722  * Interact with some options
1723  * @param page オプションページ番号
1724  * @param info 表示メッセージ
1725  * @return なし
1726  */
1727 void do_cmd_options_aux(int page, cptr info)
1728 {
1729         char    ch;
1730         int     i, k = 0, n = 0, l;
1731         int     opt[24];
1732         char    buf[80];
1733         bool    browse_only = (page == OPT_PAGE_BIRTH) && character_generated &&
1734                               (!p_ptr->wizard || !allow_debug_opts);
1735
1736
1737         /* Lookup the options */
1738         for (i = 0; i < 24; i++) opt[i] = 0;
1739
1740         /* Scan the options */
1741         for (i = 0; option_info[i].o_desc; i++)
1742         {
1743                 /* Notice options on this "page" */
1744                 if (option_info[i].o_page == page) opt[n++] = i;
1745         }
1746
1747
1748         /* Clear screen */
1749         Term_clear();
1750
1751         /* Interact with the player */
1752         while (TRUE)
1753         {
1754                 int dir;
1755
1756                 /* Prompt XXX XXX XXX */
1757                 sprintf(buf, _("%s (リターン:次, %sESC:終了, ?:ヘルプ) ", "%s (RET:next, %s, ?:help) "),
1758                                         info, browse_only ? _("", "ESC:exit") : _("y/n:変更, ", "y/n:change, ESC:accept"));
1759                 prt(buf, 0, 0);
1760
1761                 /* HACK -- description for easy-auto-destroy options */
1762                 if (page == OPT_PAGE_AUTODESTROY) 
1763                         c_prt(TERM_YELLOW, _("以下のオプションは、簡易自動破壊を使用するときのみ有効", 
1764                                                                  "Following options will protect items from easy auto-destroyer."), 6, _(6, 3));
1765
1766                 /* Display the options */
1767                 for (i = 0; i < n; i++)
1768                 {
1769                         byte a = TERM_WHITE;
1770
1771                         /* Color current option */
1772                         if (i == k) a = TERM_L_BLUE;
1773
1774                         /* Display the option text */
1775                         sprintf(buf, "%-48s: %s (%.19s)",
1776                                 option_info[opt[i]].o_desc,
1777                                 (*option_info[opt[i]].o_var ? _("はい  ", "yes") : _("いいえ", "no ")),
1778                                 option_info[opt[i]].o_text);
1779                         if ((page == OPT_PAGE_AUTODESTROY) && i > 2) c_prt(a, buf, i + 5, 0);
1780                         else c_prt(a, buf, i + 2, 0);
1781                 }
1782
1783                 if ((page == OPT_PAGE_AUTODESTROY) && (k > 2)) l = 3;
1784                 else l = 0;
1785
1786                 /* Hilite current option */
1787                 move_cursor(k + 2 + l, 50);
1788
1789                 /* Get a key */
1790                 ch = inkey();
1791
1792                 /*
1793                  * HACK - Try to translate the key into a direction
1794                  * to allow using the roguelike keys for navigation.
1795                  */
1796                 dir = get_keymap_dir(ch);
1797                 if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8))
1798                         ch = I2D(dir);
1799
1800                 /* Analyze */
1801                 switch (ch)
1802                 {
1803                         case ESCAPE:
1804                         {
1805                                 return;
1806                         }
1807
1808                         case '-':
1809                         case '8':
1810                         {
1811                                 k = (n + k - 1) % n;
1812                                 break;
1813                         }
1814
1815                         case ' ':
1816                         case '\n':
1817                         case '\r':
1818                         case '2':
1819                         {
1820                                 k = (k + 1) % n;
1821                                 break;
1822                         }
1823
1824                         case 'y':
1825                         case 'Y':
1826                         case '6':
1827                         {
1828                                 if (browse_only) break;
1829                                 (*option_info[opt[k]].o_var) = TRUE;
1830                                 k = (k + 1) % n;
1831                                 break;
1832                         }
1833
1834                         case 'n':
1835                         case 'N':
1836                         case '4':
1837                         {
1838                                 if (browse_only) break;
1839                                 (*option_info[opt[k]].o_var) = FALSE;
1840                                 k = (k + 1) % n;
1841                                 break;
1842                         }
1843
1844                         case 't':
1845                         case 'T':
1846                         {
1847                                 if (!browse_only) (*option_info[opt[k]].o_var) = !(*option_info[opt[k]].o_var);
1848                                 break;
1849                         }
1850
1851                         case '?':
1852                         {
1853                                 strnfmt(buf, sizeof(buf), _("joption.txt#%s", "option.txt#%s"), option_info[opt[k]].o_text);
1854                                 /* Peruse the help file */
1855                                 (void)show_file(TRUE, buf, NULL, 0, 0);
1856
1857                                 Term_clear();
1858                                 break;
1859                         }
1860
1861                         default:
1862                         {
1863                                 bell();
1864                                 break;
1865                         }
1866                 }
1867         }
1868 }
1869
1870
1871 /*!
1872  * @brief ウィンドウオプションを変更するコマンドのメインルーチン /
1873  * Modify the "window" options
1874  * @return なし
1875  */
1876 static void do_cmd_options_win(void)
1877 {
1878         int i, j, d;
1879         int y = 0;
1880         int x = 0;
1881         char ch;
1882         bool go = TRUE;
1883         u32b old_flag[8];
1884
1885
1886         /* Memorize old flags */
1887         for (j = 0; j < 8; j++)
1888         {
1889                 /* Acquire current flags */
1890                 old_flag[j] = window_flag[j];
1891         }
1892
1893
1894         /* Clear screen */
1895         Term_clear();
1896
1897         /* Interact */
1898         while (go)
1899         {
1900                 /* Prompt XXX XXX XXX */
1901                 prt(_("ウィンドウ・フラグ (<方向>で移動, tでチェンジ, y/n でセット, ESC)", "Window Flags (<dir>, t, y, n, ESC) "), 0, 0);
1902
1903                 /* Display the windows */
1904                 for (j = 0; j < 8; j++)
1905                 {
1906                         byte a = TERM_WHITE;
1907
1908                         cptr s = angband_term_name[j];
1909
1910                         /* Use color */
1911                         if (j == x) a = TERM_L_BLUE;
1912
1913                         /* Window name, staggered, centered */
1914                         Term_putstr(35 + j * 5 - strlen(s) / 2, 2 + j % 2, -1, a, s);
1915                 }
1916
1917                 /* Display the options */
1918                 for (i = 0; i < 16; i++)
1919                 {
1920                         byte a = TERM_WHITE;
1921
1922                         cptr str = window_flag_desc[i];
1923
1924                         /* Use color */
1925                         if (i == y) a = TERM_L_BLUE;
1926
1927                         /* Unused option */
1928                         if (!str) str = _("(未使用)", "(Unused option)");
1929
1930                         /* Flag name */
1931                         Term_putstr(0, i + 5, -1, a, str);
1932
1933                         /* Display the windows */
1934                         for (j = 0; j < 8; j++)
1935                         {
1936                                 char c = '.';
1937                                 a = TERM_WHITE;
1938
1939                                 /* Use color */
1940                                 if ((i == y) && (j == x)) a = TERM_L_BLUE;
1941
1942                                 /* Active flag */
1943                                 if (window_flag[j] & (1L << i)) c = 'X';
1944
1945                                 /* Flag value */
1946                                 Term_putch(35 + j * 5, i + 5, a, c);
1947                         }
1948                 }
1949
1950                 /* Place Cursor */
1951                 Term_gotoxy(35 + x * 5, y + 5);
1952
1953                 /* Get key */
1954                 ch = inkey();
1955
1956                 /* Analyze */
1957                 switch (ch)
1958                 {
1959                         case ESCAPE:
1960                         {
1961                                 go = FALSE;
1962                                 break;
1963                         }
1964
1965                         case 'T':
1966                         case 't':
1967                         {
1968                                 /* Clear windows */
1969                                 for (j = 0; j < 8; j++)
1970                                 {
1971                                         window_flag[j] &= ~(1L << y);
1972                                 }
1973
1974                                 /* Clear flags */
1975                                 for (i = 0; i < 16; i++)
1976                                 {
1977                                         window_flag[x] &= ~(1L << i);
1978                                 }
1979
1980                                 /* Fall through */
1981                         }
1982
1983                         case 'y':
1984                         case 'Y':
1985                         {
1986                                 /* Ignore screen */
1987                                 if (x == 0) break;
1988
1989                                 /* Set flag */
1990                                 window_flag[x] |= (1L << y);
1991                                 break;
1992                         }
1993
1994                         case 'n':
1995                         case 'N':
1996                         {
1997                                 /* Clear flag */
1998                                 window_flag[x] &= ~(1L << y);
1999                                 break;
2000                         }
2001
2002                         case '?':
2003                         {
2004                                 (void)show_file(TRUE, _("joption.txt#Window", "option.txt#Window"), NULL, 0, 0);
2005
2006                                 Term_clear(); 
2007                                 break;
2008                         }
2009
2010                         default:
2011                         {
2012                                 d = get_keymap_dir(ch);
2013
2014                                 x = (x + ddx[d] + 8) % 8;
2015                                 y = (y + ddy[d] + 16) % 16;
2016
2017                                 if (!d) bell();
2018                         }
2019                 }
2020         }
2021
2022         /* Notice changes */
2023         for (j = 0; j < 8; j++)
2024         {
2025                 term *old = Term;
2026
2027                 /* Dead window */
2028                 if (!angband_term[j]) continue;
2029
2030                 /* Ignore non-changes */
2031                 if (window_flag[j] == old_flag[j]) continue;
2032
2033                 /* Activate */
2034                 Term_activate(angband_term[j]);
2035
2036                 /* Erase */
2037                 Term_clear();
2038
2039                 /* Refresh */
2040                 Term_fresh();
2041
2042                 /* Restore */
2043                 Term_activate(old);
2044         }
2045 }
2046
2047
2048
2049 #define OPT_NUM 15
2050
2051 static struct opts
2052 {
2053         char key;
2054         cptr name;
2055         int row;
2056 }
2057 option_fields[OPT_NUM] =
2058 {
2059 #ifdef JP
2060         { '1', "    キー入力     オプション", 3 },
2061         { '2', "   マップ画面    オプション", 4 },
2062         { '3', "  テキスト表示   オプション", 5 },
2063         { '4', "  ゲームプレイ   オプション", 6 },
2064         { '5', "  行動中止関係   オプション", 7 },
2065         { '6', "  簡易自動破壊   オプション", 8 },
2066         { 'r', "   プレイ記録    オプション", 9 },
2067
2068         { 'p', "自動拾いエディタ", 11 },
2069         { 'd', " 基本ウェイト量 ", 12 },
2070         { 'h', "低ヒットポイント", 13 },
2071         { 'm', "  低魔力色閾値  ", 14 },
2072         { 'a', "   自動セーブ    オプション", 15 },
2073         { 'w', "ウインドウフラグ", 16 },
2074
2075         { 'b', "      初期       オプション (参照のみ)", 18 },
2076         { 'c', "      詐欺       オプション", 19 },
2077 #else
2078         { '1', "Input Options", 3 },
2079         { '2', "Map Screen Options", 4 },
2080         { '3', "Text Display Options", 5 },
2081         { '4', "Game-Play Options", 6 },
2082         { '5', "Disturbance Options", 7 },
2083         { '6', "Easy Auto-Destroyer Options", 8 },
2084         { 'r', "Play record Options", 9 },
2085
2086         { 'p', "Auto-picker/destroyer editor", 11 },
2087         { 'd', "Base Delay Factor", 12 },
2088         { 'h', "Hitpoint Warning", 13 },
2089         { 'm', "Mana Color Threshold", 14 },
2090         { 'a', "Autosave Options", 15 },
2091         { 'w', "Window Flags", 16 },
2092
2093         { 'b', "Birth Options (Browse Only)", 18 },
2094         { 'c', "Cheat Options", 19 },
2095 #endif
2096 };
2097
2098
2099 /*!
2100  * @brief 標準オプションを変更するコマンドのメインルーチン /
2101  * Set or unset various options.
2102  * @return なし
2103  * @details
2104  * <pre>
2105  * The user must use the "Ctrl-R" command to "adapt" to changes
2106  * in any options which control "visual" aspects of the game.
2107  * </pre>
2108  */
2109 void do_cmd_options(void)
2110 {
2111         char k;
2112         int i, d, skey;
2113         int y = 0;
2114
2115         /* Save the screen */
2116         screen_save();
2117
2118         /* Interact */
2119         while (1)
2120         {
2121                 int n = OPT_NUM;
2122
2123                 /* Does not list cheat option when cheat option is off */
2124                 if (!p_ptr->noscore && !allow_debug_opts) n--;
2125
2126                 /* Clear screen */
2127                 Term_clear();
2128
2129                 /* Why are we here */
2130                 prt(_("[ オプションの設定 ]", "TinyAngband options"), 1, 0);
2131
2132                 while(1)
2133                 {
2134                         /* Give some choices */
2135                         for (i = 0; i < n; i++)
2136                         {
2137                                 byte a = TERM_WHITE;
2138                                 if (i == y) a = TERM_L_BLUE;
2139                                 Term_putstr(5, option_fields[i].row, -1, a, 
2140                                         format("(%c) %s", toupper(option_fields[i].key), option_fields[i].name));
2141                         }
2142
2143                         prt(_("<方向>で移動, Enterで決定, ESCでキャンセル, ?でヘルプ: ", "Move to <dir>, Select to Enter, Cancel to ESC, ? to help: "), 21, 0);
2144
2145                         /* Get command */
2146                         skey = inkey_special(TRUE);
2147                         if (!(skey & SKEY_MASK)) k = (char)skey;
2148                         else k = 0;
2149
2150                         /* Exit */
2151                         if (k == ESCAPE) break;
2152
2153                         if (my_strchr("\n\r ", k))
2154                         {
2155                                 k = option_fields[y].key;
2156                                 break;
2157                         }
2158
2159                         for (i = 0; i < n; i++)
2160                         {
2161                                 if (tolower(k) == option_fields[i].key) break;
2162                         }
2163
2164                         /* Command is found */
2165                         if (i < n) break;
2166
2167                         /* Hack -- browse help */
2168                         if (k == '?') break;
2169
2170                         /* Move cursor */
2171                         d = 0;
2172                         if (skey == SKEY_UP) d = 8;
2173                         if (skey == SKEY_DOWN) d = 2;
2174                         y = (y + ddy[d] + n) % n;
2175                         if (!d) bell();
2176                 }
2177
2178                 /* Exit */
2179                 if (k == ESCAPE) break;
2180
2181                 /* Analyze */
2182                 switch (k)
2183                 {
2184                         case '1':
2185                         {
2186                                 /* Process the general options */
2187                                 do_cmd_options_aux(OPT_PAGE_INPUT, _("キー入力オプション", "Input Options"));
2188                                 break;
2189                         }
2190
2191                         case '2':
2192                         {
2193                                 /* Process the general options */
2194                                 do_cmd_options_aux(OPT_PAGE_MAPSCREEN, _("マップ画面オプション", "Map Screen Options"));
2195                                 break;
2196                         }
2197
2198                         case '3':
2199                         {
2200                                 /* Spawn */
2201                                 do_cmd_options_aux(OPT_PAGE_TEXT, _("テキスト表示オプション", "Text Display Options"));
2202                                 break;
2203                         }
2204
2205                         case '4':
2206                         {
2207                                 /* Spawn */
2208                                 do_cmd_options_aux(OPT_PAGE_GAMEPLAY, _("ゲームプレイ・オプション", "Game-Play Options"));
2209                                 break;
2210                         }
2211
2212                         case '5':
2213                         {
2214                                 /* Spawn */
2215                                 do_cmd_options_aux(OPT_PAGE_DISTURBANCE, _("行動中止関係のオプション", "Disturbance Options"));
2216                                 break;
2217                         }
2218
2219                         case '6':
2220                         {
2221                                 /* Spawn */
2222                                 do_cmd_options_aux(OPT_PAGE_AUTODESTROY, _("簡易自動破壊オプション", "Easy Auto-Destroyer Options"));
2223                                 break;
2224                         }
2225
2226                         /* Play-record Options */
2227                         case 'R':
2228                         case 'r':
2229                         {
2230                                 /* Spawn */
2231                                 do_cmd_options_aux(OPT_PAGE_PLAYRECORD, _("プレイ記録オプション", "Play-record Options"));
2232                                 break;
2233                         }
2234
2235                         /* Birth Options */
2236                         case 'B':
2237                         case 'b':
2238                         {
2239                                 /* Spawn */
2240                                 do_cmd_options_aux(OPT_PAGE_BIRTH, (!p_ptr->wizard || !allow_debug_opts) ? 
2241                                                         _("初期オプション(参照のみ)", "Birth Options(browse only)") : 
2242                                                         _("初期オプション((*)はスコアに影響)", "Birth Options((*)s effect score)"));
2243                                 break;
2244                         }
2245
2246                         /* Cheating Options */
2247                         case 'C':
2248                         {
2249                                 if (!p_ptr->noscore && !allow_debug_opts)
2250                                 {
2251                                         /* Cheat options are not permitted */
2252                                         bell();
2253                                         break;
2254                                 }
2255
2256                                 /* Spawn */
2257                                 do_cmd_options_cheat(_("詐欺師は決して勝利できない!", "Cheaters never win"));
2258                                 break;
2259                         }
2260
2261                         case 'a':
2262                         case 'A':
2263                         {
2264                                 do_cmd_options_autosave(_("自動セーブ", "Autosave"));
2265                                 break;
2266                         }
2267
2268                         /* Window flags */
2269                         case 'W':
2270                         case 'w':
2271                         {
2272                                 /* Spawn */
2273                                 do_cmd_options_win();
2274                                 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_SPELL |
2275                                                   PW_PLAYER | PW_MESSAGE | PW_OVERHEAD |
2276                                                         PW_MONSTER | PW_OBJECT | PW_SNAPSHOT |
2277                                                         PW_BORG_1 | PW_BORG_2 | PW_DUNGEON   |
2278                                                         PW_MONSTER_LIST);
2279                                 break;
2280                         }
2281
2282                         /* Auto-picker/destroyer editor */
2283                         case 'P':
2284                         case 'p':
2285                         {
2286                                 do_cmd_edit_autopick();
2287                                 break;
2288                         }
2289
2290                         /* Hack -- Delay Speed */
2291                         case 'D':
2292                         case 'd':
2293                         {
2294                                 /* Prompt */
2295                                 clear_from(18);
2296                                 prt(_("コマンド: 基本ウェイト量", "Command: Base Delay Factor"), 19, 0);
2297
2298                                 /* Get a new value */
2299                                 while (1)
2300                                 {
2301                                         int msec = delay_factor * delay_factor * delay_factor;
2302                                         prt(format(_("現在のウェイト: %d (%dミリ秒)", "Current base delay factor: %d (%d msec)"), delay_factor, msec), 22, 0);
2303                                         prt(_("ウェイト (0-9) ESCで決定: ", "Delay Factor (0-9 or ESC to accept): "), 20, 0);
2304                                         k = inkey();
2305                                         if (k == ESCAPE) break;
2306                                         else if (k == '?')
2307                                         {
2308                                                 (void)show_file(TRUE, _("joption.txt#BaseDelay", "option.txt#BaseDelay"), NULL, 0, 0);
2309                                                 Term_clear(); 
2310                                         }
2311                                         else if (isdigit(k)) delay_factor = D2I(k);
2312                                         else bell();
2313                                 }
2314
2315                                 break;
2316                         }
2317
2318                         /* Hack -- hitpoint warning factor */
2319                         case 'H':
2320                         case 'h':
2321                         {
2322                                 /* Prompt */
2323                                 clear_from(18);
2324                                 prt(_("コマンド: 低ヒットポイント警告", "Command: Hitpoint Warning"), 19, 0);
2325
2326                                 /* Get a new value */
2327                                 while (1)
2328                                 {
2329                                         prt(format(_("現在の低ヒットポイント警告: %d0%%", "Current hitpoint warning: %d0%%"), hitpoint_warn), 22, 0);
2330                                         prt(_("低ヒットポイント警告 (0-9) ESCで決定: ", "Hitpoint Warning (0-9 or ESC to accept): "), 20, 0);
2331                                         k = inkey();
2332                                         if (k == ESCAPE) break;
2333                                         else if (k == '?')
2334                                         {
2335                                                 (void)show_file(TRUE, _("joption.txt#Hitpoint", "option.txt#Hitpoint"), NULL, 0, 0);
2336                                                 Term_clear(); 
2337                                         }
2338                                         else if (isdigit(k)) hitpoint_warn = D2I(k);
2339                                         else bell();
2340                                 }
2341
2342                                 break;
2343                         }
2344
2345                         /* Hack -- mana color factor */
2346                         case 'M':
2347                         case 'm':
2348                         {
2349                                 /* Prompt */
2350                                 clear_from(18);
2351                                 prt(_("コマンド: 低魔力色閾値", "Command: Mana Color Threshold"), 19, 0);
2352                                 
2353                                 /* Get a new value */
2354                                 while (1)
2355                                 {
2356                                         prt(format(_("現在の低魔力色閾値: %d0%%", "Current mana color threshold: %d0%%"), mana_warn), 22, 0);
2357                                         prt(_("低魔力閾値 (0-9) ESCで決定: ", "Mana color Threshold (0-9 or ESC to accept): "), 20, 0);
2358                                         k = inkey();
2359                                         if (k == ESCAPE) break;
2360                                         else if (k == '?')
2361                                         {
2362                                                 (void)show_file(TRUE, _("joption.txt#Manapoint", "option.txt#Manapoint"), NULL, 0, 0);
2363                                                 Term_clear(); 
2364                                         }
2365                                         else if (isdigit(k)) mana_warn = D2I(k);
2366                                         else bell();
2367                                 }
2368
2369                                 break;
2370                         }
2371
2372                         case '?':
2373                                 (void)show_file(TRUE, _("joption.txt", "option.txt"), NULL, 0, 0);
2374                                 Term_clear(); 
2375                                 break;
2376
2377                         /* Unknown option */
2378                         default:
2379                         {
2380                                 /* Oops */
2381                                 bell();
2382                                 break;
2383                         }
2384                 }
2385
2386                 /* Flush messages */
2387                 msg_print(NULL);
2388         }
2389
2390
2391         /* Restore the screen */
2392         screen_load();
2393
2394         /* Hack - Redraw equippy chars */
2395         p_ptr->redraw |= (PR_EQUIPPY);
2396 }
2397
2398
2399
2400 /*!
2401  * @brief prefファイルを選択して処理する /
2402  * Ask for a "user pref line" and process it
2403  * @return なし
2404  * @details
2405  * XXX XXX XXX Allow absolute file names?
2406  */
2407 void do_cmd_pref(void)
2408 {
2409         char buf[80];
2410
2411         /* Default */
2412         strcpy(buf, "");
2413
2414         /* Ask for a "user pref command" */
2415         if (!get_string(_("設定変更コマンド: ", "Pref: "), buf, 80)) return;
2416
2417         /* Process that pref command */
2418         (void)process_pref_file_command(buf);
2419 }
2420
2421 /*!
2422  * @brief 自動拾い設定ファイルをロードするコマンドのメインルーチン /
2423  * @return なし
2424  */
2425 void do_cmd_reload_autopick(void)
2426 {
2427         if (!get_check(_("自動拾い設定ファイルをロードしますか? ", "Reload auto-pick preference file? "))) return;
2428         /* Load the file with messages */
2429         autopick_load_pref(TRUE);
2430 }
2431
2432 #ifdef ALLOW_MACROS
2433
2434 /*!
2435  * @brief マクロ情報をprefファイルに保存する /
2436  * @param fname ファイル名
2437  * @return なし
2438  */
2439 static errr macro_dump(cptr fname)
2440 {
2441         static cptr mark = "Macro Dump";
2442
2443         int i;
2444
2445         char buf[1024];
2446
2447         /* Build the filename */
2448         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
2449
2450         /* File type is "TEXT" */
2451         FILE_TYPE(FILE_TYPE_TEXT);
2452
2453         /* Append to the file */
2454         if (!open_auto_dump(buf, mark)) return (-1);
2455
2456         /* Start dumping */
2457         auto_dump_printf(_("\n# 自動マクロセーブ\n\n", "\n# Automatic macro dump\n\n"));
2458         
2459         /* Dump them */
2460         for (i = 0; i < macro__num; i++)
2461         {
2462                 /* Extract the action */
2463                 ascii_to_text(buf, macro__act[i]);
2464
2465                 /* Dump the macro */
2466                 auto_dump_printf("A:%s\n", buf);
2467
2468                 /* Extract the action */
2469                 ascii_to_text(buf, macro__pat[i]);
2470
2471                 /* Dump normal macros */
2472                 auto_dump_printf("P:%s\n", buf);
2473
2474                 /* End the macro */
2475                 auto_dump_printf("\n");
2476         }
2477
2478         /* Close */
2479         close_auto_dump();
2480
2481         /* Success */
2482         return (0);
2483 }
2484
2485
2486 /*!
2487  * @brief マクロのトリガーキーを取得する /
2488  * Hack -- ask for a "trigger" (see below)
2489  * @param buf キー表記を保管するバッファ
2490  * @return なし
2491  * @details
2492  * <pre>
2493  * Note the complex use of the "inkey()" function from "util.c".
2494  *
2495  * Note that both "flush()" calls are extremely important.
2496  * </pre>
2497  */
2498 static void do_cmd_macro_aux(char *buf)
2499 {
2500         int i, n = 0;
2501
2502         char tmp[1024];
2503
2504
2505         /* Flush */
2506         flush();
2507
2508         /* Do not process macros */
2509         inkey_base = TRUE;
2510
2511         /* First key */
2512         i = inkey();
2513
2514         /* Read the pattern */
2515         while (i)
2516         {
2517                 /* Save the key */
2518                 buf[n++] = i;
2519
2520                 /* Do not process macros */
2521                 inkey_base = TRUE;
2522
2523                 /* Do not wait for keys */
2524                 inkey_scan = TRUE;
2525
2526                 /* Attempt to read a key */
2527                 i = inkey();
2528         }
2529
2530         /* Terminate */
2531         buf[n] = '\0';
2532
2533         /* Flush */
2534         flush();
2535
2536
2537         /* Convert the trigger */
2538         ascii_to_text(tmp, buf);
2539
2540         /* Hack -- display the trigger */
2541         Term_addstr(-1, TERM_WHITE, tmp);
2542 }
2543
2544 #endif
2545
2546 /*!
2547  * @brief マクロのキー表記からアスキーコードを得てターミナルに表示する /
2548  * Hack -- ask for a keymap "trigger" (see below)
2549  * @param buf キー表記を取得するバッファ
2550  * @return なし
2551  * @details
2552  * <pre>
2553  * Note that both "flush()" calls are extremely important.  This may
2554  * no longer be true, since "util.c" is much simpler now.  XXX XXX XXX
2555  * </pre>
2556  */
2557 static void do_cmd_macro_aux_keymap(char *buf)
2558 {
2559         char tmp[1024];
2560
2561
2562         /* Flush */
2563         flush();
2564
2565
2566         /* Get a key */
2567         buf[0] = inkey();
2568         buf[1] = '\0';
2569
2570
2571         /* Convert to ascii */
2572         ascii_to_text(tmp, buf);
2573
2574         /* Hack -- display the trigger */
2575         Term_addstr(-1, TERM_WHITE, tmp);
2576
2577
2578         /* Flush */
2579         flush();
2580 }
2581
2582
2583 /*!
2584  * @brief キーマップをprefファイルにダンプする /
2585  * Hack -- append all keymaps to the given file
2586  * @param fname ファイルネーム
2587  * @return エラーコード
2588  * @details
2589  */
2590 static errr keymap_dump(cptr fname)
2591 {
2592         static cptr mark = "Keymap Dump";
2593         int i;
2594
2595         char key[1024];
2596         char buf[1024];
2597
2598         int mode;
2599
2600         /* Roguelike */
2601         if (rogue_like_commands)
2602         {
2603                 mode = KEYMAP_MODE_ROGUE;
2604         }
2605
2606         /* Original */
2607         else
2608         {
2609                 mode = KEYMAP_MODE_ORIG;
2610         }
2611
2612
2613         /* Build the filename */
2614         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
2615
2616         /* File type is "TEXT" */
2617         FILE_TYPE(FILE_TYPE_TEXT);
2618
2619         /* Append to the file */
2620         if (!open_auto_dump(buf, mark)) return -1;
2621
2622         /* Start dumping */
2623         auto_dump_printf(_("\n# 自動キー配置セーブ\n\n", "\n# Automatic keymap dump\n\n"));
2624         
2625         /* Dump them */
2626         for (i = 0; i < 256; i++)
2627         {
2628                 cptr act;
2629
2630                 /* Loop up the keymap */
2631                 act = keymap_act[mode][i];
2632
2633                 /* Skip empty keymaps */
2634                 if (!act) continue;
2635
2636                 /* Encode the key */
2637                 buf[0] = i;
2638                 buf[1] = '\0';
2639                 ascii_to_text(key, buf);
2640
2641                 /* Encode the action */
2642                 ascii_to_text(buf, act);
2643
2644                 /* Dump the macro */
2645                 auto_dump_printf("A:%s\n", buf);
2646                 auto_dump_printf("C:%d:%s\n", mode, key);
2647         }
2648
2649         /* Close */
2650         close_auto_dump();
2651
2652         /* Success */
2653         return (0);
2654 }
2655
2656
2657 /*!
2658  * @brief マクロを設定するコマンドのメインルーチン /
2659  * Interact with "macros"
2660  * @return なし
2661  * @details
2662  * <pre>
2663  * Note that the macro "action" must be defined before the trigger.
2664  *
2665  * Could use some helpful instructions on this page.  XXX XXX XXX
2666  * </pre>
2667  */
2668 void do_cmd_macros(void)
2669 {
2670         int i;
2671
2672         char tmp[1024];
2673
2674         char buf[1024];
2675
2676         int mode;
2677
2678
2679         /* Roguelike */
2680         if (rogue_like_commands)
2681         {
2682                 mode = KEYMAP_MODE_ROGUE;
2683         }
2684
2685         /* Original */
2686         else
2687         {
2688                 mode = KEYMAP_MODE_ORIG;
2689         }
2690
2691         /* File type is "TEXT" */
2692         FILE_TYPE(FILE_TYPE_TEXT);
2693
2694
2695         /* Save screen */
2696         screen_save();
2697
2698
2699         /* Process requests until done */
2700         while (1)
2701         {
2702                 /* Clear screen */
2703                 Term_clear();
2704
2705                 /* Describe */
2706                 prt(_("[ マクロの設定 ]", "Interact with Macros"), 2, 0);
2707
2708                 /* Describe that action */
2709                 prt(_("マクロ行動が(もしあれば)下に表示されます:", "Current action (if any) shown below:"), 20, 0);
2710
2711                 /* Analyze the current action */
2712                 ascii_to_text(buf, macro__buf);
2713
2714                 /* Display the current action */
2715                 prt(buf, 22, 0);
2716
2717
2718                 /* Selections */
2719                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
2720 #ifdef ALLOW_MACROS
2721                 prt(_("(2) ファイルにマクロを追加", "(2) Append macros to a file"), 5, 5);
2722                 prt(_("(3) マクロの確認", "(3) Query a macro"), 6, 5);
2723                 prt(_("(4) マクロの作成", "(4) Create a macro"), 7, 5);
2724                 prt(_("(5) マクロの削除", "(5) Remove a macro"), 8, 5);
2725                 prt(_("(6) ファイルにキー配置を追加", "(6) Append keymaps to a file"), 9, 5);
2726                 prt(_("(7) キー配置の確認", "(7) Query a keymap"), 10, 5);
2727                 prt(_("(8) キー配置の作成", "(8) Create a keymap"), 11, 5);
2728                 prt(_("(9) キー配置の削除", "(9) Remove a keymap"), 12, 5);
2729                 prt(_("(0) マクロ行動の入力", "(0) Enter a new action"), 13, 5);
2730 #endif /* ALLOW_MACROS */
2731
2732                 /* Prompt */
2733                 prt(_("コマンド: ", "Command: "), 16, 0);
2734
2735                 /* Get a command */
2736                 i = inkey();
2737
2738                 /* Leave */
2739                 if (i == ESCAPE) break;
2740
2741                 /* Load a 'macro' file */
2742                 else if (i == '1')
2743                 {
2744                         errr err;
2745
2746                         /* Prompt */
2747                         prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 16, 0);
2748
2749                         /* Prompt */
2750                         prt(_("ファイル: ", "File: "), 18, 0);
2751
2752                         /* Default filename */
2753                         sprintf(tmp, "%s.prf", player_base);
2754
2755                         /* Ask for a file */
2756                         if (!askfor(tmp, 80)) continue;
2757
2758                         /* Process the given filename */
2759                         err = process_pref_file(tmp);
2760                         if (-2 == err)
2761                         {
2762                                 msg_format(_("標準の設定ファイル'%s'を読み込みました。", "Loaded default '%s'."), tmp);
2763                         }
2764                         else if (err)
2765                         {
2766                                 /* Prompt */
2767                                 msg_format(_("'%s'の読み込みに失敗しました!", "Failed to load '%s'!"), tmp);
2768                         }
2769                         else
2770                         {
2771                                 msg_format(_("'%s'を読み込みました。", "Loaded '%s'."), tmp);
2772                         }
2773                 }
2774
2775 #ifdef ALLOW_MACROS
2776
2777                 /* Save macros */
2778                 else if (i == '2')
2779                 {
2780                         /* Prompt */
2781                         prt(_("コマンド: マクロをファイルに追加する", "Command: Append macros to a file"), 16, 0);
2782
2783                         /* Prompt */
2784                         prt(_("ファイル: ", "File: "), 18, 0);
2785
2786                         /* Default filename */
2787                         sprintf(tmp, "%s.prf", player_base);
2788
2789                         /* Ask for a file */
2790                         if (!askfor(tmp, 80)) continue;
2791
2792                         /* Dump the macros */
2793                         (void)macro_dump(tmp);
2794
2795                         /* Prompt */
2796                         msg_print(_("マクロを追加しました。", "Appended macros."));
2797                 }
2798
2799                 /* Query a macro */
2800                 else if (i == '3')
2801                 {
2802                         int k;
2803
2804                         /* Prompt */
2805                         prt(_("コマンド: マクロの確認", "Command: Query a macro"), 16, 0);
2806
2807
2808                         /* Prompt */
2809                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
2810
2811                         /* Get a macro trigger */
2812                         do_cmd_macro_aux(buf);
2813
2814                         /* Acquire action */
2815                         k = macro_find_exact(buf);
2816
2817                         /* Nothing found */
2818                         if (k < 0)
2819                         {
2820                                 /* Prompt */
2821                                 msg_print(_("そのキーにはマクロは定義されていません。", "Found no macro."));
2822                         }
2823
2824                         /* Found one */
2825                         else
2826                         {
2827                                 /* Obtain the action */
2828                                 strcpy(macro__buf, macro__act[k]);
2829
2830                                 /* Analyze the current action */
2831                                 ascii_to_text(buf, macro__buf);
2832
2833                                 /* Display the current action */
2834                                 prt(buf, 22, 0);
2835
2836                                 /* Prompt */
2837                                 msg_print(_("マクロを確認しました。", "Found a macro."));
2838                         }
2839                 }
2840
2841                 /* Create a macro */
2842                 else if (i == '4')
2843                 {
2844                         /* Prompt */
2845                         prt(_("コマンド: マクロの作成", "Command: Create a macro"), 16, 0);
2846
2847                         /* Prompt */
2848                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
2849
2850                         /* Get a macro trigger */
2851                         do_cmd_macro_aux(buf);
2852
2853                         /* Clear */
2854                         clear_from(20);
2855
2856                         /* Help message */
2857                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
2858                                                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
2859
2860                         /* Prompt */
2861                         prt(_("マクロ行動: ", "Action: "), 20, 0);
2862
2863                         /* Convert to text */
2864                         ascii_to_text(tmp, macro__buf);
2865
2866                         /* Get an encoded action */
2867                         if (askfor(tmp, 80))
2868                         {
2869                                 /* Convert to ascii */
2870                                 text_to_ascii(macro__buf, tmp);
2871
2872                                 /* Link the macro */
2873                                 macro_add(buf, macro__buf);
2874
2875                                 /* Prompt */
2876                                 msg_print(_("マクロを追加しました。", "Added a macro."));
2877                         }
2878                 }
2879
2880                 /* Remove a macro */
2881                 else if (i == '5')
2882                 {
2883                         /* Prompt */
2884                         prt(_("コマンド: マクロの削除", "Command: Remove a macro"), 16, 0);
2885
2886                         /* Prompt */
2887                         prt(_("トリガーキー: ", "Trigger: "), 18, 0);
2888
2889                         /* Get a macro trigger */
2890                         do_cmd_macro_aux(buf);
2891
2892                         /* Link the macro */
2893                         macro_add(buf, buf);
2894
2895                         /* Prompt */
2896                         msg_print(_("マクロを削除しました。", "Removed a macro."));
2897                 }
2898
2899                 /* Save keymaps */
2900                 else if (i == '6')
2901                 {
2902                         /* Prompt */
2903                         prt(_("コマンド: キー配置をファイルに追加する", "Command: Append keymaps to a file"), 16, 0);
2904
2905                         /* Prompt */
2906                         prt(_("ファイル: ", "File: "), 18, 0);
2907
2908                         /* Default filename */
2909                         sprintf(tmp, "%s.prf", player_base);
2910
2911                         /* Ask for a file */
2912                         if (!askfor(tmp, 80)) continue;
2913
2914                         /* Dump the macros */
2915                         (void)keymap_dump(tmp);
2916
2917                         /* Prompt */
2918                         msg_print(_("キー配置を追加しました。", "Appended keymaps."));
2919                 }
2920
2921                 /* Query a keymap */
2922                 else if (i == '7')
2923                 {
2924                         cptr act;
2925
2926                         /* Prompt */
2927                         prt(_("コマンド: キー配置の確認", "Command: Query a keymap"), 16, 0);
2928
2929                         /* Prompt */
2930                         prt(_("押すキー: ", "Keypress: "), 18, 0);
2931
2932                         /* Get a keymap trigger */
2933                         do_cmd_macro_aux_keymap(buf);
2934
2935                         /* Look up the keymap */
2936                         act = keymap_act[mode][(byte)(buf[0])];
2937
2938                         /* Nothing found */
2939                         if (!act)
2940                         {
2941                                 /* Prompt */
2942                                 msg_print(_("キー配置は定義されていません。", "Found no keymap."));
2943                         }
2944
2945                         /* Found one */
2946                         else
2947                         {
2948                                 /* Obtain the action */
2949                                 strcpy(macro__buf, act);
2950
2951                                 /* Analyze the current action */
2952                                 ascii_to_text(buf, macro__buf);
2953
2954                                 /* Display the current action */
2955                                 prt(buf, 22, 0);
2956
2957                                 /* Prompt */
2958                                 msg_print(_("キー配置を確認しました。", "Found a keymap."));
2959                         }
2960                 }
2961
2962                 /* Create a keymap */
2963                 else if (i == '8')
2964                 {
2965                         /* Prompt */
2966                         prt(_("コマンド: キー配置の作成", "Command: Create a keymap"), 16, 0);
2967
2968                         /* Prompt */
2969                         prt(_("押すキー: ", "Keypress: "), 18, 0);
2970
2971                         /* Get a keymap trigger */
2972                         do_cmd_macro_aux_keymap(buf);
2973
2974                         /* Clear */
2975                         clear_from(20);
2976
2977                         /* Help message */
2978                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
2979                                                             "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
2980
2981                         /* Prompt */
2982                         prt(_("行動: ", "Action: "), 20, 0);
2983
2984                         /* Convert to text */
2985                         ascii_to_text(tmp, macro__buf);
2986
2987                         /* Get an encoded action */
2988                         if (askfor(tmp, 80))
2989                         {
2990                                 /* Convert to ascii */
2991                                 text_to_ascii(macro__buf, tmp);
2992
2993                                 /* Free old keymap */
2994                                 string_free(keymap_act[mode][(byte)(buf[0])]);
2995
2996                                 /* Make new keymap */
2997                                 keymap_act[mode][(byte)(buf[0])] = string_make(macro__buf);
2998
2999                                 /* Prompt */
3000                                 msg_print(_("キー配置を追加しました。", "Added a keymap."));
3001                         }
3002                 }
3003
3004                 /* Remove a keymap */
3005                 else if (i == '9')
3006                 {
3007                         /* Prompt */
3008                         prt(_("コマンド: キー配置の削除", "Command: Remove a keymap"), 16, 0);
3009
3010                         /* Prompt */
3011                         prt(_("押すキー: ", "Keypress: "), 18, 0);
3012
3013                         /* Get a keymap trigger */
3014                         do_cmd_macro_aux_keymap(buf);
3015
3016                         /* Free old keymap */
3017                         string_free(keymap_act[mode][(byte)(buf[0])]);
3018
3019                         /* Make new keymap */
3020                         keymap_act[mode][(byte)(buf[0])] = NULL;
3021
3022                         /* Prompt */
3023                         msg_print(_("キー配置を削除しました。", "Removed a keymap."));
3024                 }
3025
3026                 /* Enter a new action */
3027                 else if (i == '0')
3028                 {
3029                         /* Prompt */
3030                         prt(_("コマンド: マクロ行動の入力", "Command: Enter a new action"), 16, 0);
3031
3032                         /* Clear */
3033                         clear_from(20);
3034
3035                         /* Help message */
3036                         c_prt(TERM_L_RED, _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
3037                                                                 "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."), 22, 0);
3038
3039                         /* Prompt */
3040                         prt(_("マクロ行動: ", "Action: "), 20, 0);
3041
3042                         /* Hack -- limit the value */
3043                         tmp[80] = '\0';
3044
3045                         /* Get an encoded action */
3046                         if (!askfor(buf, 80)) continue;
3047
3048                         /* Extract an action */
3049                         text_to_ascii(macro__buf, buf);
3050                 }
3051
3052 #endif /* ALLOW_MACROS */
3053
3054                 /* Oops */
3055                 else
3056                 {
3057                         /* Oops */
3058                         bell();
3059                 }
3060
3061                 /* Flush messages */
3062                 msg_print(NULL);
3063         }
3064
3065         /* Load screen */
3066         screen_load();
3067 }
3068
3069 /*!
3070  * @brief キャラクタ色の明暗表現
3071  */
3072 static cptr lighting_level_str[F_LIT_MAX] =
3073 {
3074 #ifdef JP
3075         "標準色",
3076         "明色",
3077         "暗色",
3078 #else
3079         "standard",
3080         "brightly lit",
3081         "darkened",
3082 #endif
3083 };
3084
3085
3086 /*!
3087  * @brief キャラクタのビジュアルIDを変更する際の対象指定関数
3088  * @param i 指定対象となるキャラクタコード
3089  * @param num 指定されたビジュアルIDを返す参照ポインタ
3090  * @param max ビジュアルIDの最大数
3091  * @return 指定が実際に行われた場合TRUE、キャンセルされた場合FALSE
3092  */
3093 static bool cmd_visuals_aux(int i, int *num, int max)
3094 {
3095         if (iscntrl(i))
3096         {
3097                 char str[10] = "";
3098                 int tmp;
3099
3100                 sprintf(str, "%d", *num);
3101
3102                 if (!get_string(format("Input new number(0-%d): ", max-1), str, 4))
3103                         return FALSE;
3104
3105                 tmp = strtol(str, NULL, 0);
3106                 if (tmp >= 0 && tmp < max)
3107                         *num = tmp;
3108         }
3109         else if (isupper(i))
3110                 *num = (*num + max - 1) % max;
3111         else
3112                 *num = (*num + 1) % max;
3113
3114         return TRUE;
3115 }
3116
3117 /*!
3118  * @brief キャラクタの変更メニュー表示
3119  * @param choice_msg 選択メッセージ
3120  * @return なし
3121  */
3122 static void print_visuals_menu(cptr choice_msg)
3123 {
3124         prt(_("[ 画面表示の設定 ]", "Interact with Visuals"), 1, 0);
3125         
3126         /* Give some choices */
3127         prt(_("(0) ユーザー設定ファイルのロード", "(0) Load a user pref file"), 3, 5);
3128         
3129 #ifdef ALLOW_VISUALS
3130         prt(_("(1) モンスターの 色/文字 をファイルに書き出す", "(1) Dump monster attr/chars"), 4, 5);
3131         prt(_("(2) アイテムの   色/文字 をファイルに書き出す", "(2) Dump object attr/chars"), 5, 5);
3132         prt(_("(3) 地形の       色/文字 をファイルに書き出す", "(3) Dump feature attr/chars"), 6, 5);
3133         prt(_("(4) モンスターの 色/文字 を変更する (数値操作)", "(4) Change monster attr/chars (numeric operation)"), 7, 5);
3134         prt(_("(5) アイテムの   色/文字 を変更する (数値操作)", "(5) Change object attr/chars (numeric operation)"), 8, 5);
3135         prt(_("(6) 地形の       色/文字 を変更する (数値操作)", "(6) Change feature attr/chars (numeric operation)"), 9, 5);
3136         prt(_("(7) モンスターの 色/文字 を変更する (シンボルエディタ)", "(7) Change monster attr/chars (visual mode)"), 10, 5);
3137         prt(_("(8) アイテムの   色/文字 を変更する (シンボルエディタ)", "(8) Change object attr/chars (visual mode)"), 11, 5);
3138         prt(_("(9) 地形の       色/文字 を変更する (シンボルエディタ)", "(9) Change feature attr/chars (visual mode)"), 12, 5);
3139 #endif /* ALLOW_VISUALS */
3140
3141         prt(_("(R) 画面表示方法の初期化", "(R) Reset visuals"), 13, 5);
3142
3143         /* Prompt */
3144         prt(format("コマンド: %s", choice_msg ? choice_msg : _("", "")), 15, 0);
3145 }
3146
3147 static void do_cmd_knowledge_monsters(bool *need_redraw, bool visual_only, int direct_r_idx);
3148 static void do_cmd_knowledge_objects(bool *need_redraw, bool visual_only, int direct_k_idx);
3149 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, int direct_f_idx, int *lighting_level);
3150
3151 /*
3152  * Interact with "visuals"
3153  */
3154 void do_cmd_visuals(void)
3155 {
3156         int i;
3157         char tmp[160];
3158         char buf[1024];
3159         bool need_redraw = FALSE;
3160         const char *empty_symbol = "<< ? >>";
3161
3162         if (use_bigtile) empty_symbol = "<< ?? >>";
3163
3164         /* File type is "TEXT" */
3165         FILE_TYPE(FILE_TYPE_TEXT);
3166
3167         /* Save the screen */
3168         screen_save();
3169
3170         /* Interact until done */
3171         while (1)
3172         {
3173                 /* Clear screen */
3174                 Term_clear();
3175
3176                 /* Ask for a choice */
3177                 print_visuals_menu(NULL);
3178
3179                 /* Prompt */
3180                 i = inkey();
3181
3182                 /* Done */
3183                 if (i == ESCAPE) break;
3184
3185                 switch (i)
3186                 {
3187                 /* Load a 'pref' file */
3188                 case '0':
3189                         /* Prompt */
3190                         prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 15, 0);
3191
3192                         /* Prompt */
3193                         prt(_("ファイル: ", "File: "), 17, 0);
3194
3195                         /* Default filename */
3196                         sprintf(tmp, "%s.prf", player_base);
3197
3198                         /* Query */
3199                         if (!askfor(tmp, 70)) continue;
3200
3201                         /* Process the given filename */
3202                         (void)process_pref_file(tmp);
3203
3204                         need_redraw = TRUE;
3205                         break;
3206
3207 #ifdef ALLOW_VISUALS
3208
3209                 /* Dump monster attr/chars */
3210                 case '1':
3211                 {
3212                         static cptr mark = "Monster attr/chars";
3213
3214                         /* Prompt */
3215                         prt(_("コマンド: モンスターの[色/文字]をファイルに書き出します", "Command: Dump monster attr/chars"), 15, 0);
3216
3217                         /* Prompt */
3218                         prt(_("ファイル: ", "File: "), 17, 0);
3219
3220                         /* Default filename */
3221                         sprintf(tmp, "%s.prf", player_base);
3222
3223                         /* Get a filename */
3224                         if (!askfor(tmp, 70)) continue;
3225
3226                         /* Build the filename */
3227                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
3228
3229                         /* Append to the file */
3230                         if (!open_auto_dump(buf, mark)) continue;
3231
3232                         /* Start dumping */
3233                         auto_dump_printf(_("\n# モンスターの[色/文字]の設定\n\n", "\n# Monster attr/char definitions\n\n"));
3234
3235                         /* Dump monsters */
3236                         for (i = 0; i < max_r_idx; i++)
3237                         {
3238                                 monster_race *r_ptr = &r_info[i];
3239
3240                                 /* Skip non-entries */
3241                                 if (!r_ptr->name) continue;
3242
3243                                 /* Dump a comment */
3244                                 auto_dump_printf("# %s\n", (r_name + r_ptr->name));
3245
3246                                 /* Dump the monster attr/char info */
3247                                 auto_dump_printf("R:%d:0x%02X/0x%02X\n\n", i,
3248                                         (byte)(r_ptr->x_attr), (byte)(r_ptr->x_char));
3249                         }
3250
3251                         /* Close */
3252                         close_auto_dump();
3253
3254                         /* Message */
3255                         msg_print(_("モンスターの[色/文字]をファイルに書き出しました。", "Dumped monster attr/chars."));
3256
3257                         break;
3258                 }
3259
3260                 /* Dump object attr/chars */
3261                 case '2':
3262                 {
3263                         static cptr mark = "Object attr/chars";
3264
3265                         /* Prompt */
3266                         prt(_("コマンド: アイテムの[色/文字]をファイルに書き出します", "Command: Dump object attr/chars"), 15, 0);
3267
3268                         /* Prompt */
3269                         prt(_("ファイル: ", "File: "), 17, 0);
3270
3271                         /* Default filename */
3272                         sprintf(tmp, "%s.prf", player_base);
3273
3274                         /* Get a filename */
3275                         if (!askfor(tmp, 70)) continue;
3276
3277                         /* Build the filename */
3278                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
3279
3280                         /* Append to the file */
3281                         if (!open_auto_dump(buf, mark)) continue;
3282
3283                         /* Start dumping */
3284                         auto_dump_printf(_("\n# アイテムの[色/文字]の設定\n\n", "\n# Object attr/char definitions\n\n"));
3285
3286                         /* Dump objects */
3287                         for (i = 0; i < max_k_idx; i++)
3288                         {
3289                                 char o_name[80];
3290                                 object_kind *k_ptr = &k_info[i];
3291
3292                                 /* Skip non-entries */
3293                                 if (!k_ptr->name) continue;
3294
3295                                 if (!k_ptr->flavor)
3296                                 {
3297                                         /* Tidy name */
3298                                         strip_name(o_name, i);
3299                                 }
3300                                 else
3301                                 {
3302                                         object_type forge;
3303
3304                                         /* Prepare dummy object */
3305                                         object_prep(&forge, i);
3306
3307                                         /* Get un-shuffled flavor name */
3308                                         object_desc(o_name, &forge, OD_FORCE_FLAVOR);
3309                                 }
3310
3311                                 /* Dump a comment */
3312                                 auto_dump_printf("# %s\n", o_name);
3313
3314                                 /* Dump the object attr/char info */
3315                                 auto_dump_printf("K:%d:0x%02X/0x%02X\n\n", i,
3316                                         (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char));
3317                         }
3318
3319                         /* Close */
3320                         close_auto_dump();
3321
3322                         /* Message */
3323                         msg_print(_("アイテムの[色/文字]をファイルに書き出しました。", "Dumped object attr/chars."));
3324
3325                         break;
3326                 }
3327
3328                 /* Dump feature attr/chars */
3329                 case '3':
3330                 {
3331                         static cptr mark = "Feature attr/chars";
3332
3333                         /* Prompt */
3334                         prt(_("コマンド: 地形の[色/文字]をファイルに書き出します", "Command: Dump feature attr/chars"), 15, 0);
3335
3336                         /* Prompt */
3337                         prt(_("ファイル: ", "File: "), 17, 0);
3338
3339                         /* Default filename */
3340                         sprintf(tmp, "%s.prf", player_base);
3341
3342                         /* Get a filename */
3343                         if (!askfor(tmp, 70)) continue;
3344
3345                         /* Build the filename */
3346                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
3347
3348                         /* Append to the file */
3349                         if (!open_auto_dump(buf, mark)) continue;
3350
3351                         /* Start dumping */
3352                         auto_dump_printf(_("\n# 地形の[色/文字]の設定\n\n", "\n# Feature attr/char definitions\n\n"));
3353
3354                         /* Dump features */
3355                         for (i = 0; i < max_f_idx; i++)
3356                         {
3357                                 feature_type *f_ptr = &f_info[i];
3358
3359                                 /* Skip non-entries */
3360                                 if (!f_ptr->name) continue;
3361
3362                                 /* Skip mimiccing features */
3363                                 if (f_ptr->mimic != i) continue;
3364
3365                                 /* Dump a comment */
3366                                 auto_dump_printf("# %s\n", (f_name + f_ptr->name));
3367
3368                                 /* Dump the feature attr/char info */
3369                                 auto_dump_printf("F:%d:0x%02X/0x%02X:0x%02X/0x%02X:0x%02X/0x%02X\n\n", i,
3370                                         (byte)(f_ptr->x_attr[F_LIT_STANDARD]), (byte)(f_ptr->x_char[F_LIT_STANDARD]),
3371                                         (byte)(f_ptr->x_attr[F_LIT_LITE]), (byte)(f_ptr->x_char[F_LIT_LITE]),
3372                                         (byte)(f_ptr->x_attr[F_LIT_DARK]), (byte)(f_ptr->x_char[F_LIT_DARK]));
3373                         }
3374
3375                         /* Close */
3376                         close_auto_dump();
3377
3378                         /* Message */
3379                         msg_print(_("地形の[色/文字]をファイルに書き出しました。", "Dumped feature attr/chars."));
3380
3381                         break;
3382                 }
3383
3384                 /* Modify monster attr/chars (numeric operation) */
3385                 case '4':
3386                 {
3387                         static cptr choice_msg = _("モンスターの[色/文字]を変更します", "Change monster attr/chars");
3388                         static int r = 0;
3389
3390                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
3391
3392                         /* Hack -- query until done */
3393                         while (1)
3394                         {
3395                                 monster_race *r_ptr = &r_info[r];
3396                                 char c;
3397                                 int t;
3398
3399                                 byte da = r_ptr->d_attr;
3400                                 byte dc = r_ptr->d_char;
3401                                 byte ca = r_ptr->x_attr;
3402                                 byte cc = r_ptr->x_char;
3403
3404                                 /* Label the object */
3405                                 Term_putstr(5, 17, -1, TERM_WHITE,
3406                                          format(_("モンスター = %d, 名前 = %-40.40s", "Monster = %d, Name = %-40.40s"), r, (r_name + r_ptr->name)));
3407
3408                                 /* Label the Default values */
3409                                 Term_putstr(10, 19, -1, TERM_WHITE,
3410                                         format(_("初期値  色 / 文字 = %3u / %3u", "Default attr/char = %3u / %3u"), da, dc));
3411
3412                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
3413                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
3414
3415                                 /* Label the Current values */
3416                                 Term_putstr(10, 20, -1, TERM_WHITE,
3417                                         format(_("現在値  色 / 文字 = %3u / %3u", "Current attr/char = %3u / %3u"), ca, cc));
3418
3419                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
3420                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
3421
3422                                 /* Prompt */
3423                                 Term_putstr(0, 22, -1, TERM_WHITE, 
3424                                         _("コマンド (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): "));
3425
3426                                 /* Get a command */
3427                                 i = inkey();
3428
3429                                 /* All done */
3430                                 if (i == ESCAPE) break;
3431
3432                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
3433                                 else if (isupper(i)) c = 'a' + i - 'A';
3434                                 else c = i;
3435
3436                                 switch (c)
3437                                 {
3438                                 case 'n':
3439                                         {
3440                                                 int prev_r = r;
3441                                                 do
3442                                                 {
3443                                                         if (!cmd_visuals_aux(i, &r, max_r_idx))
3444                                                         {
3445                                                                 r = prev_r;
3446                                                                 break;
3447                                                         }
3448                                                 }
3449                                                 while (!r_info[r].name);
3450                                         }
3451                                         break;
3452                                 case 'a':
3453                                         t = (int)r_ptr->x_attr;
3454                                         (void)cmd_visuals_aux(i, &t, 256);
3455                                         r_ptr->x_attr = (byte)t;
3456                                         need_redraw = TRUE;
3457                                         break;
3458                                 case 'c':
3459                                         t = (int)r_ptr->x_char;
3460                                         (void)cmd_visuals_aux(i, &t, 256);
3461                                         r_ptr->x_char = (byte)t;
3462                                         need_redraw = TRUE;
3463                                         break;
3464                                 case 'v':
3465                                         do_cmd_knowledge_monsters(&need_redraw, TRUE, r);
3466
3467                                         /* Clear screen */
3468                                         Term_clear();
3469                                         print_visuals_menu(choice_msg);
3470                                         break;
3471                                 }
3472                         }
3473
3474                         break;
3475                 }
3476
3477                 /* Modify object attr/chars (numeric operation) */
3478                 case '5':
3479                 {
3480                         static cptr choice_msg = _("アイテムの[色/文字]を変更します", "Change object attr/chars");
3481                         static int k = 0;
3482                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
3483
3484                         /* Hack -- query until done */
3485                         while (1)
3486                         {
3487                                 object_kind *k_ptr = &k_info[k];
3488                                 char c;
3489                                 int t;
3490
3491                                 byte da = k_ptr->d_attr;
3492                                 byte dc = k_ptr->d_char;
3493                                 byte ca = k_ptr->x_attr;
3494                                 byte cc = k_ptr->x_char;
3495
3496                                 /* Label the object */
3497                                 Term_putstr(5, 17, -1, TERM_WHITE,
3498                                             format(_("アイテム = %d, 名前 = %-40.40s", "Object = %d, Name = %-40.40s"),
3499                                                    k, k_name + (!k_ptr->flavor ? k_ptr->name : k_ptr->flavor_name)));
3500
3501                                 /* Label the Default values */
3502                                 Term_putstr(10, 19, -1, TERM_WHITE,
3503                                             format(_("初期値  色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
3504
3505                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
3506                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
3507
3508                                 /* Label the Current values */
3509                                 Term_putstr(10, 20, -1, TERM_WHITE,
3510                                             format(_("現在値  色 / 文字 = %3d / %3d", "Current attr/char = %3d / %3d"), ca, cc));
3511
3512                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
3513                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
3514
3515                                 /* Prompt */
3516                                 Term_putstr(0, 22, -1, TERM_WHITE,
3517                                             _("コマンド (n/N/^N/a/A/^A/c/C/^C/v/V/^V): ", "Command (n/N/^N/a/A/^A/c/C/^C/v/V/^V): "));
3518
3519                                 /* Get a command */
3520                                 i = inkey();
3521
3522                                 /* All done */
3523                                 if (i == ESCAPE) break;
3524
3525                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
3526                                 else if (isupper(i)) c = 'a' + i - 'A';
3527                                 else c = i;
3528
3529                                 switch (c)
3530                                 {
3531                                 case 'n':
3532                                         {
3533                                                 int prev_k = k;
3534                                                 do
3535                                                 {
3536                                                         if (!cmd_visuals_aux(i, &k, max_k_idx))
3537                                                         {
3538                                                                 k = prev_k;
3539                                                                 break;
3540                                                         }
3541                                                 }
3542                                                 while (!k_info[k].name);
3543                                         }
3544                                         break;
3545                                 case 'a':
3546                                         t = (int)k_ptr->x_attr;
3547                                         (void)cmd_visuals_aux(i, &t, 256);
3548                                         k_ptr->x_attr = (byte)t;
3549                                         need_redraw = TRUE;
3550                                         break;
3551                                 case 'c':
3552                                         t = (int)k_ptr->x_char;
3553                                         (void)cmd_visuals_aux(i, &t, 256);
3554                                         k_ptr->x_char = (byte)t;
3555                                         need_redraw = TRUE;
3556                                         break;
3557                                 case 'v':
3558                                         do_cmd_knowledge_objects(&need_redraw, TRUE, k);
3559
3560                                         /* Clear screen */
3561                                         Term_clear();
3562                                         print_visuals_menu(choice_msg);
3563                                         break;
3564                                 }
3565                         }
3566
3567                         break;
3568                 }
3569
3570                 /* Modify feature attr/chars (numeric operation) */
3571                 case '6':
3572                 {
3573                         static cptr choice_msg = _("地形の[色/文字]を変更します", "Change feature attr/chars");
3574                         static int f = 0;
3575                         static int lighting_level = F_LIT_STANDARD;
3576                         prt(format(_("コマンド: %s", "Command: %s"), choice_msg), 15, 0);
3577
3578                         /* Hack -- query until done */
3579                         while (1)
3580                         {
3581                                 feature_type *f_ptr = &f_info[f];
3582                                 char c;
3583                                 int t;
3584
3585                                 byte da = f_ptr->d_attr[lighting_level];
3586                                 byte dc = f_ptr->d_char[lighting_level];
3587                                 byte ca = f_ptr->x_attr[lighting_level];
3588                                 byte cc = f_ptr->x_char[lighting_level];
3589
3590                                 /* Label the object */
3591                                 prt("", 17, 5);
3592                                 Term_putstr(5, 17, -1, TERM_WHITE,
3593                                             format(_("地形 = %d, 名前 = %s, 明度 = %s", "Terrain = %d, Name = %s, Lighting = %s"),
3594                                                    f, (f_name + f_ptr->name), lighting_level_str[lighting_level]));
3595
3596                                 /* Label the Default values */
3597                                 Term_putstr(10, 19, -1, TERM_WHITE,
3598                                             format(_("初期値  色 / 文字 = %3d / %3d", "Default attr/char = %3d / %3d"), da, dc));
3599
3600                                 Term_putstr(40, 19, -1, TERM_WHITE, empty_symbol);
3601                                 Term_queue_bigchar(43, 19, da, dc, 0, 0);
3602
3603                                 /* Label the Current values */
3604 #ifdef JP
3605                                 Term_putstr(10, 20, -1, TERM_WHITE,
3606                                             format("現在値  色 / 文字 = %3d / %3d", ca, cc));
3607 #else
3608                                 Term_putstr(10, 20, -1, TERM_WHITE,
3609                                             format("Current attr/char = %3d / %3d", ca, cc));
3610 #endif
3611
3612                                 Term_putstr(40, 20, -1, TERM_WHITE, empty_symbol);
3613                                 Term_queue_bigchar(43, 20, ca, cc, 0, 0);
3614
3615                                 /* Prompt */
3616 #ifdef JP
3617                                 Term_putstr(0, 22, -1, TERM_WHITE,
3618                                             "コマンド (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ");
3619 #else
3620                                 Term_putstr(0, 22, -1, TERM_WHITE,
3621                                             "Command (n/N/^N/a/A/^A/c/C/^C/l/L/^L/d/D/^D/v/V/^V): ");
3622 #endif
3623
3624                                 /* Get a command */
3625                                 i = inkey();
3626
3627                                 /* All done */
3628                                 if (i == ESCAPE) break;
3629
3630                                 if (iscntrl(i)) c = 'a' + i - KTRL('A');
3631                                 else if (isupper(i)) c = 'a' + i - 'A';
3632                                 else c = i;
3633
3634                                 switch (c)
3635                                 {
3636                                 case 'n':
3637                                         {
3638                                                 int prev_f = f;
3639                                                 do
3640                                                 {
3641                                                         if (!cmd_visuals_aux(i, &f, max_f_idx))
3642                                                         {
3643                                                                 f = prev_f;
3644                                                                 break;
3645                                                         }
3646                                                 }
3647                                                 while (!f_info[f].name || (f_info[f].mimic != f));
3648                                         }
3649                                         break;
3650                                 case 'a':
3651                                         t = (int)f_ptr->x_attr[lighting_level];
3652                                         (void)cmd_visuals_aux(i, &t, 256);
3653                                         f_ptr->x_attr[lighting_level] = (byte)t;
3654                                         need_redraw = TRUE;
3655                                         break;
3656                                 case 'c':
3657                                         t = (int)f_ptr->x_char[lighting_level];
3658                                         (void)cmd_visuals_aux(i, &t, 256);
3659                                         f_ptr->x_char[lighting_level] = (byte)t;
3660                                         need_redraw = TRUE;
3661                                         break;
3662                                 case 'l':
3663                                         (void)cmd_visuals_aux(i, &lighting_level, F_LIT_MAX);
3664                                         break;
3665                                 case 'd':
3666                                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
3667                                         need_redraw = TRUE;
3668                                         break;
3669                                 case 'v':
3670                                         do_cmd_knowledge_features(&need_redraw, TRUE, f, &lighting_level);
3671
3672                                         /* Clear screen */
3673                                         Term_clear();
3674                                         print_visuals_menu(choice_msg);
3675                                         break;
3676                                 }
3677                         }
3678
3679                         break;
3680                 }
3681
3682                 /* Modify monster attr/chars (visual mode) */
3683                 case '7':
3684                         do_cmd_knowledge_monsters(&need_redraw, TRUE, -1);
3685                         break;
3686
3687                 /* Modify object attr/chars (visual mode) */
3688                 case '8':
3689                         do_cmd_knowledge_objects(&need_redraw, TRUE, -1);
3690                         break;
3691
3692                 /* Modify feature attr/chars (visual mode) */
3693                 case '9':
3694                 {
3695                         int lighting_level = F_LIT_STANDARD;
3696                         do_cmd_knowledge_features(&need_redraw, TRUE, -1, &lighting_level);
3697                         break;
3698                 }
3699
3700 #endif /* ALLOW_VISUALS */
3701
3702                 /* Reset visuals */
3703                 case 'R':
3704                 case 'r':
3705                         /* Reset */
3706                         reset_visuals();
3707
3708                         /* Message */
3709                         msg_print(_("画面上の[色/文字]を初期値にリセットしました。", "Visual attr/char tables reset."));
3710                         need_redraw = TRUE;
3711                         break;
3712
3713                 /* Unknown option */
3714                 default:
3715                         bell();
3716                         break;
3717                 }
3718
3719                 /* Flush messages */
3720                 msg_print(NULL);
3721         }
3722
3723         /* Restore the screen */
3724         screen_load();
3725
3726         if (need_redraw) do_cmd_redraw();
3727 }
3728
3729
3730 /*
3731  * Interact with "colors"
3732  */
3733 void do_cmd_colors(void)
3734 {
3735         int i;
3736
3737         char tmp[160];
3738
3739         char buf[1024];
3740
3741
3742         /* File type is "TEXT" */
3743         FILE_TYPE(FILE_TYPE_TEXT);
3744
3745
3746         /* Save the screen */
3747         screen_save();
3748
3749
3750         /* Interact until done */
3751         while (1)
3752         {
3753                 /* Clear screen */
3754                 Term_clear();
3755
3756                 /* Ask for a choice */
3757                 prt(_("[ カラーの設定 ]", "Interact with Colors"), 2, 0);
3758
3759                 /* Give some choices */
3760                 prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
3761
3762 #ifdef ALLOW_COLORS
3763                 prt(_("(2) カラーの設定をファイルに書き出す", "(2) Dump colors"), 5, 5);
3764                 prt(_("(3) カラーの設定を変更する", "(3) Modify colors"), 6, 5);
3765 #endif
3766
3767                 /* Prompt */
3768                 prt(_("コマンド: ", "Command: "), 8, 0);
3769                 /* Prompt */
3770                 i = inkey();
3771
3772                 /* Done */
3773                 if (i == ESCAPE) break;
3774
3775                 /* Load a 'pref' file */
3776                 if (i == '1')
3777                 {
3778                         /* Prompt */
3779                         prt(_("コマンド: ユーザー設定ファイルをロードします", "Command: Load a user pref file"), 8, 0);
3780
3781                         /* Prompt */
3782                         prt(_("ファイル: ", "File: "), 10, 0);
3783
3784                         /* Default file */
3785                         sprintf(tmp, "%s.prf", player_base);
3786
3787                         /* Query */
3788                         if (!askfor(tmp, 70)) continue;
3789
3790                         /* Process the given filename */
3791                         (void)process_pref_file(tmp);
3792
3793                         /* Mega-Hack -- react to changes */
3794                         Term_xtra(TERM_XTRA_REACT, 0);
3795
3796                         /* Mega-Hack -- redraw */
3797                         Term_redraw();
3798                 }
3799
3800 #ifdef ALLOW_COLORS
3801
3802                 /* Dump colors */
3803                 else if (i == '2')
3804                 {
3805                         static cptr mark = "Colors";
3806
3807                         /* Prompt */
3808                         prt(_("コマンド: カラーの設定をファイルに書き出します", "Command: Dump colors"), 8, 0);
3809
3810                         /* Prompt */
3811                         prt(_("ファイル: ", "File: "), 10, 0);
3812
3813                         /* Default filename */
3814                         sprintf(tmp, "%s.prf", player_base);
3815
3816                         /* Get a filename */
3817                         if (!askfor(tmp, 70)) continue;
3818
3819                         /* Build the filename */
3820                         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
3821
3822                         /* Append to the file */
3823                         if (!open_auto_dump(buf, mark)) continue;
3824
3825                         /* Start dumping */
3826                         auto_dump_printf(_("\n# カラーの設定\n\n", "\n# Color redefinitions\n\n"));
3827                         
3828                         /* Dump colors */
3829                         for (i = 0; i < 256; i++)
3830                         {
3831                                 int kv = angband_color_table[i][0];
3832                                 int rv = angband_color_table[i][1];
3833                                 int gv = angband_color_table[i][2];
3834                                 int bv = angband_color_table[i][3];
3835
3836                                 cptr name = _("未知", "unknown");
3837
3838                                 /* Skip non-entries */
3839                                 if (!kv && !rv && !gv && !bv) continue;
3840
3841                                 /* Extract the color name */
3842                                 if (i < 16) name = color_names[i];
3843
3844                                 /* Dump a comment */
3845                                 auto_dump_printf(_("# カラー '%s'\n", "# Color '%s'\n"), name);
3846                                 
3847                                 /* Dump the monster attr/char info */
3848                                 auto_dump_printf("V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n",
3849                                         i, kv, rv, gv, bv);
3850                         }
3851
3852                         /* Close */
3853                         close_auto_dump();
3854
3855                         /* Message */
3856                         msg_print(_("カラーの設定をファイルに書き出しました。", "Dumped color redefinitions."));
3857                 }
3858
3859                 /* Edit colors */
3860                 else if (i == '3')
3861                 {
3862                         static byte a = 0;
3863
3864                         /* Prompt */
3865                         prt(_("コマンド: カラーの設定を変更します", "Command: Modify colors"), 8, 0);
3866
3867                         /* Hack -- query until done */
3868                         while (1)
3869                         {
3870                                 cptr name;
3871                                 byte j;
3872
3873                                 /* Clear */
3874                                 clear_from(10);
3875
3876                                 /* Exhibit the normal colors */
3877                                 for (j = 0; j < 16; j++)
3878                                 {
3879                                         /* Exhibit this color */
3880                                         Term_putstr(j*4, 20, -1, a, "###");
3881
3882                                         /* Exhibit all colors */
3883                                         Term_putstr(j*4, 22, -1, j, format("%3d", j));
3884                                 }
3885
3886                                 /* Describe the color */
3887                                 name = ((a < 16) ? color_names[a] : _("未定義", "undefined"));
3888
3889                                 /* Describe the color */
3890                                 Term_putstr(5, 10, -1, TERM_WHITE,
3891                                             format(_("カラー = %d, 名前 = %s", "Color = %d, Name = %s"), a, name));
3892
3893                                 /* Label the Current values */
3894                                 Term_putstr(5, 12, -1, TERM_WHITE,
3895                                             format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x",
3896                                                    angband_color_table[a][0],
3897                                                    angband_color_table[a][1],
3898                                                    angband_color_table[a][2],
3899                                                    angband_color_table[a][3]));
3900
3901                                 /* Prompt */
3902                                 Term_putstr(0, 14, -1, TERM_WHITE,
3903                                         _("コマンド (n/N/k/K/r/R/g/G/b/B): ", "Command (n/N/k/K/r/R/g/G/b/B): "));
3904
3905
3906                                 /* Get a command */
3907                                 i = inkey();
3908
3909                                 /* All done */
3910                                 if (i == ESCAPE) break;
3911
3912                                 /* Analyze */
3913                                 if (i == 'n') a = (byte)(a + 1);
3914                                 if (i == 'N') a = (byte)(a - 1);
3915                                 if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
3916                                 if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
3917                                 if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
3918                                 if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
3919                                 if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
3920                                 if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
3921                                 if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
3922                                 if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
3923
3924                                 /* Hack -- react to changes */
3925                                 Term_xtra(TERM_XTRA_REACT, 0);
3926
3927                                 /* Hack -- redraw */
3928                                 Term_redraw();
3929                         }
3930                 }
3931
3932 #endif
3933
3934                 /* Unknown option */
3935                 else
3936                 {
3937                         bell();
3938                 }
3939
3940                 /* Flush messages */
3941                 msg_print(NULL);
3942         }
3943
3944
3945         /* Restore the screen */
3946         screen_load();
3947 }
3948
3949
3950 /*
3951  * Note something in the message recall
3952  */
3953 void do_cmd_note(void)
3954 {
3955         char buf[80];
3956
3957         /* Default */
3958         strcpy(buf, "");
3959
3960         /* Input */
3961         if (!get_string(_("メモ: ", "Note: "), buf, 60)) return;
3962
3963         /* Ignore empty notes */
3964         if (!buf[0] || (buf[0] == ' ')) return;
3965
3966         /* Add the note to the message recall */
3967         msg_format(_("メモ: %s", "Note: %s"), buf);
3968 }
3969
3970
3971 /*
3972  * Mention the current version
3973  */
3974 void do_cmd_version(void)
3975 {
3976         /* Silly message */
3977
3978 #if FAKE_VER_EXTRA > 0
3979         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
3980                 FAKE_VER_MAJOR-10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
3981 #else
3982         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
3983                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
3984 #endif
3985 }
3986
3987
3988
3989 /*
3990  * Array of feeling strings
3991  */
3992 static cptr do_cmd_feeling_text[11] =
3993 {
3994         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
3995         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
3996         _("恐ろしい死の幻が目に浮かび、気絶しそうになった!", "You nearly faint as horrible visions of death fill your mind!"),
3997         _("この階はとても危険なようだ。", "This level looks very dangerous."),
3998         _("とても悪い予感がする...", "You have a very bad feeling..."),
3999         _("悪い予感がする...", "You have a bad feeling..."),
4000         _("何か緊張する。", "You feel nervous."),
4001         _("少し不運な気がする...", "You feel your luck is turning..."),
4002         _("この場所は好きになれない。", "You don't like the look of this place."),
4003         _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."),
4004         _("なんて退屈なところだ...", "What a boring place...")
4005 };
4006
4007 static cptr do_cmd_feeling_text_combat[11] =
4008 {
4009         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
4010         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
4011         _("今夜もまた、誰かが命を落とす...", "You nearly faint as horrible visions of death fill your mind!"),
4012         _("この階はとても危険なようだ。", "This level looks very dangerous."),
4013         _("とても悪い予感がする...", "You have a very bad feeling..."),
4014         _("悪い予感がする...", "You have a bad feeling..."),
4015         _("何か緊張する。", "You feel nervous."),
4016         _("少し不運な気がする...", "You feel your luck is turning..."),
4017         _("この場所は好きになれない。", "You don't like the look of this place."),
4018         _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."),
4019         _("なんて退屈なところだ...", "What a boring place...")
4020 };
4021
4022 static cptr do_cmd_feeling_text_lucky[11] =
4023 {
4024         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
4025         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
4026         _("この階はこの上なく素晴らしい感じがする。", "You have a superb feeling about this level."),
4027         _("素晴らしい感じがする...", "You have an excellent feeling..."),
4028         _("とても良い感じがする...", "You have a very good feeling..."),
4029         _("良い感じがする...", "You have a good feeling..."),
4030         _("ちょっと幸運な感じがする...", "You feel strangely lucky..."),
4031         _("多少は運が向いてきたか...", "You feel your luck is turning..."),
4032         _("見た感じ悪くはない...", "You like the look of this place..."),
4033         _("全然駄目ということはないが...", "This level can't be all bad..."),
4034         _("なんて退屈なところだ...", "What a boring place...")
4035 };
4036
4037
4038 /*
4039  * Note that "feeling" is set to zero unless some time has passed.
4040  * Note that this is done when the level is GENERATED, not entered.
4041  */
4042 void do_cmd_feeling(void)
4043 {
4044         /* No useful feeling in quests */
4045         if (p_ptr->inside_quest && !random_quest_number(dun_level))
4046         {
4047                 msg_print(_("典型的なクエストのダンジョンのようだ。", "Looks like a typical quest level."));
4048                 return;
4049         }
4050
4051         /* No useful feeling in town */
4052         else if (p_ptr->town_num && !dun_level)
4053         {
4054                 if (!strcmp(town[p_ptr->town_num].name, _("荒野", "wilderness")))
4055                 {
4056                         msg_print(_("何かありそうな荒野のようだ。", "Looks like a strange wilderness."));
4057                         return;
4058                 }
4059                 else
4060                 {
4061                         msg_print(_("典型的な町のようだ。", "Looks like a typical town."));
4062                         return;
4063                 }
4064         }
4065
4066         /* No useful feeling in the wilderness */
4067         else if (!dun_level)
4068         {
4069                 msg_print(_("典型的な荒野のようだ。", "Looks like a typical wilderness."));
4070                 return;
4071         }
4072
4073         /* Display the feeling */
4074         if (p_ptr->muta3 & MUT3_GOOD_LUCK)
4075                 msg_print(do_cmd_feeling_text_lucky[p_ptr->feeling]);
4076         else if (p_ptr->pseikaku == SEIKAKU_COMBAT ||
4077                  inventory[INVEN_BOW].name1 == ART_CRIMSON)
4078                 msg_print(do_cmd_feeling_text_combat[p_ptr->feeling]);
4079         else
4080                 msg_print(do_cmd_feeling_text[p_ptr->feeling]);
4081 }
4082
4083
4084
4085 /*
4086  * Description of each monster group.
4087  */
4088 static cptr monster_group_text[] = 
4089 {
4090 #ifdef JP
4091         "ユニーク", /* "Uniques" */
4092         "乗馬可能なモンスター",       /* "Riding" */
4093         "賞金首", /* "Wanted */
4094         "アンバーの王族", /* "Ambertite" */
4095         "アリ",
4096         "コウモリ",
4097         "ムカデ",
4098         "ドラゴン",
4099         "目玉",
4100         "ネコ",
4101         "ゴーレム",
4102         "標準人間型生物",
4103         "ベトベト",
4104         "ゼリー",
4105         "コボルド",
4106         "水棲生物",
4107         "モルド",
4108         "ナーガ",
4109         "オーク",
4110         "人間",
4111         "四足獣",
4112         "ネズミ",
4113         "スケルトン",
4114         "デーモン",
4115         "ボルテックス",
4116         "イモムシ/大群",
4117         /* "unused", */
4118         "イーク",
4119         "ゾンビ/ミイラ",
4120         "天使",
4121         "鳥",
4122         "犬",
4123         /* "古代ドラゴン/ワイアーム", */
4124         "エレメンタル",
4125         "トンボ",
4126         "ゴースト",
4127         "雑種",
4128         "昆虫",
4129         "ヘビ",
4130         "キラー・ビートル",
4131         "リッチ",
4132         "多首の爬虫類",
4133         "謎の生物",
4134         "オーガ",
4135         "巨大人間型生物",
4136         "クイルスルグ",
4137         "爬虫類/両生類",
4138         "蜘蛛/サソリ/ダニ",
4139         "トロル",
4140         /* "上級デーモン", */
4141         "バンパイア",
4142         "ワイト/レイス/等",
4143         "ゾーン/ザレン/等",
4144         "イエティ",
4145         "ハウンド",
4146         "ミミック",
4147         "壁/植物/気体",
4148         "おばけキノコ",
4149         "球体",
4150         "プレイヤー",
4151 #else
4152         "Uniques",
4153         "Ridable monsters",
4154         "Wanted monsters",
4155         "Ambertite",
4156         "Ant",
4157         "Bat",
4158         "Centipede",
4159         "Dragon",
4160         "Floating Eye",
4161         "Feline",
4162         "Golem",
4163         "Hobbit/Elf/Dwarf",
4164         "Icky Thing",
4165         "Jelly",
4166         "Kobold",
4167         "Aquatic monster",
4168         "Mold",
4169         "Naga",
4170         "Orc",
4171         "Person/Human",
4172         "Quadruped",
4173         "Rodent",
4174         "Skeleton",
4175         "Demon",
4176         "Vortex",
4177         "Worm/Worm-Mass",
4178         /* "unused", */
4179         "Yeek",
4180         "Zombie/Mummy",
4181         "Angel",
4182         "Bird",
4183         "Canine",
4184         /* "Ancient Dragon/Wyrm", */
4185         "Elemental",
4186         "Dragon Fly",
4187         "Ghost",
4188         "Hybrid",
4189         "Insect",
4190         "Snake",
4191         "Killer Beetle",
4192         "Lich",
4193         "Multi-Headed Reptile",
4194         "Mystery Living",
4195         "Ogre",
4196         "Giant Humanoid",
4197         "Quylthulg",
4198         "Reptile/Amphibian",
4199         "Spider/Scorpion/Tick",
4200         "Troll",
4201         /* "Major Demon", */
4202         "Vampire",
4203         "Wight/Wraith/etc",
4204         "Xorn/Xaren/etc",
4205         "Yeti",
4206         "Zephyr Hound",
4207         "Mimic",
4208         "Wall/Plant/Gas",
4209         "Mushroom patch",
4210         "Ball",
4211         "Player",
4212 #endif
4213         NULL
4214 };
4215
4216
4217 /*
4218  * Symbols of monsters in each group. Note the "Uniques" group
4219  * is handled differently.
4220  */
4221 static cptr monster_group_char[] =
4222 {
4223         (char *) -1L,
4224         (char *) -2L,
4225         (char *) -3L,
4226         (char *) -4L,
4227         "a",
4228         "b",
4229         "c",
4230         "dD",
4231         "e",
4232         "f",
4233         "g",
4234         "h",
4235         "i",
4236         "j",
4237         "k",
4238         "l",
4239         "m",
4240         "n",
4241         "o",
4242         "pt",
4243         "q",
4244         "r",
4245         "s",
4246         "uU",
4247         "v",
4248         "w",
4249         /* "x", */
4250         "y",
4251         "z",
4252         "A",
4253         "B",
4254         "C",
4255         /* "D", */
4256         "E",
4257         "F",
4258         "G",
4259         "H",
4260         "I",
4261         "J",
4262         "K",
4263         "L",
4264         "M",
4265         "N",
4266         "O",
4267         "P",
4268         "Q",
4269         "R",
4270         "S",
4271         "T",
4272         /* "U", */
4273         "V",
4274         "W",
4275         "X",
4276         "Y",
4277         "Z",
4278         "!$&()+./=>?[\\]`{|~",
4279         "#%",
4280         ",",
4281         "*",
4282         "@",
4283         NULL
4284 };
4285
4286
4287 /*
4288  * hook function to sort monsters by level
4289  */
4290 static bool ang_sort_comp_monster_level(vptr u, vptr v, int a, int b)
4291 {
4292         u16b *who = (u16b*)(u);
4293
4294         int w1 = who[a];
4295         int w2 = who[b];
4296
4297         monster_race *r_ptr1 = &r_info[w1];
4298         monster_race *r_ptr2 = &r_info[w2];
4299
4300         /* Unused */
4301         (void)v;
4302
4303         if (r_ptr2->level > r_ptr1->level) return TRUE;
4304         if (r_ptr1->level > r_ptr2->level) return FALSE;
4305
4306         if ((r_ptr2->flags1 & RF1_UNIQUE) && !(r_ptr1->flags1 & RF1_UNIQUE)) return TRUE;
4307         if ((r_ptr1->flags1 & RF1_UNIQUE) && !(r_ptr2->flags1 & RF1_UNIQUE)) return FALSE;
4308         return w1 <= w2;
4309 }
4310
4311 /*
4312  * Build a list of monster indexes in the given group. Return the number
4313  * of monsters in the group.
4314  *
4315  * mode & 0x01 : check for non-empty group
4316  * mode & 0x02 : visual operation only
4317  */
4318 static int collect_monsters(int grp_cur, s16b mon_idx[], byte mode)
4319 {
4320         int i, mon_cnt = 0;
4321         int dummy_why;
4322
4323         /* Get a list of x_char in this group */
4324         cptr group_char = monster_group_char[grp_cur];
4325
4326         /* XXX Hack -- Check if this is the "Uniques" group */
4327         bool grp_unique = (monster_group_char[grp_cur] == (char *) -1L);
4328
4329         /* XXX Hack -- Check if this is the "Riding" group */
4330         bool grp_riding = (monster_group_char[grp_cur] == (char *) -2L);
4331
4332         /* XXX Hack -- Check if this is the "Wanted" group */
4333         bool grp_wanted = (monster_group_char[grp_cur] == (char *) -3L);
4334
4335         /* XXX Hack -- Check if this is the "Amberite" group */
4336         bool grp_amberite = (monster_group_char[grp_cur] == (char *) -4L);
4337
4338
4339         /* Check every race */
4340         for (i = 0; i < max_r_idx; i++)
4341         {
4342                 /* Access the race */
4343                 monster_race *r_ptr = &r_info[i];
4344
4345                 /* Skip empty race */
4346                 if (!r_ptr->name) continue ;
4347
4348                 /* Require known monsters */
4349                 if (!(mode & 0x02) && !cheat_know && !r_ptr->r_sights) continue;
4350
4351                 if (grp_unique)
4352                 {
4353                         if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
4354                 }
4355
4356                 else if (grp_riding)
4357                 {
4358                         if (!(r_ptr->flags7 & RF7_RIDING)) continue;
4359                 }
4360
4361                 else if (grp_wanted)
4362                 {
4363                         bool wanted = FALSE;
4364                         int j;
4365                         for (j = 0; j < MAX_KUBI; j++)
4366                         {
4367                                 if (kubi_r_idx[j] == i || kubi_r_idx[j] - 10000 == i ||
4368                                         (p_ptr->today_mon && p_ptr->today_mon == i))
4369                                 {
4370                                         wanted = TRUE;
4371                                         break;
4372                                 }
4373                         }
4374                         if (!wanted) continue;
4375                 }
4376
4377                 else if (grp_amberite)
4378                 {
4379                         if (!(r_ptr->flags3 & RF3_AMBERITE)) continue;
4380                 }
4381
4382                 else
4383                 {
4384                         /* Check for race in the group */
4385                         if (!my_strchr(group_char, r_ptr->d_char)) continue;
4386                 }
4387
4388                 /* Add the race */
4389                 mon_idx[mon_cnt++] = i;
4390
4391                 /* XXX Hack -- Just checking for non-empty group */
4392                 if (mode & 0x01) break;
4393         }
4394
4395         /* Terminate the list */
4396         mon_idx[mon_cnt] = -1;
4397
4398         /* Select the sort method */
4399         ang_sort_comp = ang_sort_comp_monster_level;
4400         ang_sort_swap = ang_sort_swap_hook;
4401
4402         /* Sort by monster level */
4403         ang_sort(mon_idx, &dummy_why, mon_cnt);
4404
4405         /* Return the number of races */
4406         return mon_cnt;
4407 }
4408
4409
4410 /*
4411  * Description of each monster group.
4412  */
4413 static cptr object_group_text[] = 
4414 {
4415 #ifdef JP
4416         "キノコ",    /* "Mushrooms" */
4417         "薬",          /* "Potions" */
4418         "油つぼ",    /* "Flasks" */
4419         "巻物",               /* "Scrolls" */
4420         "指輪",               /* "Rings" */
4421         "アミュレット",   /* "Amulets" */
4422         "笛",          /* "Whistle" */
4423         "光源",               /* "Lanterns" */
4424         "魔法棒",    /* "Wands" */
4425         "杖",          /* "Staffs" */
4426         "ロッド",    /* "Rods" */
4427         "カード",    /* "Cards" */
4428         "キャプチャー・ボール",
4429         "羊皮紙",    
4430         "くさび",
4431         "箱",
4432         "人形",
4433         "像",
4434         "ゴミ",
4435         "空のビン",
4436         "骨",
4437         "死体",
4438         "刀剣類",    /* "Swords" */
4439         "鈍器",               /* "Blunt Weapons" */
4440         "長柄武器", /* "Polearms" */
4441         "採掘道具", /* "Diggers" */
4442         "飛び道具", /* "Bows" */
4443         "弾",
4444         "矢",
4445         "ボルト",
4446         "軽装鎧",    /* "Soft Armor" */
4447         "重装鎧",    /* "Hard Armor" */
4448         "ドラゴン鎧",      /* "Dragon Armor" */
4449         "盾",  /* "Shields" */
4450         "クローク", /* "Cloaks" */
4451         "籠手",       /* "Gloves" */
4452         "ヘルメット",      /* "Helms" */
4453         "冠",  /* "Crowns" */
4454         "ブーツ",    /* "Boots" */
4455         "魔法書",
4456         "財宝",
4457         "何か",
4458 #else
4459         "Mushrooms",
4460         "Potions",
4461         "Flasks",
4462         "Scrolls",
4463         "Rings",
4464         "Amulets",
4465         "Whistle",
4466         "Lanterns",
4467         "Wands",
4468         "Staves",
4469         "Rods",
4470         "Cards",
4471         "Capture Balls",
4472         "Parchments",
4473         "Spikes",
4474         "Boxs",
4475         "Figurines",
4476         "Statues",
4477         "Junks",
4478         "Bottles",
4479         "Skeletons",
4480         "Corpses",
4481         "Swords",
4482         "Blunt Weapons",
4483         "Polearms",
4484         "Diggers",
4485         "Bows",
4486         "Shots",
4487         "Arrows",
4488         "Bolts",
4489         "Soft Armor",
4490         "Hard Armor",
4491         "Dragon Armor",
4492         "Shields",
4493         "Cloaks",
4494         "Gloves",
4495         "Helms",
4496         "Crowns",
4497         "Boots",
4498         "Spellbooks",
4499         "Treasure",
4500         "Something",
4501 #endif
4502         NULL
4503 };
4504
4505
4506 /*
4507  * TVALs of items in each group
4508  */
4509 static byte object_group_tval[] = 
4510 {
4511         TV_FOOD,
4512         TV_POTION,
4513         TV_FLASK,
4514         TV_SCROLL,
4515         TV_RING,
4516         TV_AMULET,
4517         TV_WHISTLE,
4518         TV_LITE,
4519         TV_WAND,
4520         TV_STAFF,
4521         TV_ROD,
4522         TV_CARD,
4523         TV_CAPTURE,
4524         TV_PARCHMENT,
4525         TV_SPIKE,
4526         TV_CHEST,
4527         TV_FIGURINE,
4528         TV_STATUE,
4529         TV_JUNK,
4530         TV_BOTTLE,
4531         TV_SKELETON,
4532         TV_CORPSE,
4533         TV_SWORD,
4534         TV_HAFTED,
4535         TV_POLEARM,
4536         TV_DIGGING,
4537         TV_BOW,
4538         TV_SHOT,
4539         TV_ARROW,
4540         TV_BOLT,
4541         TV_SOFT_ARMOR,
4542         TV_HARD_ARMOR,
4543         TV_DRAG_ARMOR,
4544         TV_SHIELD,
4545         TV_CLOAK,
4546         TV_GLOVES,
4547         TV_HELM,
4548         TV_CROWN,
4549         TV_BOOTS,
4550         TV_LIFE_BOOK, /* Hack -- all spellbooks */
4551         TV_GOLD,
4552         0,
4553         0,
4554 };
4555
4556
4557 /*
4558  * Build a list of object indexes in the given group. Return the number
4559  * of objects in the group.
4560  *
4561  * mode & 0x01 : check for non-empty group
4562  * mode & 0x02 : visual operation only
4563  */
4564 static int collect_objects(int grp_cur, int object_idx[], byte mode)
4565 {
4566         int i, j, k, object_cnt = 0;
4567
4568         /* Get a list of x_char in this group */
4569         byte group_tval = object_group_tval[grp_cur];
4570
4571         /* Check every object */
4572         for (i = 0; i < max_k_idx; i++)
4573         {
4574                 /* Access the object */
4575                 object_kind *k_ptr = &k_info[i];
4576
4577                 /* Skip empty objects */
4578                 if (!k_ptr->name) continue;
4579
4580                 if (mode & 0x02)
4581                 {
4582                         /* Any objects will be displayed */
4583                 }
4584                 else
4585                 {
4586                         if (!p_ptr->wizard)
4587                         {
4588                                 /* Skip non-flavoured objects */
4589                                 if (!k_ptr->flavor) continue;
4590
4591                                 /* Require objects ever seen */
4592                                 if (!k_ptr->aware) continue;
4593                         }
4594
4595                         /* Skip items with no distribution (special artifacts) */
4596                         for (j = 0, k = 0; j < 4; j++) k += k_ptr->chance[j];
4597                         if (!k) continue;
4598                 }
4599
4600                 /* Check for objects in the group */
4601                 if (TV_LIFE_BOOK == group_tval)
4602                 {
4603                         /* Hack -- All spell books */
4604                         if (TV_LIFE_BOOK <= k_ptr->tval && k_ptr->tval <= TV_HEX_BOOK)
4605                         {
4606                                 /* Add the object */
4607                                 object_idx[object_cnt++] = i;
4608                         }
4609                         else continue;
4610                 }
4611                 else if (k_ptr->tval == group_tval)
4612                 {
4613                         /* Add the object */
4614                         object_idx[object_cnt++] = i;
4615                 }
4616                 else continue;
4617
4618                 /* XXX Hack -- Just checking for non-empty group */
4619                 if (mode & 0x01) break;
4620         }
4621
4622         /* Terminate the list */
4623         object_idx[object_cnt] = -1;
4624
4625         /* Return the number of objects */
4626         return object_cnt;
4627 }
4628
4629
4630 /*
4631  * Description of each feature group.
4632  */
4633 static cptr feature_group_text[] = 
4634 {
4635         "terrains",
4636         NULL
4637 };
4638
4639
4640 /*
4641  * Build a list of feature indexes in the given group. Return the number
4642  * of features in the group.
4643  *
4644  * mode & 0x01 : check for non-empty group
4645  */
4646 static int collect_features(int grp_cur, int *feat_idx, byte mode)
4647 {
4648         int i, feat_cnt = 0;
4649
4650         /* Unused;  There is a single group. */
4651         (void)grp_cur;
4652
4653         /* Check every feature */
4654         for (i = 0; i < max_f_idx; i++)
4655         {
4656                 /* Access the index */
4657                 feature_type *f_ptr = &f_info[i];
4658
4659                 /* Skip empty index */
4660                 if (!f_ptr->name) continue;
4661
4662                 /* Skip mimiccing features */
4663                 if (f_ptr->mimic != i) continue;
4664
4665                 /* Add the index */
4666                 feat_idx[feat_cnt++] = i;
4667
4668                 /* XXX Hack -- Just checking for non-empty group */
4669                 if (mode & 0x01) break;
4670         }
4671
4672         /* Terminate the list */
4673         feat_idx[feat_cnt] = -1;
4674
4675         /* Return the number of races */
4676         return feat_cnt;
4677 }
4678
4679
4680 #if 0
4681 /*
4682  * Build a list of monster indexes in the given group. Return the number
4683  * of monsters in the group.
4684  */
4685 static int collect_artifacts(int grp_cur, int object_idx[])
4686 {
4687         int i, object_cnt = 0;
4688
4689         /* Get a list of x_char in this group */
4690         byte group_tval = object_group_tval[grp_cur];
4691
4692         /* Check every object */
4693         for (i = 0; i < max_a_idx; i++)
4694         {
4695                 /* Access the artifact */
4696                 artifact_type *a_ptr = &a_info[i];
4697
4698                 /* Skip empty artifacts */
4699                 if (!a_ptr->name) continue;
4700
4701                 /* Skip "uncreated" artifacts */
4702                 if (!a_ptr->cur_num) continue;
4703
4704                 /* Check for race in the group */
4705                 if (a_ptr->tval == group_tval)
4706                 {
4707                         /* Add the race */
4708                         object_idx[object_cnt++] = i;
4709                 }
4710         }
4711
4712         /* Terminate the list */
4713         object_idx[object_cnt] = 0;
4714
4715         /* Return the number of races */
4716         return object_cnt;
4717 }
4718 #endif /* 0 */
4719
4720
4721 /*
4722  * Encode the screen colors
4723  */
4724 static char hack[17] = "dwsorgbuDWvyRGBU";
4725
4726
4727 /*
4728  * Hack -- load a screen dump from a file
4729  */
4730 void do_cmd_load_screen(void)
4731 {
4732         int i, y, x;
4733
4734         byte a = 0;
4735         char c = ' ';
4736
4737         bool okay = TRUE;
4738
4739         FILE *fff;
4740
4741         char buf[1024];
4742
4743         int wid, hgt;
4744
4745         Term_get_size(&wid, &hgt);
4746
4747         /* Build the filename */
4748         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
4749
4750         /* Append to the file */
4751         fff = my_fopen(buf, "r");
4752
4753         /* Oops */
4754         if (!fff) {
4755                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
4756                 msg_print(NULL);
4757                 return;
4758         }
4759
4760
4761         /* Save the screen */
4762         screen_save();
4763
4764         /* Clear the screen */
4765         Term_clear();
4766
4767
4768         /* Load the screen */
4769         for (y = 0; okay; y++)
4770         {
4771                 /* Get a line of data including control code */
4772                 if (!fgets(buf, 1024, fff)) okay = FALSE;
4773
4774                 /* Get the blank line */
4775                 if (buf[0] == '\n' || buf[0] == '\0') break;
4776
4777                 /* Ignore too large screen image */
4778                 if (y >= hgt) continue;
4779
4780                 /* Show each row */
4781                 for (x = 0; x < wid - 1; x++)
4782                 {
4783                         /* End of line */
4784                         if (buf[x] == '\n' || buf[x] == '\0') break;
4785
4786                         /* Put the attr/char */
4787                         Term_draw(x, y, TERM_WHITE, buf[x]);
4788                 }
4789         }
4790
4791         /* Dump the screen */
4792         for (y = 0; okay; y++)
4793         {
4794                 /* Get a line of data including control code */
4795                 if (!fgets(buf, 1024, fff)) okay = FALSE;
4796
4797                 /* Get the blank line */
4798                 if (buf[0] == '\n' || buf[0] == '\0') break;
4799
4800                 /* Ignore too large screen image */
4801                 if (y >= hgt) continue;
4802
4803                 /* Dump each row */
4804                 for (x = 0; x < wid - 1; x++)
4805                 {
4806                         /* End of line */
4807                         if (buf[x] == '\n' || buf[x] == '\0') break;
4808
4809                         /* Get the attr/char */
4810                         (void)(Term_what(x, y, &a, &c));
4811
4812                         /* Look up the attr */
4813                         for (i = 0; i < 16; i++)
4814                         {
4815                                 /* Use attr matches */
4816                                 if (hack[i] == buf[x]) a = i;
4817                         }
4818
4819                         /* Put the attr/char */
4820                         Term_draw(x, y, a, c);
4821                 }
4822         }
4823
4824
4825         /* Close it */
4826         my_fclose(fff);
4827
4828
4829         /* Message */
4830         prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0);
4831
4832         flush();
4833         inkey();
4834
4835
4836         /* Restore the screen */
4837         screen_load();
4838 }
4839
4840
4841
4842
4843 cptr inven_res_label = _("                               酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮",
4844                                                  "                               AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv");
4845
4846
4847 #define IM_FLAG_STR  _("*", "* ")
4848 #define HAS_FLAG_STR _("+", "+ ")
4849 #define NO_FLAG_STR  _("・", ". ")
4850
4851 #define print_im_or_res_flag(IM, RES) \
4852 { \
4853         fputs(have_flag(flgs, (IM)) ? IM_FLAG_STR : \
4854               (have_flag(flgs, (RES)) ? HAS_FLAG_STR : NO_FLAG_STR), fff); \
4855 }
4856
4857 #define print_flag(TR) \
4858 { \
4859         fputs(have_flag(flgs, (TR)) ? HAS_FLAG_STR : NO_FLAG_STR, fff); \
4860 }
4861
4862
4863 /* XTRA HACK RESLIST */
4864 static void do_cmd_knowledge_inven_aux(FILE *fff, object_type *o_ptr, int *j, byte tval, char *where)
4865 {
4866         char o_name[MAX_NLEN];
4867         u32b flgs[TR_FLAG_SIZE];
4868
4869         if (!o_ptr->k_idx) return;
4870         if (o_ptr->tval != tval) return;
4871
4872         /* Identified items only */
4873         if (!object_is_known(o_ptr)) return;
4874
4875         /*
4876          * HACK:Ring of Lordly protection and Dragon equipment
4877          * have random resistances.
4878          */
4879         if ((object_is_wearable(o_ptr) && object_is_ego(o_ptr))
4880             || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE))
4881             || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY))
4882             || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
4883             || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM))
4884             || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
4885             || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE))
4886             || object_is_artifact(o_ptr))
4887         {
4888                 int i = 0;
4889                 object_desc(o_name, o_ptr, OD_NAME_ONLY);
4890
4891                 while (o_name[i] && (i < 26))
4892                 {
4893 #ifdef JP
4894                         if (iskanji(o_name[i])) i++;
4895 #endif
4896                         i++;
4897                 }
4898
4899                 if (i < 28)
4900                 {
4901                         while (i < 28)
4902                         {
4903                                 o_name[i] = ' '; i++;
4904                         }
4905                 }
4906                 o_name[i] = '\0';
4907
4908                 fprintf(fff, "%s %s", where, o_name);
4909
4910                 if (!(o_ptr->ident & (IDENT_MENTAL)))
4911                 {
4912                         fputs(_("-------不明--------------- -------不明---------\n", 
4913                                         "-------unknown------------ -------unknown------\n"), fff);
4914                 }
4915                 else
4916                 {
4917                         object_flags_known(o_ptr, flgs);
4918
4919                         print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID);
4920                         print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC);
4921                         print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE);
4922                         print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD);
4923                         print_flag(TR_RES_POIS);
4924                         print_flag(TR_RES_LITE);
4925                         print_flag(TR_RES_DARK);
4926                         print_flag(TR_RES_SHARDS);
4927                         print_flag(TR_RES_SOUND);
4928                         print_flag(TR_RES_NETHER);
4929                         print_flag(TR_RES_NEXUS);
4930                         print_flag(TR_RES_CHAOS);
4931                         print_flag(TR_RES_DISEN);
4932
4933                         fputs(" ", fff);
4934
4935                         print_flag(TR_RES_BLIND);
4936                         print_flag(TR_RES_FEAR);
4937                         print_flag(TR_RES_CONF);
4938                         print_flag(TR_FREE_ACT);
4939                         print_flag(TR_SEE_INVIS);
4940                         print_flag(TR_HOLD_EXP);
4941                         print_flag(TR_TELEPATHY);
4942                         print_flag(TR_SLOW_DIGEST);
4943                         print_flag(TR_REGEN);
4944                         print_flag(TR_LEVITATION);
4945
4946                         fputc('\n', fff);
4947                 }
4948                 (*j)++;
4949                 if (*j == 9)
4950                 {
4951                         *j = 0;
4952                         fprintf(fff, "%s\n", inven_res_label);
4953                 }
4954         }
4955 }
4956
4957 /*
4958  * Display *ID* ed weapons/armors's resistances
4959  */
4960 static void do_cmd_knowledge_inven(void)
4961 {
4962         FILE *fff;
4963
4964         char file_name[1024];
4965
4966         store_type  *st_ptr;
4967
4968         byte tval;
4969         int i = 0;
4970         int j = 0;
4971
4972         char  where[32];
4973
4974         /* Open a new file */
4975         fff = my_fopen_temp(file_name, 1024);
4976         if (!fff)
4977         {
4978             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4979             msg_print(NULL);
4980             return;
4981         }
4982         fprintf(fff, "%s\n", inven_res_label);
4983
4984         for (tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++)
4985         {
4986                 if (j != 0)
4987                 {
4988                         for (; j < 9; j++) fputc('\n', fff);
4989                         j = 0;
4990                         fprintf(fff, "%s\n", inven_res_label);
4991                 }
4992                 strcpy(where, _("装", "E "));
4993                 for (i = INVEN_RARM; i < INVEN_TOTAL; i++)
4994                 {
4995                         do_cmd_knowledge_inven_aux(fff, &inventory[i], &j, tval, where);
4996                 }
4997                 strcpy(where, _("持", "I "));
4998                 for (i = 0; i < INVEN_PACK; i++)
4999                 {
5000                         do_cmd_knowledge_inven_aux(fff, &inventory[i], &j, tval, where);
5001                 }
5002
5003                 st_ptr = &town[1].store[STORE_HOME];
5004                 strcpy(where, _("家", "H "));
5005                 for (i = 0; i < st_ptr->stock_num; i++)
5006                 {
5007                         do_cmd_knowledge_inven_aux(fff, &st_ptr->stock[i], &j, tval, where);
5008                 }
5009         }
5010
5011         /* Close the file */
5012         my_fclose(fff);
5013
5014         /* Display the file contents */
5015         show_file(TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0);
5016
5017         /* Remove the file */
5018         fd_kill(file_name);
5019 }
5020
5021
5022 void do_cmd_save_screen_html_aux(char *filename, int message)
5023 {
5024         int y, x, i;
5025
5026         byte a = 0, old_a = 0;
5027         char c = ' ';
5028
5029         FILE *fff, *tmpfff;
5030         char buf[2048];
5031
5032         int yomikomu = 0;
5033         cptr tags[4] = {
5034                 "HEADER_START:",
5035                 "HEADER_END:",
5036                 "FOOTER_START:",
5037                 "FOOTER_END:",
5038         };
5039
5040         cptr html_head[] = {
5041                 "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n",
5042                 "<pre>",
5043                 0,
5044         };
5045         cptr html_foot[] = {
5046                 "</pre>\n",
5047                 "</body>\n</html>\n",
5048                 0,
5049         };
5050
5051         int wid, hgt;
5052
5053         Term_get_size(&wid, &hgt);
5054
5055         /* File type is "TEXT" */
5056         FILE_TYPE(FILE_TYPE_TEXT);
5057
5058         /* Append to the file */
5059         fff = my_fopen(filename, "w");
5060
5061         /* Oops */
5062         if (!fff) {
5063                 if (message) {
5064                     msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename);
5065                     msg_print(NULL);
5066                 }
5067                 
5068                 return;
5069         }
5070
5071         /* Save the screen */
5072         if (message)
5073                 screen_save();
5074
5075         /* Build the filename */
5076         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf");
5077         tmpfff = my_fopen(buf, "r");
5078         if (!tmpfff) {
5079                 for (i = 0; html_head[i]; i++)
5080                         fputs(html_head[i], fff);
5081         }
5082         else {
5083                 yomikomu = 0;
5084                 while (!my_fgets(tmpfff, buf, sizeof(buf))) {
5085                         if (!yomikomu) {
5086                                 if (strncmp(buf, tags[0], strlen(tags[0])) == 0)
5087                                         yomikomu = 1;
5088                         }
5089                         else {
5090                                 if (strncmp(buf, tags[1], strlen(tags[1])) == 0)
5091                                         break;
5092                                 fprintf(fff, "%s\n", buf);
5093                         }
5094                 }
5095         }
5096
5097         /* Dump the screen */
5098         for (y = 0; y < hgt; y++)
5099         {
5100                 /* Start the row */
5101                 if (y != 0)
5102                         fprintf(fff, "\n");
5103
5104                 /* Dump each row */
5105                 for (x = 0; x < wid - 1; x++)
5106                 {
5107                         int rv, gv, bv;
5108                         cptr cc = NULL;
5109                         /* Get the attr/char */
5110                         (void)(Term_what(x, y, &a, &c));
5111
5112                         switch (c)
5113                         {
5114                         case '&': cc = "&amp;"; break;
5115                         case '<': cc = "&lt;"; break;
5116                         case '>': cc = "&gt;"; break;
5117 #ifdef WINDOWS
5118                         case 0x1f: c = '.'; break;
5119                         case 0x7f: c = (a == 0x09) ? '%' : '#'; break;
5120 #endif
5121                         }
5122
5123                         a = a & 0x0F;
5124                         if ((y == 0 && x == 0) || a != old_a) {
5125                                 rv = angband_color_table[a][1];
5126                                 gv = angband_color_table[a][2];
5127                                 bv = angband_color_table[a][3];
5128                                 fprintf(fff, "%s<font color=\"#%02x%02x%02x\">", 
5129                                         ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv);
5130                                 old_a = a;
5131                         }
5132                         if (cc)
5133                                 fprintf(fff, "%s", cc);
5134                         else
5135                                 fprintf(fff, "%c", c);
5136                 }
5137         }
5138         fprintf(fff, "</font>");
5139
5140         if (!tmpfff) {
5141                 for (i = 0; html_foot[i]; i++)
5142                         fputs(html_foot[i], fff);
5143         }
5144         else {
5145                 rewind(tmpfff);
5146                 yomikomu = 0;
5147                 while (!my_fgets(tmpfff, buf, sizeof(buf))) {
5148                         if (!yomikomu) {
5149                                 if (strncmp(buf, tags[2], strlen(tags[2])) == 0)
5150                                         yomikomu = 1;
5151                         }
5152                         else {
5153                                 if (strncmp(buf, tags[3], strlen(tags[3])) == 0)
5154                                         break;
5155                                 fprintf(fff, "%s\n", buf);
5156                         }
5157                 }
5158                 my_fclose(tmpfff);
5159         }
5160
5161         /* Skip a line */
5162         fprintf(fff, "\n");
5163
5164         /* Close it */
5165         my_fclose(fff);
5166
5167         /* Message */
5168         if (message) {
5169                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
5170                 msg_print(NULL);
5171         }
5172
5173         /* Restore the screen */
5174         if (message)
5175                 screen_load();
5176 }
5177
5178 /*
5179  * Hack -- save a screen dump to a file
5180  */
5181 static void do_cmd_save_screen_html(void)
5182 {
5183         char buf[1024], tmp[256] = "screen.html";
5184
5185         if (!get_string(_("ファイル名: ", "File name: "), tmp, 80))
5186                 return;
5187
5188         /* Build the filename */
5189         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
5190
5191         msg_print(NULL);
5192
5193         do_cmd_save_screen_html_aux(buf, 1);
5194 }
5195
5196
5197 /*
5198  * Redefinable "save_screen" action
5199  */
5200 void (*screendump_aux)(void) = NULL;
5201
5202
5203 /*
5204  * Hack -- save a screen dump to a file
5205  */
5206 void do_cmd_save_screen(void)
5207 {
5208         bool old_use_graphics = use_graphics;
5209         bool html_dump = FALSE;
5210
5211         int wid, hgt;
5212
5213         prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0);
5214         while(TRUE)
5215         {
5216                 char c = inkey();
5217                 if (c == 'Y' || c == 'y')
5218                         break;
5219                 else if (c == 'H' || c == 'h')
5220                 {
5221                         html_dump = TRUE;
5222                         break;
5223                 }
5224                 else
5225                 {
5226                         prt("", 0, 0);
5227                         return;
5228                 }
5229         }
5230
5231         Term_get_size(&wid, &hgt);
5232
5233         if (old_use_graphics)
5234         {
5235                 use_graphics = FALSE;
5236                 reset_visuals();
5237
5238                 /* Redraw everything */
5239                 p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
5240
5241                 /* Hack -- update */
5242                 handle_stuff();
5243         }
5244
5245         if (html_dump)
5246         {
5247                 do_cmd_save_screen_html();
5248                 do_cmd_redraw();
5249         }
5250
5251         /* Do we use a special screendump function ? */
5252         else if (screendump_aux)
5253         {
5254                 /* Dump the screen to a graphics file */
5255                 (*screendump_aux)();
5256         }
5257         else /* Dump the screen as text */
5258         {
5259                 int y, x;
5260
5261                 byte a = 0;
5262                 char c = ' ';
5263
5264                 FILE *fff;
5265
5266                 char buf[1024];
5267
5268                 /* Build the filename */
5269                 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
5270
5271                 /* File type is "TEXT" */
5272                 FILE_TYPE(FILE_TYPE_TEXT);
5273
5274                 /* Append to the file */
5275                 fff = my_fopen(buf, "w");
5276
5277                 /* Oops */
5278                 if (!fff)
5279                 {
5280                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf);
5281                         msg_print(NULL);
5282                         return;
5283                 }
5284
5285
5286                 /* Save the screen */
5287                 screen_save();
5288
5289
5290                 /* Dump the screen */
5291                 for (y = 0; y < hgt; y++)
5292                 {
5293                         /* Dump each row */
5294                         for (x = 0; x < wid - 1; x++)
5295                         {
5296                                 /* Get the attr/char */
5297                                 (void)(Term_what(x, y, &a, &c));
5298
5299                                 /* Dump it */
5300                                 buf[x] = c;
5301                         }
5302
5303                         /* Terminate */
5304                         buf[x] = '\0';
5305
5306                         /* End the row */
5307                         fprintf(fff, "%s\n", buf);
5308                 }
5309
5310                 /* Skip a line */
5311                 fprintf(fff, "\n");
5312
5313
5314                 /* Dump the screen */
5315                 for (y = 0; y < hgt; y++)
5316                 {
5317                         /* Dump each row */
5318                         for (x = 0; x < wid - 1; x++)
5319                         {
5320                                 /* Get the attr/char */
5321                                 (void)(Term_what(x, y, &a, &c));
5322
5323                                 /* Dump it */
5324                                 buf[x] = hack[a&0x0F];
5325                         }
5326
5327                         /* Terminate */
5328                         buf[x] = '\0';
5329
5330                         /* End the row */
5331                         fprintf(fff, "%s\n", buf);
5332                 }
5333
5334                 /* Skip a line */
5335                 fprintf(fff, "\n");
5336
5337
5338                 /* Close it */
5339                 my_fclose(fff);
5340
5341                 /* Message */
5342                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
5343                 msg_print(NULL);
5344
5345                 /* Restore the screen */
5346                 screen_load();
5347         }
5348
5349         if (old_use_graphics)
5350         {
5351                 use_graphics = TRUE;
5352                 reset_visuals();
5353
5354                 /* Redraw everything */
5355                 p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
5356
5357                 /* Hack -- update */
5358                 handle_stuff();
5359         }
5360 }
5361
5362
5363 /*
5364  * Sorting hook -- Comp function -- see below
5365  *
5366  * We use "u" to point to array of monster indexes,
5367  * and "v" to select the type of sorting to perform on "u".
5368  */
5369 static bool ang_sort_art_comp(vptr u, vptr v, int a, int b)
5370 {
5371         u16b *who = (u16b*)(u);
5372
5373         u16b *why = (u16b*)(v);
5374
5375         int w1 = who[a];
5376         int w2 = who[b];
5377
5378         int z1, z2;
5379
5380         /* Sort by total kills */
5381         if (*why >= 3)
5382         {
5383                 /* Extract total kills */
5384                 z1 = a_info[w1].tval;
5385                 z2 = a_info[w2].tval;
5386
5387                 /* Compare total kills */
5388                 if (z1 < z2) return (TRUE);
5389                 if (z1 > z2) return (FALSE);
5390         }
5391
5392
5393         /* Sort by monster level */
5394         if (*why >= 2)
5395         {
5396                 /* Extract levels */
5397                 z1 = a_info[w1].sval;
5398                 z2 = a_info[w2].sval;
5399
5400                 /* Compare levels */
5401                 if (z1 < z2) return (TRUE);
5402                 if (z1 > z2) return (FALSE);
5403         }
5404
5405
5406         /* Sort by monster experience */
5407         if (*why >= 1)
5408         {
5409                 /* Extract experience */
5410                 z1 = a_info[w1].level;
5411                 z2 = a_info[w2].level;
5412
5413                 /* Compare experience */
5414                 if (z1 < z2) return (TRUE);
5415                 if (z1 > z2) return (FALSE);
5416         }
5417
5418
5419         /* Compare indexes */
5420         return (w1 <= w2);
5421 }
5422
5423
5424 /*
5425  * Sorting hook -- Swap function -- see below
5426  *
5427  * We use "u" to point to array of monster indexes,
5428  * and "v" to select the type of sorting to perform.
5429  */
5430 static void ang_sort_art_swap(vptr u, vptr v, int a, int b)
5431 {
5432         u16b *who = (u16b*)(u);
5433
5434         u16b holder;
5435
5436         /* Unused */
5437         (void)v;
5438
5439         /* Swap */
5440         holder = who[a];
5441         who[a] = who[b];
5442         who[b] = holder;
5443 }
5444
5445
5446 /*
5447  * Check the status of "artifacts"
5448  */
5449 static void do_cmd_knowledge_artifacts(void)
5450 {
5451         int i, k, z, x, y, n = 0;
5452         u16b why = 3;
5453         s16b *who;
5454
5455         FILE *fff;
5456
5457         char file_name[1024];
5458
5459         char base_name[MAX_NLEN];
5460
5461         bool *okay;
5462
5463         /* Open a new file */
5464         fff = my_fopen_temp(file_name, 1024);
5465
5466         if (!fff) {
5467             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5468             msg_print(NULL);
5469             return;
5470         }
5471
5472         /* Allocate the "who" array */
5473         C_MAKE(who, max_a_idx, s16b);
5474
5475         /* Allocate the "okay" array */
5476         C_MAKE(okay, max_a_idx, bool);
5477
5478         /* Scan the artifacts */
5479         for (k = 0; k < max_a_idx; k++)
5480         {
5481                 artifact_type *a_ptr = &a_info[k];
5482
5483                 /* Default */
5484                 okay[k] = FALSE;
5485
5486                 /* Skip "empty" artifacts */
5487                 if (!a_ptr->name) continue;
5488
5489                 /* Skip "uncreated" artifacts */
5490                 if (!a_ptr->cur_num) continue;
5491
5492                 /* Assume okay */
5493                 okay[k] = TRUE;
5494         }
5495
5496         /* Check the dungeon */
5497         for (y = 0; y < cur_hgt; y++)
5498         {
5499                 for (x = 0; x < cur_wid; x++)
5500                 {
5501                         cave_type *c_ptr = &cave[y][x];
5502
5503                         s16b this_o_idx, next_o_idx = 0;
5504
5505                         /* Scan all objects in the grid */
5506                         for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
5507                         {
5508                                 object_type *o_ptr;
5509
5510                                 /* Acquire object */
5511                                 o_ptr = &o_list[this_o_idx];
5512
5513                                 /* Acquire next object */
5514                                 next_o_idx = o_ptr->next_o_idx;
5515
5516                                 /* Ignore non-artifacts */
5517                                 if (!object_is_fixed_artifact(o_ptr)) continue;
5518
5519                                 /* Ignore known items */
5520                                 if (object_is_known(o_ptr)) continue;
5521
5522                                 /* Note the artifact */
5523                                 okay[o_ptr->name1] = FALSE;
5524                         }
5525                 }
5526         }
5527
5528         /* Check the inventory and equipment */
5529         for (i = 0; i < INVEN_TOTAL; i++)
5530         {
5531                 object_type *o_ptr = &inventory[i];
5532
5533                 /* Ignore non-objects */
5534                 if (!o_ptr->k_idx) continue;
5535
5536                 /* Ignore non-artifacts */
5537                 if (!object_is_fixed_artifact(o_ptr)) continue;
5538
5539                 /* Ignore known items */
5540                 if (object_is_known(o_ptr)) continue;
5541
5542                 /* Note the artifact */
5543                 okay[o_ptr->name1] = FALSE;
5544         }
5545
5546         for (k = 0; k < max_a_idx; k++)
5547         {
5548                 if (okay[k]) who[n++] = k;
5549         }
5550
5551         /* Select the sort method */
5552         ang_sort_comp = ang_sort_art_comp;
5553         ang_sort_swap = ang_sort_art_swap;
5554
5555         /* Sort the array by dungeon depth of monsters */
5556         ang_sort(who, &why, n);
5557
5558         /* Scan the artifacts */
5559         for (k = 0; k < n; k++)
5560         {
5561                 artifact_type *a_ptr = &a_info[who[k]];
5562
5563                 /* Paranoia */
5564                 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
5565
5566                 /* Obtain the base object type */
5567                 z = lookup_kind(a_ptr->tval, a_ptr->sval);
5568
5569                 /* Real object */
5570                 if (z)
5571                 {
5572                         object_type forge;
5573                         object_type *q_ptr;
5574
5575                         /* Get local object */
5576                         q_ptr = &forge;
5577
5578                         /* Create fake object */
5579                         object_prep(q_ptr, z);
5580
5581                         /* Make it an artifact */
5582                         q_ptr->name1 = (byte)who[k];
5583
5584                         /* Display as if known */
5585                         q_ptr->ident |= IDENT_STORE;
5586
5587                         /* Describe the artifact */
5588                         object_desc(base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
5589                 }
5590
5591                 /* Hack -- Build the artifact name */
5592                 fprintf(fff, _("     %s\n", "     The %s\n"), base_name);
5593         }
5594
5595         /* Free the "who" array */
5596         C_KILL(who, max_a_idx, s16b);
5597
5598         /* Free the "okay" array */
5599         C_KILL(okay, max_a_idx, bool);
5600
5601         /* Close the file */
5602         my_fclose(fff);
5603
5604         /* Display the file contents */
5605         show_file(TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
5606
5607         /* Remove the file */
5608         fd_kill(file_name);
5609 }
5610
5611
5612 /*
5613  * Display known uniques
5614  * With "XTRA HACK UNIQHIST" (Originally from XAngband)
5615  */
5616 static void do_cmd_knowledge_uniques(void)
5617 {
5618         int i, k, n = 0;
5619         u16b why = 2;
5620         s16b *who;
5621
5622         FILE *fff;
5623
5624         char file_name[1024];
5625
5626         int n_alive[10];
5627         int n_alive_surface = 0;
5628         int n_alive_over100 = 0;
5629         int n_alive_total = 0;
5630         int max_lev = -1;
5631
5632         for (i = 0; i < 10; i++) n_alive[i] = 0;
5633
5634         /* Open a new file */
5635         fff = my_fopen_temp(file_name, 1024);
5636
5637         if (!fff)
5638         {
5639             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5640             msg_print(NULL);
5641             return;
5642         }
5643
5644         /* Allocate the "who" array */
5645         C_MAKE(who, max_r_idx, s16b);
5646
5647         /* Scan the monsters */
5648         for (i = 1; i < max_r_idx; i++)
5649         {
5650                 monster_race *r_ptr = &r_info[i];
5651                 int          lev;
5652
5653                 if (!r_ptr->name) continue;
5654
5655                 /* Require unique monsters */
5656                 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
5657
5658                 /* Only display "known" uniques */
5659                 if (!cheat_know && !r_ptr->r_sights) continue;
5660
5661                 /* Only print rarity <= 100 uniques */
5662                 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
5663
5664                 /* Only "alive" uniques */
5665                 if (r_ptr->max_num == 0) continue;
5666
5667                 if (r_ptr->level)
5668                 {
5669                         lev = (r_ptr->level - 1) / 10;
5670                         if (lev < 10)
5671                         {
5672                                 n_alive[lev]++;
5673                                 if (max_lev < lev) max_lev = lev;
5674                         }
5675                         else n_alive_over100++;
5676                 }
5677                 else n_alive_surface++;
5678
5679                 /* Collect "appropriate" monsters */
5680                 who[n++] = i;
5681         }
5682
5683         /* Select the sort method */
5684         ang_sort_comp = ang_sort_comp_hook;
5685         ang_sort_swap = ang_sort_swap_hook;
5686
5687         /* Sort the array by dungeon depth of monsters */
5688         ang_sort(who, &why, n);
5689
5690         if (n_alive_surface)
5691         {
5692                 fprintf(fff, _("     地上  生存: %3d体\n", "      Surface  alive: %3d\n"), n_alive_surface);
5693                 n_alive_total += n_alive_surface;
5694         }
5695         for (i = 0; i <= max_lev; i++)
5696         {
5697                 fprintf(fff, _("%3d-%3d階  生存: %3d体\n", "Level %3d-%3d  alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
5698                 n_alive_total += n_alive[i];
5699         }
5700         if (n_alive_over100)
5701         {
5702                 fprintf(fff, _("101-   階  生存: %3d体\n", "Level 101-     alive: %3d\n"), n_alive_over100);
5703                 n_alive_total += n_alive_over100;
5704         }
5705
5706         if (n_alive_total)
5707         {
5708                 fputs(_("---------  -----------\n", "-------------  ----------\n"), fff);
5709                 fprintf(fff, _("     合計  生存: %3d体\n\n", "        Total  alive: %3d\n\n"), n_alive_total);
5710         }
5711         else
5712         {
5713                 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
5714         }
5715
5716         /* Scan the monster races */
5717         for (k = 0; k < n; k++)
5718         {
5719                 monster_race *r_ptr = &r_info[who[k]];
5720
5721                 /* Print a message */
5722                 fprintf(fff, _("     %s (レベル%d)\n", "     %s (level %d)\n"), r_name + r_ptr->name, r_ptr->level);
5723         }
5724
5725         /* Free the "who" array */
5726         C_KILL(who, max_r_idx, s16b);
5727
5728         /* Close the file */
5729         my_fclose(fff);
5730
5731         /* Display the file contents */
5732         show_file(TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
5733
5734         /* Remove the file */
5735         fd_kill(file_name);
5736 }
5737
5738
5739 /*
5740  * Display weapon-exp
5741  */
5742 static void do_cmd_knowledge_weapon_exp(void)
5743 {
5744         int i, j, num, weapon_exp;
5745
5746         FILE *fff;
5747
5748         char file_name[1024];
5749         char tmp[30];
5750
5751         /* Open a new file */
5752         fff = my_fopen_temp(file_name, 1024);
5753         if (!fff) {
5754             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5755             msg_print(NULL);
5756             return;
5757         }
5758
5759         for (i = 0; i < 5; i++)
5760         {
5761                 for (num = 0; num < 64; num++)
5762                 {
5763                         for (j = 0; j < max_k_idx; j++)
5764                         {
5765                                 object_kind *k_ptr = &k_info[j];
5766
5767                                 if ((k_ptr->tval == TV_SWORD - i) && (k_ptr->sval == num))
5768                                 {
5769                                         if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
5770
5771                                         weapon_exp = p_ptr->weapon_exp[4 - i][num];
5772                                         strip_name(tmp, j);
5773                                         fprintf(fff, "%-25s ", tmp);
5774                                         if (weapon_exp >= s_info[p_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
5775                                         else fprintf(fff, " ");
5776                                         fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
5777                                         if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
5778                                         fprintf(fff, "\n");
5779                                         break;
5780                                 }
5781                         }
5782                 }
5783         }
5784
5785         /* Close the file */
5786         my_fclose(fff);
5787
5788         /* Display the file contents */
5789         show_file(TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
5790
5791         /* Remove the file */
5792         fd_kill(file_name);
5793 }
5794
5795
5796 /*!
5797  * @brief 魔法の経験値を表示するコマンドのメインルーチン
5798  * Display spell-exp
5799  * @return なし
5800  */
5801 static void do_cmd_knowledge_spell_exp(void)
5802 {
5803         int i = 0, spell_exp, exp_level;
5804
5805         FILE *fff;
5806         const magic_type *s_ptr;
5807
5808         char file_name[1024];
5809
5810         /* Open a new file */
5811         fff = my_fopen_temp(file_name, 1024);
5812         if (!fff) {
5813             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5814             msg_print(NULL);
5815             return;
5816         }
5817
5818         if (p_ptr->realm1 != REALM_NONE)
5819         {
5820                 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[p_ptr->realm1]);
5821                 for (i = 0; i < 32; i++)
5822                 {
5823                         if (!is_magic(p_ptr->realm1))
5824                         {
5825                                 s_ptr = &technic_info[p_ptr->realm1 - MIN_TECHNIC][i];
5826                         }
5827                         else
5828                         {
5829                                 s_ptr = &mp_ptr->info[p_ptr->realm1 - 1][i];
5830                         }
5831                         if (s_ptr->slevel >= 99) continue;
5832                         spell_exp = p_ptr->spell_exp[i];
5833                         exp_level = spell_exp_level(spell_exp);
5834                         fprintf(fff, "%-25s ", do_spell(p_ptr->realm1, i, SPELL_NAME));
5835                         if (p_ptr->realm1 == REALM_HISSATSU)
5836                                 fprintf(fff, "[--]");
5837                         else
5838                         {
5839                                 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
5840                                 else fprintf(fff, " ");
5841                                 fprintf(fff, "%s", exp_level_str[exp_level]);
5842                         }
5843                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
5844                         fprintf(fff, "\n");
5845                 }
5846         }
5847
5848         if (p_ptr->realm2 != REALM_NONE)
5849         {
5850                 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[p_ptr->realm2]);
5851                 for (i = 0; i < 32; i++)
5852                 {
5853                         if (!is_magic(p_ptr->realm1))
5854                         {
5855                                 s_ptr = &technic_info[p_ptr->realm2 - MIN_TECHNIC][i];
5856                         }
5857                         else
5858                         {
5859                                 s_ptr = &mp_ptr->info[p_ptr->realm2 - 1][i];
5860                         }
5861                         if (s_ptr->slevel >= 99) continue;
5862
5863                         spell_exp = p_ptr->spell_exp[i + 32];
5864                         exp_level = spell_exp_level(spell_exp);
5865                         fprintf(fff, "%-25s ", do_spell(p_ptr->realm2, i, SPELL_NAME));
5866                         if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
5867                         else fprintf(fff, " ");
5868                         fprintf(fff, "%s", exp_level_str[exp_level]);
5869                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
5870                         fprintf(fff, "\n");
5871                 }
5872         }
5873
5874         /* Close the file */
5875         my_fclose(fff);
5876
5877         /* Display the file contents */
5878         show_file(TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
5879
5880         /* Remove the file */
5881         fd_kill(file_name);
5882 }
5883
5884
5885 /*!
5886  * @brief スキル情報を表示するコマンドのメインルーチン /
5887  * Display skill-exp
5888  * @return なし
5889  */
5890 static void do_cmd_knowledge_skill_exp(void)
5891 {
5892         int i = 0, skill_exp;
5893
5894         FILE *fff;
5895
5896         char file_name[1024];
5897         char skill_name[3][20]={_("マーシャルアーツ", "Martial Arts    "),
5898                                                         _("二刀流          ", "Dual Wielding   "), 
5899                                                         _("乗馬            ", "Riding          ")};
5900
5901         /* Open a new file */
5902         fff = my_fopen_temp(file_name, 1024);
5903         if (!fff) {
5904             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5905             msg_print(NULL);
5906             return;
5907         }
5908
5909         for (i = 0; i < 3; i++)
5910         {
5911                 skill_exp = p_ptr->skill_exp[i];
5912                 fprintf(fff, "%-20s ", skill_name[i]);
5913                 if (skill_exp >= s_info[p_ptr->pclass].s_max[i]) fprintf(fff, "!");
5914                 else fprintf(fff, " ");
5915                 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
5916                 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
5917                 fprintf(fff, "\n");
5918         }
5919
5920         /* Close the file */
5921         my_fclose(fff);
5922
5923         /* Display the file contents */
5924         show_file(TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
5925
5926         /* Remove the file */
5927         fd_kill(file_name);
5928 }
5929
5930
5931 /*!
5932  * @brief 英単語、句、説を複数形を変換する / Pluralize a monster name
5933  * @param Name 変換したい文字列の参照ポインタ
5934  * @return なし
5935  */
5936 void plural_aux(char *Name)
5937 {
5938         int NameLen = strlen(Name);
5939
5940         if (my_strstr(Name, "Disembodied hand"))
5941         {
5942                 strcpy(Name, "Disembodied hands that strangled people");
5943         }
5944         else if (my_strstr(Name, "Colour out of space"))
5945         {
5946                 strcpy(Name, "Colours out of space");
5947         }
5948         else if (my_strstr(Name, "stairway to hell"))
5949         {
5950                 strcpy(Name, "stairways to hell");
5951         }
5952         else if (my_strstr(Name, "Dweller on the threshold"))
5953         {
5954                 strcpy(Name, "Dwellers on the threshold");
5955         }
5956         else if (my_strstr(Name, " of "))
5957         {
5958                 cptr aider = my_strstr(Name, " of ");
5959                 char dummy[80];
5960                 int i = 0;
5961                 cptr ctr = Name;
5962
5963                 while (ctr < aider)
5964                 {
5965                         dummy[i] = *ctr;
5966                         ctr++; i++;
5967                 }
5968
5969                 if (dummy[i-1] == 's')
5970                 {
5971                         strcpy(&(dummy[i]), "es");
5972                         i++;
5973                 }
5974                 else
5975                 {
5976                         strcpy(&(dummy[i]), "s");
5977                 }
5978
5979                 strcpy(&(dummy[i+1]), aider);
5980                 strcpy(Name, dummy);
5981         }
5982         else if (my_strstr(Name, "coins"))
5983         {
5984                 char dummy[80];
5985                 strcpy(dummy, "piles of ");
5986                 strcat(dummy, Name);
5987                 strcpy(Name, dummy);
5988                 return;
5989         }
5990         else if (my_strstr(Name, "Manes"))
5991         {
5992                 return;
5993         }
5994         else if (streq(&(Name[NameLen - 2]), "ey"))
5995         {
5996                 strcpy(&(Name[NameLen - 2]), "eys");
5997         }
5998         else if (Name[NameLen - 1] == 'y')
5999         {
6000                 strcpy(&(Name[NameLen - 1]), "ies");
6001         }
6002         else if (streq(&(Name[NameLen - 4]), "ouse"))
6003         {
6004                 strcpy(&(Name[NameLen - 4]), "ice");
6005         }
6006         else if (streq(&(Name[NameLen - 2]), "us"))
6007         {
6008                 strcpy(&(Name[NameLen - 2]), "i");
6009         }
6010         else if (streq(&(Name[NameLen - 6]), "kelman"))
6011         {
6012                 strcpy(&(Name[NameLen - 6]), "kelmen");
6013         }
6014         else if (streq(&(Name[NameLen - 8]), "wordsman"))
6015         {
6016                 strcpy(&(Name[NameLen - 8]), "wordsmen");
6017         }
6018         else if (streq(&(Name[NameLen - 7]), "oodsman"))
6019         {
6020                 strcpy(&(Name[NameLen - 7]), "oodsmen");
6021         }
6022         else if (streq(&(Name[NameLen - 7]), "eastman"))
6023         {
6024                 strcpy(&(Name[NameLen - 7]), "eastmen");
6025         }
6026         else if (streq(&(Name[NameLen - 8]), "izardman"))
6027         {
6028                 strcpy(&(Name[NameLen - 8]), "izardmen");
6029         }
6030         else if (streq(&(Name[NameLen - 5]), "geist"))
6031         {
6032                 strcpy(&(Name[NameLen - 5]), "geister");
6033         }
6034         else if (streq(&(Name[NameLen - 2]), "ex"))
6035         {
6036                 strcpy(&(Name[NameLen - 2]), "ices");
6037         }
6038         else if (streq(&(Name[NameLen - 2]), "lf"))
6039         {
6040                 strcpy(&(Name[NameLen - 2]), "lves");
6041         }
6042         else if (suffix(Name, "ch") ||
6043                  suffix(Name, "sh") ||
6044                          suffix(Name, "nx") ||
6045                          suffix(Name, "s") ||
6046                          suffix(Name, "o"))
6047         {
6048                 strcpy(&(Name[NameLen]), "es");
6049         }
6050         else
6051         {
6052                 strcpy(&(Name[NameLen]), "s");
6053         }
6054 }
6055
6056 /*!
6057  * @brief 現在のペットを表示するコマンドのメインルーチン /
6058  * Display current pets
6059  * @return なし
6060  */
6061 static void do_cmd_knowledge_pets(void)
6062 {
6063         int             i;
6064         FILE            *fff;
6065         monster_type    *m_ptr;
6066         char            pet_name[80];
6067         int             t_friends = 0;
6068         int             show_upkeep = 0;
6069         char            file_name[1024];
6070
6071
6072         /* Open a new file */
6073         fff = my_fopen_temp(file_name, 1024);
6074         if (!fff) {
6075             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6076             msg_print(NULL);
6077             return;
6078         }
6079
6080         /* Process the monsters (backwards) */
6081         for (i = m_max - 1; i >= 1; i--)
6082         {
6083                 /* Access the monster */
6084                 m_ptr = &m_list[i];
6085
6086                 /* Ignore "dead" monsters */
6087                 if (!m_ptr->r_idx) continue;
6088
6089                 /* Calculate "upkeep" for pets */
6090                 if (is_pet(m_ptr))
6091                 {
6092                         t_friends++;
6093                         monster_desc(pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
6094                         fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
6095                 }
6096         }
6097
6098         show_upkeep = calculate_upkeep();
6099
6100         fprintf(fff, "----------------------------------------------\n");
6101 #ifdef JP
6102         fprintf(fff, "    合計: %d 体のペット\n", t_friends);
6103         fprintf(fff, " 維持コスト: %d%% MP\n", show_upkeep);
6104 #else
6105         fprintf(fff, "   Total: %d pet%s.\n",
6106                 t_friends, (t_friends == 1 ? "" : "s"));
6107         fprintf(fff, "   Upkeep: %d%% mana.\n", show_upkeep);
6108 #endif
6109
6110
6111
6112         /* Close the file */
6113         my_fclose(fff);
6114
6115         /* Display the file contents */
6116         show_file(TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
6117
6118         /* Remove the file */
6119         fd_kill(file_name);
6120 }
6121
6122
6123 /*!
6124  * @brief 現在のペットを表示するコマンドのメインルーチン /
6125  * Total kill count
6126  * @return なし
6127  * @note the player ghosts are ignored.  XXX XXX XXX
6128  */
6129 static void do_cmd_knowledge_kill_count(void)
6130 {
6131         int i, k, n = 0;
6132         u16b why = 2;
6133         s16b *who;
6134
6135         FILE *fff;
6136
6137         char file_name[1024];
6138
6139         s32b Total = 0;
6140
6141
6142         /* Open a new file */
6143         fff = my_fopen_temp(file_name, 1024);
6144
6145         if (!fff) {
6146             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
6147             msg_print(NULL);
6148             return;
6149         }
6150
6151         /* Allocate the "who" array */
6152         C_MAKE(who, max_r_idx, s16b);
6153
6154         {
6155                 /* Monsters slain */
6156                 int kk;
6157
6158                 for (kk = 1; kk < max_r_idx; kk++)
6159                 {
6160                         monster_race *r_ptr = &r_info[kk];
6161
6162                         if (r_ptr->flags1 & (RF1_UNIQUE))
6163                         {
6164                                 bool dead = (r_ptr->max_num == 0);
6165
6166                                 if (dead)
6167                                 {
6168                                         Total++;
6169                                 }
6170                         }
6171                         else
6172                         {
6173                                 s16b This = r_ptr->r_pkills;
6174
6175                                 if (This > 0)
6176                                 {
6177                                         Total += This;
6178                                 }
6179                         }
6180                 }
6181
6182                 if (Total < 1)
6183                         fprintf(fff,_("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
6184                 else
6185 #ifdef JP
6186                         fprintf(fff,"あなたは%ld体の敵を倒している。\n\n", (long int)Total);
6187 #else
6188                         fprintf(fff,"You have defeated %ld %s.\n\n", (long int)Total, (Total == 1) ? "enemy" : "enemies");
6189 #endif
6190         }
6191
6192         Total = 0;
6193
6194         /* Scan the monsters */
6195         for (i = 1; i < max_r_idx; i++)
6196         {
6197                 monster_race *r_ptr = &r_info[i];
6198
6199                 /* Use that monster */
6200                 if (r_ptr->name) who[n++] = i;
6201         }
6202
6203         /* Select the sort method */
6204         ang_sort_comp = ang_sort_comp_hook;
6205         ang_sort_swap = ang_sort_swap_hook;
6206
6207         /* Sort the array by dungeon depth of monsters */
6208         ang_sort(who, &why, n);
6209
6210         /* Scan the monster races */
6211         for (k = 0; k < n; k++)
6212         {
6213                 monster_race *r_ptr = &r_info[who[k]];
6214
6215                 if (r_ptr->flags1 & (RF1_UNIQUE))
6216                 {
6217                         bool dead = (r_ptr->max_num == 0);
6218
6219                         if (dead)
6220                         {
6221                                 /* Print a message */
6222                                 fprintf(fff, "     %s\n",
6223                                     (r_name + r_ptr->name));
6224                                 Total++;
6225                         }
6226                 }
6227                 else
6228                 {
6229                         s16b This = r_ptr->r_pkills;
6230
6231                         if (This > 0)
6232                         {
6233 #ifdef JP
6234                                 /* p,tは人と数える by ita */
6235                                 if (my_strchr("pt", r_ptr->d_char))
6236                                         fprintf(fff, "     %3d 人の %s\n", This, r_name + r_ptr->name);
6237                                 else
6238                                         fprintf(fff, "     %3d 体の %s\n", This, r_name + r_ptr->name);
6239 #else
6240                                 if (This < 2)
6241                                 {
6242                                         if (my_strstr(r_name + r_ptr->name, "coins"))
6243                                         {
6244                                                 fprintf(fff, "     1 pile of %s\n", (r_name + r_ptr->name));
6245                                         }
6246                                         else
6247                                         {
6248                                                 fprintf(fff, "     1 %s\n", (r_name + r_ptr->name));
6249                                         }
6250                                 }
6251                                 else
6252                                 {
6253                                         char ToPlural[80];
6254                                         strcpy(ToPlural, (r_name + r_ptr->name));
6255                                         plural_aux(ToPlural);
6256                                         fprintf(fff, "     %d %s\n", This, ToPlural);
6257                                 }
6258 #endif
6259
6260
6261                                 Total += This;
6262                         }
6263                 }
6264         }
6265
6266         fprintf(fff,"----------------------------------------------\n");
6267 #ifdef JP
6268         fprintf(fff,"    合計: %lu 体を倒した。\n", (unsigned long int)Total);
6269 #else
6270         fprintf(fff,"   Total: %lu creature%s killed.\n",
6271                 (unsigned long int)Total, (Total == 1 ? "" : "s"));
6272 #endif
6273
6274
6275         /* Free the "who" array */
6276         C_KILL(who, max_r_idx, s16b);
6277
6278         /* Close the file */
6279         my_fclose(fff);
6280
6281         /* Display the file contents */
6282         show_file(TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
6283
6284         /* Remove the file */
6285         fd_kill(file_name);
6286 }
6287
6288
6289 /*!
6290  * @brief モンスター情報リスト中のグループを表示する /
6291  * Display the object groups.
6292  * @param col 開始行
6293  * @param row 開始列
6294  * @param wid 表示文字数幅
6295  * @param per_page リストの表示行
6296  * @param grp_idx グループのID配列
6297  * @param group_text グループ名の文字列配列
6298  * @param grp_cur 現在の選択ID
6299  * @param grp_top 現在の選択リスト最上部ID
6300  * @return なし
6301  */
6302 static void display_group_list(int col, int row, int wid, int per_page,
6303         int grp_idx[], cptr group_text[], int grp_cur, int grp_top)
6304 {
6305         int i;
6306
6307         /* Display lines until done */
6308         for (i = 0; i < per_page && (grp_idx[i] >= 0); i++)
6309         {
6310                 /* Get the group index */
6311                 int grp = grp_idx[grp_top + i];
6312
6313                 /* Choose a color */
6314                 byte attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
6315
6316                 /* Erase the entire line */
6317                 Term_erase(col, row + i, wid);
6318
6319                 /* Display the group label */
6320                 c_put_str(attr, group_text[grp], row + i, col);
6321         }
6322 }
6323
6324
6325 /* 
6326  * Move the cursor in a browser window 
6327  */
6328 static void browser_cursor(char ch, int *column, int *grp_cur, int grp_cnt, 
6329                                                    int *list_cur, int list_cnt)
6330 {
6331         int d;
6332         int col = *column;
6333         int grp = *grp_cur;
6334         int list = *list_cur;
6335
6336         /* Extract direction */
6337         if (ch == ' ')
6338         {
6339                 /* Hack -- scroll up full screen */
6340                 d = 3;
6341         }
6342         else if (ch == '-')
6343         {
6344                 /* Hack -- scroll down full screen */
6345                 d = 9;
6346         }
6347         else
6348         {
6349                 d = get_keymap_dir(ch);
6350         }
6351
6352         if (!d) return;
6353
6354         /* Diagonals - hack */
6355         if ((ddx[d] > 0) && ddy[d])
6356         {
6357                 int browser_rows;
6358                 int wid, hgt;
6359
6360                 /* Get size */
6361                 Term_get_size(&wid, &hgt);
6362
6363                 browser_rows = hgt - 8;
6364
6365                 /* Browse group list */
6366                 if (!col)
6367                 {
6368                         int old_grp = grp;
6369
6370                         /* Move up or down */
6371                         grp += ddy[d] * (browser_rows - 1);
6372
6373                         /* Verify */
6374                         if (grp >= grp_cnt)     grp = grp_cnt - 1;
6375                         if (grp < 0) grp = 0;
6376                         if (grp != old_grp)     list = 0;
6377                 }
6378
6379                 /* Browse sub-list list */
6380                 else
6381                 {
6382                         /* Move up or down */
6383                         list += ddy[d] * browser_rows;
6384
6385                         /* Verify */
6386                         if (list >= list_cnt) list = list_cnt - 1;
6387                         if (list < 0) list = 0;
6388                 }
6389
6390                 (*grp_cur) = grp;
6391                 (*list_cur) = list;
6392
6393                 return;
6394         }
6395
6396         if (ddx[d])
6397         {
6398                 col += ddx[d];
6399                 if (col < 0) col = 0;
6400                 if (col > 1) col = 1;
6401
6402                 (*column) = col;
6403
6404                 return;
6405         }
6406
6407         /* Browse group list */
6408         if (!col)
6409         {
6410                 int old_grp = grp;
6411
6412                 /* Move up or down */
6413                 grp += ddy[d];
6414
6415                 /* Verify */
6416                 if (grp >= grp_cnt)     grp = grp_cnt - 1;
6417                 if (grp < 0) grp = 0;
6418                 if (grp != old_grp)     list = 0;
6419         }
6420
6421         /* Browse sub-list list */
6422         else
6423         {
6424                 /* Move up or down */
6425                 list += ddy[d];
6426
6427                 /* Verify */
6428                 if (list >= list_cnt) list = list_cnt - 1;
6429                 if (list < 0) list = 0;
6430         }
6431
6432         (*grp_cur) = grp;
6433         (*list_cur) = list;
6434 }
6435
6436
6437 /*
6438  * Display visuals.
6439  */
6440 static void display_visual_list(int col, int row, int height, int width, byte attr_top, byte char_left)
6441 {
6442         int i, j;
6443
6444         /* Clear the display lines */
6445         for (i = 0; i < height; i++)
6446         {
6447                 Term_erase(col, row + i, width);
6448         }
6449
6450         /* Bigtile mode uses double width */
6451         if (use_bigtile) width /= 2;
6452
6453         /* Display lines until done */
6454         for (i = 0; i < height; i++)
6455         {
6456                 /* Display columns until done */
6457                 for (j = 0; j < width; j++)
6458                 {
6459                         byte a;
6460                         char c;
6461                         int x = col + j;
6462                         int y = row + i;
6463                         int ia, ic;
6464
6465                         /* Bigtile mode uses double width */
6466                         if (use_bigtile) x += j;
6467
6468                         ia = attr_top + i;
6469                         ic = char_left + j;
6470
6471                         /* Ignore illegal characters */
6472                         if (ia > 0x7f || ic > 0xff || ic < ' ' ||
6473                             (!use_graphics && ic > 0x7f))
6474                                 continue;
6475
6476                         a = (byte)ia;
6477                         c = (char)ic;
6478
6479                         /* Force correct code for both ASCII character and tile */
6480                         if (c & 0x80) a |= 0x80;
6481
6482                         /* Display symbol */
6483                         Term_queue_bigchar(x, y, a, c, 0, 0);
6484                 }
6485         }
6486 }
6487
6488
6489 /*
6490  * Place the cursor at the collect position for visual mode
6491  */
6492 static void place_visual_list_cursor(int col, int row, byte a, byte c, byte attr_top, byte char_left)
6493 {
6494         int i = (a & 0x7f) - attr_top;
6495         int j = c - char_left;
6496
6497         int x = col + j;
6498         int y = row + i;
6499
6500         /* Bigtile mode uses double width */
6501         if (use_bigtile) x += j;
6502
6503         /* Place the cursor */
6504         Term_gotoxy(x, y);
6505 }
6506
6507
6508 /*
6509  *  Clipboard variables for copy&paste in visual mode
6510  */
6511 static byte attr_idx = 0;
6512 static byte char_idx = 0;
6513
6514 /* Hack -- for feature lighting */
6515 static byte attr_idx_feat[F_LIT_MAX];
6516 static byte char_idx_feat[F_LIT_MAX];
6517
6518 /*
6519  *  Do visual mode command -- Change symbols
6520  */
6521 static bool visual_mode_command(char ch, bool *visual_list_ptr,
6522                                 int height, int width,
6523                                 byte *attr_top_ptr, byte *char_left_ptr,
6524                                 byte *cur_attr_ptr, byte *cur_char_ptr, bool *need_redraw)
6525 {
6526         static byte attr_old = 0, char_old = 0;
6527
6528         switch (ch)
6529         {
6530         case ESCAPE:
6531                 if (*visual_list_ptr)
6532                 {
6533                         /* Cancel change */
6534                         *cur_attr_ptr = attr_old;
6535                         *cur_char_ptr = char_old;
6536                         *visual_list_ptr = FALSE;
6537
6538                         return TRUE;
6539                 }
6540                 break;
6541
6542         case '\n':
6543         case '\r':
6544                 if (*visual_list_ptr)
6545                 {
6546                         /* Accept change */
6547                         *visual_list_ptr = FALSE;
6548                         *need_redraw = TRUE;
6549
6550                         return TRUE;
6551                 }
6552                 break;
6553
6554         case 'V':
6555         case 'v':
6556                 if (!*visual_list_ptr)
6557                 {
6558                         *visual_list_ptr = TRUE;
6559
6560                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
6561                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
6562
6563                         attr_old = *cur_attr_ptr;
6564                         char_old = *cur_char_ptr;
6565
6566                         return TRUE;
6567                 }
6568                 break;
6569
6570         case 'C':
6571         case 'c':
6572                 {
6573                         int i;
6574
6575                         /* Set the visual */
6576                         attr_idx = *cur_attr_ptr;
6577                         char_idx = *cur_char_ptr;
6578
6579                         /* Hack -- for feature lighting */
6580                         for (i = 0; i < F_LIT_MAX; i++)
6581                         {
6582                                 attr_idx_feat[i] = 0;
6583                                 char_idx_feat[i] = 0;
6584                         }
6585                 }
6586                 return TRUE;
6587
6588         case 'P':
6589         case 'p':
6590                 if (attr_idx || (!(char_idx & 0x80) && char_idx)) /* Allow TERM_DARK text */
6591                 {
6592                         /* Set the char */
6593                         *cur_attr_ptr = attr_idx;
6594                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
6595                         if (!*visual_list_ptr) *need_redraw = TRUE;
6596                 }
6597
6598                 if (char_idx)
6599                 {
6600                         /* Set the char */
6601                         *cur_char_ptr = char_idx;
6602                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
6603                         if (!*visual_list_ptr) *need_redraw = TRUE;
6604                 }
6605
6606                 return TRUE;
6607
6608         default:
6609                 if (*visual_list_ptr)
6610                 {
6611                         int eff_width;
6612                         int d = get_keymap_dir(ch);
6613                         byte a = (*cur_attr_ptr & 0x7f);
6614                         byte c = *cur_char_ptr;
6615
6616                         if (use_bigtile) eff_width = width / 2;
6617                         else eff_width = width;
6618
6619                         /* Restrict direction */
6620                         if ((a == 0) && (ddy[d] < 0)) d = 0;
6621                         if ((c == 0) && (ddx[d] < 0)) d = 0;
6622                         if ((a == 0x7f) && (ddy[d] > 0)) d = 0;
6623                         if ((c == 0xff) && (ddx[d] > 0)) d = 0;
6624
6625                         a += ddy[d];
6626                         c += ddx[d];
6627
6628                         /* Force correct code for both ASCII character and tile */
6629                         if (c & 0x80) a |= 0x80;
6630
6631                         /* Set the visual */
6632                         *cur_attr_ptr = a;
6633                         *cur_char_ptr = c;
6634
6635
6636                         /* Move the frame */
6637                         if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--;
6638                         if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++;
6639                         if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--;
6640                         if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++;
6641                         return TRUE;
6642                 }
6643                 break;
6644         }
6645
6646         /* Visual mode command is not used */
6647         return FALSE;
6648 }
6649
6650
6651 /*
6652  * Display the monsters in a group.
6653  */
6654 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[],
6655         int mon_cur, int mon_top, bool visual_only)
6656 {
6657         int i;
6658
6659         /* Display lines until done */
6660         for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
6661         {
6662                 byte attr;
6663
6664                 /* Get the race index */
6665                 int r_idx = mon_idx[mon_top + i] ;
6666
6667                 /* Access the race */
6668                 monster_race *r_ptr = &r_info[r_idx];
6669
6670                 /* Choose a color */
6671                 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
6672
6673                 /* Display the name */
6674                 c_prt(attr, (r_name + r_ptr->name), row + i, col);
6675
6676                 /* Hack -- visual_list mode */
6677                 if (per_page == 1)
6678                 {
6679                         c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (p_ptr->wizard || visual_only) ? 56 : 61);
6680                 }
6681                 if (p_ptr->wizard || visual_only)
6682                 {
6683                         c_prt(attr, format("%d", r_idx), row + i, 62);
6684                 }
6685
6686                 /* Erase chars before overwritten by the race letter */
6687                 Term_erase(69, row + i, 255);
6688
6689                 /* Display symbol */
6690                 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
6691
6692                 if (!visual_only)
6693                 {
6694                         /* Display kills */
6695                         if (!(r_ptr->flags1 & RF1_UNIQUE)) 
6696                                 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
6697                         else 
6698                                 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE), 
6699                                                   (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
6700                 }
6701         }
6702
6703         /* Clear remaining lines */
6704         for (; i < per_page; i++)
6705         {
6706                 Term_erase(col, row + i, 255);
6707         }
6708 }
6709
6710
6711 /*
6712  * Display known monsters.
6713  */
6714 static void do_cmd_knowledge_monsters(bool *need_redraw, bool visual_only, int direct_r_idx)
6715 {
6716         int i, len, max;
6717         int grp_cur, grp_top, old_grp_cur;
6718         int mon_cur, mon_top;
6719         int grp_cnt, grp_idx[100];
6720         int mon_cnt;
6721         s16b *mon_idx;
6722
6723         int column = 0;
6724         bool flag;
6725         bool redraw;
6726
6727         bool visual_list = FALSE;
6728         byte attr_top = 0, char_left = 0;
6729
6730         int browser_rows;
6731         int wid, hgt;
6732
6733         byte mode;
6734
6735         /* Get size */
6736         Term_get_size(&wid, &hgt);
6737
6738         browser_rows = hgt - 8;
6739
6740         /* Allocate the "mon_idx" array */
6741         C_MAKE(mon_idx, max_r_idx, s16b);
6742
6743         max = 0;
6744         grp_cnt = 0;
6745
6746         if (direct_r_idx < 0)
6747         {
6748                 mode = visual_only ? 0x03 : 0x01;
6749
6750                 /* Check every group */
6751                 for (i = 0; monster_group_text[i] != NULL; i++)
6752                 {
6753                         /* Measure the label */
6754                         len = strlen(monster_group_text[i]);
6755
6756                         /* Save the maximum length */
6757                         if (len > max) max = len;
6758
6759                         /* See if any monsters are known */
6760                         if ((monster_group_char[i] == ((char *) -1L)) || collect_monsters(i, mon_idx, mode))
6761                         {
6762                                 /* Build a list of groups with known monsters */
6763                                 grp_idx[grp_cnt++] = i;
6764                         }
6765                 }
6766
6767                 mon_cnt = 0;
6768         }
6769         else
6770         {
6771                 mon_idx[0] = direct_r_idx;
6772                 mon_cnt = 1;
6773
6774                 /* Terminate the list */
6775                 mon_idx[1] = -1;
6776
6777                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
6778                         &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
6779         }
6780
6781         /* Terminate the list */
6782         grp_idx[grp_cnt] = -1;
6783
6784         old_grp_cur = -1;
6785         grp_cur = grp_top = 0;
6786         mon_cur = mon_top = 0;
6787
6788         flag = FALSE;
6789         redraw = TRUE;
6790
6791         mode = visual_only ? 0x02 : 0x00;
6792
6793         while (!flag)
6794         {
6795                 char ch;
6796                 monster_race *r_ptr;
6797
6798                 if (redraw)
6799                 {
6800                         clear_from(0);
6801
6802 #ifdef JP
6803                         prt(format("%s - モンスター", !visual_only ? "知識" : "表示"), 2, 0);
6804                         if (direct_r_idx < 0) prt("グループ", 4, 0);
6805                         prt("名前", 4, max + 3);
6806                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
6807                         prt("文字", 4, 67);
6808                         if (!visual_only) prt("殺害数", 4, 72);
6809 #else
6810                         prt(format("%s - monsters", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
6811                         if (direct_r_idx < 0) prt("Group", 4, 0);
6812                         prt("Name", 4, max + 3);
6813                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
6814                         prt("Sym", 4, 68);
6815                         if (!visual_only) prt("Kills", 4, 73);
6816 #endif
6817
6818                         for (i = 0; i < 78; i++)
6819                         {
6820                                 Term_putch(i, 5, TERM_WHITE, '=');
6821                         }
6822
6823                         if (direct_r_idx < 0)
6824                         {
6825                                 for (i = 0; i < browser_rows; i++)
6826                                 {
6827                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
6828                                 }
6829                         }
6830
6831                         redraw = FALSE;
6832                 }
6833
6834                 if (direct_r_idx < 0)
6835                 {
6836                         /* Scroll group list */
6837                         if (grp_cur < grp_top) grp_top = grp_cur;
6838                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
6839
6840                         /* Display a list of monster groups */
6841                         display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
6842
6843                         if (old_grp_cur != grp_cur)
6844                         {
6845                                 old_grp_cur = grp_cur;
6846
6847                                 /* Get a list of monsters in the current group */
6848                                 mon_cnt = collect_monsters(grp_idx[grp_cur], mon_idx, mode);
6849                         }
6850
6851                         /* Scroll monster list */
6852                         while (mon_cur < mon_top)
6853                                 mon_top = MAX(0, mon_top - browser_rows/2);
6854                         while (mon_cur >= mon_top + browser_rows)
6855                                 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows/2);
6856                 }
6857
6858                 if (!visual_list)
6859                 {
6860                         /* Display a list of monsters in the current group */
6861                         display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
6862                 }
6863                 else
6864                 {
6865                         mon_top = mon_cur;
6866
6867                         /* Display a monster name */
6868                         display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
6869
6870                         /* Display visual list below first monster */
6871                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
6872                 }
6873
6874                 /* Prompt */
6875 #ifdef JP
6876                 prt(format("<方向>%s%s%s, ESC",
6877                         (!visual_list && !visual_only) ? ", 'r'で思い出を見る" : "",
6878                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
6879                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
6880                         hgt - 1, 0);
6881 #else
6882                 prt(format("<dir>%s%s%s, ESC",
6883                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
6884                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
6885                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
6886                         hgt - 1, 0);
6887 #endif
6888
6889                 /* Get the current monster */
6890                 r_ptr = &r_info[mon_idx[mon_cur]];
6891
6892                 if (!visual_only)
6893                 {
6894                         /* Mega Hack -- track this monster race */
6895                         if (mon_cnt) monster_race_track(mon_idx[mon_cur]);
6896
6897                         /* Hack -- handle stuff */
6898                         handle_stuff();
6899                 }
6900
6901                 if (visual_list)
6902                 {
6903                         place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
6904                 }
6905                 else if (!column)
6906                 {
6907                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
6908                 }
6909                 else
6910                 {
6911                         Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
6912                 }
6913
6914                 ch = inkey();
6915
6916                 /* Do visual mode command if needed */
6917                 if (visual_mode_command(ch, &visual_list, browser_rows-1, wid - (max + 3), &attr_top, &char_left, &r_ptr->x_attr, &r_ptr->x_char, need_redraw))
6918                 {
6919                         if (direct_r_idx >= 0)
6920                         {
6921                                 switch (ch)
6922                                 {
6923                                 case '\n':
6924                                 case '\r':
6925                                 case ESCAPE:
6926                                         flag = TRUE;
6927                                         break;
6928                                 }
6929                         }
6930                         continue;
6931                 }
6932
6933                 switch (ch)
6934                 {
6935                         case ESCAPE:
6936                         {
6937                                 flag = TRUE;
6938                                 break;
6939                         }
6940
6941                         case 'R':
6942                         case 'r':
6943                         {
6944                                 /* Recall on screen */
6945                                 if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
6946                                 {
6947                                         screen_roff(mon_idx[mon_cur], 0);
6948
6949                                         (void)inkey();
6950
6951                                         redraw = TRUE;
6952                                 }
6953                                 break;
6954                         }
6955
6956                         default:
6957                         {
6958                                 /* Move the cursor */
6959                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
6960
6961                                 break;
6962                         }
6963                 }
6964         }
6965
6966         /* Free the "mon_idx" array */
6967         C_KILL(mon_idx, max_r_idx, s16b);
6968 }
6969
6970
6971 /*
6972  * Display the objects in a group.
6973  */
6974 static void display_object_list(int col, int row, int per_page, int object_idx[],
6975         int object_cur, int object_top, bool visual_only)
6976 {
6977         int i;
6978
6979         /* Display lines until done */
6980         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
6981         {
6982                 char o_name[80];
6983                 byte a, c;
6984                 object_kind *flavor_k_ptr;
6985
6986                 /* Get the object index */
6987                 int k_idx = object_idx[object_top + i];
6988
6989                 /* Access the object */
6990                 object_kind *k_ptr = &k_info[k_idx];
6991
6992                 /* Choose a color */
6993                 byte attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
6994                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
6995
6996
6997                 if (!visual_only && k_ptr->flavor)
6998                 {
6999                         /* Appearance of this object is shuffled */
7000                         flavor_k_ptr = &k_info[k_ptr->flavor];
7001                 }
7002                 else
7003                 {
7004                         /* Appearance of this object is very normal */
7005                         flavor_k_ptr = k_ptr;
7006                 }
7007
7008
7009
7010                 attr = ((i + object_top == object_cur) ? cursor : attr);
7011
7012                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
7013                 {
7014                         /* Tidy name */
7015                         strip_name(o_name, k_idx);
7016                 }
7017                 else
7018                 {
7019                         /* Flavor name */
7020                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
7021                 }
7022
7023                 /* Display the name */
7024                 c_prt(attr, o_name, row + i, col);
7025
7026                 /* Hack -- visual_list mode */
7027                 if (per_page == 1)
7028                 {
7029                         c_prt(attr, format("%02x/%02x", flavor_k_ptr->x_attr, flavor_k_ptr->x_char), row + i, (p_ptr->wizard || visual_only) ? 64 : 68);
7030                 }
7031                 if (p_ptr->wizard || visual_only)
7032                 {
7033                         c_prt(attr, format("%d", k_idx), row + i, 70);
7034                 }
7035
7036                 a = flavor_k_ptr->x_attr;
7037                 c = flavor_k_ptr->x_char;
7038
7039                 /* Display symbol */
7040                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
7041         }
7042
7043         /* Clear remaining lines */
7044         for (; i < per_page; i++)
7045         {
7046                 Term_erase(col, row + i, 255);
7047         }
7048 }
7049
7050 /*
7051  * Describe fake object
7052  */
7053 static void desc_obj_fake(int k_idx)
7054 {
7055         object_type *o_ptr;
7056         object_type object_type_body;
7057
7058         /* Get local object */
7059         o_ptr = &object_type_body;
7060
7061         /* Wipe the object */
7062         object_wipe(o_ptr);
7063
7064         /* Create the artifact */
7065         object_prep(o_ptr, k_idx);
7066
7067         /* It's fully know */
7068         o_ptr->ident |= IDENT_KNOWN;
7069
7070         /* Track the object */
7071         /* object_actual_track(o_ptr); */
7072
7073         /* Hack - mark as fake */
7074         /* term_obj_real = FALSE; */
7075
7076         /* Hack -- Handle stuff */
7077         handle_stuff();
7078
7079         if (!screen_object(o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL))
7080         {
7081                 msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
7082                 msg_print(NULL);
7083         }
7084 }
7085
7086
7087
7088 /*
7089  * Display known objects
7090  */
7091 static void do_cmd_knowledge_objects(bool *need_redraw, bool visual_only, int direct_k_idx)
7092 {
7093         int i, len, max;
7094         int grp_cur, grp_top, old_grp_cur;
7095         int object_old, object_cur, object_top;
7096         int grp_cnt, grp_idx[100];
7097         int object_cnt;
7098         int *object_idx;
7099
7100         int column = 0;
7101         bool flag;
7102         bool redraw;
7103
7104         bool visual_list = FALSE;
7105         byte attr_top = 0, char_left = 0;
7106
7107         int browser_rows;
7108         int wid, hgt;
7109
7110         byte mode;
7111
7112         /* Get size */
7113         Term_get_size(&wid, &hgt);
7114
7115         browser_rows = hgt - 8;
7116
7117         /* Allocate the "object_idx" array */
7118         C_MAKE(object_idx, max_k_idx, int);
7119
7120         max = 0;
7121         grp_cnt = 0;
7122
7123         if (direct_k_idx < 0)
7124         {
7125                 mode = visual_only ? 0x03 : 0x01;
7126
7127                 /* Check every group */
7128                 for (i = 0; object_group_text[i] != NULL; i++)
7129                 {
7130                         /* Measure the label */
7131                         len = strlen(object_group_text[i]);
7132
7133                         /* Save the maximum length */
7134                         if (len > max) max = len;
7135
7136                         /* See if any monsters are known */
7137                         if (collect_objects(i, object_idx, mode))
7138                         {
7139                                 /* Build a list of groups with known monsters */
7140                                 grp_idx[grp_cnt++] = i;
7141                         }
7142                 }
7143
7144                 object_old = -1;
7145                 object_cnt = 0;
7146         }
7147         else
7148         {
7149                 object_kind *k_ptr = &k_info[direct_k_idx];
7150                 object_kind *flavor_k_ptr;
7151
7152                 if (!visual_only && k_ptr->flavor)
7153                 {
7154                         /* Appearance of this object is shuffled */
7155                         flavor_k_ptr = &k_info[k_ptr->flavor];
7156                 }
7157                 else
7158                 {
7159                         /* Appearance of this object is very normal */
7160                         flavor_k_ptr = k_ptr;
7161                 }
7162
7163                 object_idx[0] = direct_k_idx;
7164                 object_old = direct_k_idx;
7165                 object_cnt = 1;
7166
7167                 /* Terminate the list */
7168                 object_idx[1] = -1;
7169
7170                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
7171                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
7172         }
7173
7174         /* Terminate the list */
7175         grp_idx[grp_cnt] = -1;
7176
7177         old_grp_cur = -1;
7178         grp_cur = grp_top = 0;
7179         object_cur = object_top = 0;
7180
7181         flag = FALSE;
7182         redraw = TRUE;
7183
7184         mode = visual_only ? 0x02 : 0x00;
7185
7186         while (!flag)
7187         {
7188                 char ch;
7189                 object_kind *k_ptr, *flavor_k_ptr;
7190
7191                 if (redraw)
7192                 {
7193                         clear_from(0);
7194
7195 #ifdef JP
7196                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
7197                         if (direct_k_idx < 0) prt("グループ", 4, 0);
7198                         prt("名前", 4, max + 3);
7199                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 70);
7200                         prt("文字", 4, 74);
7201 #else
7202                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
7203                         if (direct_k_idx < 0) prt("Group", 4, 0);
7204                         prt("Name", 4, max + 3);
7205                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 70);
7206                         prt("Sym", 4, 75);
7207 #endif
7208
7209                         for (i = 0; i < 78; i++)
7210                         {
7211                                 Term_putch(i, 5, TERM_WHITE, '=');
7212                         }
7213
7214                         if (direct_k_idx < 0)
7215                         {
7216                                 for (i = 0; i < browser_rows; i++)
7217                                 {
7218                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
7219                                 }
7220                         }
7221
7222                         redraw = FALSE;
7223                 }
7224
7225                 if (direct_k_idx < 0)
7226                 {
7227                         /* Scroll group list */
7228                         if (grp_cur < grp_top) grp_top = grp_cur;
7229                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
7230
7231                         /* Display a list of object groups */
7232                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
7233
7234                         if (old_grp_cur != grp_cur)
7235                         {
7236                                 old_grp_cur = grp_cur;
7237
7238                                 /* Get a list of objects in the current group */
7239                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
7240                         }
7241
7242                         /* Scroll object list */
7243                         while (object_cur < object_top)
7244                                 object_top = MAX(0, object_top - browser_rows/2);
7245                         while (object_cur >= object_top + browser_rows)
7246                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows/2);
7247                 }
7248
7249                 if (!visual_list)
7250                 {
7251                         /* Display a list of objects in the current group */
7252                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
7253                 }
7254                 else
7255                 {
7256                         object_top = object_cur;
7257
7258                         /* Display a list of objects in the current group */
7259                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
7260
7261                         /* Display visual list below first object */
7262                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
7263                 }
7264
7265                 /* Get the current object */
7266                 k_ptr = &k_info[object_idx[object_cur]];
7267
7268                 if (!visual_only && k_ptr->flavor)
7269                 {
7270                         /* Appearance of this object is shuffled */
7271                         flavor_k_ptr = &k_info[k_ptr->flavor];
7272                 }
7273                 else
7274                 {
7275                         /* Appearance of this object is very normal */
7276                         flavor_k_ptr = k_ptr;
7277                 }
7278
7279                 /* Prompt */
7280 #ifdef JP
7281                 prt(format("<方向>%s%s%s, ESC",
7282                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
7283                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
7284                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
7285                         hgt - 1, 0);
7286 #else
7287                 prt(format("<dir>%s%s%s, ESC",
7288                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
7289                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
7290                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
7291                         hgt - 1, 0);
7292 #endif
7293
7294                 if (!visual_only)
7295                 {
7296                         /* Mega Hack -- track this object */
7297                         if (object_cnt) object_kind_track(object_idx[object_cur]);
7298
7299                         /* The "current" object changed */
7300                         if (object_old != object_idx[object_cur])
7301                         {
7302                                 /* Hack -- handle stuff */
7303                                 handle_stuff();
7304
7305                                 /* Remember the "current" object */
7306                                 object_old = object_idx[object_cur];
7307                         }
7308                 }
7309
7310                 if (visual_list)
7311                 {
7312                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
7313                 }
7314                 else if (!column)
7315                 {
7316                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
7317                 }
7318                 else
7319                 {
7320                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
7321                 }
7322
7323                 ch = inkey();
7324
7325                 /* Do visual mode command if needed */
7326                 if (visual_mode_command(ch, &visual_list, browser_rows-1, wid - (max + 3), &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw))
7327                 {
7328                         if (direct_k_idx >= 0)
7329                         {
7330                                 switch (ch)
7331                                 {
7332                                 case '\n':
7333                                 case '\r':
7334                                 case ESCAPE:
7335                                         flag = TRUE;
7336                                         break;
7337                                 }
7338                         }
7339                         continue;
7340                 }
7341
7342                 switch (ch)
7343                 {
7344                         case ESCAPE:
7345                         {
7346                                 flag = TRUE;
7347                                 break;
7348                         }
7349
7350                         case 'R':
7351                         case 'r':
7352                         {
7353                                 /* Recall on screen */
7354                                 if (!visual_list && !visual_only && (grp_cnt > 0))
7355                                 {
7356                                         desc_obj_fake(object_idx[object_cur]);
7357                                         redraw = TRUE;
7358                                 }
7359                                 break;
7360                         }
7361
7362                         default:
7363                         {
7364                                 /* Move the cursor */
7365                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
7366                                 break;
7367                         }
7368                 }
7369         }
7370
7371         /* Free the "object_idx" array */
7372         C_KILL(object_idx, max_k_idx, int);
7373 }
7374
7375
7376 /*
7377  * Display the features in a group.
7378  */
7379 static void display_feature_list(int col, int row, int per_page, int *feat_idx,
7380         int feat_cur, int feat_top, bool visual_only, int lighting_level)
7381 {
7382         int lit_col[F_LIT_MAX], i, j;
7383         int f_idx_col = use_bigtile ? 62 : 64;
7384
7385         /* Correct columns 1 and 4 */
7386         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
7387         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
7388                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
7389
7390         /* Display lines until done */
7391         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
7392         {
7393                 byte attr;
7394
7395                 /* Get the index */
7396                 int f_idx = feat_idx[feat_top + i];
7397
7398                 /* Access the index */
7399                 feature_type *f_ptr = &f_info[f_idx];
7400
7401                 int row_i = row + i;
7402
7403                 /* Choose a color */
7404                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
7405
7406                 /* Display the name */
7407                 c_prt(attr, f_name + f_ptr->name, row_i, col);
7408
7409                 /* Hack -- visual_list mode */
7410                 if (per_page == 1)
7411                 {
7412                         /* Display lighting level */
7413                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
7414
7415                         c_prt(attr, format("%02x/%02x", f_ptr->x_attr[lighting_level], f_ptr->x_char[lighting_level]), row_i, f_idx_col - ((p_ptr->wizard || visual_only) ? 6 : 2));
7416                 }
7417                 if (p_ptr->wizard || visual_only)
7418                 {
7419                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
7420                 }
7421
7422                 /* Display symbol */
7423                 Term_queue_bigchar(lit_col[F_LIT_STANDARD], row_i, f_ptr->x_attr[F_LIT_STANDARD], f_ptr->x_char[F_LIT_STANDARD], 0, 0);
7424
7425                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
7426                 for (j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
7427                 {
7428                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
7429                 }
7430                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
7431
7432                 /* Mega-hack -- Use non-standard colour */
7433                 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
7434                 {
7435                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
7436                 }
7437         }
7438
7439         /* Clear remaining lines */
7440         for (; i < per_page; i++)
7441         {
7442                 Term_erase(col, row + i, 255);
7443         }
7444 }
7445
7446
7447 /*
7448  * Interact with feature visuals.
7449  */
7450 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, int direct_f_idx, int *lighting_level)
7451 {
7452         int i, len, max;
7453         int grp_cur, grp_top, old_grp_cur;
7454         int feat_cur, feat_top;
7455         int grp_cnt, grp_idx[100];
7456         int feat_cnt;
7457         int *feat_idx;
7458
7459         int column = 0;
7460         bool flag;
7461         bool redraw;
7462
7463         bool visual_list = FALSE;
7464         byte attr_top = 0, char_left = 0;
7465
7466         int browser_rows;
7467         int wid, hgt;
7468
7469         byte attr_old[F_LIT_MAX];
7470         byte char_old[F_LIT_MAX];
7471         byte *cur_attr_ptr, *cur_char_ptr;
7472
7473         (void)C_WIPE(attr_old, F_LIT_MAX, byte);
7474         (void)C_WIPE(char_old, F_LIT_MAX, byte);
7475
7476         /* Get size */
7477         Term_get_size(&wid, &hgt);
7478
7479         browser_rows = hgt - 8;
7480
7481         /* Allocate the "feat_idx" array */
7482         C_MAKE(feat_idx, max_f_idx, int);
7483
7484         max = 0;
7485         grp_cnt = 0;
7486
7487         if (direct_f_idx < 0)
7488         {
7489                 /* Check every group */
7490                 for (i = 0; feature_group_text[i] != NULL; i++)
7491                 {
7492                         /* Measure the label */
7493                         len = strlen(feature_group_text[i]);
7494
7495                         /* Save the maximum length */
7496                         if (len > max) max = len;
7497
7498                         /* See if any features are known */
7499                         if (collect_features(i, feat_idx, 0x01))
7500                         {
7501                                 /* Build a list of groups with known features */
7502                                 grp_idx[grp_cnt++] = i;
7503                         }
7504                 }
7505
7506                 feat_cnt = 0;
7507         }
7508         else
7509         {
7510                 feature_type *f_ptr = &f_info[direct_f_idx];
7511
7512                 feat_idx[0] = direct_f_idx;
7513                 feat_cnt = 1;
7514
7515                 /* Terminate the list */
7516                 feat_idx[1] = -1;
7517
7518                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
7519                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
7520
7521                 for (i = 0; i < F_LIT_MAX; i++)
7522                 {
7523                         attr_old[i] = f_ptr->x_attr[i];
7524                         char_old[i] = f_ptr->x_char[i];
7525                 }
7526         }
7527
7528         /* Terminate the list */
7529         grp_idx[grp_cnt] = -1;
7530
7531         old_grp_cur = -1;
7532         grp_cur = grp_top = 0;
7533         feat_cur = feat_top = 0;
7534
7535         flag = FALSE;
7536         redraw = TRUE;
7537
7538         while (!flag)
7539         {
7540                 char ch;
7541                 feature_type *f_ptr;
7542
7543                 if (redraw)
7544                 {
7545                         clear_from(0);
7546
7547 #ifdef JP
7548                         prt("表示 - 地形", 2, 0);
7549                         if (direct_f_idx < 0) prt("グループ", 4, 0);
7550                         prt("名前", 4, max + 3);
7551                         if (use_bigtile)
7552                         {
7553                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
7554                                 prt("文字 ( l/ d)", 4, 66);
7555                         }
7556                         else
7557                         {
7558                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 64);
7559                                 prt("文字 (l/d)", 4, 68);
7560                         }
7561 #else
7562                         prt("Visuals - features", 2, 0);
7563                         if (direct_f_idx < 0) prt("Group", 4, 0);
7564                         prt("Name", 4, max + 3);
7565                         if (use_bigtile)
7566                         {
7567                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
7568                                 prt("Sym ( l/ d)", 4, 67);
7569                         }
7570                         else
7571                         {
7572                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 64);
7573                                 prt("Sym (l/d)", 4, 69);
7574                         }
7575 #endif
7576
7577                         for (i = 0; i < 78; i++)
7578                         {
7579                                 Term_putch(i, 5, TERM_WHITE, '=');
7580                         }
7581
7582                         if (direct_f_idx < 0)
7583                         {
7584                                 for (i = 0; i < browser_rows; i++)
7585                                 {
7586                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
7587                                 }
7588                         }
7589
7590                         redraw = FALSE;
7591                 }
7592
7593                 if (direct_f_idx < 0)
7594                 {
7595                         /* Scroll group list */
7596                         if (grp_cur < grp_top) grp_top = grp_cur;
7597                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
7598
7599                         /* Display a list of feature groups */
7600                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
7601
7602                         if (old_grp_cur != grp_cur)
7603                         {
7604                                 old_grp_cur = grp_cur;
7605
7606                                 /* Get a list of features in the current group */
7607                                 feat_cnt = collect_features(grp_idx[grp_cur], feat_idx, 0x00);
7608                         }
7609
7610                         /* Scroll feature list */
7611                         while (feat_cur < feat_top)
7612                                 feat_top = MAX(0, feat_top - browser_rows/2);
7613                         while (feat_cur >= feat_top + browser_rows)
7614                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows/2);
7615                 }
7616
7617                 if (!visual_list)
7618                 {
7619                         /* Display a list of features in the current group */
7620                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
7621                 }
7622                 else
7623                 {
7624                         feat_top = feat_cur;
7625
7626                         /* Display a list of features in the current group */
7627                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
7628
7629                         /* Display visual list below first object */
7630                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
7631                 }
7632
7633                 /* Prompt */
7634 #ifdef JP
7635                 prt(format("<方向>%s, 'd'で標準光源効果%s, ESC",
7636                         visual_list ? ", ENTERで決定, 'a'で対象明度変更" : ", 'v'でシンボル変更",
7637                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
7638                         hgt - 1, 0);
7639 #else
7640                 prt(format("<dir>%s, 'd' for default lighting%s, ESC",
7641                         visual_list ? ", ENTER to accept, 'a' for lighting level" : ", 'v' for visuals",
7642                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
7643                         hgt - 1, 0);
7644 #endif
7645
7646                 /* Get the current feature */
7647                 f_ptr = &f_info[feat_idx[feat_cur]];
7648                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
7649                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
7650
7651                 if (visual_list)
7652                 {
7653                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
7654                 }
7655                 else if (!column)
7656                 {
7657                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
7658                 }
7659                 else
7660                 {
7661                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
7662                 }
7663
7664                 ch = inkey();
7665
7666                 if (visual_list && ((ch == 'A') || (ch == 'a')))
7667                 {
7668                         int prev_lighting_level = *lighting_level;
7669
7670                         if (ch == 'A')
7671                         {
7672                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
7673                                 else (*lighting_level)--;
7674                         }
7675                         else
7676                         {
7677                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
7678                                 else (*lighting_level)++;
7679                         }
7680
7681                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
7682                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
7683
7684                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
7685                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
7686
7687                         continue;
7688                 }
7689
7690                 else if ((ch == 'D') || (ch == 'd'))
7691                 {
7692                         byte prev_x_attr = f_ptr->x_attr[*lighting_level];
7693                         byte prev_x_char = f_ptr->x_char[*lighting_level];
7694
7695                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
7696
7697                         if (visual_list)
7698                         {
7699                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
7700                                          attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
7701
7702                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
7703                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
7704                         }
7705                         else *need_redraw = TRUE;
7706
7707                         continue;
7708                 }
7709
7710                 /* Do visual mode command if needed */
7711                 else if (visual_mode_command(ch, &visual_list, browser_rows-1, wid - (max + 3), &attr_top, &char_left, cur_attr_ptr, cur_char_ptr, need_redraw))
7712                 {
7713                         switch (ch)
7714                         {
7715                         /* Restore previous visual settings */
7716                         case ESCAPE:
7717                                 for (i = 0; i < F_LIT_MAX; i++)
7718                                 {
7719                                         f_ptr->x_attr[i] = attr_old[i];
7720                                         f_ptr->x_char[i] = char_old[i];
7721                                 }
7722
7723                                 /* Fall through */
7724
7725                         case '\n':
7726                         case '\r':
7727                                 if (direct_f_idx >= 0) flag = TRUE;
7728                                 else *lighting_level = F_LIT_STANDARD;
7729                                 break;
7730
7731                         /* Preserve current visual settings */
7732                         case 'V':
7733                         case 'v':
7734                                 for (i = 0; i < F_LIT_MAX; i++)
7735                                 {
7736                                         attr_old[i] = f_ptr->x_attr[i];
7737                                         char_old[i] = f_ptr->x_char[i];
7738                                 }
7739                                 *lighting_level = F_LIT_STANDARD;
7740                                 break;
7741
7742                         case 'C':
7743                         case 'c':
7744                                 if (!visual_list)
7745                                 {
7746                                         for (i = 0; i < F_LIT_MAX; i++)
7747                                         {
7748                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
7749                                                 char_idx_feat[i] = f_ptr->x_char[i];
7750                                         }
7751                                 }
7752                                 break;
7753
7754                         case 'P':
7755                         case 'p':
7756                                 if (!visual_list)
7757                                 {
7758                                         /* Allow TERM_DARK text */
7759                                         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
7760                                         {
7761                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
7762                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
7763                                         }
7764                                 }
7765                                 break;
7766                         }
7767                         continue;
7768                 }
7769
7770                 switch (ch)
7771                 {
7772                         case ESCAPE:
7773                         {
7774                                 flag = TRUE;
7775                                 break;
7776                         }
7777
7778                         default:
7779                         {
7780                                 /* Move the cursor */
7781                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
7782                                 break;
7783                         }
7784                 }
7785         }
7786
7787         /* Free the "feat_idx" array */
7788         C_KILL(feat_idx, max_f_idx, int);
7789 }
7790
7791
7792 /*
7793  * List wanted monsters
7794  */
7795 static void do_cmd_knowledge_kubi(void)
7796 {
7797         int i;
7798         FILE *fff;
7799         
7800         char file_name[1024];
7801         
7802         
7803         /* Open a new file */
7804         fff = my_fopen_temp(file_name, 1024);
7805         if (!fff) {
7806             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7807             msg_print(NULL);
7808             return;
7809         }
7810         
7811         if (fff)
7812         {
7813                 bool listed = FALSE;
7814
7815 #ifdef JP
7816                 fprintf(fff, "今日のターゲット : %s\n", (p_ptr->today_mon ? r_name + r_info[p_ptr->today_mon].name : "不明"));
7817                 fprintf(fff, "\n");
7818                 fprintf(fff, "賞金首リスト\n");
7819 #else
7820                 fprintf(fff, "Today target : %s\n", (p_ptr->today_mon ? r_name + r_info[p_ptr->today_mon].name : "unknown"));
7821                 fprintf(fff, "\n");
7822                 fprintf(fff, "List of wanted monsters\n");
7823 #endif
7824                 fprintf(fff, "----------------------------------------------\n");
7825
7826                 for (i = 0; i < MAX_KUBI; i++)
7827                 {
7828                         if (kubi_r_idx[i] <= 10000)
7829                         {
7830                                 fprintf(fff,"%s\n", r_name + r_info[kubi_r_idx[i]].name);
7831
7832                                 listed = TRUE;
7833                         }
7834                 }
7835
7836                 if (!listed)
7837                 {
7838                         fprintf(fff,"\n%s\n", _("賞金首はもう残っていません。", "There is no more wanted monster."));
7839                 }
7840         }
7841         
7842         /* Close the file */
7843         my_fclose(fff);
7844         
7845         /* Display the file contents */
7846         show_file(TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
7847         
7848         /* Remove the file */
7849         fd_kill(file_name);
7850 }
7851
7852 /*
7853  * List virtues & status
7854  */
7855 static void do_cmd_knowledge_virtues(void)
7856 {
7857         FILE *fff;
7858         
7859         char file_name[1024];
7860         
7861         
7862         /* Open a new file */
7863         fff = my_fopen_temp(file_name, 1024);
7864         if (!fff) {
7865             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7866             msg_print(NULL);
7867             return;
7868         }
7869         
7870         if (fff)
7871         {
7872                 fprintf(fff, _("現在の属性 : %s\n\n", "Your alighnment : %s\n\n"), your_alignment());
7873                 dump_virtues(fff);
7874         }
7875         
7876         /* Close the file */
7877         my_fclose(fff);
7878         
7879         /* Display the file contents */
7880         show_file(TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
7881         
7882         /* Remove the file */
7883         fd_kill(file_name);
7884 }
7885
7886 /*
7887 * Dungeon
7888 *
7889 */
7890 static void do_cmd_knowledge_dungeon(void)
7891 {
7892         FILE *fff;
7893         
7894         char file_name[1024];
7895         int i;
7896         
7897         
7898         /* Open a new file */
7899         fff = my_fopen_temp(file_name, 1024);
7900         if (!fff) {
7901             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7902             msg_print(NULL);
7903             return;
7904         }
7905         
7906         if (fff)
7907         {
7908                 for (i = 1; i < max_d_idx; i++)
7909                 {
7910                         bool seiha = FALSE;
7911
7912                         if (!d_info[i].maxdepth) continue;
7913                         if (!max_dlv[i]) continue;
7914                         if (d_info[i].final_guardian)
7915                         {
7916                                 if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
7917                         }
7918                         else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
7919                         
7920                         fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, max_dlv[i]);
7921                 }
7922         }
7923         
7924         /* Close the file */
7925         my_fclose(fff);
7926         
7927         /* Display the file contents */
7928         show_file(TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
7929         
7930         /* Remove the file */
7931         fd_kill(file_name);
7932 }
7933
7934 /*
7935 * List virtues & status
7936 *
7937 */
7938 static void do_cmd_knowledge_stat(void)
7939 {
7940         FILE *fff;
7941         
7942         char file_name[1024];
7943         int percent, v_nr;
7944         
7945         /* Open a new file */
7946         fff = my_fopen_temp(file_name, 1024);
7947         if (!fff) {
7948             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7949             msg_print(NULL);
7950             return;
7951         }
7952         
7953         if (fff)
7954         {
7955                 percent = (int)(((long)p_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
7956                         (2 * p_ptr->hitdie +
7957                         ((PY_MAX_LEVEL - 1+3) * (p_ptr->hitdie + 1))));
7958
7959 #ifdef JP
7960                 if (p_ptr->knowledge & KNOW_HPRATE) fprintf(fff, "現在の体力ランク : %d/100\n\n", percent);
7961                 else fprintf(fff, "現在の体力ランク : ???\n\n");
7962                 fprintf(fff, "能力の最大値\n\n");
7963 #else
7964                 if (p_ptr->knowledge & KNOW_HPRATE) fprintf(fff, "Your current Life Rating is %d/100.\n\n", percent);
7965                 else fprintf(fff, "Your current Life Rating is ???.\n\n");
7966                 fprintf(fff, "Limits of maximum stats\n\n");
7967 #endif
7968                 for (v_nr = 0; v_nr < 6; v_nr++)
7969                 {
7970                         if ((p_ptr->knowledge & KNOW_STAT) || p_ptr->stat_max[v_nr] == p_ptr->stat_max_max[v_nr]) fprintf(fff, "%s 18/%d\n", stat_names[v_nr], p_ptr->stat_max_max[v_nr]-18);
7971                         else fprintf(fff, "%s ???\n", stat_names[v_nr]);
7972                 }
7973         }
7974
7975         dump_yourself(fff);
7976
7977         /* Close the file */
7978         my_fclose(fff);
7979         
7980         /* Display the file contents */
7981         show_file(TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
7982         
7983         /* Remove the file */
7984         fd_kill(file_name);
7985 }
7986
7987
7988 /*
7989  * Print all active quests
7990  */
7991 static void do_cmd_knowledge_quests_current(FILE *fff)
7992 {
7993         char tmp_str[120];
7994         char rand_tmp_str[120] = "\0";
7995         char name[80];
7996         monster_race *r_ptr;
7997         int i;
7998         int rand_level = 100;
7999         int total = 0;
8000
8001         fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
8002
8003         for (i = 1; i < max_quests; i++)
8004         {
8005                 if ((quest[i].status == QUEST_STATUS_TAKEN) ||
8006                         ((quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER)) ||
8007                         (quest[i].status == QUEST_STATUS_COMPLETED))
8008                 {
8009                         /* Set the quest number temporary */
8010                         int old_quest = p_ptr->inside_quest;
8011                         int j;
8012
8013                         /* Clear the text */
8014                         for (j = 0; j < 10; j++) quest_text[j][0] = '\0';
8015                         quest_text_line = 0;
8016
8017                         p_ptr->inside_quest = i;
8018
8019                         /* Get the quest text */
8020                         init_flags = INIT_SHOW_TEXT;
8021
8022                         process_dungeon_file("q_info.txt", 0, 0, 0, 0);
8023
8024                         /* Reset the old quest number */
8025                         p_ptr->inside_quest = old_quest;
8026
8027                         /* No info from "silent" quests */
8028                         if (quest[i].flags & QUEST_FLAG_SILENT) continue;
8029
8030                         total++;
8031
8032                         if (quest[i].type != QUEST_TYPE_RANDOM)
8033                         {
8034                                 char note[80] = "\0";
8035
8036                                 if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
8037                                 {
8038                                         switch (quest[i].type)
8039                                         {
8040                                         case QUEST_TYPE_KILL_LEVEL:
8041                                         case QUEST_TYPE_KILL_ANY_LEVEL:
8042                                                 r_ptr = &r_info[quest[i].r_idx];
8043                                                 strcpy(name, r_name + r_ptr->name);
8044                                                 if (quest[i].max_num > 1)
8045                                                 {
8046 #ifdef JP
8047                                                         sprintf(note," - %d 体の%sを倒す。(あと %d 体)",
8048                                                                 quest[i].max_num, name, quest[i].max_num - quest[i].cur_num);
8049 #else
8050                                                         plural_aux(name);
8051                                                         sprintf(note," - kill %d %s, have killed %d.",
8052                                                                 quest[i].max_num, name, quest[i].cur_num);
8053 #endif
8054                                                 }
8055                                                 else
8056                                                         sprintf(note,_(" - %sを倒す。", " - kill %s."),name);
8057                                                 break;
8058
8059                                         case QUEST_TYPE_FIND_ARTIFACT:
8060                                                 if (quest[i].k_idx)
8061                                                 {
8062                                                         artifact_type *a_ptr = &a_info[quest[i].k_idx];
8063                                                         object_type forge;
8064                                                         object_type *q_ptr = &forge;
8065                                                         int k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
8066                                                         object_prep(q_ptr, k_idx);
8067                                                         q_ptr->name1 = quest[i].k_idx;
8068                                                         q_ptr->ident = IDENT_STORE;
8069                                                         object_desc(name, q_ptr, OD_NAME_ONLY);
8070                                                 }
8071                                                 sprintf(note,_("\n   - %sを見つけ出す。", "\n   - Find out %s."), name);
8072                                                 break;
8073                                         case QUEST_TYPE_FIND_EXIT:
8074                                                 sprintf(note,_(" - 出口に到達する。", " - Reach to Exit."));
8075                                                 break;
8076
8077                                         case QUEST_TYPE_KILL_NUMBER:
8078 #ifdef JP
8079                                                 sprintf(note," - %d 体のモンスターを倒す。(あと %d 体)",
8080                                                         quest[i].max_num, quest[i].max_num - quest[i].cur_num);
8081 #else
8082                                                 sprintf(note," - Kill %d monsters, have killed %d.",
8083                                                         quest[i].max_num, quest[i].cur_num);
8084 #endif
8085                                                 break;
8086
8087                                         case QUEST_TYPE_KILL_ALL:
8088                                         case QUEST_TYPE_TOWER:
8089                                                 sprintf(note,_(" - 全てのモンスターを倒す。", " - Kill all monsters."));
8090                                                 break;
8091                                         }
8092                                 }
8093
8094                                 /* Print the quest info */
8095 #ifdef JP
8096                                 sprintf(tmp_str, "  %s (危険度:%d階相当)%s\n",
8097                                         quest[i].name, quest[i].level, note);
8098 #else
8099                                 sprintf(tmp_str, "  %s (Danger level: %d)%s\n",
8100                                         quest[i].name, quest[i].level, note);
8101 #endif
8102
8103                                 fputs(tmp_str, fff);
8104
8105                                 if (quest[i].status == QUEST_STATUS_COMPLETED)
8106                                 {
8107                                         sprintf(tmp_str, _("    クエスト達成 - まだ報酬を受けとってない。\n", "    Quest Completed - Unrewarded\n"));
8108                                         fputs(tmp_str, fff);
8109                                 }
8110                                 else
8111                                 {
8112                                         j = 0;
8113
8114                                         while (quest_text[j][0] && j < 10)
8115                                         {
8116                                                 fprintf(fff, "    %s\n", quest_text[j]);
8117                                                 j++;
8118                                         }
8119                                 }
8120                         }
8121                         else if (quest[i].level < rand_level) /* QUEST_TYPE_RANDOM */
8122                         {
8123                                 /* New random */
8124                                 rand_level = quest[i].level;
8125
8126                                 if (max_dlv[DUNGEON_ANGBAND] >= rand_level)
8127                                 {
8128                                         /* Print the quest info */
8129                                         r_ptr = &r_info[quest[i].r_idx];
8130                                         strcpy(name, r_name + r_ptr->name);
8131
8132                                         if (quest[i].max_num > 1)
8133                                         {
8134 #ifdef JP
8135                                                 sprintf(rand_tmp_str,"  %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
8136                                                         quest[i].name, quest[i].level,
8137                                                         quest[i].max_num, name, quest[i].max_num - quest[i].cur_num);
8138 #else
8139                                                 plural_aux(name);
8140
8141                                                 sprintf(rand_tmp_str,"  %s (Dungeon level: %d)\n  Kill %d %s, have killed %d.\n",
8142                                                         quest[i].name, quest[i].level,
8143                                                         quest[i].max_num, name, quest[i].cur_num);
8144 #endif
8145                                         }
8146                                         else
8147                                         {
8148 #ifdef JP
8149                                                 sprintf(rand_tmp_str,"  %s (%d 階) - %sを倒す。\n",
8150                                                         quest[i].name, quest[i].level, name);
8151 #else
8152                                                 sprintf(rand_tmp_str,"  %s (Dungeon level: %d)\n  Kill %s.\n",
8153                                                         quest[i].name, quest[i].level, name);
8154 #endif
8155                                         }
8156                                 }
8157                         }
8158                 }
8159         }
8160
8161         /* Print the current random quest  */
8162         if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
8163
8164         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
8165 }
8166
8167
8168 static bool do_cmd_knowledge_quests_aux(FILE *fff, int q_idx)
8169 {
8170         char tmp_str[120];
8171         char playtime_str[16];
8172         quest_type* const q_ptr = &quest[q_idx];
8173
8174         if (is_fixed_quest_idx(q_idx))
8175         {
8176                 /* Set the quest number temporary */
8177                 int old_quest = p_ptr->inside_quest;
8178
8179                 p_ptr->inside_quest = q_idx;
8180
8181                 /* Get the quest */
8182                 init_flags = INIT_NAME_ONLY;
8183
8184                 process_dungeon_file("q_info.txt", 0, 0, 0, 0);
8185
8186                 /* Reset the old quest number */
8187                 p_ptr->inside_quest = old_quest;
8188
8189                 /* No info from "silent" quests */
8190                 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
8191         }
8192
8193         strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
8194                 q_ptr->comptime/(60*60), (q_ptr->comptime/60)%60, q_ptr->comptime%60);
8195
8196         if (!is_fixed_quest_idx(q_idx) && q_ptr->r_idx)
8197         {
8198                 /* Print the quest info */
8199                 if (q_ptr->complev == 0)
8200                 {
8201                         sprintf(tmp_str,
8202                                 _("  %-35s (%3d階)            -   不戦勝 - %s\n",
8203                                   "  %-35s (Dungeon level: %3d) - Unearned - %s\n") ,
8204                                 r_name+r_info[q_ptr->r_idx].name,
8205                                 q_ptr->level, playtime_str);
8206                 }
8207                 else
8208                 {
8209                         sprintf(tmp_str,
8210                                 _("  %-35s (%3d階)            - レベル%2d - %s\n",
8211                                   "  %-35s (Dungeon level: %3d) - level %2d - %s\n") ,
8212                                 r_name+r_info[q_ptr->r_idx].name,
8213                                 q_ptr->level,
8214                                 q_ptr->complev,
8215                                 playtime_str);
8216                 }
8217         }
8218         else
8219         {
8220                 /* Print the quest info */
8221                 sprintf(tmp_str,
8222                         _("  %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
8223                           "  %-35s (Danger  level: %3d) - level %2d - %s\n") ,
8224                         q_ptr->name, q_ptr->level, q_ptr->complev, playtime_str);
8225         }
8226
8227         fputs(tmp_str, fff);
8228
8229         return TRUE;
8230 }
8231
8232 /*
8233  * Print all finished quests
8234  */
8235 void do_cmd_knowledge_quests_completed(FILE *fff, int quest_num[])
8236 {
8237         int i;
8238         int total = 0;
8239
8240         fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
8241         for (i = 1; i < max_quests; i++)
8242         {
8243                 int q_idx = quest_num[i];
8244                 quest_type* const q_ptr = &quest[q_idx];
8245
8246                 if (q_ptr->status == QUEST_STATUS_FINISHED &&
8247                     do_cmd_knowledge_quests_aux(fff, q_idx))
8248                 {
8249                         ++ total;
8250                 }
8251         }
8252         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
8253 }
8254
8255
8256 /*
8257  * Print all failed quests
8258  */
8259 void do_cmd_knowledge_quests_failed(FILE *fff, int quest_num[])
8260 {
8261         int i;
8262         int total = 0;
8263
8264         fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
8265         for (i = 1; i < max_quests; i++)
8266         {
8267                 int q_idx = quest_num[i];
8268                 quest_type* const q_ptr = &quest[q_idx];
8269
8270                 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
8271                     do_cmd_knowledge_quests_aux(fff, q_idx))
8272                 {
8273                         ++ total;
8274                 }
8275         }
8276         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
8277 }
8278
8279
8280 /*
8281  * Print all random quests
8282  */
8283 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
8284 {
8285         char tmp_str[120];
8286         int i;
8287         int total = 0;
8288
8289         fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
8290         for (i = 1; i < max_quests; i++)
8291         {
8292                 /* No info from "silent" quests */
8293                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
8294
8295                 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
8296                 {
8297                         total++;
8298
8299                         /* Print the quest info */
8300 #ifdef JP
8301                         sprintf(tmp_str, "  %s (%d階, %s)\n",
8302                                 quest[i].name, quest[i].level, r_name+r_info[quest[i].r_idx].name);
8303 #else
8304                         sprintf(tmp_str, "  %s (%d, %s)\n",
8305                                 quest[i].name, quest[i].level, r_name+r_info[quest[i].r_idx].name);
8306 #endif
8307                         fputs(tmp_str, fff);
8308                 }
8309         }
8310         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
8311 }
8312
8313
8314 bool ang_sort_comp_quest_num(vptr u, vptr v, int a, int b)
8315 {
8316         int *q_num = (int *)u;
8317         quest_type *qa = &quest[q_num[a]];
8318         quest_type *qb = &quest[q_num[b]];
8319
8320         /* Unused */
8321         (void)v;
8322
8323         return (qa->comptime <= qb->comptime);
8324 }
8325
8326 void ang_sort_swap_quest_num(vptr u, vptr v, int a, int b)
8327 {
8328         int *q_num = (int *)u;
8329         int tmp;
8330
8331         /* Unused */
8332         (void)v;
8333
8334         tmp = q_num[a];
8335         q_num[a] = q_num[b];
8336         q_num[b] = tmp;
8337 }
8338
8339
8340 /*
8341  * Print quest status of all active quests
8342  */
8343 static void do_cmd_knowledge_quests(void)
8344 {
8345         FILE *fff;
8346         char file_name[1024];
8347         int *quest_num, dummy, i;
8348
8349         /* Open a new file */
8350         fff = my_fopen_temp(file_name, 1024);
8351         if (!fff)
8352         {
8353             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8354             msg_print(NULL);
8355             return;
8356         }
8357
8358         /* Allocate Memory */
8359         C_MAKE(quest_num, max_quests, int);
8360
8361         /* Sort by compete level */
8362         for (i = 1; i < max_quests; i++) quest_num[i] = i;
8363         ang_sort_comp = ang_sort_comp_quest_num;
8364         ang_sort_swap = ang_sort_swap_quest_num;
8365         ang_sort(quest_num, &dummy, max_quests);
8366
8367         /* Dump Quest Information */
8368         do_cmd_knowledge_quests_current(fff);
8369         fputc('\n', fff);
8370         do_cmd_knowledge_quests_completed(fff, quest_num);
8371         fputc('\n', fff);
8372         do_cmd_knowledge_quests_failed(fff, quest_num);
8373         if (p_ptr->wizard)
8374         {
8375                 fputc('\n', fff);
8376                 do_cmd_knowledge_quests_wiz_random(fff);
8377         }
8378
8379         /* Close the file */
8380         my_fclose(fff);
8381
8382         /* Display the file contents */
8383         show_file(TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
8384
8385         /* Remove the file */
8386         fd_kill(file_name);
8387
8388         /* Free Memory */
8389         C_KILL(quest_num, max_quests, int);
8390 }
8391
8392
8393 /*
8394  * List my home
8395  */
8396 static void do_cmd_knowledge_home(void)
8397 {
8398         FILE *fff;
8399
8400         int i;
8401         char file_name[1024];
8402         store_type  *st_ptr;
8403         char o_name[MAX_NLEN];
8404         cptr            paren = ")";
8405
8406         process_dungeon_file("w_info.txt", 0, 0, max_wild_y, max_wild_x);
8407
8408         /* Open a new file */
8409         fff = my_fopen_temp(file_name, 1024);
8410         if (!fff) {
8411                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8412                 msg_print(NULL);
8413                 return;
8414         }
8415
8416         if (fff)
8417         {
8418                 /* Print all homes in the different towns */
8419                 st_ptr = &town[1].store[STORE_HOME];
8420
8421                 /* Home -- if anything there */
8422                 if (st_ptr->stock_num)
8423                 {
8424 #ifdef JP
8425                         int x = 1;
8426 #endif
8427                         /* Header with name of the town */
8428                         fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
8429
8430                         /* Dump all available items */
8431                         for (i = 0; i < st_ptr->stock_num; i++)
8432                         {
8433 #ifdef JP
8434                                 if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
8435                                 object_desc(o_name, &st_ptr->stock[i], 0);
8436                                 if (strlen(o_name) <= 80-3)
8437                                 {
8438                                         fprintf(fff, "%c%s %s\n", I2A(i%12), paren, o_name);
8439                                 }
8440                                 else
8441                                 {
8442                                         int n;
8443                                         char *t;
8444                                         for (n = 0, t = o_name; n < 80-3; n++, t++)
8445                                                 if(iskanji(*t)) {t++; n++;}
8446                                         if (n == 81-3) n = 79-3; /* 最後が漢字半分 */
8447
8448                                         fprintf(fff, "%c%s %.*s\n", I2A(i%12), paren, n, o_name);
8449                                         fprintf(fff, "   %.77s\n", o_name+n);
8450                                 }
8451 #else
8452                                 object_desc(o_name, &st_ptr->stock[i], 0);
8453                                 fprintf(fff, "%c%s %s\n", I2A(i%12), paren, o_name);
8454 #endif
8455
8456                         }
8457
8458                         /* Add an empty line */
8459                         fprintf(fff, "\n\n");
8460                 }
8461         }
8462
8463         /* Close the file */
8464         my_fclose(fff);
8465
8466         /* Display the file contents */
8467         show_file(TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
8468
8469         /* Remove the file */
8470         fd_kill(file_name);
8471 }
8472
8473
8474 /*
8475  * Check the status of "autopick"
8476  */
8477 static void do_cmd_knowledge_autopick(void)
8478 {
8479         int k;
8480         FILE *fff;
8481         char file_name[1024];
8482
8483         /* Open a new file */
8484         fff = my_fopen_temp(file_name, 1024);
8485
8486         if (!fff)
8487         {
8488             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8489             msg_print(NULL);
8490             return;
8491         }
8492
8493         if (!max_autopick)
8494         {
8495             fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
8496         }
8497         else
8498         {
8499                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
8500                                            "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
8501         }
8502
8503         for (k = 0; k < max_autopick; k++)
8504         {
8505                 cptr tmp;
8506                 byte act = autopick_list[k].action;
8507                 if (act & DONT_AUTOPICK)
8508                 {
8509                         tmp = _("放置", "Leave");
8510                 }
8511                 else if (act & DO_AUTODESTROY)
8512                 {
8513                         tmp = _("破壊", "Destroy");
8514                 }
8515                 else if (act & DO_AUTOPICK)
8516                 {
8517                         tmp = _("拾う", "Pickup");
8518                 }
8519                 else /* if (act & DO_QUERY_AUTOPICK) */ /* Obvious */
8520                 {
8521                         tmp = _("確認", "Query");
8522                 }
8523
8524                 if (act & DO_DISPLAY)
8525                         fprintf(fff, "%11s", format("[%s]", tmp));
8526                 else
8527                         fprintf(fff, "%11s", format("(%s)", tmp));
8528
8529                 tmp = autopick_line_from_entry(&autopick_list[k]);
8530                 fprintf(fff, " %s", tmp);
8531                 string_free(tmp);
8532                 fprintf(fff, "\n");
8533         }
8534         /* Close the file */
8535         my_fclose(fff);
8536         /* Display the file contents */
8537         show_file(TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
8538
8539         /* Remove the file */
8540         fd_kill(file_name);
8541 }
8542
8543
8544 /*
8545  * Interact with "knowledge"
8546  */
8547 void do_cmd_knowledge(void)
8548 {
8549         int i, p = 0;
8550         bool need_redraw = FALSE;
8551
8552         /* File type is "TEXT" */
8553         FILE_TYPE(FILE_TYPE_TEXT);
8554
8555         /* Save the screen */
8556         screen_save();
8557
8558         /* Interact until done */
8559         while (1)
8560         {
8561                 /* Clear screen */
8562                 Term_clear();
8563
8564                 /* Ask for a choice */
8565 #ifdef JP
8566                 prt(format("%d/2 ページ", (p+1)), 2, 65);
8567                 prt("現在の知識を確認する", 3, 0);
8568 #else
8569                 prt(format("page %d/2", (p+1)), 2, 65);
8570                 prt("Display current knowledge", 3, 0);
8571 #endif
8572
8573                 /* Give some choices */
8574 #ifdef JP
8575                 if (p == 0)
8576                 {
8577                         prt("(1) 既知の伝説のアイテム                 の一覧", 6, 5);
8578                         prt("(2) 既知のアイテム                       の一覧", 7, 5);
8579                         prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5);
8580                         prt("(4) 既知のモンスター                     の一覧", 9, 5);
8581                         prt("(5) 倒した敵の数                         の一覧", 10, 5);
8582                         if (!vanilla_town) prt("(6) 賞金首                               の一覧", 11, 5);
8583                         prt("(7) 現在のペット                         の一覧", 12, 5);
8584                         prt("(8) 我が家のアイテム                     の一覧", 13, 5);
8585                         prt("(9) *鑑定*済み装備の耐性                 の一覧", 14, 5);
8586                         prt("(0) 地形の表示文字/タイル                の一覧", 15, 5);
8587                 }
8588                 else
8589                 {
8590                         prt("(a) 自分に関する情報                     の一覧", 6, 5);
8591                         prt("(b) 突然変異                             の一覧", 7, 5);
8592                         prt("(c) 武器の経験値                         の一覧", 8, 5);
8593                         prt("(d) 魔法の経験値                         の一覧", 9, 5);
8594                         prt("(e) 技能の経験値                         の一覧", 10, 5);
8595                         prt("(f) プレイヤーの徳                       の一覧", 11, 5);
8596                         prt("(g) 入ったダンジョン                     の一覧", 12, 5);
8597                         prt("(h) 実行中のクエスト                     の一覧", 13, 5);
8598                         prt("(i) 現在の自動拾い/破壊設定              の一覧", 14, 5);
8599                 }
8600 #else
8601                 if (p == 0)
8602                 {
8603                         prt("(1) Display known artifacts", 6, 5);
8604                         prt("(2) Display known objects", 7, 5);
8605                         prt("(3) Display remaining uniques", 8, 5);
8606                         prt("(4) Display known monster", 9, 5);
8607                         prt("(5) Display kill count", 10, 5);
8608                         if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5);
8609                         prt("(7) Display current pets", 12, 5);
8610                         prt("(8) Display home inventory", 13, 5);
8611                         prt("(9) Display *identified* equip.", 14, 5);
8612                         prt("(0) Display terrain symbols.", 15, 5);
8613                 }
8614                 else
8615                 {
8616                         prt("(a) Display about yourself", 6, 5);
8617                         prt("(b) Display mutations", 7, 5);
8618                         prt("(c) Display weapon proficiency", 8, 5);
8619                         prt("(d) Display spell proficiency", 9, 5);
8620                         prt("(e) Display misc. proficiency", 10, 5);
8621                         prt("(f) Display virtues", 11, 5);
8622                         prt("(g) Display dungeons", 12, 5);
8623                         prt("(h) Display current quests", 13, 5);
8624                         prt("(i) Display auto pick/destroy", 14, 5);
8625                 }
8626 #endif
8627                 /* Prompt */
8628 #ifdef JP
8629                 prt("-続く-", 17, 8);
8630                 prt("ESC) 抜ける", 21, 1);
8631                 prt("SPACE) 次ページ", 21, 30);
8632                 /*prt("-) 前ページ", 21, 60);*/
8633                 prt("コマンド:", 20, 0);
8634 #else
8635                 prt("-more-", 17, 8);
8636                 prt("ESC) Exit menu", 21, 1);
8637                 prt("SPACE) Next page", 21, 30);
8638                 /*prt("-) Previous page", 21, 60);*/
8639                 prt("Command: ", 20, 0);
8640 #endif
8641
8642                 /* Prompt */
8643                 i = inkey();
8644
8645                 /* Done */
8646                 if (i == ESCAPE) break;
8647                 switch (i)
8648                 {
8649                 case ' ': /* Page change */
8650                 case '-':
8651                         p = 1 - p;
8652                         break;
8653                 case '1': /* Artifacts */
8654                         do_cmd_knowledge_artifacts();
8655                         break;
8656                 case '2': /* Objects */
8657                         do_cmd_knowledge_objects(&need_redraw, FALSE, -1);
8658                         break;
8659                 case '3': /* Uniques */
8660                         do_cmd_knowledge_uniques();
8661                         break;
8662                 case '4': /* Monsters */
8663                         do_cmd_knowledge_monsters(&need_redraw, FALSE, -1);
8664                         break;
8665                 case '5': /* Kill count  */
8666                         do_cmd_knowledge_kill_count();
8667                         break;
8668                 case '6': /* wanted */
8669                         if (!vanilla_town) do_cmd_knowledge_kubi();
8670                         break;
8671                 case '7': /* Pets */
8672                         do_cmd_knowledge_pets();
8673                         break;
8674                 case '8': /* Home */
8675                         do_cmd_knowledge_home();
8676                         break;
8677                 case '9': /* Resist list */
8678                         do_cmd_knowledge_inven();
8679                         break;
8680                 case '0': /* Feature list */
8681                         {
8682                                 int lighting_level = F_LIT_STANDARD;
8683                                 do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
8684                         }
8685                         break;
8686                 /* Next page */
8687                 case 'a': /* Max stat */
8688                         do_cmd_knowledge_stat();
8689                         break;
8690                 case 'b': /* Mutations */
8691                         do_cmd_knowledge_mutations();
8692                         break;
8693                 case 'c': /* weapon-exp */
8694                         do_cmd_knowledge_weapon_exp();
8695                         break;
8696                 case 'd': /* spell-exp */
8697                         do_cmd_knowledge_spell_exp();
8698                         break;
8699                 case 'e': /* skill-exp */
8700                         do_cmd_knowledge_skill_exp();
8701                         break;
8702                 case 'f': /* Virtues */
8703                         do_cmd_knowledge_virtues();
8704                         break;
8705                 case 'g': /* Dungeon */
8706                         do_cmd_knowledge_dungeon();
8707                         break;
8708                 case 'h': /* Quests */
8709                         do_cmd_knowledge_quests();
8710                         break;
8711                 case 'i': /* Autopick */
8712                         do_cmd_knowledge_autopick();
8713                         break;
8714                 default: /* Unknown option */
8715                         bell();
8716                 }
8717
8718                 /* Flush messages */
8719                 msg_print(NULL);
8720         }
8721
8722         /* Restore the screen */
8723         screen_load();
8724
8725         if (need_redraw) do_cmd_redraw();
8726 }
8727
8728
8729 /*
8730  * Check on the status of an active quest
8731  */
8732 void do_cmd_checkquest(void)
8733 {
8734         /* File type is "TEXT" */
8735         FILE_TYPE(FILE_TYPE_TEXT);
8736
8737         /* Save the screen */
8738         screen_save();
8739
8740         /* Quest info */
8741         do_cmd_knowledge_quests();
8742
8743         /* Restore the screen */
8744         screen_load();
8745 }
8746
8747
8748 /*
8749  * Display the time and date
8750  */
8751 void do_cmd_time(void)
8752 {
8753         int day, hour, min, full, start, end, num;
8754         char desc[1024];
8755
8756         char buf[1024];
8757         char day_buf[10];
8758
8759         FILE *fff;
8760
8761         extract_day_hour_min(&day, &hour, &min);
8762
8763         full = hour * 100 + min;
8764
8765         start = 9999;
8766         end = -9999;
8767
8768         num = 0;
8769
8770         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
8771
8772         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
8773         else strcpy(day_buf, "*****");
8774
8775         /* Message */
8776 #ifdef JP
8777         msg_format("%s日目, 時刻は%d:%02d %sです。",
8778                    day_buf, (hour % 12 == 0) ? 12 : (hour % 12),
8779                    min, (hour < 12) ? "AM" : "PM");
8780 #else
8781         msg_format("This is day %s. The time is %d:%02d %s.",
8782                    day_buf, (hour % 12 == 0) ? 12 : (hour % 12),
8783                    min, (hour < 12) ? "AM" : "PM");
8784 #endif
8785
8786
8787         /* Find the path */
8788         if (!randint0(10) || p_ptr->image)
8789         {
8790                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
8791         }
8792         else
8793         {
8794                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
8795         }
8796
8797         /* Open this file */
8798         fff = my_fopen(buf, "rt");
8799
8800         /* Oops */
8801         if (!fff) return;
8802
8803         /* Find this time */
8804         while (!my_fgets(fff, buf, sizeof(buf)))
8805         {
8806                 /* Ignore comments */
8807                 if (!buf[0] || (buf[0] == '#')) continue;
8808
8809                 /* Ignore invalid lines */
8810                 if (buf[1] != ':') continue;
8811
8812                 /* Process 'Start' */
8813                 if (buf[0] == 'S')
8814                 {
8815                         /* Extract the starting time */
8816                         start = atoi(buf + 2);
8817
8818                         /* Assume valid for an hour */
8819                         end = start + 59;
8820
8821                         /* Next... */
8822                         continue;
8823                 }
8824
8825                 /* Process 'End' */
8826                 if (buf[0] == 'E')
8827                 {
8828                         /* Extract the ending time */
8829                         end = atoi(buf + 2);
8830
8831                         /* Next... */
8832                         continue;
8833                 }
8834
8835                 /* Ignore incorrect range */
8836                 if ((start > full) || (full > end)) continue;
8837
8838                 /* Process 'Description' */
8839                 if (buf[0] == 'D')
8840                 {
8841                         num++;
8842
8843                         /* Apply the randomizer */
8844                         if (!randint0(num)) strcpy(desc, buf + 2);
8845
8846                         /* Next... */
8847                         continue;
8848                 }
8849         }
8850
8851         /* Message */
8852         msg_print(desc);
8853
8854         /* Close the file */
8855         my_fclose(fff);
8856 }