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