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