OSDN Git Service

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