OSDN Git Service

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