OSDN Git Service

[Refactor] #37353 player-item.c/h 削除。 xtra2.c を player-status.c に分離。 / Delete player...
[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
47
48 /*
49  */
50
51 /*
52  *  Mark strings for auto dump
53  */
54 static char auto_dump_header[] = "# vvvvvvv== %s ==vvvvvvv";
55 static char auto_dump_footer[] = "# ^^^^^^^== %s ==^^^^^^^";
56
57 /*
58  * Variables for auto dump
59  */
60 static FILE *auto_dump_stream;
61 static cptr auto_dump_mark;
62 static int auto_dump_line_num;
63
64
65 /*!
66  * @brief prf出力内容を消去する /
67  * Remove old lines automatically generated before.
68  * @param orig_file 消去を行うファイル名
69  */
70 static void remove_auto_dump(cptr orig_file)
71 {
72         FILE *tmp_fff, *orig_fff;
73
74         char tmp_file[1024];
75         char buf[1024];
76         bool between_mark = FALSE;
77         bool changed = FALSE;
78         int line_num = 0;
79         long header_location = 0;
80         char header_mark_str[80];
81         char footer_mark_str[80];
82         size_t mark_len;
83
84         /* Prepare a header/footer mark string */
85         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
86         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
87
88         mark_len = strlen(footer_mark_str);
89
90         /* Open an old dump file in read-only mode */
91         orig_fff = my_fopen(orig_file, "r");
92
93         /* If original file does not exist, nothing to do */
94         if (!orig_fff) return;
95
96         /* Open a new (temporary) file */
97         tmp_fff = my_fopen_temp(tmp_file, 1024);
98
99         if (!tmp_fff)
100         {
101             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
102             msg_print(NULL);
103             return;
104         }
105
106         /* Loop for every line */
107         while (TRUE)
108         {
109                 /* Read a line */
110                 if (my_fgets(orig_fff, buf, sizeof(buf)))
111                 {
112                         /* Read error: Assume End of File */
113
114                         /*
115                          * Was looking for the footer, but not found.
116                          *
117                          * Since automatic dump might be edited by hand,
118                          * it's dangerous to kill these lines.
119                          * Seek back to the next line of the (pseudo) header,
120                          * and read again.
121                          */
122                         if (between_mark)
123                         {
124                                 fseek(orig_fff, header_location, SEEK_SET);
125                                 between_mark = FALSE;
126                                 continue;
127                         }
128
129                         /* Success -- End the loop */
130                         else
131                         {
132                                 break;
133                         }
134                 }
135
136                 /* We are looking for the header mark of automatic dump */
137                 if (!between_mark)
138                 {
139                         /* Is this line a header? */
140                         if (!strcmp(buf, header_mark_str))
141                         {
142                                 /* Memorise seek point of this line */
143                                 header_location = ftell(orig_fff);
144
145                                 /* Initialize counter for number of lines */
146                                 line_num = 0;
147
148                                 /* Look for the footer from now */
149                                 between_mark = TRUE;
150
151                                 /* There are some changes */
152                                 changed = TRUE;
153                         }
154
155                         /* Not a header */
156                         else
157                         {
158                                 /* Copy orginally lines */
159                                 fprintf(tmp_fff, "%s\n", buf);
160                         }
161                 }
162
163                 /* We are looking for the footer mark of automatic dump */
164                 else
165                 {
166                         /* Is this line a footer? */
167                         if (!strncmp(buf, footer_mark_str, mark_len))
168                         {
169                                 int tmp;
170
171                                 /*
172                                  * Compare the number of lines
173                                  *
174                                  * If there is an inconsistency between
175                                  * actual number of lines and the
176                                  * number here, the automatic dump
177                                  * might be edited by hand.  So it's
178                                  * dangerous to kill these lines.
179                                  * Seek back to the next line of the
180                                  * (pseudo) header, and read again.
181                                  */
182                                 if (!sscanf(buf + mark_len, " (%d)", &tmp)
183                                     || tmp != line_num)
184                                 {
185                                         fseek(orig_fff, header_location, SEEK_SET);
186                                 }
187
188                                 /* Look for another header */
189                                 between_mark = FALSE;
190                         }
191
192                         /* Not a footer */
193                         else
194                         {
195                                 /* Ignore old line, and count number of lines */
196                                 line_num++;
197                         }
198                 }
199         }
200
201         /* Close files */
202         my_fclose(orig_fff);
203         my_fclose(tmp_fff);
204
205         /* If there are some changes, overwrite the original file with new one */
206         if (changed)
207         {
208                 /* Copy contents of temporary file */
209
210                 tmp_fff = my_fopen(tmp_file, "r");
211                 orig_fff = my_fopen(orig_file, "w");
212
213                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
214                         fprintf(orig_fff, "%s\n", buf);
215
216                 my_fclose(orig_fff);
217                 my_fclose(tmp_fff);
218         }
219
220         /* Kill the temporary file */
221         fd_kill(tmp_file);
222
223         return;
224 }
225
226
227 /*!
228  * @brief prfファイルのフォーマットに従った内容を出力する /
229  * Dump a formatted line, using "vstrnfmt()".
230  * @param fmt 出力内容
231  */
232 static void auto_dump_printf(cptr fmt, ...)
233 {
234         cptr p;
235         va_list vp;
236
237         char buf[1024];
238
239         /* Begin the Varargs Stuff */
240         va_start(vp, fmt);
241
242         /* Format the args, save the length */
243         (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
244
245         /* End the Varargs Stuff */
246         va_end(vp);
247
248         /* Count number of lines */
249         for (p = buf; *p; p++)
250         {
251                 if (*p == '\n') auto_dump_line_num++;
252         }
253
254         /* Dump it */
255         fprintf(auto_dump_stream, "%s", buf);
256 }
257
258
259 /*!
260  * @brief prfファイルをファイルオープンする /
261  * Open file to append auto dump.
262  * @param buf ファイル名
263  * @param mark 出力するヘッダマーク
264  * @return ファイルポインタを取得できたらTRUEを返す
265  */
266 static bool open_auto_dump(cptr buf, cptr mark)
267 {
268
269         char header_mark_str[80];
270
271         /* Save the mark string */
272         auto_dump_mark = mark;
273
274         /* Prepare a header mark string */
275         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
276
277         /* Remove old macro dumps */
278         remove_auto_dump(buf);
279
280         /* Append to the file */
281         auto_dump_stream = my_fopen(buf, "a");
282
283         /* Failure */
284         if (!auto_dump_stream) {
285                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
286                 msg_print(NULL);
287
288                 /* Failed */
289                 return FALSE;
290         }
291
292         /* Start dumping */
293         fprintf(auto_dump_stream, "%s\n", header_mark_str);
294
295         /* Initialize counter */
296         auto_dump_line_num = 0;
297
298         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
299                                            "# *Warning!*  The lines below are an automatic dump.\n"));
300         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n", 
301                                            "# Don't edit them; changes will be deleted and replaced automatically.\n"));
302         /* Success */
303         return TRUE;
304 }
305
306 /*!
307  * @brief prfファイルをファイルクローズする /
308  * Append foot part and close auto dump.
309  * @return なし
310  */
311 static void close_auto_dump(void)
312 {
313         char footer_mark_str[80];
314
315         /* Prepare a footer mark string */
316         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
317
318         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
319                                            "# *Warning!*  The lines below are an automatic dump.\n"));
320         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n", 
321                                            "# Don't edit them; changes will be deleted and replaced automatically.\n"));
322         /* End of dump */
323         fprintf(auto_dump_stream, "%s (%d)\n", footer_mark_str, auto_dump_line_num);
324
325         /* Close */
326         my_fclose(auto_dump_stream);
327
328         return;
329 }
330
331
332 #ifndef JP
333
334 /*!
335  * @brief Return suffix of ordinal number
336  * @param num number
337  * @return pointer of suffix string.
338  */
339 cptr get_ordinal_number_suffix(int num)
340 {
341         num = ABS(num) % 100;
342         switch (num % 10)
343         {
344         case 1:
345                 return (num == 11) ? "th" : "st";
346         case 2:
347                 return (num == 12) ? "th" : "nd";
348         case 3:
349                 return (num == 13) ? "th" : "rd";
350         default:
351                 return "th";
352         }
353 }
354 #endif
355
356
357 /*!
358  * @brief 日記にメッセージを追加する /
359  * Take note to the diary.
360  * @param type 日記内容のID
361  * @param num 日記内容のIDに応じた数値
362  * @param note 日記内容のIDに応じた文字列参照ポインタ
363  * @return エラーID
364  */
365 errr do_cmd_write_nikki(int type, int num, cptr note)
366 {
367         int day, hour, min;
368         FILE *fff = NULL;
369         GAME_TEXT file_name[MAX_NLEN];
370         char buf[1024];
371         cptr note_level = "";
372         bool do_level = TRUE;
373         char note_level_buf[40];
374         QUEST_IDX q_idx;
375
376         static bool disable_nikki = FALSE;
377
378         extract_day_hour_min(&day, &hour, &min);
379
380         if (disable_nikki) return(-1);
381
382         if (type == NIKKI_FIX_QUEST_C ||
383             type == NIKKI_FIX_QUEST_F ||
384             type == NIKKI_RAND_QUEST_C ||
385             type == NIKKI_RAND_QUEST_F ||
386             type == NIKKI_TO_QUEST)
387         {
388                 IDX old_quest;
389
390                 old_quest = p_ptr->inside_quest;
391                 p_ptr->inside_quest = (quest[num].type == QUEST_TYPE_RANDOM) ? 0 : num;
392
393                 /* Get the quest text */
394                 init_flags = INIT_NAME_ONLY;
395
396                 process_dungeon_file("q_info.txt", 0, 0, 0, 0);
397
398                 /* Reset the old quest number */
399                 p_ptr->inside_quest = old_quest;
400         }
401
402         /* different filne name to avoid mixing */
403         sprintf(file_name,_("playrecord-%s.txt", "playrec-%s.txt"),savefile_base);
404
405         /* Build the filename */
406         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
407
408         /* File type is "TEXT" */
409         FILE_TYPE(FILE_TYPE_TEXT);
410
411         fff = my_fopen(buf, "a");
412
413         /* Failure */
414         if (!fff)
415         {
416                 msg_format(_("%s を開くことができませんでした。プレイ記録を一時停止します。", "Failed to open %s. Play-Record is disabled temporally."), buf);
417                 msg_format(NULL);
418                 disable_nikki=TRUE;
419                 return (-1);
420         }
421
422         q_idx = quest_number(dun_level);
423
424         if (write_level)
425         {
426                 if (p_ptr->inside_arena)
427                         note_level = _("アリーナ:", "Arane:");
428                 else if (!dun_level)
429                         note_level = _("地上:", "Surface:");
430                 else if (q_idx && (is_fixed_quest_idx(q_idx)
431                         && !((q_idx == QUEST_OBERON) || (q_idx == QUEST_SERPENT))))
432                         note_level = _("クエスト:", "Quest:");
433                 else
434                 {
435 #ifdef JP
436                         sprintf(note_level_buf, "%d階(%s):", (int)dun_level, d_name+d_info[dungeon_type].name);
437 #else
438                         sprintf(note_level_buf, "%s L%d:", d_name+d_info[dungeon_type].name, (int)dun_level);
439 #endif
440                         note_level = note_level_buf;
441                 }
442         }
443
444         switch(type)
445         {
446                 case NIKKI_HIGAWARI:
447                 {
448                         if (day < MAX_DAYS) fprintf(fff, _("%d日目\n", "Day %d\n"), day);
449                         else fputs(_("*****日目\n", "Day *****\n"), fff);
450                         do_level = FALSE;
451                         break;
452                 }
453                 case NIKKI_BUNSHOU:
454                 {
455                         if (num)
456                         {
457                                 fprintf(fff, "%s\n",note);
458                                 do_level = FALSE;
459                         }
460                         else
461                                 fprintf(fff, " %2d:%02d %20s %s\n",hour, min, note_level, note);
462                         break;
463                 }
464                 case NIKKI_ART:
465                 {
466                         fprintf(fff, _(" %2d:%02d %20s %sを発見した。\n", " %2d:%02d %20s discovered %s.\n"), hour, min, note_level, note);
467                         break;
468                 }
469                 case NIKKI_ART_SCROLL:
470                 {
471                         fprintf(fff, _(" %2d:%02d %20s 巻物によって%sを生成した。\n", " %2d:%02d %20s created %s by scroll.\n"), hour, min, note_level, note);
472                         break;
473                 }
474                 case NIKKI_UNIQUE:
475                 {
476                         fprintf(fff, _(" %2d:%02d %20s %sを倒した。\n", " %2d:%02d %20s defeated %s.\n"), hour, min, note_level, note);
477                         break;
478                 }
479                 case NIKKI_FIX_QUEST_C:
480                 {
481                         if (quest[num].flags & QUEST_FLAG_SILENT) break;
482                         fprintf(fff, _(" %2d:%02d %20s クエスト「%s」を達成した。\n",
483                                                    " %2d:%02d %20s completed quest '%s'.\n"), hour, min, note_level, quest[num].name);
484                         break;
485                 }
486                 case NIKKI_FIX_QUEST_F:
487                 {
488                         if (quest[num].flags & QUEST_FLAG_SILENT) break;
489                         fprintf(fff, _(" %2d:%02d %20s クエスト「%s」から命からがら逃げ帰った。\n",
490                                                    " %2d:%02d %20s run away from quest '%s'.\n"), hour, min, note_level, quest[num].name);
491                         break;
492                 }
493                 case NIKKI_RAND_QUEST_C:
494                 {
495                         GAME_TEXT name[MAX_NLEN];
496                         strcpy(name, r_name+r_info[quest[num].r_idx].name);
497                         fprintf(fff, _(" %2d:%02d %20s ランダムクエスト(%s)を達成した。\n",
498                                                    " %2d:%02d %20s completed random quest '%s'\n"), hour, min, note_level, name);
499                         break;
500                 }
501                 case NIKKI_RAND_QUEST_F:
502                 {
503                         GAME_TEXT name[MAX_NLEN];
504                         strcpy(name, r_name+r_info[quest[num].r_idx].name);
505                         fprintf(fff, _(" %2d:%02d %20s ランダムクエスト(%s)から逃げ出した。\n",
506                                                    " %2d:%02d %20s ran away from quest '%s'.\n"), hour, min, note_level, name);
507                         break;
508                 }
509                 case NIKKI_MAXDEAPTH:
510                 {
511                         fprintf(fff, _(" %2d:%02d %20s %sの最深階%d階に到達した。\n",
512                                                    " %2d:%02d %20s reached level %d of %s for the first time.\n"), hour, min, note_level,
513                                                    _(d_name+d_info[dungeon_type].name, num),
514                                                    _(num, d_name+d_info[dungeon_type].name));
515                         break;
516                 }
517                 case NIKKI_TRUMP:
518                 {
519                         fprintf(fff, _(" %2d:%02d %20s %s%sの最深階を%d階にセットした。\n",
520                                                    " %2d:%02d %20s reset recall level of %s to %d %s.\n"), hour, min, note_level, note,
521                                                    _(d_name + d_info[num].name, (int)max_dlv[num]),
522                                                    _((int)max_dlv[num], d_name + d_info[num].name));
523                         break;
524                 }
525                 case NIKKI_STAIR:
526                 {
527                         cptr to;
528                         if (q_idx && (is_fixed_quest_idx(q_idx)
529                              && !((q_idx == QUEST_OBERON) || (q_idx == QUEST_SERPENT))))
530                         {
531                                 to = _("地上", "the surface");
532                         }
533                         else
534                         {
535                                 if (!(dun_level+num)) to = _("地上", "the surface");
536                                 else to = format(_("%d階", "level %d"), dun_level+num);
537                         }
538                         fprintf(fff, _(" %2d:%02d %20s %sへ%s。\n", " %2d:%02d %20s %s %s.\n"), hour, min, note_level, _(to, note), _(note, to));
539                         break;
540                 }
541                 case NIKKI_RECALL:
542                 {
543                         if (!num)
544                         fprintf(fff, _(" %2d:%02d %20s 帰還を使って%sの%d階へ下りた。\n", " %2d:%02d %20s recalled to dungeon level %d of %s.\n"), 
545                                                 hour, min, note_level, _(d_name+d_info[dungeon_type].name, (int)max_dlv[dungeon_type]), 
546                                                                                            _((int)max_dlv[dungeon_type], d_name+d_info[dungeon_type].name));
547                         else
548                                 fprintf(fff, _(" %2d:%02d %20s 帰還を使って地上へと戻った。\n", " %2d:%02d %20s recalled from dungeon to surface.\n"), hour, min, note_level);
549                         break;
550                 }
551                 case NIKKI_TO_QUEST:
552                 {
553                         if (quest[num].flags & QUEST_FLAG_SILENT) break;
554                         fprintf(fff, _(" %2d:%02d %20s クエスト「%s」へと突入した。\n", " %2d:%02d %20s entered the quest '%s'.\n"),
555                                                 hour, min, note_level, quest[num].name);
556                         break;
557                 }
558                 case NIKKI_TELE_LEV:
559                 {
560                         fprintf(fff, _(" %2d:%02d %20s レベル・テレポートで脱出した。\n", " %2d:%02d %20s Got out using teleport level.\n"),
561                                                 hour, min, note_level);
562                         break;
563                 }
564                 case NIKKI_BUY:
565                 {
566                         fprintf(fff, _(" %2d:%02d %20s %sを購入した。\n", " %2d:%02d %20s bought %s.\n"), hour, min, note_level, note);
567                         break;
568                 }
569                 case NIKKI_SELL:
570                 {
571                         fprintf(fff, _(" %2d:%02d %20s %sを売却した。\n", " %2d:%02d %20s sold %s.\n"), hour, min, note_level, note);
572                         break;
573                 }
574                 case NIKKI_ARENA:
575                 {
576                         if (num < 0)
577                         {
578                                 int n = -num;
579                                 fprintf(fff, _(" %2d:%02d %20s 闘技場の%d%s回戦で、%sの前に敗れ去った。\n", " %2d:%02d %20s beaten by %s in the %d%s fight.\n"),
580                                                         hour, min, note_level, _(n, note), _("", n), _(note, get_ordinal_number_suffix(n)));
581                                 break;
582                         }
583                         fprintf(fff, _(" %2d:%02d %20s 闘技場の%d%s回戦(%s)に勝利した。\n", " %2d:%02d %20s won the %d%s fight (%s).\n"),
584                                                 hour, min, note_level, num, _("", get_ordinal_number_suffix(num)), note);
585                         
586                         if (num == MAX_ARENA_MONS)
587                         {
588                                 fprintf(fff, _("                 闘技場のすべての敵に勝利し、チャンピオンとなった。\n",
589                                                            "                 won all fight to become a Chanpion.\n"));
590                                 do_level = FALSE;
591                         }
592                         break;
593                 }
594                 case NIKKI_HANMEI:
595                 {
596                         fprintf(fff, _(" %2d:%02d %20s %sを識別した。\n", " %2d:%02d %20s identified %s.\n"), hour, min, note_level, note);
597                         break;
598                 }
599                 case NIKKI_WIZ_TELE:
600                 {
601                         cptr to;
602                         if (!dun_level)
603                                 to = _("地上", "the surface");
604                         else
605                                 to = format(_("%d階(%s)", "level %d of %s"), dun_level, d_name+d_info[dungeon_type].name);
606
607                         fprintf(fff, _(" %2d:%02d %20s %sへとウィザード・テレポートで移動した。\n",
608                                                    " %2d:%02d %20s wizard-teleport to %s.\n"), hour, min, note_level, to);
609                         break;
610                 }
611                 case NIKKI_PAT_TELE:
612                 {
613                         cptr to;
614                         if (!dun_level)
615                                 to = _("地上", "the surface");
616                         else
617                                 to = format(_("%d階(%s)", "level %d of %s"), dun_level, d_name+d_info[dungeon_type].name);
618
619                         fprintf(fff, _(" %2d:%02d %20s %sへとパターンの力で移動した。\n",
620                                                    " %2d:%02d %20s used Pattern to teleport to %s.\n"), hour, min, note_level, to);
621                         break;
622                 }
623                 case NIKKI_LEVELUP:
624                 {
625                         fprintf(fff, _(" %2d:%02d %20s レベルが%dに上がった。\n", " %2d:%02d %20s reached player level %d.\n"), hour, min, note_level, num);
626                         break;
627                 }
628                 case NIKKI_GAMESTART:
629                 {
630                         time_t ct = time((time_t*)0);
631                         do_level = FALSE;
632                         if (num)
633                         {
634                                 fprintf(fff, "%s %s",note, ctime(&ct));
635                         }
636                         else
637                                 fprintf(fff, " %2d:%02d %20s %s %s",hour, min, note_level, note, ctime(&ct));
638                         break;
639                 }
640                 case NIKKI_NAMED_PET:
641                 {
642                         fprintf(fff, " %2d:%02d %20s ", hour, min, note_level);
643                         switch (num)
644                         {
645                                 case RECORD_NAMED_PET_NAME:
646                                         fprintf(fff, _("%sを旅の友にすることに決めた。\n", "decided to travel together with %s.\n"), note);
647                                         break;
648                                 case RECORD_NAMED_PET_UNNAME:
649                                         fprintf(fff, _("%sの名前を消した。\n", "unnamed %s.\n"), note);
650                                         break;
651                                 case RECORD_NAMED_PET_DISMISS:
652                                         fprintf(fff, _("%sを解放した。\n", "dismissed %s.\n"), note);
653                                         break;
654                                 case RECORD_NAMED_PET_DEATH:
655                                         fprintf(fff, _("%sが死んでしまった。\n", "%s died.\n"), note);
656                                         break;
657                                 case RECORD_NAMED_PET_MOVED:
658                                         fprintf(fff, _("%sをおいて別のマップへ移動した。\n", "moved to another map leaving %s behind.\n"), note);
659                                         break;
660                                 case RECORD_NAMED_PET_LOST_SIGHT:
661                                         fprintf(fff, _("%sとはぐれてしまった。\n", "lost sight of %s.\n"), note);
662                                         break;
663                                 case RECORD_NAMED_PET_DESTROY:
664                                         fprintf(fff, _("%sが*破壊*によって消え去った。\n", "%s was made disappeared by *destruction*.\n"), note);
665                                         break;
666                                 case RECORD_NAMED_PET_EARTHQUAKE:
667                                         fprintf(fff, _("%sが岩石に押し潰された。\n", "%s was crushed by falling rocks.\n"), note);
668                                         break;
669                                 case RECORD_NAMED_PET_GENOCIDE:
670                                         fprintf(fff, _("%sが抹殺によって消え去った。\n", "%s was made disappeared by genocide.\n"), note);
671                                         break;
672                                 case RECORD_NAMED_PET_WIZ_ZAP:
673                                         fprintf(fff, _("%sがデバッグコマンドによって消え去った。\n", "%s was removed by debug command.\n"), note);
674                                         break;
675                                 case RECORD_NAMED_PET_TELE_LEVEL:
676                                         fprintf(fff, _("%sがテレポート・レベルによって消え去った。\n", "%s was made disappeared by teleport level.\n"), note);
677                                         break;
678                                 case RECORD_NAMED_PET_BLAST:
679                                         fprintf(fff, _("%sを爆破した。\n", "blasted %s.\n"), note);
680                                         break;
681                                 case RECORD_NAMED_PET_HEAL_LEPER:
682                                         fprintf(fff, _("%sの病気が治り旅から外れた。\n", "%s was healed and left.\n"), note);
683                                         break;
684                                 case RECORD_NAMED_PET_COMPACT:
685                                         fprintf(fff, _("%sがモンスター情報圧縮によって消え去った。\n", "%s was made disappeared by compacting monsters.\n"), note);
686                                         break;
687                                 case RECORD_NAMED_PET_LOSE_PARENT:
688                                         fprintf(fff, _("%sの召喚者が既にいないため消え去った。\n", "%s disappeared because there does not exist summoner.\n"), note);
689                                         break;
690
691
692                                 default:
693                                         fprintf(fff, "\n");
694                                         break;
695                         }
696                         break;
697                 }
698
699                 case NIKKI_WIZARD_LOG:
700                         fprintf(fff, "%s\n", note);
701                         break;
702
703                 default:
704                         break;
705         }
706
707         my_fclose(fff);
708
709         if (do_level) write_level = FALSE;
710
711         return (0);
712 }
713
714
715 #define MAX_SUBTITLE (sizeof(subtitle)/sizeof(subtitle[0]))
716
717 /*!
718  * @brief 日記のタイトル表記と内容出力 /
719  * @return なし
720  * @details
721  * 日記のタイトルは本関数の subtitle ローカル変数で定義されている。
722  */
723 static void do_cmd_disp_nikki(void)
724 {
725         char nikki_title[256];
726         GAME_TEXT file_name[MAX_NLEN];
727         char buf[1024];
728         char tmp[80];
729 #ifdef JP
730         /*! */
731         static const char subtitle[][30] = {"最強の肉体を求めて",
732                                            "人生それははかない",
733                                            "明日に向かって",
734                                            "棚からぼたもち",
735                                            "あとの祭り",
736                                            "それはいい考えだ",
737                                            "何とでも言え",
738                                            "兎にも角にも",
739                                            "ウソだけど",
740                                            "もはやこれまで",
741                                            "なんでこうなるの",
742                                            "それは無理だ",
743                                            "倒すべき敵はゲ○ツ",
744                                            "ん~?聞こえんなぁ",
745                                            "オレの名を言ってみろ",
746                                            "頭が変になっちゃった",
747                                            "互換しません",
748                                            "せっかくだから",
749                                            "まだまだ甘いね",
750                                            "むごいむごすぎる",
751                                            "こんなもんじゃない",
752                                            "だめだこりゃ",
753                                            "次いってみよう",
754                                            "ちょっとだけよ",
755                                            "哀しき冒険者",
756                                            "野望の果て",
757                                            "無限地獄",
758                                            "神に喧嘩を売る者",
759                                            "未知の世界へ",
760                                            "最高の頭脳を求めて"};
761 #else
762         static const char subtitle[][51] ={"Quest of The World's Toughest Body",
763                                            "Attack is the best form of defence.",
764                                            "Might is right.",
765                                            "An unexpected windfall",
766                                            "A drowning man will catch at a straw",
767                                            "Don't count your chickens before they are hatched.",
768                                            "It is no use crying over spilt milk.",
769                                            "Seeing is believing.",
770                                            "Strike the iron while it is hot.",
771                                            "I don't care what follows.",
772                                            "To dig a well to put out a house on fire.",
773                                            "Tomorrow is another day.",
774                                            "Easy come, easy go.",
775                                            "The more haste, the less speed.",
776                                            "Where there is life, there is hope.",
777                                            "There is no royal road to *WINNER*.",
778                                            "Danger past, God forgotten.",
779                                            "The best thing to do now is to run away.",
780                                            "Life is but an empty dream.",
781                                            "Dead men tell no tales.",
782                                            "A book that remains shut is but a block.",
783                                            "Misfortunes never come singly.",
784                                            "A little knowledge is a dangerous thing.",
785                                            "History repeats itself.",
786                                            "*WINNER* was not built in a day.",
787                                            "Ignorance is bliss.",
788                                            "To lose is to win?",
789                                            "No medicine can cure folly.",
790                                            "All good things come to an end.",
791                                            "M$ Empire strikes back.",
792                                            "To see is to believe",
793                                            "Time is money.",
794                                            "Quest of The World's Greatest Brain"};
795 #endif
796         sprintf(file_name,_("playrecord-%s.txt", "playrec-%s.txt"),savefile_base);
797
798         /* Build the filename */
799         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
800
801         if (p_ptr->pclass == CLASS_WARRIOR || p_ptr->pclass == CLASS_MONK || p_ptr->pclass == CLASS_SAMURAI || p_ptr->pclass == CLASS_BERSERKER)
802                 strcpy(tmp,subtitle[randint0(MAX_SUBTITLE-1)]);
803         else if (IS_WIZARD_CLASS())
804                 strcpy(tmp,subtitle[randint0(MAX_SUBTITLE-1)+1]);
805         else strcpy(tmp,subtitle[randint0(MAX_SUBTITLE-2)+1]);
806
807 #ifdef JP
808         sprintf(nikki_title, "「%s%s%sの伝説 -%s-」",
809                 ap_ptr->title, ap_ptr->no ? "の" : "", p_ptr->name, tmp);
810 #else
811         sprintf(nikki_title, "Legend of %s %s '%s'",
812                 ap_ptr->title, p_ptr->name, tmp);
813 #endif
814
815         /* Display the file contents */
816         show_file(FALSE, buf, nikki_title, -1, 0);
817 }
818
819 /*!
820  * @brief 日記に任意の内容を表記するコマンドのメインルーチン /
821  * @return なし
822  */
823 static void do_cmd_bunshou(void)
824 {
825         char tmp[80] = "\0";
826         char bunshou[80] = "\0";
827
828         if (get_string(_("内容: ", "diary note: "), tmp, 79))
829         {
830                 strcpy(bunshou, tmp);
831
832                 do_cmd_write_nikki(NIKKI_BUNSHOU, 0, bunshou);
833         }
834 }
835
836 /*!
837  * @brief 最後に取得したアイテムの情報を日記に追加するメインルーチン /
838  * @return なし
839  */
840 static void do_cmd_last_get(void)
841 {
842         char buf[256];
843         s32b turn_tmp;
844
845         if (record_o_name[0] == '\0') return;
846
847         sprintf(buf,_("%sの入手を記録します。", "Do you really want to record getting %s? "),record_o_name);
848         if (!get_check(buf)) return;
849
850         turn_tmp = turn;
851         turn = record_turn;
852         sprintf(buf,_("%sを手に入れた。", "descover %s."), record_o_name);
853         do_cmd_write_nikki(NIKKI_BUNSHOU, 0, buf);
854         turn = turn_tmp;
855 }
856
857 /*!
858  * @brief ファイル中の全日記記録を消去する /
859  * @return なし
860  */
861 static void do_cmd_erase_nikki(void)
862 {
863         GAME_TEXT file_name[MAX_NLEN];
864         char buf[256];
865         FILE *fff = NULL;
866
867         if (!get_check(_("本当に記録を消去しますか?", "Do you really want to delete all your record? "))) return;
868                 sprintf(file_name,_("playrecord-%s.txt", "playrec-%s.txt"),savefile_base);
869
870         /* Build the filename */
871         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, file_name);
872
873         /* Remove the file */
874         fd_kill(buf);
875
876         fff = my_fopen(buf, "w");
877         if(fff){
878                 my_fclose(fff);
879                 msg_format(_("記録を消去しました。", "deleted record."));
880         }else{
881                 msg_format(_("%s の消去に失敗しました。", "failed to delete %s."), buf);
882         }
883         msg_print(NULL);
884 }
885
886 /*!
887  * @brief 日記コマンド
888  * @return なし
889  */
890 void do_cmd_nikki(void)
891 {
892         int i;
893
894         /* File type is "TEXT" */
895         FILE_TYPE(FILE_TYPE_TEXT);
896         screen_save();
897
898         /* Interact until done */
899         while (1)
900         {
901                 Term_clear();
902
903                 /* Ask for a choice */
904                 prt(_("[ 記録の設定 ]", "[ Play Record ]"), 2, 0);
905
906                 /* Give some choices */
907                 prt(_("(1) 記録を見る", "(1) Display your record"), 4, 5);
908                 prt(_("(2) 文章を記録する", "(2) Add record"), 5, 5);
909                 prt(_("(3) 直前に入手又は鑑定したものを記録する", "(3) Record item you last get/identify"), 6, 5);
910                 prt(_("(4) 記録を消去する", "(4) Delete your record"), 7, 5);
911
912                 prt(_("(R) プレイ動画を記録する/中止する", "(R) Record playing movie / or stop it"), 9, 5);
913
914                 /* Prompt */
915                 prt(_("コマンド:", "Command: "), 18, 0);
916
917                 /* Prompt */
918                 i = inkey();
919
920                 if (i == ESCAPE) break;
921
922                 switch (i)
923                 {
924                 case '1':
925                         do_cmd_disp_nikki();
926                         break;
927                 case '2':
928                         do_cmd_bunshou();
929                         break;
930                 case '3':
931                         do_cmd_last_get();
932                         break;
933                 case '4':
934                         do_cmd_erase_nikki();
935                         break;
936                 case 'r': case 'R':
937                         screen_load();
938                         prepare_movie_hooks();
939                         return;
940                 default: /* Unknown option */
941                         bell();
942                 }
943
944                 msg_erase();
945         }
946         screen_load();
947 }
948
949 /*!
950  * @brief 画面を再描画するコマンドのメインルーチン
951  * Hack -- redraw the screen
952  * @return なし
953  * @details
954  * <pre>
955  * This command performs various low level updates, clears all the "extra"
956  * windows, does a total redraw of the main window, and requests all of the
957  * interesting updates and redraws that I can think of.
958  *
959  * This command is also used to "instantiate" the results of the user
960  * selecting various things, such as graphics mode, so it must call
961  * the "TERM_XTRA_REACT" hook before redrawing the windows.
962  * </pre>
963  */
964 void do_cmd_redraw(void)
965 {
966         int j;
967
968         term *old = Term;
969
970
971         /* Hack -- react to changes */
972         Term_xtra(TERM_XTRA_REACT, 0);
973
974
975         /* Combine and Reorder the pack (later) */
976         p_ptr->notice |= (PN_COMBINE | PN_REORDER);
977
978
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         cptr 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                         cptr 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                                 cptr 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                                         cptr 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(cptr 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(cptr 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, cptr 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                         cptr 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                         cptr 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         cptr 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(cptr fname)
2305 {
2306         static cptr 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(cptr fname)
2446 {
2447         static cptr 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                 cptr 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                         cptr 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 cptr 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(cptr 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         cptr 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 cptr 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 cptr 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 cptr 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 cptr choice_msg = _("モンスターの[色/文字]を変更します", "Change monster attr/chars");
3226                         static 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 cptr 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 cptr 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 cptr 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                                 cptr 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                                 cptr 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         /* Silly message */
3792
3793 #if FAKE_VER_EXTRA > 0
3794         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d.%d", "You are playing Hengband %d.%d.%d.%d."),
3795                 FAKE_VER_MAJOR-10, FAKE_VER_MINOR, FAKE_VER_PATCH, FAKE_VER_EXTRA);
3796 #else
3797         msg_format(_("変愚蛮怒(Hengband) %d.%d.%d", "You are playing Hengband %d.%d.%d."),
3798                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH);
3799 #endif
3800 }
3801
3802
3803
3804 /*
3805  * Array of feeling strings
3806  */
3807 static cptr do_cmd_feeling_text[11] =
3808 {
3809         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
3810         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
3811         _("恐ろしい死の幻が目に浮かび、気絶しそうになった!", "You nearly faint as horrible visions of death fill your mind!"),
3812         _("この階はとても危険なようだ。", "This level looks very dangerous."),
3813         _("とても悪い予感がする...", "You have a very bad feeling..."),
3814         _("悪い予感がする...", "You have a bad feeling..."),
3815         _("何か緊張する。", "You feel nervous."),
3816         _("少し不運な気がする...", "You feel your luck is turning..."),
3817         _("この場所は好きになれない。", "You don't like the look of this place."),
3818         _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."),
3819         _("なんて退屈なところだ...", "What a boring place...")
3820 };
3821
3822 static cptr do_cmd_feeling_text_combat[11] =
3823 {
3824         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
3825         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
3826         _("今夜もまた、誰かが命を落とす...", "You nearly faint as horrible visions of death fill your mind!"),
3827         _("この階はとても危険なようだ。", "This level looks very dangerous."),
3828         _("とても悪い予感がする...", "You have a very bad feeling..."),
3829         _("悪い予感がする...", "You have a bad feeling..."),
3830         _("何か緊張する。", "You feel nervous."),
3831         _("少し不運な気がする...", "You feel your luck is turning..."),
3832         _("この場所は好きになれない。", "You don't like the look of this place."),
3833         _("この階はそれなりに安全なようだ。", "This level looks reasonably safe."),
3834         _("なんて退屈なところだ...", "What a boring place...")
3835 };
3836
3837 static cptr do_cmd_feeling_text_lucky[11] =
3838 {
3839         _("この階の雰囲気を感じとれなかった...", "Looks like any other level."),
3840         _("この階には何か特別なものがあるような気がする。", "You feel there is something special about this level."),
3841         _("この階はこの上なく素晴らしい感じがする。", "You have a superb feeling about this level."),
3842         _("素晴らしい感じがする...", "You have an excellent feeling..."),
3843         _("とても良い感じがする...", "You have a very good feeling..."),
3844         _("良い感じがする...", "You have a good feeling..."),
3845         _("ちょっと幸運な感じがする...", "You feel strangely lucky..."),
3846         _("多少は運が向いてきたか...", "You feel your luck is turning..."),
3847         _("見た感じ悪くはない...", "You like the look of this place..."),
3848         _("全然駄目ということはないが...", "This level can't be all bad..."),
3849         _("なんて退屈なところだ...", "What a boring place...")
3850 };
3851
3852
3853 /*
3854  * Note that "feeling" is set to zero unless some time has passed.
3855  * Note that this is done when the level is GENERATED, not entered.
3856  */
3857 void do_cmd_feeling(void)
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 cptr 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 cptr 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         cptr 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 cptr 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 int collect_objects(int grp_cur, IDX object_idx[], BIT_FLAGS8 mode)
4381 {
4382         IDX i;
4383         int j, k, object_cnt = 0;
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 cptr 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 int collect_features(int grp_cur, IDX *feat_idx, BIT_FLAGS8 mode)
4464 {
4465         IDX i;
4466         int 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, y, x;
4551
4552         TERM_COLOR a = 0;
4553         char c = ' ';
4554
4555         bool okay = TRUE;
4556
4557         FILE *fff;
4558
4559         char buf[1024];
4560
4561         int wid, hgt;
4562
4563         Term_get_size(&wid, &hgt);
4564
4565         /* Build the filename */
4566         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
4567
4568         /* Append to the file */
4569         fff = my_fopen(buf, "r");
4570
4571         if (!fff) {
4572                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
4573                 msg_print(NULL);
4574                 return;
4575         }
4576
4577         screen_save();
4578         Term_clear();
4579
4580         /* Load the screen */
4581         for (y = 0; okay; y++)
4582         {
4583                 /* Get a line of data including control code */
4584                 if (!fgets(buf, 1024, fff)) okay = FALSE;
4585
4586                 /* Get the blank line */
4587                 if (buf[0] == '\n' || buf[0] == '\0') break;
4588
4589                 /* Ignore too large screen image */
4590                 if (y >= hgt) continue;
4591
4592                 /* Show each row */
4593                 for (x = 0; x < wid - 1; x++)
4594                 {
4595                         /* End of line */
4596                         if (buf[x] == '\n' || buf[x] == '\0') break;
4597
4598                         /* Put the attr/char */
4599                         Term_draw(x, y, TERM_WHITE, buf[x]);
4600                 }
4601         }
4602
4603         /* Dump the screen */
4604         for (y = 0; okay; y++)
4605         {
4606                 /* Get a line of data including control code */
4607                 if (!fgets(buf, 1024, fff)) okay = FALSE;
4608
4609                 /* Get the blank line */
4610                 if (buf[0] == '\n' || buf[0] == '\0') break;
4611
4612                 /* Ignore too large screen image */
4613                 if (y >= hgt) continue;
4614
4615                 /* Dump each row */
4616                 for (x = 0; x < wid - 1; x++)
4617                 {
4618                         /* End of line */
4619                         if (buf[x] == '\n' || buf[x] == '\0') break;
4620
4621                         /* Get the attr/char */
4622                         (void)(Term_what(x, y, &a, &c));
4623
4624                         /* Look up the attr */
4625                         for (i = 0; i < 16; i++)
4626                         {
4627                                 /* Use attr matches */
4628                                 if (hack[i] == buf[x]) a = (byte_hack)i;
4629                         }
4630
4631                         /* Put the attr/char */
4632                         Term_draw(x, y, a, c);
4633                 }
4634         }
4635
4636
4637         /* Close it */
4638         my_fclose(fff);
4639
4640
4641         prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0);
4642
4643         flush();
4644         inkey();
4645
4646         screen_load();
4647 }
4648
4649
4650
4651
4652 cptr inven_res_label = _("                               酸電火冷毒光闇破轟獄因沌劣 盲怖乱痺透命感消復浮",
4653                                                  "                               AcElFiCoPoLiDkShSoNtNxCaDi BlFeCfFaSeHlEpSdRgLv");
4654
4655
4656 #define IM_FLAG_STR  _("*", "* ")
4657 #define HAS_FLAG_STR _("+", "+ ")
4658 #define NO_FLAG_STR  _("・", ". ")
4659
4660 #define print_im_or_res_flag(IM, RES) \
4661 { \
4662         fputs(have_flag(flgs, (IM)) ? IM_FLAG_STR : \
4663               (have_flag(flgs, (RES)) ? HAS_FLAG_STR : NO_FLAG_STR), fff); \
4664 }
4665
4666 #define print_flag(TR) \
4667 { \
4668         fputs(have_flag(flgs, (TR)) ? HAS_FLAG_STR : NO_FLAG_STR, fff); \
4669 }
4670
4671
4672 /* XTRA HACK RESLIST */
4673 static void do_cmd_knowledge_inven_aux(FILE *fff, object_type *o_ptr, int *j, OBJECT_TYPE_VALUE tval, char *where)
4674 {
4675         GAME_TEXT o_name[MAX_NLEN];
4676         BIT_FLAGS flgs[TR_FLAG_SIZE];
4677
4678         if (!o_ptr->k_idx) return;
4679         if (o_ptr->tval != tval) return;
4680
4681         /* Identified items only */
4682         if (!object_is_known(o_ptr)) return;
4683
4684         /*
4685          * HACK:Ring of Lordly protection and Dragon equipment
4686          * have random resistances.
4687          */
4688         if ((object_is_wearable(o_ptr) && object_is_ego(o_ptr))
4689             || ((tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_RESISTANCE))
4690             || ((tval == TV_RING) && (o_ptr->sval == SV_RING_LORDLY))
4691             || ((tval == TV_SHIELD) && (o_ptr->sval == SV_DRAGON_SHIELD))
4692             || ((tval == TV_HELM) && (o_ptr->sval == SV_DRAGON_HELM))
4693             || ((tval == TV_GLOVES) && (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES))
4694             || ((tval == TV_BOOTS) && (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE))
4695             || object_is_artifact(o_ptr))
4696         {
4697                 int i = 0;
4698                 object_desc(o_name, o_ptr, OD_NAME_ONLY);
4699
4700                 while (o_name[i] && (i < 26))
4701                 {
4702 #ifdef JP
4703                         if (iskanji(o_name[i])) i++;
4704 #endif
4705                         i++;
4706                 }
4707
4708                 if (i < 28)
4709                 {
4710                         while (i < 28)
4711                         {
4712                                 o_name[i] = ' '; i++;
4713                         }
4714                 }
4715                 o_name[i] = '\0';
4716
4717                 fprintf(fff, "%s %s", where, o_name);
4718
4719                 if (!(o_ptr->ident & (IDENT_MENTAL)))
4720                 {
4721                         fputs(_("-------不明--------------- -------不明---------\n", 
4722                                         "-------unknown------------ -------unknown------\n"), fff);
4723                 }
4724                 else
4725                 {
4726                         object_flags_known(o_ptr, flgs);
4727
4728                         print_im_or_res_flag(TR_IM_ACID, TR_RES_ACID);
4729                         print_im_or_res_flag(TR_IM_ELEC, TR_RES_ELEC);
4730                         print_im_or_res_flag(TR_IM_FIRE, TR_RES_FIRE);
4731                         print_im_or_res_flag(TR_IM_COLD, TR_RES_COLD);
4732                         print_flag(TR_RES_POIS);
4733                         print_flag(TR_RES_LITE);
4734                         print_flag(TR_RES_DARK);
4735                         print_flag(TR_RES_SHARDS);
4736                         print_flag(TR_RES_SOUND);
4737                         print_flag(TR_RES_NETHER);
4738                         print_flag(TR_RES_NEXUS);
4739                         print_flag(TR_RES_CHAOS);
4740                         print_flag(TR_RES_DISEN);
4741
4742                         fputs(" ", fff);
4743
4744                         print_flag(TR_RES_BLIND);
4745                         print_flag(TR_RES_FEAR);
4746                         print_flag(TR_RES_CONF);
4747                         print_flag(TR_FREE_ACT);
4748                         print_flag(TR_SEE_INVIS);
4749                         print_flag(TR_HOLD_EXP);
4750                         print_flag(TR_TELEPATHY);
4751                         print_flag(TR_SLOW_DIGEST);
4752                         print_flag(TR_REGEN);
4753                         print_flag(TR_LEVITATION);
4754
4755                         fputc('\n', fff);
4756                 }
4757                 (*j)++;
4758                 if (*j == 9)
4759                 {
4760                         *j = 0;
4761                         fprintf(fff, "%s\n", inven_res_label);
4762                 }
4763         }
4764 }
4765
4766 /*
4767  * Display *ID* ed weapons/armors's resistances
4768  */
4769 static void do_cmd_knowledge_inven(void)
4770 {
4771         FILE *fff;
4772
4773         GAME_TEXT file_name[1024];
4774
4775         store_type  *st_ptr;
4776
4777         OBJECT_TYPE_VALUE tval;
4778         int i = 0;
4779         int j = 0;
4780
4781         char  where[32];
4782
4783         /* Open a new file */
4784         fff = my_fopen_temp(file_name, 1024);
4785         if (!fff)
4786         {
4787             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
4788             msg_print(NULL);
4789             return;
4790         }
4791         fprintf(fff, "%s\n", inven_res_label);
4792
4793         for (tval = TV_WEARABLE_BEGIN; tval <= TV_WEARABLE_END; tval++)
4794         {
4795                 if (j != 0)
4796                 {
4797                         for (; j < 9; j++) fputc('\n', fff);
4798                         j = 0;
4799                         fprintf(fff, "%s\n", inven_res_label);
4800                 }
4801                 strcpy(where, _("装", "E "));
4802                 for (i = INVEN_RARM; i < INVEN_TOTAL; i++)
4803                 {
4804                         do_cmd_knowledge_inven_aux(fff, &inventory[i], &j, tval, where);
4805                 }
4806                 strcpy(where, _("持", "I "));
4807                 for (i = 0; i < INVEN_PACK; i++)
4808                 {
4809                         do_cmd_knowledge_inven_aux(fff, &inventory[i], &j, tval, where);
4810                 }
4811
4812                 st_ptr = &town[1].store[STORE_HOME];
4813                 strcpy(where, _("家", "H "));
4814                 for (i = 0; i < st_ptr->stock_num; i++)
4815                 {
4816                         do_cmd_knowledge_inven_aux(fff, &st_ptr->stock[i], &j, tval, where);
4817                 }
4818         }
4819         my_fclose(fff);
4820
4821         /* Display the file contents */
4822         show_file(TRUE, file_name, _("*鑑定*済み武器/防具の耐性リスト", "Resistances of *identified* equipment"), 0, 0);
4823
4824         /* Remove the file */
4825         fd_kill(file_name);
4826 }
4827
4828
4829 void do_cmd_save_screen_html_aux(char *filename, int message)
4830 {
4831         int y, x, i;
4832
4833         TERM_COLOR a = 0, old_a = 0;
4834         char c = ' ';
4835
4836         FILE *fff, *tmpfff;
4837         char buf[2048];
4838
4839         int yomikomu = 0;
4840         cptr tags[4] = {
4841                 "HEADER_START:",
4842                 "HEADER_END:",
4843                 "FOOTER_START:",
4844                 "FOOTER_END:",
4845         };
4846
4847         cptr html_head[] = {
4848                 "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n",
4849                 "<pre>",
4850                 0,
4851         };
4852         cptr html_foot[] = {
4853                 "</pre>\n",
4854                 "</body>\n</html>\n",
4855                 0,
4856         };
4857
4858         int wid, hgt;
4859
4860         Term_get_size(&wid, &hgt);
4861
4862         /* File type is "TEXT" */
4863         FILE_TYPE(FILE_TYPE_TEXT);
4864
4865         /* Append to the file */
4866         fff = my_fopen(filename, "w");
4867
4868         if (!fff) {
4869                 if (message) {
4870                     msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename);
4871                     msg_print(NULL);
4872                 }
4873                 
4874                 return;
4875         }
4876         if (message) screen_save();
4877
4878         /* Build the filename */
4879         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf");
4880         tmpfff = my_fopen(buf, "r");
4881         if (!tmpfff) {
4882                 for (i = 0; html_head[i]; i++)
4883                         fputs(html_head[i], fff);
4884         }
4885         else {
4886                 yomikomu = 0;
4887                 while (!my_fgets(tmpfff, buf, sizeof(buf))) {
4888                         if (!yomikomu) {
4889                                 if (strncmp(buf, tags[0], strlen(tags[0])) == 0)
4890                                         yomikomu = 1;
4891                         }
4892                         else {
4893                                 if (strncmp(buf, tags[1], strlen(tags[1])) == 0)
4894                                         break;
4895                                 fprintf(fff, "%s\n", buf);
4896                         }
4897                 }
4898         }
4899
4900         /* Dump the screen */
4901         for (y = 0; y < hgt; y++)
4902         {
4903                 /* Start the row */
4904                 if (y != 0)
4905                         fprintf(fff, "\n");
4906
4907                 /* Dump each row */
4908                 for (x = 0; x < wid - 1; x++)
4909                 {
4910                         int rv, gv, bv;
4911                         cptr cc = NULL;
4912                         /* Get the attr/char */
4913                         (void)(Term_what(x, y, &a, &c));
4914
4915                         switch (c)
4916                         {
4917                         case '&': cc = "&amp;"; break;
4918                         case '<': cc = "&lt;"; break;
4919                         case '>': cc = "&gt;"; break;
4920 #ifdef WINDOWS
4921                         case 0x1f: c = '.'; break;
4922                         case 0x7f: c = (a == 0x09) ? '%' : '#'; break;
4923 #endif
4924                         }
4925
4926                         a = a & 0x0F;
4927                         if ((y == 0 && x == 0) || a != old_a) {
4928                                 rv = angband_color_table[a][1];
4929                                 gv = angband_color_table[a][2];
4930                                 bv = angband_color_table[a][3];
4931                                 fprintf(fff, "%s<font color=\"#%02x%02x%02x\">", 
4932                                         ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv);
4933                                 old_a = a;
4934                         }
4935                         if (cc)
4936                                 fprintf(fff, "%s", cc);
4937                         else
4938                                 fprintf(fff, "%c", c);
4939                 }
4940         }
4941         fprintf(fff, "</font>");
4942
4943         if (!tmpfff) {
4944                 for (i = 0; html_foot[i]; i++)
4945                         fputs(html_foot[i], fff);
4946         }
4947         else {
4948                 rewind(tmpfff);
4949                 yomikomu = 0;
4950                 while (!my_fgets(tmpfff, buf, sizeof(buf))) {
4951                         if (!yomikomu) {
4952                                 if (strncmp(buf, tags[2], strlen(tags[2])) == 0)
4953                                         yomikomu = 1;
4954                         }
4955                         else {
4956                                 if (strncmp(buf, tags[3], strlen(tags[3])) == 0)
4957                                         break;
4958                                 fprintf(fff, "%s\n", buf);
4959                         }
4960                 }
4961                 my_fclose(tmpfff);
4962         }
4963
4964         /* Skip a line */
4965         fprintf(fff, "\n");
4966
4967         /* Close it */
4968         my_fclose(fff);
4969
4970         if (message) {
4971                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
4972                 msg_print(NULL);
4973         }
4974         if (message)
4975                 screen_load();
4976 }
4977
4978 /*
4979  * Hack -- save a screen dump to a file
4980  */
4981 static void do_cmd_save_screen_html(void)
4982 {
4983         char buf[1024], tmp[256] = "screen.html";
4984
4985         if (!get_string(_("ファイル名: ", "File name: "), tmp, 80))
4986                 return;
4987
4988         /* Build the filename */
4989         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
4990
4991         msg_print(NULL);
4992
4993         do_cmd_save_screen_html_aux(buf, 1);
4994 }
4995
4996
4997 /*
4998  * Redefinable "save_screen" action
4999  */
5000 void (*screendump_aux)(void) = NULL;
5001
5002
5003 /*
5004  * Hack -- save a screen dump to a file
5005  */
5006 void do_cmd_save_screen(void)
5007 {
5008         bool old_use_graphics = use_graphics;
5009         bool html_dump = FALSE;
5010
5011         int wid, hgt;
5012
5013         prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0);
5014         while(TRUE)
5015         {
5016                 char c = inkey();
5017                 if (c == 'Y' || c == 'y')
5018                         break;
5019                 else if (c == 'H' || c == 'h')
5020                 {
5021                         html_dump = TRUE;
5022                         break;
5023                 }
5024                 else
5025                 {
5026                         prt("", 0, 0);
5027                         return;
5028                 }
5029         }
5030
5031         Term_get_size(&wid, &hgt);
5032
5033         if (old_use_graphics)
5034         {
5035                 use_graphics = FALSE;
5036                 reset_visuals();
5037                 p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
5038                 handle_stuff();
5039         }
5040
5041         if (html_dump)
5042         {
5043                 do_cmd_save_screen_html();
5044                 do_cmd_redraw();
5045         }
5046
5047         /* Do we use a special screendump function ? */
5048         else if (screendump_aux)
5049         {
5050                 /* Dump the screen to a graphics file */
5051                 (*screendump_aux)();
5052         }
5053         else /* Dump the screen as text */
5054         {
5055                 int y, x;
5056
5057                 TERM_COLOR a = 0;
5058                 char c = ' ';
5059
5060                 FILE *fff;
5061
5062                 char buf[1024];
5063
5064                 /* Build the filename */
5065                 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
5066
5067                 /* File type is "TEXT" */
5068                 FILE_TYPE(FILE_TYPE_TEXT);
5069
5070                 /* Append to the file */
5071                 fff = my_fopen(buf, "w");
5072
5073                 if (!fff)
5074                 {
5075                         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf);
5076                         msg_print(NULL);
5077                         return;
5078                 }
5079
5080                 screen_save();
5081
5082
5083                 /* Dump the screen */
5084                 for (y = 0; y < hgt; y++)
5085                 {
5086                         /* Dump each row */
5087                         for (x = 0; x < wid - 1; x++)
5088                         {
5089                                 /* Get the attr/char */
5090                                 (void)(Term_what(x, y, &a, &c));
5091
5092                                 /* Dump it */
5093                                 buf[x] = c;
5094                         }
5095
5096                         /* Terminate */
5097                         buf[x] = '\0';
5098
5099                         /* End the row */
5100                         fprintf(fff, "%s\n", buf);
5101                 }
5102
5103                 /* Skip a line */
5104                 fprintf(fff, "\n");
5105
5106
5107                 /* Dump the screen */
5108                 for (y = 0; y < hgt; y++)
5109                 {
5110                         /* Dump each row */
5111                         for (x = 0; x < wid - 1; x++)
5112                         {
5113                                 /* Get the attr/char */
5114                                 (void)(Term_what(x, y, &a, &c));
5115
5116                                 /* Dump it */
5117                                 buf[x] = hack[a&0x0F];
5118                         }
5119
5120                         /* Terminate */
5121                         buf[x] = '\0';
5122
5123                         /* End the row */
5124                         fprintf(fff, "%s\n", buf);
5125                 }
5126
5127                 /* Skip a line */
5128                 fprintf(fff, "\n");
5129
5130                 /* Close it */
5131                 my_fclose(fff);
5132
5133                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
5134                 msg_print(NULL);
5135                 screen_load();
5136         }
5137
5138         if (old_use_graphics)
5139         {
5140                 use_graphics = TRUE;
5141                 reset_visuals();
5142                 p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
5143                 handle_stuff();
5144         }
5145 }
5146
5147
5148 /*
5149  * Sorting hook -- Comp function -- see below
5150  *
5151  * We use "u" to point to array of monster indexes,
5152  * and "v" to select the type of sorting to perform on "u".
5153  */
5154 static bool ang_sort_art_comp(vptr u, vptr v, int a, int b)
5155 {
5156         u16b *who = (u16b*)(u);
5157
5158         u16b *why = (u16b*)(v);
5159
5160         int w1 = who[a];
5161         int w2 = who[b];
5162
5163         int z1, z2;
5164
5165         /* Sort by total kills */
5166         if (*why >= 3)
5167         {
5168                 /* Extract total kills */
5169                 z1 = a_info[w1].tval;
5170                 z2 = a_info[w2].tval;
5171
5172                 /* Compare total kills */
5173                 if (z1 < z2) return (TRUE);
5174                 if (z1 > z2) return (FALSE);
5175         }
5176
5177
5178         /* Sort by monster level */
5179         if (*why >= 2)
5180         {
5181                 /* Extract levels */
5182                 z1 = a_info[w1].sval;
5183                 z2 = a_info[w2].sval;
5184
5185                 /* Compare levels */
5186                 if (z1 < z2) return (TRUE);
5187                 if (z1 > z2) return (FALSE);
5188         }
5189
5190
5191         /* Sort by monster experience */
5192         if (*why >= 1)
5193         {
5194                 /* Extract experience */
5195                 z1 = a_info[w1].level;
5196                 z2 = a_info[w2].level;
5197
5198                 /* Compare experience */
5199                 if (z1 < z2) return (TRUE);
5200                 if (z1 > z2) return (FALSE);
5201         }
5202
5203
5204         /* Compare indexes */
5205         return (w1 <= w2);
5206 }
5207
5208
5209 /*
5210  * Sorting hook -- Swap function -- see below
5211  *
5212  * We use "u" to point to array of monster indexes,
5213  * and "v" to select the type of sorting to perform.
5214  */
5215 static void ang_sort_art_swap(vptr u, vptr v, int a, int b)
5216 {
5217         u16b *who = (u16b*)(u);
5218
5219         u16b holder;
5220
5221         /* Unused */
5222         (void)v;
5223
5224         /* Swap */
5225         holder = who[a];
5226         who[a] = who[b];
5227         who[b] = holder;
5228 }
5229
5230
5231 /*
5232  * Check the status of "artifacts"
5233  */
5234 static void do_cmd_knowledge_artifacts(void)
5235 {
5236         IDX i;
5237         IDX k;
5238         POSITION x, y;
5239         int n = 0;
5240         IDX z;
5241         u16b why = 3;
5242         IDX *who;
5243
5244         FILE *fff;
5245
5246         GAME_TEXT file_name[1024];
5247
5248         GAME_TEXT base_name[MAX_NLEN];
5249
5250         bool *okay;
5251
5252         /* Open a new file */
5253         fff = my_fopen_temp(file_name, 1024);
5254
5255         if (!fff) {
5256             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5257             msg_print(NULL);
5258             return;
5259         }
5260
5261         /* Allocate the "who" array */
5262         C_MAKE(who, max_a_idx, s16b);
5263
5264         /* Allocate the "okay" array */
5265         C_MAKE(okay, max_a_idx, bool);
5266
5267         /* Scan the artifacts */
5268         for (k = 0; k < max_a_idx; k++)
5269         {
5270                 artifact_type *a_ptr = &a_info[k];
5271
5272                 /* Default */
5273                 okay[k] = FALSE;
5274
5275                 /* Skip "empty" artifacts */
5276                 if (!a_ptr->name) continue;
5277
5278                 /* Skip "uncreated" artifacts */
5279                 if (!a_ptr->cur_num) continue;
5280
5281                 /* Assume okay */
5282                 okay[k] = TRUE;
5283         }
5284
5285         /* Check the dungeon */
5286         for (y = 0; y < cur_hgt; y++)
5287         {
5288                 for (x = 0; x < cur_wid; x++)
5289                 {
5290                         cave_type *c_ptr = &cave[y][x];
5291
5292                         OBJECT_IDX this_o_idx, next_o_idx = 0;
5293
5294                         /* Scan all objects in the grid */
5295                         for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
5296                         {
5297                                 object_type *o_ptr;
5298                                 o_ptr = &o_list[this_o_idx];
5299
5300                                 /* Acquire next object */
5301                                 next_o_idx = o_ptr->next_o_idx;
5302
5303                                 /* Ignore non-artifacts */
5304                                 if (!object_is_fixed_artifact(o_ptr)) continue;
5305
5306                                 /* Ignore known items */
5307                                 if (object_is_known(o_ptr)) continue;
5308
5309                                 /* Note the artifact */
5310                                 okay[o_ptr->name1] = FALSE;
5311                         }
5312                 }
5313         }
5314
5315         /* Check the inventory and equipment */
5316         for (i = 0; i < INVEN_TOTAL; i++)
5317         {
5318                 object_type *o_ptr = &inventory[i];
5319
5320                 /* Ignore non-objects */
5321                 if (!o_ptr->k_idx) continue;
5322
5323                 /* Ignore non-artifacts */
5324                 if (!object_is_fixed_artifact(o_ptr)) continue;
5325
5326                 /* Ignore known items */
5327                 if (object_is_known(o_ptr)) continue;
5328
5329                 /* Note the artifact */
5330                 okay[o_ptr->name1] = FALSE;
5331         }
5332
5333         for (k = 0; k < max_a_idx; k++)
5334         {
5335                 if (okay[k]) who[n++] = k;
5336         }
5337
5338         /* Select the sort method */
5339         ang_sort_comp = ang_sort_art_comp;
5340         ang_sort_swap = ang_sort_art_swap;
5341
5342         /* Sort the array by dungeon depth of monsters */
5343         ang_sort(who, &why, n);
5344
5345         /* Scan the artifacts */
5346         for (k = 0; k < n; k++)
5347         {
5348                 artifact_type *a_ptr = &a_info[who[k]];
5349
5350                 /* Paranoia */
5351                 strcpy(base_name, _("未知の伝説のアイテム", "Unknown Artifact"));
5352
5353                 /* Obtain the base object type */
5354                 z = lookup_kind(a_ptr->tval, a_ptr->sval);
5355
5356                 /* Real object */
5357                 if (z)
5358                 {
5359                         object_type forge;
5360                         object_type *q_ptr;
5361                         q_ptr = &forge;
5362
5363                         /* Create fake object */
5364                         object_prep(q_ptr, z);
5365
5366                         /* Make it an artifact */
5367                         q_ptr->name1 = (byte)who[k];
5368
5369                         /* Display as if known */
5370                         q_ptr->ident |= IDENT_STORE;
5371
5372                         /* Describe the artifact */
5373                         object_desc(base_name, q_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
5374                 }
5375
5376                 /* Hack -- Build the artifact name */
5377                 fprintf(fff, _("     %s\n", "     The %s\n"), base_name);
5378         }
5379
5380         /* Free the "who" array */
5381         C_KILL(who, max_a_idx, s16b);
5382
5383         /* Free the "okay" array */
5384         C_KILL(okay, max_a_idx, bool);
5385         my_fclose(fff);
5386
5387         /* Display the file contents */
5388         show_file(TRUE, file_name, _("既知の伝説のアイテム", "Artifacts Seen"), 0, 0);
5389
5390         /* Remove the file */
5391         fd_kill(file_name);
5392 }
5393
5394
5395 /*
5396  * Display known uniques
5397  * With "XTRA HACK UNIQHIST" (Originally from XAngband)
5398  */
5399 static void do_cmd_knowledge_uniques(void)
5400 {
5401         IDX i;
5402         int k, n = 0;
5403         u16b why = 2;
5404         IDX *who;
5405
5406         FILE *fff;
5407
5408         GAME_TEXT file_name[1024];
5409
5410         int n_alive[10];
5411         int n_alive_surface = 0;
5412         int n_alive_over100 = 0;
5413         int n_alive_total = 0;
5414         int max_lev = -1;
5415
5416         for (i = 0; i < 10; i++) n_alive[i] = 0;
5417
5418         /* Open a new file */
5419         fff = my_fopen_temp(file_name, 1024);
5420
5421         if (!fff)
5422         {
5423                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5424                 msg_print(NULL);
5425                 return;
5426         }
5427
5428         /* Allocate the "who" array */
5429         C_MAKE(who, max_r_idx, s16b);
5430
5431         /* Scan the monsters */
5432         for (i = 1; i < max_r_idx; i++)
5433         {
5434                 monster_race *r_ptr = &r_info[i];
5435                 int          lev;
5436
5437                 if (!r_ptr->name) continue;
5438
5439                 /* Require unique monsters */
5440                 if (!(r_ptr->flags1 & RF1_UNIQUE)) continue;
5441
5442                 /* Only display "known" uniques */
5443                 if (!cheat_know && !r_ptr->r_sights) continue;
5444
5445                 /* Only print rarity <= 100 uniques */
5446                 if (!r_ptr->rarity || ((r_ptr->rarity > 100) && !(r_ptr->flags1 & RF1_QUESTOR))) continue;
5447
5448                 /* Only "alive" uniques */
5449                 if (r_ptr->max_num == 0) continue;
5450
5451                 if (r_ptr->level)
5452                 {
5453                         lev = (r_ptr->level - 1) / 10;
5454                         if (lev < 10)
5455                         {
5456                                 n_alive[lev]++;
5457                                 if (max_lev < lev) max_lev = lev;
5458                         }
5459                         else n_alive_over100++;
5460                 }
5461                 else n_alive_surface++;
5462
5463                 /* Collect "appropriate" monsters */
5464                 who[n++] = i;
5465         }
5466
5467         /* Select the sort method */
5468         ang_sort_comp = ang_sort_comp_hook;
5469         ang_sort_swap = ang_sort_swap_hook;
5470
5471         /* Sort the array by dungeon depth of monsters */
5472         ang_sort(who, &why, n);
5473
5474         if (n_alive_surface)
5475         {
5476                 fprintf(fff, _("     地上  生存: %3d体\n", "      Surface  alive: %3d\n"), n_alive_surface);
5477                 n_alive_total += n_alive_surface;
5478         }
5479         for (i = 0; i <= max_lev; i++)
5480         {
5481                 fprintf(fff, _("%3d-%3d階  生存: %3d体\n", "Level %3d-%3d  alive: %3d\n"), 1 + i * 10, 10 + i * 10, n_alive[i]);
5482                 n_alive_total += n_alive[i];
5483         }
5484         if (n_alive_over100)
5485         {
5486                 fprintf(fff, _("101-   階  生存: %3d体\n", "Level 101-     alive: %3d\n"), n_alive_over100);
5487                 n_alive_total += n_alive_over100;
5488         }
5489
5490         if (n_alive_total)
5491         {
5492                 fputs(_("---------  -----------\n", "-------------  ----------\n"), fff);
5493                 fprintf(fff, _("     合計  生存: %3d体\n\n", "        Total  alive: %3d\n\n"), n_alive_total);
5494         }
5495         else
5496         {
5497                 fputs(_("現在は既知の生存ユニークはいません。\n", "No known uniques alive.\n"), fff);
5498         }
5499
5500         /* Scan the monster races */
5501         for (k = 0; k < n; k++)
5502         {
5503                 monster_race *r_ptr = &r_info[who[k]];
5504
5505                 fprintf(fff, _("     %s (レベル%d)\n", "     %s (level %d)\n"), r_name + r_ptr->name, (int)r_ptr->level);
5506         }
5507
5508         /* Free the "who" array */
5509         C_KILL(who, max_r_idx, s16b);
5510         my_fclose(fff);
5511
5512         /* Display the file contents */
5513         show_file(TRUE, file_name, _("まだ生きているユニーク・モンスター", "Alive Uniques"), 0, 0);
5514
5515         /* Remove the file */
5516         fd_kill(file_name);
5517 }
5518
5519
5520 /*
5521  * Display weapon-exp
5522  */
5523 static void do_cmd_knowledge_weapon_exp(void)
5524 {
5525         int i, num, weapon_exp;
5526         KIND_OBJECT_IDX j;
5527
5528         FILE *fff;
5529
5530         GAME_TEXT file_name[1024];
5531         char tmp[30];
5532
5533         /* Open a new file */
5534         fff = my_fopen_temp(file_name, 1024);
5535         if (!fff) {
5536             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5537             msg_print(NULL);
5538             return;
5539         }
5540
5541         for (i = 0; i < 5; i++)
5542         {
5543                 for (num = 0; num < 64; num++)
5544                 {
5545                         for (j = 0; j < max_k_idx; j++)
5546                         {
5547                                 object_kind *k_ptr = &k_info[j];
5548
5549                                 if ((k_ptr->tval == TV_SWORD - i) && (k_ptr->sval == num))
5550                                 {
5551                                         if ((k_ptr->tval == TV_BOW) && (k_ptr->sval == SV_CRIMSON || k_ptr->sval == SV_HARP)) continue;
5552
5553                                         weapon_exp = p_ptr->weapon_exp[4 - i][num];
5554                                         strip_name(tmp, j);
5555                                         fprintf(fff, "%-25s ", tmp);
5556                                         if (weapon_exp >= s_info[p_ptr->pclass].w_max[4 - i][num]) fprintf(fff, "!");
5557                                         else fprintf(fff, " ");
5558                                         fprintf(fff, "%s", exp_level_str[weapon_exp_level(weapon_exp)]);
5559                                         if (cheat_xtra) fprintf(fff, " %d", weapon_exp);
5560                                         fprintf(fff, "\n");
5561                                         break;
5562                                 }
5563                         }
5564                 }
5565         }
5566         my_fclose(fff);
5567
5568         /* Display the file contents */
5569         show_file(TRUE, file_name, _("武器の経験値", "Weapon Proficiency"), 0, 0);
5570
5571         /* Remove the file */
5572         fd_kill(file_name);
5573 }
5574
5575
5576 /*!
5577  * @brief 魔法の経験値を表示するコマンドのメインルーチン
5578  * Display spell-exp
5579  * @return なし
5580  */
5581 static void do_cmd_knowledge_spell_exp(void)
5582 {
5583         SPELL_IDX i = 0;
5584         int spell_exp, exp_level;
5585
5586         FILE *fff;
5587         const magic_type *s_ptr;
5588
5589         GAME_TEXT file_name[1024];
5590
5591         /* Open a new file */
5592         fff = my_fopen_temp(file_name, 1024);
5593         if (!fff) {
5594             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5595             msg_print(NULL);
5596             return;
5597         }
5598
5599         if (p_ptr->realm1 != REALM_NONE)
5600         {
5601                 fprintf(fff, _("%sの魔法書\n", "%s Spellbook\n"), realm_names[p_ptr->realm1]);
5602                 for (i = 0; i < 32; i++)
5603                 {
5604                         if (!is_magic(p_ptr->realm1))
5605                         {
5606                                 s_ptr = &technic_info[p_ptr->realm1 - MIN_TECHNIC][i];
5607                         }
5608                         else
5609                         {
5610                                 s_ptr = &mp_ptr->info[p_ptr->realm1 - 1][i];
5611                         }
5612                         if (s_ptr->slevel >= 99) continue;
5613                         spell_exp = p_ptr->spell_exp[i];
5614                         exp_level = spell_exp_level(spell_exp);
5615                         fprintf(fff, "%-25s ", do_spell(p_ptr->realm1, i, SPELL_NAME));
5616                         if (p_ptr->realm1 == REALM_HISSATSU)
5617                                 fprintf(fff, "[--]");
5618                         else
5619                         {
5620                                 if (exp_level >= EXP_LEVEL_MASTER) fprintf(fff, "!");
5621                                 else fprintf(fff, " ");
5622                                 fprintf(fff, "%s", exp_level_str[exp_level]);
5623                         }
5624                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
5625                         fprintf(fff, "\n");
5626                 }
5627         }
5628
5629         if (p_ptr->realm2 != REALM_NONE)
5630         {
5631                 fprintf(fff, _("%sの魔法書\n", "\n%s Spellbook\n"), realm_names[p_ptr->realm2]);
5632                 for (i = 0; i < 32; i++)
5633                 {
5634                         if (!is_magic(p_ptr->realm1))
5635                         {
5636                                 s_ptr = &technic_info[p_ptr->realm2 - MIN_TECHNIC][i];
5637                         }
5638                         else
5639                         {
5640                                 s_ptr = &mp_ptr->info[p_ptr->realm2 - 1][i];
5641                         }
5642                         if (s_ptr->slevel >= 99) continue;
5643
5644                         spell_exp = p_ptr->spell_exp[i + 32];
5645                         exp_level = spell_exp_level(spell_exp);
5646                         fprintf(fff, "%-25s ", do_spell(p_ptr->realm2, i, SPELL_NAME));
5647                         if (exp_level >= EXP_LEVEL_EXPERT) fprintf(fff, "!");
5648                         else fprintf(fff, " ");
5649                         fprintf(fff, "%s", exp_level_str[exp_level]);
5650                         if (cheat_xtra) fprintf(fff, " %d", spell_exp);
5651                         fprintf(fff, "\n");
5652                 }
5653         }
5654         my_fclose(fff);
5655
5656         /* Display the file contents */
5657         show_file(TRUE, file_name, _("魔法の経験値", "Spell Proficiency"), 0, 0);
5658
5659         /* Remove the file */
5660         fd_kill(file_name);
5661 }
5662
5663
5664 /*!
5665  * @brief スキル情報を表示するコマンドのメインルーチン /
5666  * Display skill-exp
5667  * @return なし
5668  */
5669 static void do_cmd_knowledge_skill_exp(void)
5670 {
5671         int i = 0, skill_exp;
5672
5673         FILE *fff;
5674
5675         GAME_TEXT file_name[1024];
5676         GAME_TEXT skill_name[3][20]={_("マーシャルアーツ", "Martial Arts    "),
5677                                                         _("二刀流          ", "Dual Wielding   "), 
5678                                                         _("乗馬            ", "Riding          ")};
5679
5680         /* Open a new file */
5681         fff = my_fopen_temp(file_name, 1024);
5682         if (!fff) {
5683             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5684             msg_print(NULL);
5685             return;
5686         }
5687
5688         for (i = 0; i < 3; i++)
5689         {
5690                 skill_exp = p_ptr->skill_exp[i];
5691                 fprintf(fff, "%-20s ", skill_name[i]);
5692                 if (skill_exp >= s_info[p_ptr->pclass].s_max[i]) fprintf(fff, "!");
5693                 else fprintf(fff, " ");
5694                 fprintf(fff, "%s", exp_level_str[(i == GINOU_RIDING) ? riding_exp_level(skill_exp) : weapon_exp_level(skill_exp)]);
5695                 if (cheat_xtra) fprintf(fff, " %d", skill_exp);
5696                 fprintf(fff, "\n");
5697         }
5698         my_fclose(fff);
5699
5700         /* Display the file contents */
5701         show_file(TRUE, file_name, _("技能の経験値", "Miscellaneous Proficiency"), 0, 0);
5702
5703         /* Remove the file */
5704         fd_kill(file_name);
5705 }
5706
5707
5708 /*!
5709  * @brief 英単語、句、説を複数形を変換する / Pluralize a monster name
5710  * @param Name 変換したい文字列の参照ポインタ
5711  * @return なし
5712  */
5713 void plural_aux(char *Name)
5714 {
5715         int NameLen = strlen(Name);
5716
5717         if (my_strstr(Name, "Disembodied hand"))
5718         {
5719                 strcpy(Name, "Disembodied hands that strangled people");
5720         }
5721         else if (my_strstr(Name, "Colour out of space"))
5722         {
5723                 strcpy(Name, "Colours out of space");
5724         }
5725         else if (my_strstr(Name, "stairway to hell"))
5726         {
5727                 strcpy(Name, "stairways to hell");
5728         }
5729         else if (my_strstr(Name, "Dweller on the threshold"))
5730         {
5731                 strcpy(Name, "Dwellers on the threshold");
5732         }
5733         else if (my_strstr(Name, " of "))
5734         {
5735                 cptr aider = my_strstr(Name, " of ");
5736                 char dummy[80];
5737                 int i = 0;
5738                 cptr ctr = Name;
5739
5740                 while (ctr < aider)
5741                 {
5742                         dummy[i] = *ctr;
5743                         ctr++; i++;
5744                 }
5745
5746                 if (dummy[i-1] == 's')
5747                 {
5748                         strcpy(&(dummy[i]), "es");
5749                         i++;
5750                 }
5751                 else
5752                 {
5753                         strcpy(&(dummy[i]), "s");
5754                 }
5755
5756                 strcpy(&(dummy[i+1]), aider);
5757                 strcpy(Name, dummy);
5758         }
5759         else if (my_strstr(Name, "coins"))
5760         {
5761                 char dummy[80];
5762                 strcpy(dummy, "piles of ");
5763                 strcat(dummy, Name);
5764                 strcpy(Name, dummy);
5765                 return;
5766         }
5767         else if (my_strstr(Name, "Manes"))
5768         {
5769                 return;
5770         }
5771         else if (streq(&(Name[NameLen - 2]), "ey"))
5772         {
5773                 strcpy(&(Name[NameLen - 2]), "eys");
5774         }
5775         else if (Name[NameLen - 1] == 'y')
5776         {
5777                 strcpy(&(Name[NameLen - 1]), "ies");
5778         }
5779         else if (streq(&(Name[NameLen - 4]), "ouse"))
5780         {
5781                 strcpy(&(Name[NameLen - 4]), "ice");
5782         }
5783         else if (streq(&(Name[NameLen - 2]), "us"))
5784         {
5785                 strcpy(&(Name[NameLen - 2]), "i");
5786         }
5787         else if (streq(&(Name[NameLen - 6]), "kelman"))
5788         {
5789                 strcpy(&(Name[NameLen - 6]), "kelmen");
5790         }
5791         else if (streq(&(Name[NameLen - 8]), "wordsman"))
5792         {
5793                 strcpy(&(Name[NameLen - 8]), "wordsmen");
5794         }
5795         else if (streq(&(Name[NameLen - 7]), "oodsman"))
5796         {
5797                 strcpy(&(Name[NameLen - 7]), "oodsmen");
5798         }
5799         else if (streq(&(Name[NameLen - 7]), "eastman"))
5800         {
5801                 strcpy(&(Name[NameLen - 7]), "eastmen");
5802         }
5803         else if (streq(&(Name[NameLen - 8]), "izardman"))
5804         {
5805                 strcpy(&(Name[NameLen - 8]), "izardmen");
5806         }
5807         else if (streq(&(Name[NameLen - 5]), "geist"))
5808         {
5809                 strcpy(&(Name[NameLen - 5]), "geister");
5810         }
5811         else if (streq(&(Name[NameLen - 2]), "ex"))
5812         {
5813                 strcpy(&(Name[NameLen - 2]), "ices");
5814         }
5815         else if (streq(&(Name[NameLen - 2]), "lf"))
5816         {
5817                 strcpy(&(Name[NameLen - 2]), "lves");
5818         }
5819         else if (suffix(Name, "ch") ||
5820                  suffix(Name, "sh") ||
5821                          suffix(Name, "nx") ||
5822                          suffix(Name, "s") ||
5823                          suffix(Name, "o"))
5824         {
5825                 strcpy(&(Name[NameLen]), "es");
5826         }
5827         else
5828         {
5829                 strcpy(&(Name[NameLen]), "s");
5830         }
5831 }
5832
5833 /*!
5834  * @brief 現在のペットを表示するコマンドのメインルーチン /
5835  * Display current pets
5836  * @return なし
5837  */
5838 static void do_cmd_knowledge_pets(void)
5839 {
5840         int             i;
5841         FILE            *fff;
5842         monster_type    *m_ptr;
5843         GAME_TEXT pet_name[MAX_NLEN];
5844         int             t_friends = 0;
5845         int             show_upkeep = 0;
5846         GAME_TEXT file_name[1024];
5847
5848
5849         /* Open a new file */
5850         fff = my_fopen_temp(file_name, 1024);
5851         if (!fff) {
5852             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5853             msg_print(NULL);
5854             return;
5855         }
5856
5857         /* Process the monsters (backwards) */
5858         for (i = m_max - 1; i >= 1; i--)
5859         {
5860                 /* Access the monster */
5861                 m_ptr = &m_list[i];
5862
5863                 /* Ignore "dead" monsters */
5864                 if (!m_ptr->r_idx) continue;
5865
5866                 /* Calculate "upkeep" for pets */
5867                 if (is_pet(m_ptr))
5868                 {
5869                         t_friends++;
5870                         monster_desc(pet_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
5871                         fprintf(fff, "%s (%s)\n", pet_name, look_mon_desc(m_ptr, 0x00));
5872                 }
5873         }
5874
5875         show_upkeep = calculate_upkeep();
5876
5877         fprintf(fff, "----------------------------------------------\n");
5878 #ifdef JP
5879         fprintf(fff, "    合計: %d 体のペット\n", t_friends);
5880         fprintf(fff, " 維持コスト: %d%% MP\n", show_upkeep);
5881 #else
5882         fprintf(fff, "   Total: %d pet%s.\n",
5883                 t_friends, (t_friends == 1 ? "" : "s"));
5884         fprintf(fff, "   Upkeep: %d%% mana.\n", show_upkeep);
5885 #endif
5886
5887
5888         my_fclose(fff);
5889
5890         /* Display the file contents */
5891         show_file(TRUE, file_name, _("現在のペット", "Current Pets"), 0, 0);
5892
5893         /* Remove the file */
5894         fd_kill(file_name);
5895 }
5896
5897
5898 /*!
5899  * @brief 現在のペットを表示するコマンドのメインルーチン /
5900  * Total kill count
5901  * @return なし
5902  * @note the player ghosts are ignored.  
5903  */
5904 static void do_cmd_knowledge_kill_count(void)
5905 {
5906         IDX i;
5907         int k, n = 0;
5908         u16b why = 2;
5909         IDX *who;
5910
5911         FILE *fff;
5912
5913         GAME_TEXT file_name[1024];
5914
5915         s32b Total = 0;
5916
5917
5918         /* Open a new file */
5919         fff = my_fopen_temp(file_name, 1024);
5920
5921         if (!fff) {
5922             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
5923             msg_print(NULL);
5924             return;
5925         }
5926
5927         /* Allocate the "who" array */
5928         C_MAKE(who, max_r_idx, s16b);
5929
5930         {
5931                 /* Monsters slain */
5932                 int kk;
5933
5934                 for (kk = 1; kk < max_r_idx; kk++)
5935                 {
5936                         monster_race *r_ptr = &r_info[kk];
5937
5938                         if (r_ptr->flags1 & (RF1_UNIQUE))
5939                         {
5940                                 bool dead = (r_ptr->max_num == 0);
5941
5942                                 if (dead)
5943                                 {
5944                                         Total++;
5945                                 }
5946                         }
5947                         else
5948                         {
5949                                 MONSTER_NUMBER This = r_ptr->r_pkills;
5950
5951                                 if (This > 0)
5952                                 {
5953                                         Total += This;
5954                                 }
5955                         }
5956                 }
5957
5958                 if (Total < 1)
5959                         fprintf(fff,_("あなたはまだ敵を倒していない。\n\n", "You have defeated no enemies yet.\n\n"));
5960                 else
5961 #ifdef JP
5962                         fprintf(fff,"あなたは%ld体の敵を倒している。\n\n", (long int)Total);
5963 #else
5964                         fprintf(fff,"You have defeated %ld %s.\n\n", (long int)Total, (Total == 1) ? "enemy" : "enemies");
5965 #endif
5966         }
5967
5968         Total = 0;
5969
5970         /* Scan the monsters */
5971         for (i = 1; i < max_r_idx; i++)
5972         {
5973                 monster_race *r_ptr = &r_info[i];
5974
5975                 /* Use that monster */
5976                 if (r_ptr->name) who[n++] = i;
5977         }
5978
5979         /* Select the sort method */
5980         ang_sort_comp = ang_sort_comp_hook;
5981         ang_sort_swap = ang_sort_swap_hook;
5982
5983         /* Sort the array by dungeon depth of monsters */
5984         ang_sort(who, &why, n);
5985
5986         /* Scan the monster races */
5987         for (k = 0; k < n; k++)
5988         {
5989                 monster_race *r_ptr = &r_info[who[k]];
5990
5991                 if (r_ptr->flags1 & (RF1_UNIQUE))
5992                 {
5993                         bool dead = (r_ptr->max_num == 0);
5994
5995                         if (dead)
5996                         {
5997                                 fprintf(fff, "     %s\n", (r_name + r_ptr->name));
5998                                 Total++;
5999                         }
6000                 }
6001                 else
6002                 {
6003                         MONSTER_NUMBER This = r_ptr->r_pkills;
6004
6005                         if (This > 0)
6006                         {
6007 #ifdef JP
6008                                 /* p,tは人と数える by ita */
6009                                 if (my_strchr("pt", r_ptr->d_char))
6010                                         fprintf(fff, "     %3d 人の %s\n", (int)This, r_name + r_ptr->name);
6011                                 else
6012                                         fprintf(fff, "     %3d 体の %s\n", (int)This, r_name + r_ptr->name);
6013 #else
6014                                 if (This < 2)
6015                                 {
6016                                         if (my_strstr(r_name + r_ptr->name, "coins"))
6017                                         {
6018                                                 fprintf(fff, "     1 pile of %s\n", (r_name + r_ptr->name));
6019                                         }
6020                                         else
6021                                         {
6022                                                 fprintf(fff, "     1 %s\n", (r_name + r_ptr->name));
6023                                         }
6024                                 }
6025                                 else
6026                                 {
6027                                         char ToPlural[80];
6028                                         strcpy(ToPlural, (r_name + r_ptr->name));
6029                                         plural_aux(ToPlural);
6030                                         fprintf(fff, "     %d %s\n", This, ToPlural);
6031                                 }
6032 #endif
6033
6034
6035                                 Total += This;
6036                         }
6037                 }
6038         }
6039
6040         fprintf(fff,"----------------------------------------------\n");
6041 #ifdef JP
6042         fprintf(fff,"    合計: %lu 体を倒した。\n", (unsigned long int)Total);
6043 #else
6044         fprintf(fff,"   Total: %lu creature%s killed.\n", (unsigned long int)Total, (Total == 1 ? "" : "s"));
6045 #endif
6046
6047
6048         /* Free the "who" array */
6049         C_KILL(who, max_r_idx, s16b);
6050         my_fclose(fff);
6051
6052         /* Display the file contents */
6053         show_file(TRUE, file_name, _("倒した敵の数", "Kill Count"), 0, 0);
6054
6055         /* Remove the file */
6056         fd_kill(file_name);
6057 }
6058
6059
6060 /*!
6061  * @brief モンスター情報リスト中のグループを表示する /
6062  * Display the object groups.
6063  * @param col 開始行
6064  * @param row 開始列
6065  * @param wid 表示文字数幅
6066  * @param per_page リストの表示行
6067  * @param grp_idx グループのID配列
6068  * @param group_text グループ名の文字列配列
6069  * @param grp_cur 現在の選択ID
6070  * @param grp_top 現在の選択リスト最上部ID
6071  * @return なし
6072  */
6073 static void display_group_list(int col, int row, int wid, int per_page, IDX grp_idx[], cptr group_text[], int grp_cur, int grp_top)
6074 {
6075         int i;
6076
6077         /* Display lines until done */
6078         for (i = 0; i < per_page && (grp_idx[i] >= 0); i++)
6079         {
6080                 /* Get the group index */
6081                 int grp = grp_idx[grp_top + i];
6082
6083                 /* Choose a color */
6084                 TERM_COLOR attr = (grp_top + i == grp_cur) ? TERM_L_BLUE : TERM_WHITE;
6085
6086                 /* Erase the entire line */
6087                 Term_erase(col, row + i, wid);
6088
6089                 /* Display the group label */
6090                 c_put_str(attr, group_text[grp], row + i, col);
6091         }
6092 }
6093
6094
6095 /* 
6096  * Move the cursor in a browser window 
6097  */
6098 static void browser_cursor(char ch, int *column, IDX *grp_cur, int grp_cnt, 
6099                                                    IDX *list_cur, int list_cnt)
6100 {
6101         int d;
6102         int col = *column;
6103         IDX grp = *grp_cur;
6104         IDX list = *list_cur;
6105
6106         /* Extract direction */
6107         if (ch == ' ')
6108         {
6109                 /* Hack -- scroll up full screen */
6110                 d = 3;
6111         }
6112         else if (ch == '-')
6113         {
6114                 /* Hack -- scroll down full screen */
6115                 d = 9;
6116         }
6117         else
6118         {
6119                 d = get_keymap_dir(ch);
6120         }
6121
6122         if (!d) return;
6123
6124         /* Diagonals - hack */
6125         if ((ddx[d] > 0) && ddy[d])
6126         {
6127                 int browser_rows;
6128                 int wid, hgt;
6129
6130                 Term_get_size(&wid, &hgt);
6131
6132                 browser_rows = hgt - 8;
6133
6134                 /* Browse group list */
6135                 if (!col)
6136                 {
6137                         int old_grp = grp;
6138
6139                         /* Move up or down */
6140                         grp += ddy[d] * (browser_rows - 1);
6141
6142                         /* Verify */
6143                         if (grp >= grp_cnt)     grp = grp_cnt - 1;
6144                         if (grp < 0) grp = 0;
6145                         if (grp != old_grp)     list = 0;
6146                 }
6147
6148                 /* Browse sub-list list */
6149                 else
6150                 {
6151                         /* Move up or down */
6152                         list += ddy[d] * browser_rows;
6153
6154                         /* Verify */
6155                         if (list >= list_cnt) list = list_cnt - 1;
6156                         if (list < 0) list = 0;
6157                 }
6158
6159                 (*grp_cur) = grp;
6160                 (*list_cur) = list;
6161
6162                 return;
6163         }
6164
6165         if (ddx[d])
6166         {
6167                 col += ddx[d];
6168                 if (col < 0) col = 0;
6169                 if (col > 1) col = 1;
6170
6171                 (*column) = col;
6172
6173                 return;
6174         }
6175
6176         /* Browse group list */
6177         if (!col)
6178         {
6179                 int old_grp = grp;
6180
6181                 /* Move up or down */
6182                 grp += ddy[d];
6183
6184                 /* Verify */
6185                 if (grp >= grp_cnt)     grp = grp_cnt - 1;
6186                 if (grp < 0) grp = 0;
6187                 if (grp != old_grp)     list = 0;
6188         }
6189
6190         /* Browse sub-list list */
6191         else
6192         {
6193                 /* Move up or down */
6194                 list += ddy[d];
6195
6196                 /* Verify */
6197                 if (list >= list_cnt) list = list_cnt - 1;
6198                 if (list < 0) list = 0;
6199         }
6200
6201         (*grp_cur) = grp;
6202         (*list_cur) = list;
6203 }
6204
6205
6206 /*
6207  * Display visuals.
6208  */
6209 static void display_visual_list(int col, int row, int height, int width, TERM_COLOR attr_top, byte char_left)
6210 {
6211         int i, j;
6212
6213         /* Clear the display lines */
6214         for (i = 0; i < height; i++)
6215         {
6216                 Term_erase(col, row + i, width);
6217         }
6218
6219         /* Bigtile mode uses double width */
6220         if (use_bigtile) width /= 2;
6221
6222         /* Display lines until done */
6223         for (i = 0; i < height; i++)
6224         {
6225                 /* Display columns until done */
6226                 for (j = 0; j < width; j++)
6227                 {
6228                         byte a;
6229                         char c;
6230                         TERM_LEN x = col + j;
6231                         TERM_LEN y = row + i;
6232                         int ia, ic;
6233
6234                         /* Bigtile mode uses double width */
6235                         if (use_bigtile) x += j;
6236
6237                         ia = attr_top + i;
6238                         ic = char_left + j;
6239
6240                         /* Ignore illegal characters */
6241                         if (ia > 0x7f || ic > 0xff || ic < ' ' ||
6242                             (!use_graphics && ic > 0x7f))
6243                                 continue;
6244
6245                         a = (byte)ia;
6246                         c = (char)ic;
6247
6248                         /* Force correct code for both ASCII character and tile */
6249                         if (c & 0x80) a |= 0x80;
6250
6251                         /* Display symbol */
6252                         Term_queue_bigchar(x, y, a, c, 0, 0);
6253                 }
6254         }
6255 }
6256
6257
6258 /*
6259  * Place the cursor at the collect position for visual mode
6260  */
6261 static void place_visual_list_cursor(TERM_LEN col, TERM_LEN row, TERM_COLOR a, byte c, TERM_COLOR attr_top, byte char_left)
6262 {
6263         int i = (a & 0x7f) - attr_top;
6264         int j = c - char_left;
6265
6266         TERM_LEN x = col + j;
6267         TERM_LEN y = row + i;
6268
6269         /* Bigtile mode uses double width */
6270         if (use_bigtile) x += j;
6271
6272         /* Place the cursor */
6273         Term_gotoxy(x, y);
6274 }
6275
6276
6277 /*
6278  *  Clipboard variables for copy&paste in visual mode
6279  */
6280 static TERM_COLOR attr_idx = 0;
6281 static byte char_idx = 0;
6282
6283 /* Hack -- for feature lighting */
6284 static TERM_COLOR attr_idx_feat[F_LIT_MAX];
6285 static byte char_idx_feat[F_LIT_MAX];
6286
6287 /*
6288  *  Do visual mode command -- Change symbols
6289  */
6290 static bool visual_mode_command(char ch, bool *visual_list_ptr,
6291                                 int height, int width,
6292                                 TERM_COLOR *attr_top_ptr, byte *char_left_ptr,
6293                                 TERM_COLOR *cur_attr_ptr, SYMBOL_CODE *cur_char_ptr, bool *need_redraw)
6294 {
6295         static TERM_COLOR attr_old = 0;
6296         static SYMBOL_CODE char_old = 0;
6297
6298         switch (ch)
6299         {
6300         case ESCAPE:
6301                 if (*visual_list_ptr)
6302                 {
6303                         /* Cancel change */
6304                         *cur_attr_ptr = attr_old;
6305                         *cur_char_ptr = char_old;
6306                         *visual_list_ptr = FALSE;
6307
6308                         return TRUE;
6309                 }
6310                 break;
6311
6312         case '\n':
6313         case '\r':
6314                 if (*visual_list_ptr)
6315                 {
6316                         /* Accept change */
6317                         *visual_list_ptr = FALSE;
6318                         *need_redraw = TRUE;
6319
6320                         return TRUE;
6321                 }
6322                 break;
6323
6324         case 'V':
6325         case 'v':
6326                 if (!*visual_list_ptr)
6327                 {
6328                         *visual_list_ptr = TRUE;
6329
6330                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
6331                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
6332
6333                         attr_old = *cur_attr_ptr;
6334                         char_old = *cur_char_ptr;
6335
6336                         return TRUE;
6337                 }
6338                 break;
6339
6340         case 'C':
6341         case 'c':
6342                 {
6343                         int i;
6344
6345                         /* Set the visual */
6346                         attr_idx = *cur_attr_ptr;
6347                         char_idx = *cur_char_ptr;
6348
6349                         /* Hack -- for feature lighting */
6350                         for (i = 0; i < F_LIT_MAX; i++)
6351                         {
6352                                 attr_idx_feat[i] = 0;
6353                                 char_idx_feat[i] = 0;
6354                         }
6355                 }
6356                 return TRUE;
6357
6358         case 'P':
6359         case 'p':
6360                 if (attr_idx || (!(char_idx & 0x80) && char_idx)) /* Allow TERM_DARK text */
6361                 {
6362                         /* Set the char */
6363                         *cur_attr_ptr = attr_idx;
6364                         *attr_top_ptr = MAX(0, (*cur_attr_ptr & 0x7f) - 5);
6365                         if (!*visual_list_ptr) *need_redraw = TRUE;
6366                 }
6367
6368                 if (char_idx)
6369                 {
6370                         /* Set the char */
6371                         *cur_char_ptr = char_idx;
6372                         *char_left_ptr = MAX(0, *cur_char_ptr - 10);
6373                         if (!*visual_list_ptr) *need_redraw = TRUE;
6374                 }
6375
6376                 return TRUE;
6377
6378         default:
6379                 if (*visual_list_ptr)
6380                 {
6381                         int eff_width;
6382                         int d = get_keymap_dir(ch);
6383                         byte a = (*cur_attr_ptr & 0x7f);
6384                         byte c = *cur_char_ptr;
6385
6386                         if (use_bigtile) eff_width = width / 2;
6387                         else eff_width = width;
6388
6389                         /* Restrict direction */
6390                         if ((a == 0) && (ddy[d] < 0)) d = 0;
6391                         if ((c == 0) && (ddx[d] < 0)) d = 0;
6392                         if ((a == 0x7f) && (ddy[d] > 0)) d = 0;
6393                         if ((c == 0xff) && (ddx[d] > 0)) d = 0;
6394
6395                         a += ddy[d];
6396                         c += ddx[d];
6397
6398                         /* Force correct code for both ASCII character and tile */
6399                         if (c & 0x80) a |= 0x80;
6400
6401                         /* Set the visual */
6402                         *cur_attr_ptr = a;
6403                         *cur_char_ptr = c;
6404
6405
6406                         /* Move the frame */
6407                         if ((ddx[d] < 0) && *char_left_ptr > MAX(0, (int)c - 10)) (*char_left_ptr)--;
6408                         if ((ddx[d] > 0) && *char_left_ptr + eff_width < MIN(0xff, (int)c + 10)) (*char_left_ptr)++;
6409                         if ((ddy[d] < 0) && *attr_top_ptr > MAX(0, (int)(a & 0x7f) - 4)) (*attr_top_ptr)--;
6410                         if ((ddy[d] > 0) && *attr_top_ptr + height < MIN(0x7f, (a & 0x7f) + 4)) (*attr_top_ptr)++;
6411                         return TRUE;
6412                 }
6413                 break;
6414         }
6415
6416         /* Visual mode command is not used */
6417         return FALSE;
6418 }
6419
6420
6421 /*
6422  * Display the monsters in a group.
6423  */
6424 static void display_monster_list(int col, int row, int per_page, s16b mon_idx[],
6425         int mon_cur, int mon_top, bool visual_only)
6426 {
6427         int i;
6428
6429         /* Display lines until done */
6430         for (i = 0; i < per_page && (mon_idx[mon_top + i] >= 0); i++)
6431         {
6432                 TERM_COLOR attr;
6433
6434                 /* Get the race index */
6435                 MONRACE_IDX r_idx = mon_idx[mon_top + i] ;
6436
6437                 /* Access the race */
6438                 monster_race *r_ptr = &r_info[r_idx];
6439
6440                 /* Choose a color */
6441                 attr = ((i + mon_top == mon_cur) ? TERM_L_BLUE : TERM_WHITE);
6442
6443                 /* Display the name */
6444                 c_prt(attr, (r_name + r_ptr->name), row + i, col);
6445
6446                 /* Hack -- visual_list mode */
6447                 if (per_page == 1)
6448                 {
6449                         c_prt(attr, format("%02x/%02x", r_ptr->x_attr, r_ptr->x_char), row + i, (p_ptr->wizard || visual_only) ? 56 : 61);
6450                 }
6451                 if (p_ptr->wizard || visual_only)
6452                 {
6453                         c_prt(attr, format("%d", r_idx), row + i, 62);
6454                 }
6455
6456                 /* Erase chars before overwritten by the race letter */
6457                 Term_erase(69, row + i, 255);
6458
6459                 /* Display symbol */
6460                 Term_queue_bigchar(use_bigtile ? 69 : 70, row + i, r_ptr->x_attr, r_ptr->x_char, 0, 0);
6461
6462                 if (!visual_only)
6463                 {
6464                         /* Display kills */
6465                         if (!(r_ptr->flags1 & RF1_UNIQUE)) 
6466                                 put_str(format("%5d", r_ptr->r_pkills), row + i, 73);
6467                         else 
6468                                 c_put_str((r_ptr->max_num == 0 ? TERM_L_DARK : TERM_WHITE), 
6469                                                   (r_ptr->max_num == 0 ? _("死亡", " dead") : _("生存", "alive")), row + i, 74);
6470                 }
6471         }
6472
6473         /* Clear remaining lines */
6474         for (; i < per_page; i++)
6475         {
6476                 Term_erase(col, row + i, 255);
6477         }
6478 }
6479
6480
6481 /*
6482  * Display known monsters.
6483  */
6484 static void do_cmd_knowledge_monsters(bool *need_redraw, bool visual_only, IDX direct_r_idx)
6485 {
6486         IDX i;
6487         int len, max;
6488         IDX grp_cur, grp_top, old_grp_cur;
6489         IDX mon_cur, mon_top;
6490         IDX grp_cnt, grp_idx[100];
6491         IDX mon_cnt;
6492         IDX *mon_idx;
6493
6494         int column = 0;
6495         bool flag;
6496         bool redraw;
6497
6498         bool visual_list = FALSE;
6499         TERM_COLOR attr_top = 0;
6500         byte char_left = 0;
6501
6502         int browser_rows;
6503         TERM_LEN wid, hgt;
6504
6505         BIT_FLAGS8 mode;
6506
6507         Term_get_size(&wid, &hgt);
6508
6509         browser_rows = hgt - 8;
6510
6511         /* Allocate the "mon_idx" array */
6512         C_MAKE(mon_idx, max_r_idx, s16b);
6513
6514         max = 0;
6515         grp_cnt = 0;
6516
6517         if (direct_r_idx < 0)
6518         {
6519                 mode = visual_only ? 0x03 : 0x01;
6520
6521                 /* Check every group */
6522                 for (i = 0; monster_group_text[i] != NULL; i++)
6523                 {
6524                         /* Measure the label */
6525                         len = strlen(monster_group_text[i]);
6526
6527                         /* Save the maximum length */
6528                         if (len > max) max = len;
6529
6530                         /* See if any monsters are known */
6531                         if ((monster_group_char[i] == ((char *) -1L)) || collect_monsters(i, mon_idx, mode))
6532                         {
6533                                 /* Build a list of groups with known monsters */
6534                                 grp_idx[grp_cnt++] = i;
6535                         }
6536                 }
6537
6538                 mon_cnt = 0;
6539         }
6540         else
6541         {
6542                 mon_idx[0] = direct_r_idx;
6543                 mon_cnt = 1;
6544
6545                 /* Terminate the list */
6546                 mon_idx[1] = -1;
6547
6548                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
6549                         &attr_top, &char_left, &r_info[direct_r_idx].x_attr, &r_info[direct_r_idx].x_char, need_redraw);
6550         }
6551
6552         /* Terminate the list */
6553         grp_idx[grp_cnt] = -1;
6554
6555         old_grp_cur = -1;
6556         grp_cur = grp_top = 0;
6557         mon_cur = mon_top = 0;
6558
6559         flag = FALSE;
6560         redraw = TRUE;
6561
6562         mode = visual_only ? 0x02 : 0x00;
6563
6564         while (!flag)
6565         {
6566                 char ch;
6567                 monster_race *r_ptr;
6568
6569                 if (redraw)
6570                 {
6571                         clear_from(0);
6572
6573 #ifdef JP
6574                         prt(format("%s - モンスター", !visual_only ? "知識" : "表示"), 2, 0);
6575                         if (direct_r_idx < 0) prt("グループ", 4, 0);
6576                         prt("名前", 4, max + 3);
6577                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
6578                         prt("文字", 4, 67);
6579                         if (!visual_only) prt("殺害数", 4, 72);
6580 #else
6581                         prt(format("%s - monsters", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
6582                         if (direct_r_idx < 0) prt("Group", 4, 0);
6583                         prt("Name", 4, max + 3);
6584                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
6585                         prt("Sym", 4, 68);
6586                         if (!visual_only) prt("Kills", 4, 73);
6587 #endif
6588
6589                         for (i = 0; i < 78; i++)
6590                         {
6591                                 Term_putch(i, 5, TERM_WHITE, '=');
6592                         }
6593
6594                         if (direct_r_idx < 0)
6595                         {
6596                                 for (i = 0; i < browser_rows; i++)
6597                                 {
6598                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
6599                                 }
6600                         }
6601
6602                         redraw = FALSE;
6603                 }
6604
6605                 if (direct_r_idx < 0)
6606                 {
6607                         /* Scroll group list */
6608                         if (grp_cur < grp_top) grp_top = grp_cur;
6609                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
6610
6611                         /* Display a list of monster groups */
6612                         display_group_list(0, 6, max, browser_rows, grp_idx, monster_group_text, grp_cur, grp_top);
6613
6614                         if (old_grp_cur != grp_cur)
6615                         {
6616                                 old_grp_cur = grp_cur;
6617
6618                                 /* Get a list of monsters in the current group */
6619                                 mon_cnt = collect_monsters(grp_idx[grp_cur], mon_idx, mode);
6620                         }
6621
6622                         /* Scroll monster list */
6623                         while (mon_cur < mon_top)
6624                                 mon_top = MAX(0, mon_top - browser_rows/2);
6625                         while (mon_cur >= mon_top + browser_rows)
6626                                 mon_top = MIN(mon_cnt - browser_rows, mon_top + browser_rows/2);
6627                 }
6628
6629                 if (!visual_list)
6630                 {
6631                         /* Display a list of monsters in the current group */
6632                         display_monster_list(max + 3, 6, browser_rows, mon_idx, mon_cur, mon_top, visual_only);
6633                 }
6634                 else
6635                 {
6636                         mon_top = mon_cur;
6637
6638                         /* Display a monster name */
6639                         display_monster_list(max + 3, 6, 1, mon_idx, mon_cur, mon_top, visual_only);
6640
6641                         /* Display visual list below first monster */
6642                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
6643                 }
6644
6645                 /* Prompt */
6646 #ifdef JP
6647                 prt(format("<方向>%s%s%s, ESC",
6648                         (!visual_list && !visual_only) ? ", 'r'で思い出を見る" : "",
6649                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
6650                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
6651                         hgt - 1, 0);
6652 #else
6653                 prt(format("<dir>%s%s%s, ESC",
6654                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
6655                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
6656                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
6657                         hgt - 1, 0);
6658 #endif
6659
6660                 /* Get the current monster */
6661                 r_ptr = &r_info[mon_idx[mon_cur]];
6662
6663                 if (!visual_only)
6664                 {
6665                         /* Mega Hack -- track this monster race */
6666                         if (mon_cnt) monster_race_track(mon_idx[mon_cur]);
6667                         handle_stuff();
6668                 }
6669
6670                 if (visual_list)
6671                 {
6672                         place_visual_list_cursor(max + 3, 7, r_ptr->x_attr, r_ptr->x_char, attr_top, char_left);
6673                 }
6674                 else if (!column)
6675                 {
6676                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
6677                 }
6678                 else
6679                 {
6680                         Term_gotoxy(max + 3, 6 + (mon_cur - mon_top));
6681                 }
6682
6683                 ch = inkey();
6684
6685                 /* Do visual mode command if needed */
6686                 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))
6687                 {
6688                         if (direct_r_idx >= 0)
6689                         {
6690                                 switch (ch)
6691                                 {
6692                                 case '\n':
6693                                 case '\r':
6694                                 case ESCAPE:
6695                                         flag = TRUE;
6696                                         break;
6697                                 }
6698                         }
6699                         continue;
6700                 }
6701
6702                 switch (ch)
6703                 {
6704                         case ESCAPE:
6705                         {
6706                                 flag = TRUE;
6707                                 break;
6708                         }
6709
6710                         case 'R':
6711                         case 'r':
6712                         {
6713                                 /* Recall on screen */
6714                                 if (!visual_list && !visual_only && (mon_idx[mon_cur] > 0))
6715                                 {
6716                                         screen_roff(mon_idx[mon_cur], 0);
6717
6718                                         (void)inkey();
6719
6720                                         redraw = TRUE;
6721                                 }
6722                                 break;
6723                         }
6724
6725                         default:
6726                         {
6727                                 /* Move the cursor */
6728                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &mon_cur, mon_cnt);
6729
6730                                 break;
6731                         }
6732                 }
6733         }
6734
6735         /* Free the "mon_idx" array */
6736         C_KILL(mon_idx, max_r_idx, s16b);
6737 }
6738
6739
6740 /*
6741  * Display the objects in a group.
6742  */
6743 static void display_object_list(int col, int row, int per_page, IDX object_idx[],
6744         int object_cur, int object_top, bool visual_only)
6745 {
6746         int i;
6747
6748         /* Display lines until done */
6749         for (i = 0; i < per_page && (object_idx[object_top + i] >= 0); i++)
6750         {
6751                 GAME_TEXT o_name[MAX_NLEN];
6752                 TERM_COLOR a;
6753                 byte c;
6754                 object_kind *flavor_k_ptr;
6755
6756                 /* Get the object index */
6757                 KIND_OBJECT_IDX k_idx = object_idx[object_top + i];
6758
6759                 /* Access the object */
6760                 object_kind *k_ptr = &k_info[k_idx];
6761
6762                 /* Choose a color */
6763                 TERM_COLOR attr = ((k_ptr->aware || visual_only) ? TERM_WHITE : TERM_SLATE);
6764                 byte cursor = ((k_ptr->aware || visual_only) ? TERM_L_BLUE : TERM_BLUE);
6765
6766
6767                 if (!visual_only && k_ptr->flavor)
6768                 {
6769                         /* Appearance of this object is shuffled */
6770                         flavor_k_ptr = &k_info[k_ptr->flavor];
6771                 }
6772                 else
6773                 {
6774                         /* Appearance of this object is very normal */
6775                         flavor_k_ptr = k_ptr;
6776                 }
6777
6778
6779
6780                 attr = ((i + object_top == object_cur) ? cursor : attr);
6781
6782                 if (!k_ptr->flavor || (!visual_only && k_ptr->aware))
6783                 {
6784                         /* Tidy name */
6785                         strip_name(o_name, k_idx);
6786                 }
6787                 else
6788                 {
6789                         /* Flavor name */
6790                         strcpy(o_name, k_name + flavor_k_ptr->flavor_name);
6791                 }
6792
6793                 /* Display the name */
6794                 c_prt(attr, o_name, row + i, col);
6795
6796                 /* Hack -- visual_list mode */
6797                 if (per_page == 1)
6798                 {
6799                         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);
6800                 }
6801                 if (p_ptr->wizard || visual_only)
6802                 {
6803                         c_prt(attr, format("%d", k_idx), row + i, 70);
6804                 }
6805
6806                 a = flavor_k_ptr->x_attr;
6807                 c = flavor_k_ptr->x_char;
6808
6809                 /* Display symbol */
6810                 Term_queue_bigchar(use_bigtile ? 76 : 77, row + i, a, c, 0, 0);
6811         }
6812
6813         /* Clear remaining lines */
6814         for (; i < per_page; i++)
6815         {
6816                 Term_erase(col, row + i, 255);
6817         }
6818 }
6819
6820 /*
6821  * Describe fake object
6822  */
6823 static void desc_obj_fake(KIND_OBJECT_IDX k_idx)
6824 {
6825         object_type *o_ptr;
6826         object_type object_type_body;
6827         o_ptr = &object_type_body;
6828         object_wipe(o_ptr);
6829
6830         /* Create the artifact */
6831         object_prep(o_ptr, k_idx);
6832
6833         /* It's fully know */
6834         o_ptr->ident |= IDENT_KNOWN;
6835
6836         /* Track the object */
6837         /* object_actual_track(o_ptr); */
6838
6839         /* Hack - mark as fake */
6840         /* term_obj_real = FALSE; */
6841         handle_stuff();
6842
6843         if (!screen_object(o_ptr, SCROBJ_FAKE_OBJECT | SCROBJ_FORCE_DETAIL))
6844         {
6845                 msg_print(_("特に変わったところはないようだ。", "You see nothing special."));
6846                 msg_print(NULL);
6847         }
6848 }
6849
6850
6851
6852 /*
6853  * Display known objects
6854  */
6855 static void do_cmd_knowledge_objects(bool *need_redraw, bool visual_only, IDX direct_k_idx)
6856 {
6857         IDX i;
6858         int len, max;
6859         IDX grp_cur, grp_top, old_grp_cur;
6860         IDX object_old, object_cur, object_top;
6861         int grp_cnt;
6862         IDX grp_idx[100];
6863         int object_cnt;
6864         IDX *object_idx;
6865
6866         int column = 0;
6867         bool flag;
6868         bool redraw;
6869
6870         bool visual_list = FALSE;
6871         TERM_COLOR attr_top = 0;
6872         byte char_left = 0;
6873
6874         int browser_rows;
6875         int wid, hgt;
6876
6877         byte mode;
6878
6879         Term_get_size(&wid, &hgt);
6880
6881         browser_rows = hgt - 8;
6882
6883         /* Allocate the "object_idx" array */
6884         C_MAKE(object_idx, max_k_idx, IDX);
6885
6886         max = 0;
6887         grp_cnt = 0;
6888
6889         if (direct_k_idx < 0)
6890         {
6891                 mode = visual_only ? 0x03 : 0x01;
6892
6893                 /* Check every group */
6894                 for (i = 0; object_group_text[i] != NULL; i++)
6895                 {
6896                         /* Measure the label */
6897                         len = strlen(object_group_text[i]);
6898
6899                         /* Save the maximum length */
6900                         if (len > max) max = len;
6901
6902                         /* See if any monsters are known */
6903                         if (collect_objects(i, object_idx, mode))
6904                         {
6905                                 /* Build a list of groups with known monsters */
6906                                 grp_idx[grp_cnt++] = i;
6907                         }
6908                 }
6909
6910                 object_old = -1;
6911                 object_cnt = 0;
6912         }
6913         else
6914         {
6915                 object_kind *k_ptr = &k_info[direct_k_idx];
6916                 object_kind *flavor_k_ptr;
6917
6918                 if (!visual_only && k_ptr->flavor)
6919                 {
6920                         /* Appearance of this object is shuffled */
6921                         flavor_k_ptr = &k_info[k_ptr->flavor];
6922                 }
6923                 else
6924                 {
6925                         /* Appearance of this object is very normal */
6926                         flavor_k_ptr = k_ptr;
6927                 }
6928
6929                 object_idx[0] = direct_k_idx;
6930                 object_old = direct_k_idx;
6931                 object_cnt = 1;
6932
6933                 /* Terminate the list */
6934                 object_idx[1] = -1;
6935
6936                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
6937                         &attr_top, &char_left, &flavor_k_ptr->x_attr, &flavor_k_ptr->x_char, need_redraw);
6938         }
6939
6940         /* Terminate the list */
6941         grp_idx[grp_cnt] = -1;
6942
6943         old_grp_cur = -1;
6944         grp_cur = grp_top = 0;
6945         object_cur = object_top = 0;
6946
6947         flag = FALSE;
6948         redraw = TRUE;
6949
6950         mode = visual_only ? 0x02 : 0x00;
6951
6952         while (!flag)
6953         {
6954                 char ch;
6955                 object_kind *k_ptr, *flavor_k_ptr;
6956
6957                 if (redraw)
6958                 {
6959                         clear_from(0);
6960
6961 #ifdef JP
6962                         prt(format("%s - アイテム", !visual_only ? "知識" : "表示"), 2, 0);
6963                         if (direct_k_idx < 0) prt("グループ", 4, 0);
6964                         prt("名前", 4, max + 3);
6965                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 70);
6966                         prt("文字", 4, 74);
6967 #else
6968                         prt(format("%s - objects", !visual_only ? "Knowledge" : "Visuals"), 2, 0);
6969                         if (direct_k_idx < 0) prt("Group", 4, 0);
6970                         prt("Name", 4, max + 3);
6971                         if (p_ptr->wizard || visual_only) prt("Idx", 4, 70);
6972                         prt("Sym", 4, 75);
6973 #endif
6974
6975                         for (i = 0; i < 78; i++)
6976                         {
6977                                 Term_putch(i, 5, TERM_WHITE, '=');
6978                         }
6979
6980                         if (direct_k_idx < 0)
6981                         {
6982                                 for (i = 0; i < browser_rows; i++)
6983                                 {
6984                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
6985                                 }
6986                         }
6987
6988                         redraw = FALSE;
6989                 }
6990
6991                 if (direct_k_idx < 0)
6992                 {
6993                         /* Scroll group list */
6994                         if (grp_cur < grp_top) grp_top = grp_cur;
6995                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
6996
6997                         /* Display a list of object groups */
6998                         display_group_list(0, 6, max, browser_rows, grp_idx, object_group_text, grp_cur, grp_top);
6999
7000                         if (old_grp_cur != grp_cur)
7001                         {
7002                                 old_grp_cur = grp_cur;
7003
7004                                 /* Get a list of objects in the current group */
7005                                 object_cnt = collect_objects(grp_idx[grp_cur], object_idx, mode);
7006                         }
7007
7008                         /* Scroll object list */
7009                         while (object_cur < object_top)
7010                                 object_top = MAX(0, object_top - browser_rows/2);
7011                         while (object_cur >= object_top + browser_rows)
7012                                 object_top = MIN(object_cnt - browser_rows, object_top + browser_rows/2);
7013                 }
7014
7015                 if (!visual_list)
7016                 {
7017                         /* Display a list of objects in the current group */
7018                         display_object_list(max + 3, 6, browser_rows, object_idx, object_cur, object_top, visual_only);
7019                 }
7020                 else
7021                 {
7022                         object_top = object_cur;
7023
7024                         /* Display a list of objects in the current group */
7025                         display_object_list(max + 3, 6, 1, object_idx, object_cur, object_top, visual_only);
7026
7027                         /* Display visual list below first object */
7028                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
7029                 }
7030
7031                 /* Get the current object */
7032                 k_ptr = &k_info[object_idx[object_cur]];
7033
7034                 if (!visual_only && k_ptr->flavor)
7035                 {
7036                         /* Appearance of this object is shuffled */
7037                         flavor_k_ptr = &k_info[k_ptr->flavor];
7038                 }
7039                 else
7040                 {
7041                         /* Appearance of this object is very normal */
7042                         flavor_k_ptr = k_ptr;
7043                 }
7044
7045                 /* Prompt */
7046 #ifdef JP
7047                 prt(format("<方向>%s%s%s, ESC",
7048                         (!visual_list && !visual_only) ? ", 'r'で詳細を見る" : "",
7049                         visual_list ? ", ENTERで決定" : ", 'v'でシンボル変更",
7050                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
7051                         hgt - 1, 0);
7052 #else
7053                 prt(format("<dir>%s%s%s, ESC",
7054                         (!visual_list && !visual_only) ? ", 'r' to recall" : "",
7055                         visual_list ? ", ENTER to accept" : ", 'v' for visuals",
7056                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
7057                         hgt - 1, 0);
7058 #endif
7059
7060                 if (!visual_only)
7061                 {
7062                         /* Mega Hack -- track this object */
7063                         if (object_cnt) object_kind_track(object_idx[object_cur]);
7064
7065                         /* The "current" object changed */
7066                         if (object_old != object_idx[object_cur])
7067                         {
7068                                 handle_stuff();
7069
7070                                 /* Remember the "current" object */
7071                                 object_old = object_idx[object_cur];
7072                         }
7073                 }
7074
7075                 if (visual_list)
7076                 {
7077                         place_visual_list_cursor(max + 3, 7, flavor_k_ptr->x_attr, flavor_k_ptr->x_char, attr_top, char_left);
7078                 }
7079                 else if (!column)
7080                 {
7081                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
7082                 }
7083                 else
7084                 {
7085                         Term_gotoxy(max + 3, 6 + (object_cur - object_top));
7086                 }
7087
7088                 ch = inkey();
7089
7090                 /* Do visual mode command if needed */
7091                 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))
7092                 {
7093                         if (direct_k_idx >= 0)
7094                         {
7095                                 switch (ch)
7096                                 {
7097                                 case '\n':
7098                                 case '\r':
7099                                 case ESCAPE:
7100                                         flag = TRUE;
7101                                         break;
7102                                 }
7103                         }
7104                         continue;
7105                 }
7106
7107                 switch (ch)
7108                 {
7109                         case ESCAPE:
7110                         {
7111                                 flag = TRUE;
7112                                 break;
7113                         }
7114
7115                         case 'R':
7116                         case 'r':
7117                         {
7118                                 /* Recall on screen */
7119                                 if (!visual_list && !visual_only && (grp_cnt > 0))
7120                                 {
7121                                         desc_obj_fake(object_idx[object_cur]);
7122                                         redraw = TRUE;
7123                                 }
7124                                 break;
7125                         }
7126
7127                         default:
7128                         {
7129                                 /* Move the cursor */
7130                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &object_cur, object_cnt);
7131                                 break;
7132                         }
7133                 }
7134         }
7135
7136         /* Free the "object_idx" array */
7137         C_KILL(object_idx, max_k_idx, IDX);
7138 }
7139
7140
7141 /*
7142  * Display the features in a group.
7143  */
7144 static void display_feature_list(int col, int row, int per_page, FEAT_IDX *feat_idx,
7145         FEAT_IDX feat_cur, FEAT_IDX feat_top, bool visual_only, int lighting_level)
7146 {
7147         int lit_col[F_LIT_MAX], i, j;
7148         int f_idx_col = use_bigtile ? 62 : 64;
7149
7150         /* Correct columns 1 and 4 */
7151         lit_col[F_LIT_STANDARD] = use_bigtile ? (71 - F_LIT_MAX) : 71;
7152         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
7153                 lit_col[i] = lit_col[F_LIT_STANDARD] + 2 + (i - F_LIT_NS_BEGIN) * 2 + (use_bigtile ? i : 0);
7154
7155         /* Display lines until done */
7156         for (i = 0; i < per_page && (feat_idx[feat_top + i] >= 0); i++)
7157         {
7158                 TERM_COLOR attr;
7159
7160                 /* Get the index */
7161                 FEAT_IDX f_idx = feat_idx[feat_top + i];
7162
7163                 /* Access the index */
7164                 feature_type *f_ptr = &f_info[f_idx];
7165
7166                 int row_i = row + i;
7167
7168                 /* Choose a color */
7169                 attr = ((i + feat_top == feat_cur) ? TERM_L_BLUE : TERM_WHITE);
7170
7171                 /* Display the name */
7172                 c_prt(attr, f_name + f_ptr->name, row_i, col);
7173
7174                 /* Hack -- visual_list mode */
7175                 if (per_page == 1)
7176                 {
7177                         /* Display lighting level */
7178                         c_prt(attr, format("(%s)", lighting_level_str[lighting_level]), row_i, col + 1 + strlen(f_name + f_ptr->name));
7179
7180                         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));
7181                 }
7182                 if (p_ptr->wizard || visual_only)
7183                 {
7184                         c_prt(attr, format("%d", f_idx), row_i, f_idx_col);
7185                 }
7186
7187                 /* Display symbol */
7188                 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);
7189
7190                 Term_putch(lit_col[F_LIT_NS_BEGIN], row_i, TERM_SLATE, '(');
7191                 for (j = F_LIT_NS_BEGIN + 1; j < F_LIT_MAX; j++)
7192                 {
7193                         Term_putch(lit_col[j], row_i, TERM_SLATE, '/');
7194                 }
7195                 Term_putch(lit_col[F_LIT_MAX - 1] + (use_bigtile ? 3 : 2), row_i, TERM_SLATE, ')');
7196
7197                 /* Mega-hack -- Use non-standard colour */
7198                 for (j = F_LIT_NS_BEGIN; j < F_LIT_MAX; j++)
7199                 {
7200                         Term_queue_bigchar(lit_col[j] + 1, row_i, f_ptr->x_attr[j], f_ptr->x_char[j], 0, 0);
7201                 }
7202         }
7203
7204         /* Clear remaining lines */
7205         for (; i < per_page; i++)
7206         {
7207                 Term_erase(col, row + i, 255);
7208         }
7209 }
7210
7211
7212 /*
7213  * Interact with feature visuals.
7214  */
7215 static void do_cmd_knowledge_features(bool *need_redraw, bool visual_only, IDX direct_f_idx, IDX *lighting_level)
7216 {
7217         IDX i;
7218         int len, max;
7219         IDX grp_cur, grp_top, old_grp_cur;
7220         IDX feat_cur, feat_top;
7221         int grp_cnt;
7222         IDX grp_idx[100];
7223         int feat_cnt;
7224         IDX *feat_idx;
7225
7226         int column = 0;
7227         bool flag;
7228         bool redraw;
7229
7230         bool visual_list = FALSE;
7231         TERM_COLOR attr_top = 0;
7232         byte char_left = 0;
7233
7234         int browser_rows;
7235         int wid, hgt;
7236
7237         TERM_COLOR attr_old[F_LIT_MAX];
7238         SYMBOL_CODE char_old[F_LIT_MAX];
7239         TERM_COLOR *cur_attr_ptr;
7240         SYMBOL_CODE *cur_char_ptr;
7241
7242         (void)C_WIPE(attr_old, F_LIT_MAX, byte);
7243         (void)C_WIPE(char_old, F_LIT_MAX, byte);
7244
7245         Term_get_size(&wid, &hgt);
7246
7247         browser_rows = hgt - 8;
7248
7249         /* Allocate the "feat_idx" array */
7250         C_MAKE(feat_idx, max_f_idx, IDX);
7251
7252         max = 0;
7253         grp_cnt = 0;
7254
7255         if (direct_f_idx < 0)
7256         {
7257                 /* Check every group */
7258                 for (i = 0; feature_group_text[i] != NULL; i++)
7259                 {
7260                         /* Measure the label */
7261                         len = strlen(feature_group_text[i]);
7262
7263                         /* Save the maximum length */
7264                         if (len > max) max = len;
7265
7266                         /* See if any features are known */
7267                         if (collect_features(i, feat_idx, 0x01))
7268                         {
7269                                 /* Build a list of groups with known features */
7270                                 grp_idx[grp_cnt++] = i;
7271                         }
7272                 }
7273
7274                 feat_cnt = 0;
7275         }
7276         else
7277         {
7278                 feature_type *f_ptr = &f_info[direct_f_idx];
7279
7280                 feat_idx[0] = direct_f_idx;
7281                 feat_cnt = 1;
7282
7283                 /* Terminate the list */
7284                 feat_idx[1] = -1;
7285
7286                 (void)visual_mode_command('v', &visual_list, browser_rows - 1, wid - (max + 3),
7287                         &attr_top, &char_left, &f_ptr->x_attr[*lighting_level], &f_ptr->x_char[*lighting_level], need_redraw);
7288
7289                 for (i = 0; i < F_LIT_MAX; i++)
7290                 {
7291                         attr_old[i] = f_ptr->x_attr[i];
7292                         char_old[i] = f_ptr->x_char[i];
7293                 }
7294         }
7295
7296         /* Terminate the list */
7297         grp_idx[grp_cnt] = -1;
7298
7299         old_grp_cur = -1;
7300         grp_cur = grp_top = 0;
7301         feat_cur = feat_top = 0;
7302
7303         flag = FALSE;
7304         redraw = TRUE;
7305
7306         while (!flag)
7307         {
7308                 char ch;
7309                 feature_type *f_ptr;
7310
7311                 if (redraw)
7312                 {
7313                         clear_from(0);
7314
7315 #ifdef JP
7316                         prt("表示 - 地形", 2, 0);
7317                         if (direct_f_idx < 0) prt("グループ", 4, 0);
7318                         prt("名前", 4, max + 3);
7319                         if (use_bigtile)
7320                         {
7321                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
7322                                 prt("文字 ( l/ d)", 4, 66);
7323                         }
7324                         else
7325                         {
7326                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 64);
7327                                 prt("文字 (l/d)", 4, 68);
7328                         }
7329 #else
7330                         prt("Visuals - features", 2, 0);
7331                         if (direct_f_idx < 0) prt("Group", 4, 0);
7332                         prt("Name", 4, max + 3);
7333                         if (use_bigtile)
7334                         {
7335                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 62);
7336                                 prt("Sym ( l/ d)", 4, 67);
7337                         }
7338                         else
7339                         {
7340                                 if (p_ptr->wizard || visual_only) prt("Idx", 4, 64);
7341                                 prt("Sym (l/d)", 4, 69);
7342                         }
7343 #endif
7344
7345                         for (i = 0; i < 78; i++)
7346                         {
7347                                 Term_putch(i, 5, TERM_WHITE, '=');
7348                         }
7349
7350                         if (direct_f_idx < 0)
7351                         {
7352                                 for (i = 0; i < browser_rows; i++)
7353                                 {
7354                                         Term_putch(max + 1, 6 + i, TERM_WHITE, '|');
7355                                 }
7356                         }
7357
7358                         redraw = FALSE;
7359                 }
7360
7361                 if (direct_f_idx < 0)
7362                 {
7363                         /* Scroll group list */
7364                         if (grp_cur < grp_top) grp_top = grp_cur;
7365                         if (grp_cur >= grp_top + browser_rows) grp_top = grp_cur - browser_rows + 1;
7366
7367                         /* Display a list of feature groups */
7368                         display_group_list(0, 6, max, browser_rows, grp_idx, feature_group_text, grp_cur, grp_top);
7369
7370                         if (old_grp_cur != grp_cur)
7371                         {
7372                                 old_grp_cur = grp_cur;
7373
7374                                 /* Get a list of features in the current group */
7375                                 feat_cnt = collect_features(grp_idx[grp_cur], feat_idx, 0x00);
7376                         }
7377
7378                         /* Scroll feature list */
7379                         while (feat_cur < feat_top)
7380                                 feat_top = MAX(0, feat_top - browser_rows/2);
7381                         while (feat_cur >= feat_top + browser_rows)
7382                                 feat_top = MIN(feat_cnt - browser_rows, feat_top + browser_rows/2);
7383                 }
7384
7385                 if (!visual_list)
7386                 {
7387                         /* Display a list of features in the current group */
7388                         display_feature_list(max + 3, 6, browser_rows, feat_idx, feat_cur, feat_top, visual_only, F_LIT_STANDARD);
7389                 }
7390                 else
7391                 {
7392                         feat_top = feat_cur;
7393
7394                         /* Display a list of features in the current group */
7395                         display_feature_list(max + 3, 6, 1, feat_idx, feat_cur, feat_top, visual_only, *lighting_level);
7396
7397                         /* Display visual list below first object */
7398                         display_visual_list(max + 3, 7, browser_rows-1, wid - (max + 3), attr_top, char_left);
7399                 }
7400
7401                 /* Prompt */
7402 #ifdef JP
7403                 prt(format("<方向>%s, 'd'で標準光源効果%s, ESC",
7404                         visual_list ? ", ENTERで決定, 'a'で対象明度変更" : ", 'v'でシンボル変更",
7405                         (attr_idx || char_idx) ? ", 'c', 'p'でペースト" : ", 'c'でコピー"),
7406                         hgt - 1, 0);
7407 #else
7408                 prt(format("<dir>%s, 'd' for default lighting%s, ESC",
7409                         visual_list ? ", ENTER to accept, 'a' for lighting level" : ", 'v' for visuals",
7410                         (attr_idx || char_idx) ? ", 'c', 'p' to paste" : ", 'c' to copy"),
7411                         hgt - 1, 0);
7412 #endif
7413
7414                 /* Get the current feature */
7415                 f_ptr = &f_info[feat_idx[feat_cur]];
7416                 cur_attr_ptr = &f_ptr->x_attr[*lighting_level];
7417                 cur_char_ptr = &f_ptr->x_char[*lighting_level];
7418
7419                 if (visual_list)
7420                 {
7421                         place_visual_list_cursor(max + 3, 7, *cur_attr_ptr, *cur_char_ptr, attr_top, char_left);
7422                 }
7423                 else if (!column)
7424                 {
7425                         Term_gotoxy(0, 6 + (grp_cur - grp_top));
7426                 }
7427                 else
7428                 {
7429                         Term_gotoxy(max + 3, 6 + (feat_cur - feat_top));
7430                 }
7431
7432                 ch = inkey();
7433
7434                 if (visual_list && ((ch == 'A') || (ch == 'a')))
7435                 {
7436                         int prev_lighting_level = *lighting_level;
7437
7438                         if (ch == 'A')
7439                         {
7440                                 if (*lighting_level <= 0) *lighting_level = F_LIT_MAX - 1;
7441                                 else (*lighting_level)--;
7442                         }
7443                         else
7444                         {
7445                                 if (*lighting_level >= F_LIT_MAX - 1) *lighting_level = 0;
7446                                 else (*lighting_level)++;
7447                         }
7448
7449                         if (f_ptr->x_attr[prev_lighting_level] != f_ptr->x_attr[*lighting_level])
7450                                 attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
7451
7452                         if (f_ptr->x_char[prev_lighting_level] != f_ptr->x_char[*lighting_level])
7453                                 char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
7454
7455                         continue;
7456                 }
7457
7458                 else if ((ch == 'D') || (ch == 'd'))
7459                 {
7460                         TERM_COLOR prev_x_attr = f_ptr->x_attr[*lighting_level];
7461                         byte prev_x_char = f_ptr->x_char[*lighting_level];
7462
7463                         apply_default_feat_lighting(f_ptr->x_attr, f_ptr->x_char);
7464
7465                         if (visual_list)
7466                         {
7467                                 if (prev_x_attr != f_ptr->x_attr[*lighting_level])
7468                                          attr_top = MAX(0, (f_ptr->x_attr[*lighting_level] & 0x7f) - 5);
7469
7470                                 if (prev_x_char != f_ptr->x_char[*lighting_level])
7471                                         char_left = MAX(0, f_ptr->x_char[*lighting_level] - 10);
7472                         }
7473                         else *need_redraw = TRUE;
7474
7475                         continue;
7476                 }
7477
7478                 /* Do visual mode command if needed */
7479                 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))
7480                 {
7481                         switch (ch)
7482                         {
7483                         /* Restore previous visual settings */
7484                         case ESCAPE:
7485                                 for (i = 0; i < F_LIT_MAX; i++)
7486                                 {
7487                                         f_ptr->x_attr[i] = attr_old[i];
7488                                         f_ptr->x_char[i] = char_old[i];
7489                                 }
7490
7491                                 /* Fall through */
7492
7493                         case '\n':
7494                         case '\r':
7495                                 if (direct_f_idx >= 0) flag = TRUE;
7496                                 else *lighting_level = F_LIT_STANDARD;
7497                                 break;
7498
7499                         /* Preserve current visual settings */
7500                         case 'V':
7501                         case 'v':
7502                                 for (i = 0; i < F_LIT_MAX; i++)
7503                                 {
7504                                         attr_old[i] = f_ptr->x_attr[i];
7505                                         char_old[i] = f_ptr->x_char[i];
7506                                 }
7507                                 *lighting_level = F_LIT_STANDARD;
7508                                 break;
7509
7510                         case 'C':
7511                         case 'c':
7512                                 if (!visual_list)
7513                                 {
7514                                         for (i = 0; i < F_LIT_MAX; i++)
7515                                         {
7516                                                 attr_idx_feat[i] = f_ptr->x_attr[i];
7517                                                 char_idx_feat[i] = f_ptr->x_char[i];
7518                                         }
7519                                 }
7520                                 break;
7521
7522                         case 'P':
7523                         case 'p':
7524                                 if (!visual_list)
7525                                 {
7526                                         /* Allow TERM_DARK text */
7527                                         for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
7528                                         {
7529                                                 if (attr_idx_feat[i] || (!(char_idx_feat[i] & 0x80) && char_idx_feat[i])) f_ptr->x_attr[i] = attr_idx_feat[i];
7530                                                 if (char_idx_feat[i]) f_ptr->x_char[i] = char_idx_feat[i];
7531                                         }
7532                                 }
7533                                 break;
7534                         }
7535                         continue;
7536                 }
7537
7538                 switch (ch)
7539                 {
7540                         case ESCAPE:
7541                         {
7542                                 flag = TRUE;
7543                                 break;
7544                         }
7545
7546                         default:
7547                         {
7548                                 /* Move the cursor */
7549                                 browser_cursor(ch, &column, &grp_cur, grp_cnt, &feat_cur, feat_cnt);
7550                                 break;
7551                         }
7552                 }
7553         }
7554
7555         /* Free the "feat_idx" array */
7556         C_KILL(feat_idx, max_f_idx, IDX);
7557 }
7558
7559
7560 /*
7561  * List wanted monsters
7562  */
7563 static void do_cmd_knowledge_kubi(void)
7564 {
7565         int i;
7566         FILE *fff;
7567         
7568         GAME_TEXT file_name[1024];
7569         
7570         
7571         /* Open a new file */
7572         fff = my_fopen_temp(file_name, 1024);
7573         if (!fff) {
7574             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7575             msg_print(NULL);
7576             return;
7577         }
7578         
7579         if (fff)
7580         {
7581                 bool listed = FALSE;
7582
7583 #ifdef JP
7584                 fprintf(fff, "今日のターゲット : %s\n", (p_ptr->today_mon ? r_name + r_info[p_ptr->today_mon].name : "不明"));
7585                 fprintf(fff, "\n");
7586                 fprintf(fff, "賞金首リスト\n");
7587 #else
7588                 fprintf(fff, "Today target : %s\n", (p_ptr->today_mon ? r_name + r_info[p_ptr->today_mon].name : "unknown"));
7589                 fprintf(fff, "\n");
7590                 fprintf(fff, "List of wanted monsters\n");
7591 #endif
7592                 fprintf(fff, "----------------------------------------------\n");
7593
7594                 for (i = 0; i < MAX_KUBI; i++)
7595                 {
7596                         if (kubi_r_idx[i] <= 10000)
7597                         {
7598                                 fprintf(fff,"%s\n", r_name + r_info[kubi_r_idx[i]].name);
7599
7600                                 listed = TRUE;
7601                         }
7602                 }
7603
7604                 if (!listed)
7605                 {
7606                         fprintf(fff,"\n%s\n", _("賞金首はもう残っていません。", "There is no more wanted monster."));
7607                 }
7608         }
7609                 my_fclose(fff);
7610         
7611         /* Display the file contents */
7612         show_file(TRUE, file_name, _("賞金首の一覧", "Wanted monsters"), 0, 0);
7613         
7614         /* Remove the file */
7615         fd_kill(file_name);
7616 }
7617
7618 /*
7619  * List virtues & status
7620  */
7621 static void do_cmd_knowledge_virtues(void)
7622 {
7623         FILE *fff;      
7624         GAME_TEXT file_name[1024];
7625                 
7626         /* Open a new file */
7627         fff = my_fopen_temp(file_name, 1024);
7628         if (!fff) {
7629             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7630             msg_print(NULL);
7631             return;
7632         }
7633         
7634         if (fff)
7635         {
7636                 fprintf(fff, _("現在の属性 : %s\n\n", "Your alighnment : %s\n\n"), your_alignment());
7637                 dump_virtues(fff);
7638         }
7639                 my_fclose(fff);
7640         
7641         /* Display the file contents */
7642         show_file(TRUE, file_name, _("八つの徳", "Virtues"), 0, 0);
7643         
7644         /* Remove the file */
7645         fd_kill(file_name);
7646 }
7647
7648 /*
7649 * Dungeon
7650 *
7651 */
7652 static void do_cmd_knowledge_dungeon(void)
7653 {
7654         FILE *fff;
7655         
7656         GAME_TEXT file_name[1024];
7657         int i;
7658                 
7659         /* Open a new file */
7660         fff = my_fopen_temp(file_name, 1024);
7661         if (!fff) {
7662             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7663             msg_print(NULL);
7664             return;
7665         }
7666         
7667         if (fff)
7668         {
7669                 for (i = 1; i < max_d_idx; i++)
7670                 {
7671                         bool seiha = FALSE;
7672
7673                         if (!d_info[i].maxdepth) continue;
7674                         if (!max_dlv[i]) continue;
7675                         if (d_info[i].final_guardian)
7676                         {
7677                                 if (!r_info[d_info[i].final_guardian].max_num) seiha = TRUE;
7678                         }
7679                         else if (max_dlv[i] == d_info[i].maxdepth) seiha = TRUE;
7680                         
7681                         fprintf(fff, _("%c%-12s :  %3d 階\n", "%c%-16s :  level %3d\n"), seiha ? '!' : ' ', d_name + d_info[i].name, (int)max_dlv[i]);
7682                 }
7683         }
7684                 my_fclose(fff);
7685         
7686         /* Display the file contents */
7687         show_file(TRUE, file_name, _("今までに入ったダンジョン", "Dungeon"), 0, 0);
7688         
7689         /* Remove the file */
7690         fd_kill(file_name);
7691 }
7692
7693 /*
7694 * List virtues & status
7695 *
7696 */
7697 static void do_cmd_knowledge_stat(void)
7698 {
7699         FILE *fff;
7700         
7701         GAME_TEXT file_name[1024];
7702         int percent, v_nr;
7703         
7704         /* Open a new file */
7705         fff = my_fopen_temp(file_name, 1024);
7706         if (!fff) {
7707             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
7708             msg_print(NULL);
7709             return;
7710         }
7711         
7712         if (fff)
7713         {
7714                 percent = (int)(((long)p_ptr->player_hp[PY_MAX_LEVEL - 1] * 200L) /
7715                         (2 * p_ptr->hitdie +
7716                         ((PY_MAX_LEVEL - 1+3) * (p_ptr->hitdie + 1))));
7717
7718 #ifdef JP
7719                 if (p_ptr->knowledge & KNOW_HPRATE) fprintf(fff, "現在の体力ランク : %d/100\n\n", percent);
7720                 else fprintf(fff, "現在の体力ランク : ???\n\n");
7721                 fprintf(fff, "能力の最大値\n\n");
7722 #else
7723                 if (p_ptr->knowledge & KNOW_HPRATE) fprintf(fff, "Your current Life Rating is %d/100.\n\n", percent);
7724                 else fprintf(fff, "Your current Life Rating is ???.\n\n");
7725                 fprintf(fff, "Limits of maximum stats\n\n");
7726 #endif
7727                 for (v_nr = 0; v_nr < 6; v_nr++)
7728                 {
7729                         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);
7730                         else fprintf(fff, "%s ???\n", stat_names[v_nr]);
7731                 }
7732         }
7733
7734         dump_yourself(fff);
7735         my_fclose(fff);
7736         
7737         /* Display the file contents */
7738         show_file(TRUE, file_name, _("自分に関する情報", "HP-rate & Max stat"), 0, 0);
7739         
7740         /* Remove the file */
7741         fd_kill(file_name);
7742 }
7743
7744
7745 /*
7746  * Print all active quests
7747  */
7748 static void do_cmd_knowledge_quests_current(FILE *fff)
7749 {
7750         char tmp_str[120];
7751         char rand_tmp_str[120] = "\0";
7752         GAME_TEXT name[MAX_NLEN];
7753         monster_race *r_ptr;
7754         IDX i;
7755         int rand_level = 100;
7756         int total = 0;
7757
7758         fprintf(fff, _("《遂行中のクエスト》\n", "< Current Quest >\n"));
7759
7760         for (i = 1; i < max_q_idx; i++)
7761         {
7762                 if ((quest[i].status == QUEST_STATUS_TAKEN) ||
7763                         ((quest[i].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[i].type == QUEST_TYPE_TOWER)) ||
7764                         (quest[i].status == QUEST_STATUS_COMPLETED))
7765                 {
7766                         /* Set the quest number temporary */
7767                         IDX old_quest = p_ptr->inside_quest;
7768                         int j;
7769
7770                         /* Clear the text */
7771                         for (j = 0; j < 10; j++) quest_text[j][0] = '\0';
7772                         quest_text_line = 0;
7773
7774                         p_ptr->inside_quest = i;
7775
7776                         /* Get the quest text */
7777                         init_flags = INIT_SHOW_TEXT;
7778
7779                         process_dungeon_file("q_info.txt", 0, 0, 0, 0);
7780
7781                         /* Reset the old quest number */
7782                         p_ptr->inside_quest = old_quest;
7783
7784                         /* No info from "silent" quests */
7785                         if (quest[i].flags & QUEST_FLAG_SILENT) continue;
7786
7787                         total++;
7788
7789                         if (quest[i].type != QUEST_TYPE_RANDOM)
7790                         {
7791                                 char note[80] = "\0";
7792
7793                                 if (quest[i].status == QUEST_STATUS_TAKEN || quest[i].status == QUEST_STATUS_STAGE_COMPLETED)
7794                                 {
7795                                         switch (quest[i].type)
7796                                         {
7797                                         case QUEST_TYPE_KILL_LEVEL:
7798                                         case QUEST_TYPE_KILL_ANY_LEVEL:
7799                                                 r_ptr = &r_info[quest[i].r_idx];
7800                                                 strcpy(name, r_name + r_ptr->name);
7801                                                 if (quest[i].max_num > 1)
7802                                                 {
7803 #ifdef JP
7804                                                         sprintf(note," - %d 体の%sを倒す。(あと %d 体)",
7805                                                                 (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
7806 #else
7807                                                         plural_aux(name);
7808                                                         sprintf(note," - kill %d %s, have killed %d.",
7809                                                                 (int)quest[i].max_num, name, (int)quest[i].cur_num);
7810 #endif
7811                                                 }
7812                                                 else
7813                                                         sprintf(note,_(" - %sを倒す。", " - kill %s."),name);
7814                                                 break;
7815
7816                                         case QUEST_TYPE_FIND_ARTIFACT:
7817                                                 if (quest[i].k_idx)
7818                                                 {
7819                                                         artifact_type *a_ptr = &a_info[quest[i].k_idx];
7820                                                         object_type forge;
7821                                                         object_type *q_ptr = &forge;
7822                                                         KIND_OBJECT_IDX k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
7823                                                         object_prep(q_ptr, k_idx);
7824                                                         q_ptr->name1 = quest[i].k_idx;
7825                                                         q_ptr->ident = IDENT_STORE;
7826                                                         object_desc(name, q_ptr, OD_NAME_ONLY);
7827                                                 }
7828                                                 sprintf(note,_("\n   - %sを見つけ出す。", "\n   - Find out %s."), name);
7829                                                 break;
7830                                         case QUEST_TYPE_FIND_EXIT:
7831                                                 sprintf(note,_(" - 出口に到達する。", " - Reach to Exit."));
7832                                                 break;
7833
7834                                         case QUEST_TYPE_KILL_NUMBER:
7835 #ifdef JP
7836                                                 sprintf(note," - %d 体のモンスターを倒す。(あと %d 体)",
7837                                                         (int)quest[i].max_num, (int)(quest[i].max_num - quest[i].cur_num));
7838 #else
7839                                                 sprintf(note," - Kill %d monsters, have killed %d.",
7840                                                         (int)quest[i].max_num, (int)quest[i].cur_num);
7841 #endif
7842                                                 break;
7843
7844                                         case QUEST_TYPE_KILL_ALL:
7845                                         case QUEST_TYPE_TOWER:
7846                                                 sprintf(note,_(" - 全てのモンスターを倒す。", " - Kill all monsters."));
7847                                                 break;
7848                                         }
7849                                 }
7850
7851                                 /* Print the quest info */
7852                                 sprintf(tmp_str, _("  %s (危険度:%d階相当)%s\n", "  %s (Danger level: %d)%s\n"),
7853                                         quest[i].name, (int)quest[i].level, note);
7854
7855                                 fputs(tmp_str, fff);
7856
7857                                 if (quest[i].status == QUEST_STATUS_COMPLETED)
7858                                 {
7859                                         sprintf(tmp_str, _("    クエスト達成 - まだ報酬を受けとってない。\n", "    Quest Completed - Unrewarded\n"));
7860                                         fputs(tmp_str, fff);
7861                                 }
7862                                 else
7863                                 {
7864                                         j = 0;
7865
7866                                         while (quest_text[j][0] && j < 10)
7867                                         {
7868                                                 fprintf(fff, "    %s\n", quest_text[j]);
7869                                                 j++;
7870                                         }
7871                                 }
7872                         }
7873                         else if (quest[i].level < rand_level) /* QUEST_TYPE_RANDOM */
7874                         {
7875                                 /* New random */
7876                                 rand_level = quest[i].level;
7877
7878                                 if (max_dlv[DUNGEON_ANGBAND] >= rand_level)
7879                                 {
7880                                         /* Print the quest info */
7881                                         r_ptr = &r_info[quest[i].r_idx];
7882                                         strcpy(name, r_name + r_ptr->name);
7883
7884                                         if (quest[i].max_num > 1)
7885                                         {
7886 #ifdef JP
7887                                                 sprintf(rand_tmp_str,"  %s (%d 階) - %d 体の%sを倒す。(あと %d 体)\n",
7888                                                         quest[i].name, (int)quest[i].level,
7889                                                         (int)quest[i].max_num, name, (int)(quest[i].max_num - quest[i].cur_num));
7890 #else
7891                                                 plural_aux(name);
7892
7893                                                 sprintf(rand_tmp_str,"  %s (Dungeon level: %d)\n  Kill %d %s, have killed %d.\n",
7894                                                         quest[i].name, (int)quest[i].level,
7895                                                         (int)quest[i].max_num, name, (int)quest[i].cur_num);
7896 #endif
7897                                         }
7898                                         else
7899                                         {
7900                                                 sprintf(rand_tmp_str,_("  %s (%d 階) - %sを倒す。\n", "  %s (Dungeon level: %d)\n  Kill %s.\n"),
7901                                                         quest[i].name, (int)quest[i].level, name);
7902                                         }
7903                                 }
7904                         }
7905                 }
7906         }
7907
7908         /* Print the current random quest  */
7909         if (rand_tmp_str[0]) fputs(rand_tmp_str, fff);
7910
7911         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
7912 }
7913
7914
7915 static bool do_cmd_knowledge_quests_aux(FILE *fff, IDX q_idx)
7916 {
7917         char tmp_str[120];
7918         char playtime_str[16];
7919         quest_type* const q_ptr = &quest[q_idx];
7920
7921         if (is_fixed_quest_idx(q_idx))
7922         {
7923                 /* Set the quest number temporary */
7924                 IDX old_quest = p_ptr->inside_quest;
7925
7926                 p_ptr->inside_quest = q_idx;
7927
7928                 /* Get the quest */
7929                 init_flags = INIT_NAME_ONLY;
7930
7931                 process_dungeon_file("q_info.txt", 0, 0, 0, 0);
7932
7933                 /* Reset the old quest number */
7934                 p_ptr->inside_quest = old_quest;
7935
7936                 /* No info from "silent" quests */
7937                 if (q_ptr->flags & QUEST_FLAG_SILENT) return FALSE;
7938         }
7939
7940         strnfmt(playtime_str, sizeof(playtime_str), "%02d:%02d:%02d",
7941                 q_ptr->comptime/(60*60), (q_ptr->comptime/60)%60, q_ptr->comptime%60);
7942
7943         if (!is_fixed_quest_idx(q_idx) && q_ptr->r_idx)
7944         {
7945                 /* Print the quest info */
7946                 if (q_ptr->complev == 0)
7947                 {
7948                         sprintf(tmp_str,
7949                                 _("  %-35s (%3d階)            -   不戦勝 - %s\n",
7950                                   "  %-35s (Dungeon level: %3d) - Unearned - %s\n") ,
7951                                 r_name+r_info[q_ptr->r_idx].name,
7952                                 (int)q_ptr->level, playtime_str);
7953                 }
7954                 else
7955                 {
7956                         sprintf(tmp_str,
7957                                 _("  %-35s (%3d階)            - レベル%2d - %s\n",
7958                                   "  %-35s (Dungeon level: %3d) - level %2d - %s\n") ,
7959                                 r_name+r_info[q_ptr->r_idx].name,
7960                                 (int)q_ptr->level,
7961                                 q_ptr->complev,
7962                                 playtime_str);
7963                 }
7964         }
7965         else
7966         {
7967                 /* Print the quest info */
7968                 sprintf(tmp_str,
7969                         _("  %-35s (危険度:%3d階相当) - レベル%2d - %s\n",
7970                           "  %-35s (Danger  level: %3d) - level %2d - %s\n") ,
7971                         q_ptr->name, (int)q_ptr->level, q_ptr->complev, playtime_str);
7972         }
7973
7974         fputs(tmp_str, fff);
7975
7976         return TRUE;
7977 }
7978
7979 /*
7980  * Print all finished quests
7981  */
7982 void do_cmd_knowledge_quests_completed(FILE *fff, IDX quest_num[])
7983 {
7984         int i;
7985         int total = 0;
7986
7987         fprintf(fff, _("《達成したクエスト》\n", "< Completed Quest >\n"));
7988         for (i = 1; i < max_q_idx; i++)
7989         {
7990                 IDX q_idx = quest_num[i];
7991                 quest_type* const q_ptr = &quest[q_idx];
7992
7993                 if (q_ptr->status == QUEST_STATUS_FINISHED &&
7994                     do_cmd_knowledge_quests_aux(fff, q_idx))
7995                 {
7996                         ++ total;
7997                 }
7998         }
7999         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
8000 }
8001
8002
8003 /*
8004  * Print all failed quests
8005  */
8006 void do_cmd_knowledge_quests_failed(FILE *fff, IDX quest_num[])
8007 {
8008         IDX i;
8009         int total = 0;
8010
8011         fprintf(fff, _("《失敗したクエスト》\n", "< Failed Quest >\n"));
8012         for (i = 1; i < max_q_idx; i++)
8013         {
8014                 IDX q_idx = quest_num[i];
8015                 quest_type* const q_ptr = &quest[q_idx];
8016
8017                 if (((q_ptr->status == QUEST_STATUS_FAILED_DONE) || (q_ptr->status == QUEST_STATUS_FAILED)) &&
8018                     do_cmd_knowledge_quests_aux(fff, q_idx))
8019                 {
8020                         ++ total;
8021                 }
8022         }
8023         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
8024 }
8025
8026
8027 /*
8028  * Print all random quests
8029  */
8030 static void do_cmd_knowledge_quests_wiz_random(FILE *fff)
8031 {
8032         char tmp_str[120];
8033         int i;
8034         int total = 0;
8035
8036         fprintf(fff, _("《残りのランダムクエスト》\n", "< Remaining Random Quest >\n"));
8037         for (i = 1; i < max_q_idx; i++)
8038         {
8039                 /* No info from "silent" quests */
8040                 if (quest[i].flags & QUEST_FLAG_SILENT) continue;
8041
8042                 if ((quest[i].type == QUEST_TYPE_RANDOM) && (quest[i].status == QUEST_STATUS_TAKEN))
8043                 {
8044                         total++;
8045
8046                         /* Print the quest info */
8047                         sprintf(tmp_str, _("  %s (%d階, %s)\n", "  %s (%d, %s)\n"),
8048                                 quest[i].name, (int)quest[i].level, r_name+r_info[quest[i].r_idx].name);
8049                         fputs(tmp_str, fff);
8050                 }
8051         }
8052         if (!total) fprintf(fff, _("  なし\n", "  Nothing.\n"));
8053 }
8054
8055
8056 bool ang_sort_comp_quest_num(vptr u, vptr v, int a, int b)
8057 {
8058         QUEST_IDX *q_num = (QUEST_IDX *)u;
8059         quest_type *qa = &quest[q_num[a]];
8060         quest_type *qb = &quest[q_num[b]];
8061
8062         /* Unused */
8063         (void)v;
8064
8065         return (qa->comptime != qb->comptime) ?
8066                 (qa->comptime < qb->comptime) :
8067                 (qa->level <= qb->level);
8068 }
8069
8070 void ang_sort_swap_quest_num(vptr u, vptr v, int a, int b)
8071 {
8072         QUEST_IDX *q_num = (QUEST_IDX *)u;
8073         QUEST_IDX tmp;
8074
8075         /* Unused */
8076         (void)v;
8077
8078         tmp = q_num[a];
8079         q_num[a] = q_num[b];
8080         q_num[b] = tmp;
8081 }
8082
8083
8084 /*
8085  * Print quest status of all active quests
8086  */
8087 static void do_cmd_knowledge_quests(void)
8088 {
8089         FILE *fff;
8090         GAME_TEXT file_name[1024];
8091         IDX *quest_num;
8092         int dummy;
8093         IDX i;
8094
8095         /* Open a new file */
8096         fff = my_fopen_temp(file_name, 1024);
8097         if (!fff)
8098         {
8099             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8100             msg_print(NULL);
8101             return;
8102         }
8103
8104         /* Allocate Memory */
8105         C_MAKE(quest_num, max_q_idx, IDX);
8106
8107         /* Sort by compete level */
8108         for (i = 1; i < max_q_idx; i++) quest_num[i] = i;
8109         ang_sort_comp = ang_sort_comp_quest_num;
8110         ang_sort_swap = ang_sort_swap_quest_num;
8111         ang_sort(quest_num, &dummy, max_q_idx);
8112
8113         /* Dump Quest Information */
8114         do_cmd_knowledge_quests_current(fff);
8115         fputc('\n', fff);
8116         do_cmd_knowledge_quests_completed(fff, quest_num);
8117         fputc('\n', fff);
8118         do_cmd_knowledge_quests_failed(fff, quest_num);
8119         if (p_ptr->wizard)
8120         {
8121                 fputc('\n', fff);
8122                 do_cmd_knowledge_quests_wiz_random(fff);
8123         }
8124         my_fclose(fff);
8125
8126         /* Display the file contents */
8127         show_file(TRUE, file_name, _("クエスト達成状況", "Quest status"), 0, 0);
8128
8129         /* Remove the file */
8130         fd_kill(file_name);
8131
8132         /* Free Memory */
8133         C_KILL(quest_num, max_q_idx, IDX);
8134 }
8135
8136
8137 /*
8138  * List my home
8139  */
8140 static void do_cmd_knowledge_home(void)
8141 {
8142         FILE *fff;
8143
8144         int i;
8145         GAME_TEXT file_name[1024];
8146         store_type  *st_ptr;
8147         GAME_TEXT o_name[MAX_NLEN];
8148         cptr            paren = ")";
8149
8150         process_dungeon_file("w_info.txt", 0, 0, max_wild_y, max_wild_x);
8151
8152         /* Open a new file */
8153         fff = my_fopen_temp(file_name, 1024);
8154         if (!fff) {
8155                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8156                 msg_print(NULL);
8157                 return;
8158         }
8159
8160         if (fff)
8161         {
8162                 /* Print all homes in the different towns */
8163                 st_ptr = &town[1].store[STORE_HOME];
8164
8165                 /* Home -- if anything there */
8166                 if (st_ptr->stock_num)
8167                 {
8168 #ifdef JP
8169                         TERM_LEN x = 1;
8170 #endif
8171                         /* Header with name of the town */
8172                         fprintf(fff, _("  [ 我が家のアイテム ]\n", "  [Home Inventory]\n"));
8173
8174                         /* Dump all available items */
8175                         for (i = 0; i < st_ptr->stock_num; i++)
8176                         {
8177 #ifdef JP
8178                                 if ((i % 12) == 0) fprintf(fff, "\n ( %d ページ )\n", x++);
8179                                 object_desc(o_name, &st_ptr->stock[i], 0);
8180                                 if (strlen(o_name) <= 80-3)
8181                                 {
8182                                         fprintf(fff, "%c%s %s\n", I2A(i%12), paren, o_name);
8183                                 }
8184                                 else
8185                                 {
8186                                         int n;
8187                                         char *t;
8188                                         for (n = 0, t = o_name; n < 80-3; n++, t++)
8189                                                 if(iskanji(*t)) {t++; n++;}
8190                                         if (n == 81-3) n = 79-3; /* 最後が漢字半分 */
8191
8192                                         fprintf(fff, "%c%s %.*s\n", I2A(i%12), paren, n, o_name);
8193                                         fprintf(fff, "   %.77s\n", o_name+n);
8194                                 }
8195 #else
8196                                 object_desc(o_name, &st_ptr->stock[i], 0);
8197                                 fprintf(fff, "%c%s %s\n", I2A(i%12), paren, o_name);
8198 #endif
8199
8200                         }
8201
8202                         /* Add an empty line */
8203                         fprintf(fff, "\n\n");
8204                 }
8205         }
8206         my_fclose(fff);
8207
8208         /* Display the file contents */
8209         show_file(TRUE, file_name, _("我が家のアイテム", "Home Inventory"), 0, 0);
8210
8211         /* Remove the file */
8212         fd_kill(file_name);
8213 }
8214
8215
8216 /*
8217  * Check the status of "autopick"
8218  */
8219 static void do_cmd_knowledge_autopick(void)
8220 {
8221         int k;
8222         FILE *fff;
8223         GAME_TEXT file_name[1024];
8224
8225         /* Open a new file */
8226         fff = my_fopen_temp(file_name, 1024);
8227
8228         if (!fff)
8229         {
8230             msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), file_name);
8231             msg_print(NULL);
8232             return;
8233         }
8234
8235         if (!max_autopick)
8236         {
8237             fprintf(fff, _("自動破壊/拾いには何も登録されていません。", "No preference for auto picker/destroyer."));
8238         }
8239         else
8240         {
8241                 fprintf(fff, _("   自動拾い/破壊には現在 %d行登録されています。\n\n",
8242                                            "   There are %d registered lines for auto picker/destroyer.\n\n"), max_autopick);
8243         }
8244
8245         for (k = 0; k < max_autopick; k++)
8246         {
8247                 cptr tmp;
8248                 byte act = autopick_list[k].action;
8249                 if (act & DONT_AUTOPICK)
8250                 {
8251                         tmp = _("放置", "Leave");
8252                 }
8253                 else if (act & DO_AUTODESTROY)
8254                 {
8255                         tmp = _("破壊", "Destroy");
8256                 }
8257                 else if (act & DO_AUTOPICK)
8258                 {
8259                         tmp = _("拾う", "Pickup");
8260                 }
8261                 else
8262                 {
8263                         tmp = _("確認", "Query");
8264                 }
8265
8266                 if (act & DO_DISPLAY)
8267                         fprintf(fff, "%11s", format("[%s]", tmp));
8268                 else
8269                         fprintf(fff, "%11s", format("(%s)", tmp));
8270
8271                 tmp = autopick_line_from_entry(&autopick_list[k]);
8272                 fprintf(fff, " %s", tmp);
8273                 string_free(tmp);
8274                 fprintf(fff, "\n");
8275         }
8276         my_fclose(fff);
8277         /* Display the file contents */
8278         show_file(TRUE, file_name, _("自動拾い/破壊 設定リスト", "Auto-picker/Destroyer"), 0, 0);
8279
8280         /* Remove the file */
8281         fd_kill(file_name);
8282 }
8283
8284
8285 /*
8286  * Interact with "knowledge"
8287  */
8288 void do_cmd_knowledge(void)
8289 {
8290         int i, p = 0;
8291         bool need_redraw = FALSE;
8292
8293         /* File type is "TEXT" */
8294         FILE_TYPE(FILE_TYPE_TEXT);
8295         screen_save();
8296
8297         /* Interact until done */
8298         while (1)
8299         {
8300                 Term_clear();
8301
8302                 /* Ask for a choice */
8303                 prt(format(_("%d/2 ページ", "page %d/2"), (p+1)), 2, 65);
8304                 prt(_("現在の知識を確認する", "Display current knowledge"), 3, 0);
8305
8306                 /* Give some choices */
8307 #ifdef JP
8308                 if (p == 0)
8309                 {
8310                         prt("(1) 既知の伝説のアイテム                 の一覧", 6, 5);
8311                         prt("(2) 既知のアイテム                       の一覧", 7, 5);
8312                         prt("(3) 既知の生きているユニーク・モンスター の一覧", 8, 5);
8313                         prt("(4) 既知のモンスター                     の一覧", 9, 5);
8314                         prt("(5) 倒した敵の数                         の一覧", 10, 5);
8315                         if (!vanilla_town) prt("(6) 賞金首                               の一覧", 11, 5);
8316                         prt("(7) 現在のペット                         の一覧", 12, 5);
8317                         prt("(8) 我が家のアイテム                     の一覧", 13, 5);
8318                         prt("(9) *鑑定*済み装備の耐性                 の一覧", 14, 5);
8319                         prt("(0) 地形の表示文字/タイル                の一覧", 15, 5);
8320                 }
8321                 else
8322                 {
8323                         prt("(a) 自分に関する情報                     の一覧", 6, 5);
8324                         prt("(b) 突然変異                             の一覧", 7, 5);
8325                         prt("(c) 武器の経験値                         の一覧", 8, 5);
8326                         prt("(d) 魔法の経験値                         の一覧", 9, 5);
8327                         prt("(e) 技能の経験値                         の一覧", 10, 5);
8328                         prt("(f) プレイヤーの徳                       の一覧", 11, 5);
8329                         prt("(g) 入ったダンジョン                     の一覧", 12, 5);
8330                         prt("(h) 実行中のクエスト                     の一覧", 13, 5);
8331                         prt("(i) 現在の自動拾い/破壊設定              の一覧", 14, 5);
8332                 }
8333 #else
8334                 if (p == 0)
8335                 {
8336                         prt("(1) Display known artifacts", 6, 5);
8337                         prt("(2) Display known objects", 7, 5);
8338                         prt("(3) Display remaining uniques", 8, 5);
8339                         prt("(4) Display known monster", 9, 5);
8340                         prt("(5) Display kill count", 10, 5);
8341                         if (!vanilla_town) prt("(6) Display wanted monsters", 11, 5);
8342                         prt("(7) Display current pets", 12, 5);
8343                         prt("(8) Display home inventory", 13, 5);
8344                         prt("(9) Display *identified* equip.", 14, 5);
8345                         prt("(0) Display terrain symbols.", 15, 5);
8346                 }
8347                 else
8348                 {
8349                         prt("(a) Display about yourself", 6, 5);
8350                         prt("(b) Display mutations", 7, 5);
8351                         prt("(c) Display weapon proficiency", 8, 5);
8352                         prt("(d) Display spell proficiency", 9, 5);
8353                         prt("(e) Display misc. proficiency", 10, 5);
8354                         prt("(f) Display virtues", 11, 5);
8355                         prt("(g) Display dungeons", 12, 5);
8356                         prt("(h) Display current quests", 13, 5);
8357                         prt("(i) Display auto pick/destroy", 14, 5);
8358                 }
8359 #endif
8360                 /* Prompt */
8361                 prt(_("-続く-", "-more-"), 17, 8);
8362                 prt(_("ESC) 抜ける", "ESC) Exit menu"), 21, 1);
8363                 prt(_("SPACE) 次ページ", "SPACE) Next page"), 21, 30);
8364                 /*prt("-) 前ページ", 21, 60);*/
8365                 prt(_("コマンド:", "Command: "), 20, 0);
8366                 i = inkey();
8367
8368                 if (i == ESCAPE) break;
8369                 switch (i)
8370                 {
8371                 case ' ': /* Page change */
8372                 case '-':
8373                         p = 1 - p;
8374                         break;
8375                 case '1': /* Artifacts */
8376                         do_cmd_knowledge_artifacts();
8377                         break;
8378                 case '2': /* Objects */
8379                         do_cmd_knowledge_objects(&need_redraw, FALSE, -1);
8380                         break;
8381                 case '3': /* Uniques */
8382                         do_cmd_knowledge_uniques();
8383                         break;
8384                 case '4': /* Monsters */
8385                         do_cmd_knowledge_monsters(&need_redraw, FALSE, -1);
8386                         break;
8387                 case '5': /* Kill count  */
8388                         do_cmd_knowledge_kill_count();
8389                         break;
8390                 case '6': /* wanted */
8391                         if (!vanilla_town) do_cmd_knowledge_kubi();
8392                         break;
8393                 case '7': /* Pets */
8394                         do_cmd_knowledge_pets();
8395                         break;
8396                 case '8': /* Home */
8397                         do_cmd_knowledge_home();
8398                         break;
8399                 case '9': /* Resist list */
8400                         do_cmd_knowledge_inven();
8401                         break;
8402                 case '0': /* Feature list */
8403                         {
8404                                 IDX lighting_level = F_LIT_STANDARD;
8405                                 do_cmd_knowledge_features(&need_redraw, FALSE, -1, &lighting_level);
8406                         }
8407                         break;
8408                 /* Next page */
8409                 case 'a': /* Max stat */
8410                         do_cmd_knowledge_stat();
8411                         break;
8412                 case 'b': /* Mutations */
8413                         do_cmd_knowledge_mutations();
8414                         break;
8415                 case 'c': /* weapon-exp */
8416                         do_cmd_knowledge_weapon_exp();
8417                         break;
8418                 case 'd': /* spell-exp */
8419                         do_cmd_knowledge_spell_exp();
8420                         break;
8421                 case 'e': /* skill-exp */
8422                         do_cmd_knowledge_skill_exp();
8423                         break;
8424                 case 'f': /* Virtues */
8425                         do_cmd_knowledge_virtues();
8426                         break;
8427                 case 'g': /* Dungeon */
8428                         do_cmd_knowledge_dungeon();
8429                         break;
8430                 case 'h': /* Quests */
8431                         do_cmd_knowledge_quests();
8432                         break;
8433                 case 'i': /* Autopick */
8434                         do_cmd_knowledge_autopick();
8435                         break;
8436                 default: /* Unknown option */
8437                         bell();
8438                 }
8439
8440                 msg_erase();
8441         }
8442         screen_load();
8443
8444         if (need_redraw) do_cmd_redraw();
8445 }
8446
8447
8448 /*
8449  * Check on the status of an active quest
8450  */
8451 void do_cmd_checkquest(void)
8452 {
8453         /* File type is "TEXT" */
8454         FILE_TYPE(FILE_TYPE_TEXT);
8455         screen_save();
8456
8457         /* Quest info */
8458         do_cmd_knowledge_quests();
8459         screen_load();
8460 }
8461
8462
8463 /*
8464  * Display the time and date
8465  */
8466 void do_cmd_time(void)
8467 {
8468         int day, hour, min, full, start, end, num;
8469         char desc[1024];
8470
8471         char buf[1024];
8472         char day_buf[10];
8473
8474         FILE *fff;
8475
8476         extract_day_hour_min(&day, &hour, &min);
8477
8478         full = hour * 100 + min;
8479
8480         start = 9999;
8481         end = -9999;
8482
8483         num = 0;
8484
8485         strcpy(desc, _("変な時刻だ。", "It is a strange time."));
8486
8487         if (day < MAX_DAYS) sprintf(day_buf, "%d", day);
8488         else strcpy(day_buf, "*****");
8489
8490 #ifdef JP
8491         msg_format("%s日目, 時刻は%d:%02d %sです。",
8492                    day_buf, (hour % 12 == 0) ? 12 : (hour % 12),
8493                    min, (hour < 12) ? "AM" : "PM");
8494 #else
8495         msg_format("This is day %s. The time is %d:%02d %s.",
8496                    day_buf, (hour % 12 == 0) ? 12 : (hour % 12),
8497                    min, (hour < 12) ? "AM" : "PM");
8498 #endif
8499
8500
8501         /* Find the path */
8502         if (!randint0(10) || p_ptr->image)
8503         {
8504                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timefun_j.txt", "timefun.txt"));
8505         }
8506         else
8507         {
8508                 path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, _("timenorm_j.txt", "timenorm.txt"));
8509         }
8510
8511         /* Open this file */
8512         fff = my_fopen(buf, "rt");
8513
8514         if (!fff) return;
8515
8516         /* Find this time */
8517         while (!my_fgets(fff, buf, sizeof(buf)))
8518         {
8519                 /* Ignore comments */
8520                 if (!buf[0] || (buf[0] == '#')) continue;
8521
8522                 /* Ignore invalid lines */
8523                 if (buf[1] != ':') continue;
8524
8525                 /* Process 'Start' */
8526                 if (buf[0] == 'S')
8527                 {
8528                         /* Extract the starting time */
8529                         start = atoi(buf + 2);
8530
8531                         /* Assume valid for an hour */
8532                         end = start + 59;
8533
8534                         /* Next... */
8535                         continue;
8536                 }
8537
8538                 /* Process 'End' */
8539                 if (buf[0] == 'E')
8540                 {
8541                         /* Extract the ending time */
8542                         end = atoi(buf + 2);
8543
8544                         /* Next... */
8545                         continue;
8546                 }
8547
8548                 /* Ignore incorrect range */
8549                 if ((start > full) || (full > end)) continue;
8550
8551                 /* Process 'Description' */
8552                 if (buf[0] == 'D')
8553                 {
8554                         num++;
8555
8556                         /* Apply the randomizer */
8557                         if (!randint0(num)) strcpy(desc, buf + 2);
8558
8559                         /* Next... */
8560                         continue;
8561                 }
8562         }
8563
8564         msg_print(desc);
8565         my_fclose(fff);
8566 }