OSDN Git Service

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