OSDN Git Service

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