OSDN Git Service

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