OSDN Git Service

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