OSDN Git Service

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